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:
nattthebear 2016-03-23 19:45:02 -04:00
parent f42c0d4a39
commit 8136aa0f03
13 changed files with 222 additions and 201 deletions

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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
}
}

View File

@ -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
{

View File

@ -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);

View File

@ -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;
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -47,7 +47,7 @@
#include "scd.h"
/* External Hardware */
typedef union
typedef struct
{
md_cart_t md_cart;
cd_hw_t cd_hw;

View File

@ -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];
}

View File

@ -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);

View File

@ -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