Skip to content

Commit

Permalink
mgba - fix bug where hard reset caused memorydomains to get permanent…
Browse files Browse the repository at this point in the history
…ly wrecked
  • Loading branch information
zeromus committed Mar 27, 2016
1 parent c30817a commit 776e696
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 57 deletions.
61 changes: 40 additions & 21 deletions BizHawk.Emulation.Common/Base Implementations/MemoryDomain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ public MemoryDomain(string name, long size, Endian endian, Func<long, byte> peek

public Action<long, byte> PokeByte { get; private set; }

public void SetPeekPokeDelegates(Func<long, byte> peeker, Action<long, byte> poker)
{
PeekByte = peeker;
PokeByte = poker;
}

/// <summary>
/// creates a memorydomain that references a managed byte array
/// </summary>
Expand Down Expand Up @@ -62,41 +68,54 @@ public static MemoryDomain FromByteArray(string name, Endian endian, byte[] data
);
}

/// <summary>
/// create a memorydomain that references an unmanaged memory block
/// </summary>
/// <param name="data">must remain valid as long as the MemoryDomain exists!</param>
/// <param name="writable">if false, writes will be ignored</param>
/// <returns></returns>
public unsafe static MemoryDomain FromIntPtr(string name, long size, Endian endian, IntPtr data, bool writable = true, int byteSize = 1)
public void SetDelegatesForIntPtr(long size, Endian endian, IntPtr data, bool writable = true, int byteSize = 1)
{
Func<long, byte> peeker;
Action<long, byte> poker;
CreateDelegatesForIntPtr(size, endian, data, out peeker, out poker, writable, byteSize);
PeekByte = peeker;
PokeByte = poker;
}

public unsafe static void CreateDelegatesForIntPtr(long size, Endian endian, IntPtr data, out Func<long, byte> peeker, out Action<long, byte> poker, bool writable = true, int byteSize = 1)
{
if (data == IntPtr.Zero)
throw new ArgumentNullException("data");
if ((ulong)size >= 0x80000000)
throw new ArgumentOutOfRangeException("size");
byte* p = (byte*)data;
uint l = (uint)size;
return new MemoryDomain
(
name,
size,
endian,
delegate(long addr)

peeker = delegate(long addr)
{
if ((uint)addr >= l)
throw new ArgumentOutOfRangeException();
return p[addr];
},
};

poker =
writable ?
delegate(long addr, byte val)
{
if ((uint)addr >= l)
throw new ArgumentOutOfRangeException();
p[addr] = val;
}
: (Action<long, byte>)null,
byteSize
);
: (Action<long, byte>)null;
}

/// <summary>
/// create a memorydomain that references an unmanaged memory block
/// </summary>
/// <param name="data">must remain valid as long as the MemoryDomain exists!</param>
/// <param name="writable">if false, writes will be ignored</param>
/// <returns></returns>
public unsafe static MemoryDomain FromIntPtr(string name, long size, Endian endian, IntPtr data, bool writable = true, int byteSize = 1)
{
if (data == IntPtr.Zero)
throw new ArgumentNullException("data");
if ((ulong)size >= 0x80000000)
throw new ArgumentOutOfRangeException("size");

var md = new MemoryDomain(name,size,endian, null, null, byteSize);
md.SetDelegatesForIntPtr(size, endian, data, writable, byteSize);
return md;
}

/// <summary>
Expand Down
92 changes: 56 additions & 36 deletions BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,11 @@ public MGBAHawk(byte[] file, CoreComm comm, SyncSettings syncSettings, Settings
LibmGBA.BizSkipBios(core);
}


CreateMemoryDomains(file.Length);
var ser = new BasicServiceProvider(this);
ser.Register<IDisassemblable>(new ArmV4Disassembler());
ser.Register<IMemoryDomains>(CreateMemoryDomains(file.Length));
ser.Register<IMemoryDomains>(MemoryDomains);

ServiceProvider = ser;
CoreComm = comm;
Expand All @@ -78,6 +80,8 @@ public MGBAHawk(byte[] file, CoreComm comm, SyncSettings syncSettings, Settings
}
}

MemoryDomainList MemoryDomains;

public IEmulatorServiceProvider ServiceProvider { get; private set; }
public ControllerDefinition ControllerDefinition { get { return GBA.GBAController; } }
public IController Controller { get; set; }
Expand All @@ -86,7 +90,11 @@ public void FrameAdvance(bool render, bool rendersound = true)
{
Frame++;
if (Controller["Power"])
{
LibmGBA.BizReset(core);
//BizReset caused memorydomain pointers to change.
WireMemoryDomainPointers();
}

IsLagFrame = LibmGBA.BizAdvance(core, VBANext.GetButtons(Controller), videobuff, ref nsamp, soundbuff,
RTCTime(),
Expand Down Expand Up @@ -168,46 +176,42 @@ public void DiscardSamples()
unsafe byte PeekWRAM(IntPtr xwram, long addr) { return ((byte*)xwram.ToPointer())[addr];}
unsafe void PokeWRAM(IntPtr xwram, long addr, byte value) { ((byte*)xwram.ToPointer())[addr] = value; }

private MemoryDomainList CreateMemoryDomains(int romsize)
void WireMemoryDomainPointers()
{
var s = new LibmGBA.MemoryAreas();
var mm = new List<MemoryDomain>();
LibmGBA.BizGetMemoryAreas(core, s);

var l = MemoryDomain.Endian.Little;
mm.Add(MemoryDomain.FromIntPtr("IWRAM", 32 * 1024, l, s.iwram, true, 4));
mm.Add(MemoryDomain.FromIntPtr("EWRAM", 256 * 1024, l, s.wram, true, 4));
mm.Add(MemoryDomain.FromIntPtr("BIOS", 16 * 1024, l, s.bios, false, 4));
mm.Add(MemoryDomain.FromIntPtr("PALRAM", 1024, l, s.palram, false, 4));
mm.Add(MemoryDomain.FromIntPtr("VRAM", 96 * 1024, l, s.vram, true, 4));
mm.Add(MemoryDomain.FromIntPtr("OAM", 1024, l, s.oam, false, 4));
mm.Add(MemoryDomain.FromIntPtr("ROM", romsize, l, s.rom, false, 4));
var LE = MemoryDomain.Endian.Little;
MemoryDomains["IWRAM"].SetDelegatesForIntPtr(MemoryDomains["IWRAM"].Size, LE, s.wram, true, 4);
MemoryDomains["EWRAM"].SetDelegatesForIntPtr(MemoryDomains["EWRAM"].Size, LE, s.wram, true, 4);
MemoryDomains["BIOS"].SetDelegatesForIntPtr(MemoryDomains["BIOS"].Size, LE, s.bios, false, 4);
MemoryDomains["PALRAM"].SetDelegatesForIntPtr(MemoryDomains["PALRAM"].Size, LE, s.palram, false, 4);
MemoryDomains["VRAM"].SetDelegatesForIntPtr(MemoryDomains["VRAM"].Size, LE, s.vram, true, 4);
MemoryDomains["OAM"].SetDelegatesForIntPtr(MemoryDomains["OAM"].Size, LE, s.oam, false, 4);
MemoryDomains["ROM"].SetDelegatesForIntPtr(MemoryDomains["ROM"].Size, LE, s.rom, false, 4);

// special combined ram memory domain
{
var ew = mm[1];
var iw = mm[0];
MemoryDomain cr = new MemoryDomain("Combined WRAM", (256 + 32) * 1024, MemoryDomain.Endian.Little,
delegate(long addr)
{
if (addr < 0 || addr >= (256 + 32) * 1024)
throw new IndexOutOfRangeException();
if (addr >= 256 * 1024)
return PeekWRAM(s.iwram,addr & 32767);
else
return PeekWRAM(s.wram, addr);
},
delegate(long addr, byte val)
{
if (addr < 0 || addr >= (256 + 32) * 1024)
throw new IndexOutOfRangeException();
if (addr >= 256 * 1024)
PokeWRAM(s.iwram, addr & 32767, val);
else
PokeWRAM(s.wram, addr, val);
}, 4);
mm.Add(cr);
}
MemoryDomains["Combined WRAM"].SetPeekPokeDelegates(
delegate(long addr)
{
LibmGBA.BizGetMemoryAreas(core, s);
if (addr < 0 || addr >= (256 + 32) * 1024)
throw new IndexOutOfRangeException();
if (addr >= 256 * 1024)
return PeekWRAM(s.iwram, addr & 32767);
else
return PeekWRAM(s.wram, addr);
},
delegate(long addr, byte val)
{
if (addr < 0 || addr >= (256 + 32) * 1024)
throw new IndexOutOfRangeException();
if (addr >= 256 * 1024)
PokeWRAM(s.iwram, addr & 32767, val);
else
PokeWRAM(s.wram, addr, val);
}
);

_gpumem = new GBAGPUMemoryAreas
{
Expand All @@ -217,8 +221,24 @@ private MemoryDomainList CreateMemoryDomains(int romsize)
vram = s.vram
};

return new MemoryDomainList(mm);
}

private void CreateMemoryDomains(int romsize)
{
var LE = MemoryDomain.Endian.Little;

var mm = new List<MemoryDomain>();
mm.Add(new MemoryDomain("IWRAM", 32 * 1024, LE, null, null, 4));
mm.Add(new MemoryDomain("EWRAM", 256 * 1024, LE, null, null, 4));
mm.Add(new MemoryDomain("BIOS", 16 * 1024, LE, null, null, 4));
mm.Add(new MemoryDomain("PALRAM", 1024, LE, null, null, 4));
mm.Add(new MemoryDomain("VRAM", 96 * 1024, LE, null, null, 4));
mm.Add(new MemoryDomain("OAM", 1024, LE, null, null, 4));
mm.Add(new MemoryDomain("ROM", romsize, LE, null, null, 4));
mm.Add(new MemoryDomain("Combined WRAM", (256 + 32) * 1024, LE, null, null, 4));

MemoryDomains = new MemoryDomainList(mm);
WireMemoryDomainPointers();
}

#endregion
Expand Down

0 comments on commit 776e696

Please sign in to comment.