Add the basics of multiple memory arenas to elfrunner. With a bit of tweaking, gpgx core states are now 3.5MB (and could get smaller)
This commit is contained in:
parent
f42c0d4a39
commit
8136aa0f03
|
@ -89,9 +89,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
{
|
||||
if (!disposed)
|
||||
{
|
||||
// KillMemCallbacks(); // not needed when not single instance
|
||||
if (NativeData != null)
|
||||
NativeData.Dispose();
|
||||
if (Elf != null)
|
||||
Elf.Dispose();
|
||||
if (CD != null)
|
||||
CD.Dispose();
|
||||
disposed = true;
|
||||
|
|
|
@ -12,11 +12,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
public byte[] CloneSaveRam()
|
||||
{
|
||||
int size = 0;
|
||||
IntPtr area = IntPtr.Zero;
|
||||
Core.gpgx_get_sram(ref area, ref size);
|
||||
if (size <= 0 || area == IntPtr.Zero)
|
||||
IntPtr area = Core.gpgx_get_sram(ref size);
|
||||
if (size == 0 || area == IntPtr.Zero)
|
||||
return new byte[0];
|
||||
Core.gpgx_sram_prepread();
|
||||
|
||||
byte[] ret = new byte[size];
|
||||
Marshal.Copy(area, ret, 0, size);
|
||||
|
@ -25,16 +23,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
|
||||
public void StoreSaveRam(byte[] data)
|
||||
{
|
||||
int size = 0;
|
||||
IntPtr area = IntPtr.Zero;
|
||||
Core.gpgx_get_sram(ref area, ref size);
|
||||
if (size <= 0 || area == IntPtr.Zero)
|
||||
return;
|
||||
if (size != data.Length)
|
||||
throw new Exception("Unexpected saveram size");
|
||||
|
||||
Marshal.Copy(data, 0, area, size);
|
||||
Core.gpgx_sram_commitwrite();
|
||||
if (!Core.gpgx_put_sram(data, data.Length))
|
||||
throw new Exception("Core rejected saveram");
|
||||
}
|
||||
|
||||
public bool SaveRamModified
|
||||
|
@ -42,8 +32,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
get
|
||||
{
|
||||
int size = 0;
|
||||
IntPtr area = IntPtr.Zero;
|
||||
Core.gpgx_get_sram(ref area, ref size);
|
||||
IntPtr area = Core.gpgx_get_sram(ref size);
|
||||
return size > 0 && area != IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,71 +28,10 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
state.ReadFromHexFast(hex);
|
||||
LoadStateBinary(new BinaryReader(new MemoryStream(state)));
|
||||
}
|
||||
#if true
|
||||
|
||||
public byte[] SaveStateBinary()
|
||||
{
|
||||
var ms = new MemoryStream(_savebuff2, true);
|
||||
var bw = new BinaryWriter(ms);
|
||||
SaveStateBinary(bw);
|
||||
bw.Flush();
|
||||
ms.Close();
|
||||
return _savebuff2;
|
||||
}
|
||||
|
||||
public void LoadStateBinary(BinaryReader reader)
|
||||
{
|
||||
int newlen = reader.ReadInt32();
|
||||
if (newlen != _savebuff.Length)
|
||||
{
|
||||
throw new Exception("Unexpected state size");
|
||||
}
|
||||
|
||||
reader.Read(_savebuff, 0, _savebuff.Length);
|
||||
if (!Core.gpgx_state_load(_savebuff, _savebuff.Length))
|
||||
{
|
||||
throw new Exception("gpgx_state_load() returned false");
|
||||
}
|
||||
|
||||
// other variables
|
||||
Frame = reader.ReadInt32();
|
||||
LagCount = reader.ReadInt32();
|
||||
IsLagFrame = reader.ReadBoolean();
|
||||
UpdateVideo();
|
||||
}
|
||||
|
||||
public void SaveStateBinary(BinaryWriter writer)
|
||||
{
|
||||
if (!Core.gpgx_state_save(_savebuff, _savebuff.Length))
|
||||
throw new Exception("gpgx_state_save() returned false");
|
||||
|
||||
writer.Write(_savebuff.Length);
|
||||
writer.Write(_savebuff);
|
||||
// other variables
|
||||
writer.Write(Frame);
|
||||
writer.Write(LagCount);
|
||||
writer.Write(IsLagFrame);
|
||||
}
|
||||
|
||||
private byte[] _savebuff;
|
||||
private byte[] _savebuff2;
|
||||
|
||||
private void InitStateBuffers()
|
||||
{
|
||||
byte[] tmp = new byte[Core.gpgx_state_max_size()];
|
||||
int size = Core.gpgx_state_size(tmp, tmp.Length);
|
||||
if (size <= 0)
|
||||
throw new Exception("Couldn't Determine GPGX internal state size!");
|
||||
_savebuff = new byte[size];
|
||||
_savebuff2 = new byte[_savebuff.Length + 13];
|
||||
Console.WriteLine("GPGX Internal State Size: {0}", size);
|
||||
}
|
||||
|
||||
#else
|
||||
public void LoadStateBinary(BinaryReader reader)
|
||||
{
|
||||
var elf = (ElfRunner)NativeData;
|
||||
elf.LoadStateBinary(reader);
|
||||
Elf.LoadStateBinary(reader);
|
||||
// other variables
|
||||
Frame = reader.ReadInt32();
|
||||
LagCount = reader.ReadInt32();
|
||||
|
@ -107,8 +46,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
|
||||
public void SaveStateBinary(BinaryWriter writer)
|
||||
{
|
||||
var elf = (ElfRunner)NativeData;
|
||||
elf.SaveStateBinary(writer);
|
||||
Elf.SaveStateBinary(writer);
|
||||
// other variables
|
||||
writer.Write(Frame);
|
||||
writer.Write(LagCount);
|
||||
|
@ -128,6 +66,5 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
private void InitStateBuffers()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
IInputPollable, IDebuggable, IDriveLight, ICodeDataLogger, IDisassemblable
|
||||
{
|
||||
LibGPGX Core;
|
||||
IDisposable NativeData;
|
||||
ElfRunner Elf;
|
||||
|
||||
DiscSystem.Disc CD;
|
||||
DiscSystem.DiscSectorReader DiscSectorReader;
|
||||
|
@ -68,20 +68,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
|
||||
try
|
||||
{
|
||||
IImportResolver iimp;
|
||||
if (IntPtr.Size == 8) // there is no 64 bit build of gpgx right now otherwise
|
||||
{
|
||||
var elf = new ElfRunner(Path.Combine(comm.CoreFileProvider.DllPath(), "gpgx.elf"), 65536, 40 * 1024 * 1024);
|
||||
NativeData = elf;
|
||||
iimp = elf;
|
||||
}
|
||||
else
|
||||
{
|
||||
var dll = new InstanceDll(Path.Combine(comm.CoreFileProvider.DllPath(), LibGPGX.DllName));
|
||||
NativeData = dll;
|
||||
iimp = dll;
|
||||
}
|
||||
Core = BizInvoker.GetInvoker<LibGPGX>(iimp);
|
||||
Elf = new ElfRunner(Path.Combine(comm.CoreFileProvider.DllPath(), "gpgx.elf"), 65536, 36 * 1024 * 1024, 4 * 1024 * 1024);
|
||||
|
||||
Core = BizInvoker.GetInvoker<LibGPGX>(Elf);
|
||||
|
||||
_syncSettings = (GPGXSyncSettings)SyncSettings ?? new GPGXSyncSettings();
|
||||
_settings = (GPGXSettings)Settings ?? new GPGXSettings();
|
||||
|
@ -171,6 +160,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
|
||||
Tracer = new GPGXTraceBuffer(this, MemoryDomains, this);
|
||||
(ServiceProvider as BasicServiceProvider).Register<ITraceable>(Tracer);
|
||||
|
||||
Elf.Seal();
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
|
@ -57,22 +57,16 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
[BizImport(CallingConvention.Cdecl)]
|
||||
public abstract void gpgx_get_fps(ref int num, ref int den);
|
||||
|
||||
[BizImport(CallingConvention.Cdecl)]
|
||||
public abstract int gpgx_state_max_size();
|
||||
[BizImport(CallingConvention.Cdecl)]
|
||||
public abstract int gpgx_state_size(byte[] dest, int size);
|
||||
[BizImport(CallingConvention.Cdecl)]
|
||||
public abstract bool gpgx_state_save(byte[] dest, int size);
|
||||
[BizImport(CallingConvention.Cdecl)]
|
||||
public abstract bool gpgx_state_load(byte[] src, int size);
|
||||
|
||||
[BizImport(CallingConvention.Cdecl, Compatibility = true)]
|
||||
public abstract bool gpgx_get_control([Out]InputData dest, int bytes);
|
||||
[BizImport(CallingConvention.Cdecl, Compatibility = true)]
|
||||
public abstract bool gpgx_put_control([In]InputData src, int bytes);
|
||||
|
||||
[BizImport(CallingConvention.Cdecl)]
|
||||
public abstract void gpgx_get_sram(ref IntPtr area, ref int size);
|
||||
public abstract IntPtr gpgx_get_sram(ref int size);
|
||||
|
||||
[BizImport(CallingConvention.Cdecl)]
|
||||
public abstract bool gpgx_put_sram(byte[] data, int size);
|
||||
|
||||
[BizImport(CallingConvention.Cdecl)]
|
||||
public abstract void gpgx_clear_sram();
|
||||
|
@ -85,14 +79,6 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
// the unmanaged char pointer was allocated in hglobal and try to free it that way
|
||||
public abstract IntPtr gpgx_get_memdom(int which, ref IntPtr area, ref int size);
|
||||
|
||||
// call this before reading sram returned by gpgx_get_sram()
|
||||
[BizImport(CallingConvention.Cdecl)]
|
||||
public abstract void gpgx_sram_prepread();
|
||||
|
||||
// call this after writing sram returned by gpgx_get_sram()
|
||||
[BizImport(CallingConvention.Cdecl)]
|
||||
public abstract void gpgx_sram_commitwrite();
|
||||
|
||||
[BizImport(CallingConvention.Cdecl)]
|
||||
public abstract void gpgx_reset(bool hard);
|
||||
|
||||
|
|
|
@ -29,11 +29,31 @@ namespace BizHawk.Emulation.Cores
|
|||
/// </summary>
|
||||
private Heap _heap;
|
||||
|
||||
/// <summary>
|
||||
/// sealed heap (writable only during init)
|
||||
/// </summary>
|
||||
private Heap _sealedheap;
|
||||
|
||||
/// <summary>
|
||||
/// invisible heap (not savestated, use with care)
|
||||
/// </summary>
|
||||
private Heap _invisibleheap;
|
||||
|
||||
private long _loadoffset;
|
||||
private Dictionary<string, SymbolEntry<long>> _symdict;
|
||||
private List<SymbolEntry<long>> _symlist;
|
||||
|
||||
public ElfRunner(string filename, long heapsize, long sealedheapsize)
|
||||
private List<IDisposable> _disposeList = new List<IDisposable>();
|
||||
|
||||
private ulong GetHeapStart(ulong prevend)
|
||||
{
|
||||
// if relocatable, we won't have constant pointers, so put the heap anywhere
|
||||
// otherwise, put the heap at a canonical location aligned 1MB from the end of the elf, then incremented 16MB
|
||||
ulong heapstart = HasRelocations() ? 0 : ((prevend - 1) | 0xfffff) + 0x1000001;
|
||||
return heapstart;
|
||||
}
|
||||
|
||||
public ElfRunner(string filename, long heapsize, long sealedheapsize, long invisibleheapsize)
|
||||
{
|
||||
using (var fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
|
@ -61,6 +81,7 @@ namespace BizHawk.Emulation.Cores
|
|||
|
||||
try
|
||||
{
|
||||
_disposeList.Add(_base);
|
||||
_base.Set(_base.Start, _base.Size, MemoryBlock.Protection.RW);
|
||||
|
||||
foreach (var seg in loadsegs)
|
||||
|
@ -82,10 +103,28 @@ namespace BizHawk.Emulation.Cores
|
|||
_base.Set((ulong)(sec.LoadAddress + _loadoffset), (ulong)sec.Size, MemoryBlock.Protection.RW);
|
||||
}
|
||||
|
||||
// if relocatable, we won't have constant pointers, so put the heap anywhere
|
||||
// otherwise, put the heap at a canonical location aligned 1MB from the end of the elf, then incremented 16MB
|
||||
ulong heapstart = HasRelocations() ? 0 : ((_base.End - 1) | 0xfffff) + 0x1000001;
|
||||
_heap = new Heap(heapstart, (ulong)heapsize, "sbrk-heap");
|
||||
ulong end = _base.End;
|
||||
|
||||
if (heapsize > 0)
|
||||
{
|
||||
_heap = new Heap(GetHeapStart(end), (ulong)heapsize, "sbrk-heap");
|
||||
end = _heap.Memory.End;
|
||||
_disposeList.Add(_heap);
|
||||
}
|
||||
|
||||
if (sealedheapsize > 0)
|
||||
{
|
||||
_sealedheap = new Heap(GetHeapStart(end), (ulong)sealedheapsize, "sealed-heap");
|
||||
end = _sealedheap.Memory.End;
|
||||
_disposeList.Add(_sealedheap);
|
||||
}
|
||||
|
||||
if (invisibleheapsize > 0)
|
||||
{
|
||||
_invisibleheap = new Heap(GetHeapStart(end), (ulong)invisibleheapsize, "invisible-heap");
|
||||
end = _invisibleheap.Memory.End;
|
||||
_disposeList.Add(_invisibleheap);
|
||||
}
|
||||
|
||||
//FixupGOT();
|
||||
ConnectAllClibPatches();
|
||||
|
@ -99,7 +138,7 @@ namespace BizHawk.Emulation.Cores
|
|||
}
|
||||
catch
|
||||
{
|
||||
_base.Dispose();
|
||||
Dispose();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
@ -213,6 +252,11 @@ namespace BizHawk.Emulation.Cores
|
|||
//GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public void Seal()
|
||||
{
|
||||
_sealedheap.Seal();
|
||||
}
|
||||
|
||||
//~ElfRunner()
|
||||
//{
|
||||
// Dispose(false);
|
||||
|
@ -222,16 +266,9 @@ namespace BizHawk.Emulation.Cores
|
|||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (_base != null)
|
||||
{
|
||||
_base.Dispose();
|
||||
_base = null;
|
||||
}
|
||||
if (_heap != null)
|
||||
{
|
||||
_heap.Dispose();
|
||||
_heap = null;
|
||||
}
|
||||
foreach (var d in _disposeList)
|
||||
d.Dispose();
|
||||
_disposeList.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -259,6 +296,12 @@ namespace BizHawk.Emulation.Cores
|
|||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate void DebugPuts_D(string s);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate IntPtr SbrkSealed_D(UIntPtr n);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate IntPtr SbrkInvisible_D(UIntPtr n);
|
||||
|
||||
[CLibPatch("_ecl_trap")]
|
||||
private void Trap()
|
||||
{
|
||||
|
@ -268,9 +311,7 @@ namespace BizHawk.Emulation.Cores
|
|||
[CLibPatch("_ecl_sbrk")]
|
||||
private IntPtr Sbrk(UIntPtr n)
|
||||
{
|
||||
var ret = Z.US(_heap.Allocate((ulong)n, 1));
|
||||
Console.WriteLine("Expanding waterbox heap to {0} bytes", _heap.Used);
|
||||
return ret;
|
||||
return Z.US(_heap.Allocate((ulong)n, 1));
|
||||
}
|
||||
|
||||
[CLibPatch("_ecl_debug_puts")]
|
||||
|
@ -279,6 +320,18 @@ namespace BizHawk.Emulation.Cores
|
|||
Console.WriteLine("Waterbox debug puts: {0}", s);
|
||||
}
|
||||
|
||||
[CLibPatch("_ecl_sbrk_sealed")]
|
||||
private IntPtr SbrkSealed(UIntPtr n)
|
||||
{
|
||||
return Z.US(_sealedheap.Allocate((ulong)n, 16));
|
||||
}
|
||||
|
||||
[CLibPatch("_ecl_sbrk_invisible")]
|
||||
private IntPtr SbrkInvisible(UIntPtr n)
|
||||
{
|
||||
return Z.US(_invisibleheap.Allocate((ulong)n, 16));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// list of delegates that need to not be GCed
|
||||
/// </summary>
|
||||
|
@ -286,6 +339,8 @@ namespace BizHawk.Emulation.Cores
|
|||
|
||||
private void ConnectAllClibPatches()
|
||||
{
|
||||
_delegates.Clear(); // in case we're reconnecting
|
||||
|
||||
var methods = GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
||||
.Where(mi => mi.GetCustomAttributes(typeof(CLibPatchAttribute), false).Length > 0);
|
||||
foreach (var mi in methods)
|
||||
|
@ -344,7 +399,9 @@ namespace BizHawk.Emulation.Cores
|
|||
ms.CopyTo(bw.BaseStream);
|
||||
}
|
||||
|
||||
_heap.SaveStateBinary(bw);
|
||||
if (_heap != null) _heap.SaveStateBinary(bw);
|
||||
if (_sealedheap != null) _sealedheap.SaveStateBinary(bw);
|
||||
bw.Write(MAGIC);
|
||||
}
|
||||
|
||||
public void LoadStateBinary(BinaryReader br)
|
||||
|
@ -365,7 +422,14 @@ namespace BizHawk.Emulation.Cores
|
|||
CopySome(br.BaseStream, ms, len);
|
||||
}
|
||||
|
||||
_heap.LoadStateBinary(br);
|
||||
if (_heap != null) _heap.LoadStateBinary(br);
|
||||
if (_sealedheap != null) _sealedheap.LoadStateBinary(br);
|
||||
if (br.ReadUInt64() != MAGIC)
|
||||
throw new InvalidOperationException("Magic not magic enough!");
|
||||
|
||||
// the syscall trampolines were overwritten in loadstate (they're in .bss), and if we're cross-session,
|
||||
// are no longer valid. cores must similiarly resend any external pointers they gave the core.
|
||||
ConnectAllClibPatches();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -463,6 +527,7 @@ namespace BizHawk.Emulation.Cores
|
|||
ulong ret = Memory.Start + Used;
|
||||
Memory.Set(ret, newused - Used, MemoryBlock.Protection.RW);
|
||||
Used = newused;
|
||||
Console.WriteLine("Allocated {0} bytes on {1}", size, Name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,8 +29,6 @@ char MS_BIOS_JP[256] = "MS_BIOS_JP";
|
|||
|
||||
char romextension[4];
|
||||
|
||||
static uint32_t bitmap_data_[1024 * 512];
|
||||
|
||||
static int16 soundbuffer[4096];
|
||||
static int nsamples;
|
||||
|
||||
|
@ -65,6 +63,8 @@ ECL_ENTRY void (*biz_writecb)(unsigned addr) = NULL;
|
|||
CDCallback biz_cdcallback = NULL;
|
||||
unsigned biz_lastpc = 0;
|
||||
|
||||
uint8 *tempsram;
|
||||
|
||||
static void update_viewport(void)
|
||||
{
|
||||
vwidth = bitmap.viewport.w + (bitmap.viewport.x * 2);
|
||||
|
@ -295,23 +295,78 @@ GPGX_EX void gpgx_clear_sram(void)
|
|||
|
||||
// a bit hacky:
|
||||
// in order to present a single memory block to the frontend,
|
||||
// we copy the bram bits next to the ebram bits
|
||||
// we copy the both the bram and the ebram to another area
|
||||
|
||||
GPGX_EX void gpgx_sram_prepread(void)
|
||||
GPGX_EX void* gpgx_get_sram(int *size)
|
||||
{
|
||||
if (!sram.on && cdd.loaded && scd.cartridge.id)
|
||||
if (sram.on)
|
||||
{
|
||||
void *dest = scd.cartridge.area + scd.cartridge.mask + 1;
|
||||
memcpy(dest, scd.bram, 0x2000);
|
||||
*size = saveramsize();
|
||||
return sram.sram;
|
||||
}
|
||||
else if (cdd.loaded && scd.cartridge.id)
|
||||
{
|
||||
int sz = scd.cartridge.mask + 1;
|
||||
memcpy(tempsram, scd.cartridge.area, sz);
|
||||
memcpy(tempsram + sz, scd.bram, 0x2000);
|
||||
*size = sz + 0x2000;
|
||||
return tempsram;
|
||||
}
|
||||
else if (cdd.loaded)
|
||||
{
|
||||
*size = 0x2000;
|
||||
return scd.bram;
|
||||
}
|
||||
else if (scd.cartridge.id)
|
||||
{
|
||||
*size = scd.cartridge.mask + 1;
|
||||
return scd.cartridge.area;
|
||||
}
|
||||
else
|
||||
{
|
||||
*size = 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
GPGX_EX void gpgx_sram_commitwrite(void)
|
||||
GPGX_EX int gpgx_put_sram(const uint8 *data, int size)
|
||||
{
|
||||
if (!sram.on && cdd.loaded && scd.cartridge.id)
|
||||
if (sram.on)
|
||||
{
|
||||
void *src = scd.cartridge.area + scd.cartridge.mask + 1;
|
||||
memcpy(scd.bram, src, 0x2000);
|
||||
if (size != saveramsize())
|
||||
return 0;
|
||||
memcpy(sram.sram, data, size);
|
||||
return 1;
|
||||
}
|
||||
else if (cdd.loaded && scd.cartridge.id)
|
||||
{
|
||||
int sz = scd.cartridge.mask + 1;
|
||||
if (size != sz + 0x2000)
|
||||
return 0;
|
||||
memcpy(scd.cartridge.area, data, sz);
|
||||
memcpy(scd.bram, data + sz, 0x2000);
|
||||
return 1;
|
||||
}
|
||||
else if (cdd.loaded)
|
||||
{
|
||||
if (size != 0x2000)
|
||||
return 0;
|
||||
memcpy(scd.bram, data, size);
|
||||
return 1;
|
||||
}
|
||||
else if (scd.cartridge.id)
|
||||
{
|
||||
int sz = scd.cartridge.mask + 1;
|
||||
if (size != sz)
|
||||
return 0;
|
||||
memcpy(scd.cartridge.area, data, size);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (size != 0)
|
||||
return 0;
|
||||
return 1; // "successful"?
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -460,35 +515,6 @@ GPGX_EX unsigned gpgx_peek_s68k_bus(unsigned addr)
|
|||
return 0xff;
|
||||
}
|
||||
|
||||
GPGX_EX void gpgx_get_sram(void **area, int *size)
|
||||
{
|
||||
if (!area || !size)
|
||||
return;
|
||||
|
||||
if (sram.on)
|
||||
{
|
||||
*area = sram.sram;
|
||||
*size = saveramsize();
|
||||
}
|
||||
else if (scd.cartridge.id)
|
||||
{
|
||||
*area = scd.cartridge.area;
|
||||
*size = scd.cartridge.mask + 1 + 0x2000;
|
||||
}
|
||||
else if (cdd.loaded)
|
||||
{
|
||||
*area = scd.bram;
|
||||
*size = 0x2000;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (area)
|
||||
*area = NULL;
|
||||
if (size)
|
||||
*size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
struct InitSettings
|
||||
{
|
||||
uint8_t Filter;
|
||||
|
@ -504,8 +530,7 @@ struct InitSettings
|
|||
GPGX_EX int gpgx_init(const char *feromextension, ECL_ENTRY int (*feload_archive_cb)(const char *filename, unsigned char *buffer, int maxsize), int sixbutton, char system_a, char system_b, int region, struct InitSettings *settings)
|
||||
{
|
||||
memset(&bitmap, 0, sizeof(bitmap));
|
||||
memset(bitmap_data_, 0, sizeof(bitmap_data_));
|
||||
|
||||
|
||||
strncpy(romextension, feromextension, 3);
|
||||
romextension[3] = 0;
|
||||
|
||||
|
@ -514,7 +539,10 @@ GPGX_EX int gpgx_init(const char *feromextension, ECL_ENTRY int (*feload_archive
|
|||
bitmap.width = 1024;
|
||||
bitmap.height = 512;
|
||||
bitmap.pitch = 1024 * 4;
|
||||
bitmap.data = (uint8_t *)bitmap_data_;
|
||||
bitmap.data = alloc_invisible(2 * 1024 * 1024);
|
||||
tempsram = alloc_invisible(24 * 1024);
|
||||
|
||||
ext.md_cart.rom = alloc_sealed(32 * 1024 * 1024);
|
||||
|
||||
/* sound options */
|
||||
config.psg_preamp = 150;
|
||||
|
@ -528,7 +556,7 @@ GPGX_EX int gpgx_init(const char *feromextension, ECL_ENTRY int (*feload_archive
|
|||
config.lg = settings->LowGain; //1.0;
|
||||
config.mg = settings->MidGain; //1.0;
|
||||
config.hg = settings->HighGain; //1.0;
|
||||
config.dac_bits = 14; /* MAX DEPTH */
|
||||
config.dac_bits = 14; /* MAX DEPTH */
|
||||
config.ym2413= 2; /* AUTO */
|
||||
config.mono = 0; /* STEREO output */
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ typedef struct
|
|||
/* Cartridge type */
|
||||
typedef struct
|
||||
{
|
||||
uint8 rom[MAXROMSIZE]; /* ROM area */
|
||||
uint8 *rom; /* ROM area */
|
||||
uint8 *base; /* ROM base (saved for OS/Cartridge ROM swap) */
|
||||
uint32 romsize; /* ROM size */
|
||||
uint32 mask; /* ROM mask */
|
||||
|
|
|
@ -35,12 +35,12 @@
|
|||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* CD compatible ROM/RAM cartridge */
|
||||
typedef struct
|
||||
typedef struct
|
||||
{
|
||||
uint8 area[0x810000]; /* cartridge ROM/RAM area (max. 8MB + 64KB backup) */
|
||||
uint8 area[0x4000]; // not unioned with cartrom, so need not be a specific size for that; and we only use 16k ebram in bizhawk
|
||||
uint8 boot; /* cartridge boot mode (0x00: boot from CD with ROM/RAM cartridge enabled, 0x40: boot from ROM cartridge with CD enabled) */
|
||||
uint8 id; /* RAM cartridge ID (related to RAM size, 0 if disabled) */
|
||||
uint8 prot; /* RAM cartridge write protection */
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
#include "scd.h"
|
||||
|
||||
/* External Hardware */
|
||||
typedef union
|
||||
typedef struct
|
||||
{
|
||||
md_cart_t md_cart;
|
||||
cd_hw_t cd_hw;
|
||||
|
|
|
@ -436,7 +436,7 @@ int load_bios(void)
|
|||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -445,7 +445,7 @@ int load_bios(void)
|
|||
{
|
||||
/* check if Game Gear BOOTROM is already loaded */
|
||||
if (!(system_bios & SYSTEM_GG))
|
||||
{
|
||||
{
|
||||
/* mark both Master System & Game Gear BOOTROM as unloaded */
|
||||
system_bios &= ~(SYSTEM_SMS | SYSTEM_GG);
|
||||
|
||||
|
@ -464,7 +464,7 @@ int load_bios(void)
|
|||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -473,7 +473,7 @@ int load_bios(void)
|
|||
{
|
||||
/* check if Master System BOOTROM is already loaded */
|
||||
if (!(system_bios & SYSTEM_SMS) || ((system_bios & 0x0c) != (region_code >> 4)))
|
||||
{
|
||||
{
|
||||
/* mark both Master System & Game Gear BOOTROM as unloaded */
|
||||
system_bios &= ~(SYSTEM_SMS | SYSTEM_GG);
|
||||
|
||||
|
@ -506,7 +506,7 @@ int load_bios(void)
|
|||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -557,7 +557,7 @@ int load_rom(const char *filename)
|
|||
{
|
||||
/* load file into ROM buffer */
|
||||
char extension[4];
|
||||
size = load_archive(filename, cart.rom, sizeof(cart.rom), extension);
|
||||
size = load_archive(filename, cart.rom, 32 * 1024 * 1024, extension);
|
||||
if (!size)
|
||||
{
|
||||
/* mark all BOOTROM as unloaded since they could have been overwritten */
|
||||
|
@ -641,7 +641,7 @@ int load_rom(const char *filename)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* initialize ROM size */
|
||||
cart.romsize = size;
|
||||
|
||||
|
@ -653,7 +653,7 @@ int load_rom(const char *filename)
|
|||
|
||||
/* CD image file */
|
||||
if (system_hw == SYSTEM_MCD)
|
||||
{
|
||||
{
|
||||
/* load CD BOOT ROM */
|
||||
if (!load_bios())
|
||||
{
|
||||
|
@ -950,8 +950,8 @@ int load_rom(const char *filename)
|
|||
/****************************************************************************
|
||||
* get_region
|
||||
*
|
||||
* Set console region from ROM header passed as parameter or
|
||||
* from previous auto-detection (if NULL)
|
||||
* Set console region from ROM header passed as parameter or
|
||||
* from previous auto-detection (if NULL)
|
||||
*
|
||||
****************************************************************************/
|
||||
void get_region(char *romheader)
|
||||
|
@ -972,7 +972,7 @@ void get_region(char *romheader)
|
|||
case 0x64:
|
||||
region_code = REGION_EUROPE;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
region_code = REGION_JAPAN_NTSC;
|
||||
break;
|
||||
|
@ -1032,7 +1032,7 @@ void get_region(char *romheader)
|
|||
/* need PAL settings */
|
||||
region_code = REGION_EUROPE;
|
||||
}
|
||||
else if ((rominfo.realchecksum == 0x532e) && (strstr(rominfo.product,"1011-00") != NULL))
|
||||
else if ((rominfo.realchecksum == 0x532e) && (strstr(rominfo.product,"1011-00") != NULL))
|
||||
{
|
||||
/* On Dal Jang Goon (Korea) needs JAPAN region code */
|
||||
region_code = REGION_JAPAN_NTSC;
|
||||
|
@ -1053,7 +1053,7 @@ void get_region(char *romheader)
|
|||
/* restore auto-detected region */
|
||||
region_code = rom_region;
|
||||
}
|
||||
|
||||
|
||||
/* force console region if requested */
|
||||
if (config.region_detect == 1) region_code = REGION_USA;
|
||||
else if (config.region_detect == 2) region_code = REGION_EUROPE;
|
||||
|
@ -1091,7 +1091,7 @@ char *get_company(void)
|
|||
int i;
|
||||
char company[10];
|
||||
|
||||
for (i = 3; i < 8; i++)
|
||||
for (i = 3; i < 8; i++)
|
||||
{
|
||||
company[i - 3] = rominfo.copyright[i];
|
||||
}
|
||||
|
|
|
@ -8,6 +8,19 @@ ECL_EXPORT ECL_ENTRY __attribute__((noreturn)) void (*_ecl_trap)(void); // somet
|
|||
ECL_EXPORT ECL_ENTRY void *(*_ecl_sbrk)(size_t n); // sbrk. won't return if the request can't be satisfied
|
||||
ECL_EXPORT ECL_ENTRY void (*_ecl_debug_puts)(const char *); // low level debug write, doesn't involve STDIO
|
||||
|
||||
ECL_EXPORT ECL_ENTRY void *(*_ecl_sbrk_sealed)(size_t n); // allocate memory; see emulibc.h
|
||||
ECL_EXPORT ECL_ENTRY void *(*_ecl_sbrk_invisible)(size_t n); // allocate memory; see emulibc.h
|
||||
|
||||
void *alloc_sealed(size_t size)
|
||||
{
|
||||
return _ecl_sbrk_sealed(size);
|
||||
}
|
||||
|
||||
void *alloc_invisible(size_t size)
|
||||
{
|
||||
return _ecl_sbrk_invisible(size);
|
||||
}
|
||||
|
||||
void *_PDCLIB_sbrk(size_t n)
|
||||
{
|
||||
void *ret = _ecl_sbrk(n);
|
||||
|
|
|
@ -1,9 +1,22 @@
|
|||
#ifndef _EMULIBC_H
|
||||
#define _EMULIBC_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
// mark an entry point or callback pointer
|
||||
#define ECL_ENTRY __attribute__((ms_abi))
|
||||
// mark a visible symbol
|
||||
#define ECL_EXPORT __attribute__((visibility("default")))
|
||||
|
||||
// allocate memory from the "sealed" pool. this memory can never be freed,
|
||||
// and can only be allocated or written to during the init phase. after that, the host
|
||||
// seals the pool, making it read only and all of its contents frozen. good for LUTs and
|
||||
// ROMs
|
||||
void *alloc_sealed(size_t size);
|
||||
|
||||
// allocate memory from the "invisible" pool. this memory can never be freed.
|
||||
// this memory is not savestated! this should only be used for a large buffer whose contents
|
||||
// you are absolutely sure will not harm savestates
|
||||
void *alloc_invisible(size_t size);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue