gpgx: when in cartridge mode, sram is fully supported. when in cd mode, 8K internal bupram + 128K external bupram is supported. this all works and has been tested with a few games. sram files from previous revision won't work.
This commit is contained in:
parent
8bd8af15fe
commit
adc3df41bd
|
@ -310,83 +310,32 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
|
||||
#region saveram
|
||||
|
||||
// this all feels very messy
|
||||
|
||||
struct SaveRamInfo
|
||||
{
|
||||
public int totalsize;
|
||||
public IntPtr[] areas;
|
||||
public int[] sizes;
|
||||
|
||||
public int arraysize { get { return totalsize + 4 * LibGPGX.MAX_SRAM_TYPES; } }
|
||||
}
|
||||
|
||||
SaveRamInfo GetSaveRamInfo()
|
||||
{
|
||||
SaveRamInfo ret = new SaveRamInfo
|
||||
{
|
||||
areas = new IntPtr[LibGPGX.MAX_SRAM_TYPES],
|
||||
sizes = new int[LibGPGX.MAX_SRAM_TYPES],
|
||||
};
|
||||
for (int i = 0; i < LibGPGX.MAX_SRAM_TYPES; i++)
|
||||
{
|
||||
IntPtr area = IntPtr.Zero;
|
||||
int size = 0;
|
||||
LibGPGX.gpgx_get_sram(ref area, ref size, i);
|
||||
ret.areas[i] = area;
|
||||
ret.sizes[i] = size;
|
||||
ret.totalsize += size;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public byte[] ReadSaveRam()
|
||||
{
|
||||
var sri = GetSaveRamInfo();
|
||||
if (sri.totalsize == 0)
|
||||
int size = 0;
|
||||
IntPtr area = IntPtr.Zero;
|
||||
LibGPGX.gpgx_get_sram(ref area, ref size);
|
||||
if (size <= 0 || area == IntPtr.Zero)
|
||||
return new byte[0];
|
||||
LibGPGX.gpgx_sram_prepread();
|
||||
|
||||
byte[] ret = new byte[sri.arraysize];
|
||||
|
||||
MemoryStream ms = new MemoryStream(ret, true);
|
||||
BinaryWriter bw = new BinaryWriter(ms);
|
||||
|
||||
for (int i = 0; i < LibGPGX.MAX_SRAM_TYPES; i++)
|
||||
{
|
||||
bw.Write(sri.sizes[i]);
|
||||
if (sri.areas[i] != IntPtr.Zero)
|
||||
{
|
||||
byte[] data = new byte[sri.sizes[i]];
|
||||
Marshal.Copy(sri.areas[i], data, 0, sri.sizes[i]);
|
||||
bw.Write(data);
|
||||
}
|
||||
}
|
||||
bw.Flush();
|
||||
ms.Close();
|
||||
byte[] ret = new byte[size];
|
||||
Marshal.Copy(area, ret, 0, size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void StoreSaveRam(byte[] data)
|
||||
{
|
||||
var sri = GetSaveRamInfo();
|
||||
if (sri.arraysize!= data.Length)
|
||||
throw new Exception("Unexpected SaveRam size");
|
||||
int size = 0;
|
||||
IntPtr area = IntPtr.Zero;
|
||||
LibGPGX.gpgx_get_sram(ref area, ref size);
|
||||
if (size <= 0 || area == IntPtr.Zero)
|
||||
return;
|
||||
if (size != data.Length)
|
||||
throw new Exception("Unexpected saveram size");
|
||||
|
||||
MemoryStream ms = new MemoryStream(data, false);
|
||||
BinaryReader br = new BinaryReader(ms);
|
||||
|
||||
for (int i = 0; i < LibGPGX.MAX_SRAM_TYPES; i++)
|
||||
{
|
||||
int size = br.ReadInt32();
|
||||
if (size != sri.sizes[i])
|
||||
throw new Exception("Unexpected SaveRam size");
|
||||
if (sri.areas[i] != IntPtr.Zero)
|
||||
{
|
||||
byte[] tmp = new byte[sri.sizes[i]];
|
||||
br.Read(tmp, 0, sri.sizes[i]);
|
||||
Marshal.Copy(tmp, 0, sri.areas[i], sri.sizes[i]);
|
||||
}
|
||||
}
|
||||
Marshal.Copy(data, 0, area, size);
|
||||
LibGPGX.gpgx_sram_commitwrite();
|
||||
}
|
||||
|
||||
public void ClearSaveRam()
|
||||
|
@ -398,7 +347,10 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
{
|
||||
get
|
||||
{
|
||||
return GetSaveRamInfo().totalsize > 0;
|
||||
int size = 0;
|
||||
IntPtr area = IntPtr.Zero;
|
||||
LibGPGX.gpgx_get_sram(ref area, ref size);
|
||||
return size > 0 && area != IntPtr.Zero;
|
||||
}
|
||||
set
|
||||
{
|
||||
|
|
|
@ -38,13 +38,21 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool gpgx_put_control(IntPtr src, int bytes);
|
||||
|
||||
public const int MAX_SRAM_TYPES = 3;
|
||||
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gpgx_get_sram(ref IntPtr area, ref int size, int type);
|
||||
public static extern void gpgx_get_sram(ref IntPtr area, ref int size);
|
||||
|
||||
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gpgx_clear_sram();
|
||||
|
||||
// call this before reading sram returned by gpgx_get_sram()
|
||||
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gpgx_sram_prepread();
|
||||
|
||||
// call this after writing sram returned by gpgx_get_sram()
|
||||
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void gpgx_sram_commitwrite();
|
||||
|
||||
|
||||
public static bool gpgx_get_control(InputData dest)
|
||||
{
|
||||
int bytes = Marshal.SizeOf(typeof(InputData));
|
||||
|
|
|
@ -181,59 +181,82 @@ GPGX_EX void gpgx_advance(void)
|
|||
GPGX_EX void gpgx_clear_sram(void)
|
||||
{
|
||||
// clear sram
|
||||
if (sram.sram)
|
||||
memset(sram.sram, 0, 0x10000);
|
||||
if (sram.on)
|
||||
memset(sram.sram, 0xff, 0x10000);
|
||||
|
||||
// clear and format bram
|
||||
memset(scd.bram, 0, 0x2000);
|
||||
brm_format[0x10] = brm_format[0x12] = brm_format[0x14] = brm_format[0x16] = 0x00;
|
||||
brm_format[0x11] = brm_format[0x13] = brm_format[0x15] = brm_format[0x17] = (sizeof(scd.bram) / 64) - 3;
|
||||
memcpy(scd.bram + 0x2000 - 0x40, brm_format, 0x40);
|
||||
if (cdd.loaded)
|
||||
{
|
||||
// clear and format bram
|
||||
memset(scd.bram, 0, 0x2000);
|
||||
brm_format[0x10] = brm_format[0x12] = brm_format[0x14] = brm_format[0x16] = 0x00;
|
||||
brm_format[0x11] = brm_format[0x13] = brm_format[0x15] = brm_format[0x17] = (sizeof(scd.bram) / 64) - 3;
|
||||
memcpy(scd.bram + 0x2000 - 0x40, brm_format, 0x40);
|
||||
|
||||
// clear and format ebram
|
||||
memset(scd.cartridge.area, 0x00, scd.cartridge.mask + 1);
|
||||
brm_format[0x10] = brm_format[0x12] = brm_format[0x14] = brm_format[0x16] = (((scd.cartridge.mask + 1) / 64) - 3) >> 8;
|
||||
brm_format[0x11] = brm_format[0x13] = brm_format[0x15] = brm_format[0x17] = (((scd.cartridge.mask + 1) / 64) - 3) & 0xff;
|
||||
memcpy(scd.cartridge.area + scd.cartridge.mask + 1 - 0x40, brm_format, 0x40);
|
||||
}
|
||||
|
||||
GPGX_EX void gpgx_get_sram(void **area, int *size, int type)
|
||||
{
|
||||
if (type == 0)
|
||||
{
|
||||
// cart sram
|
||||
if (sram.on)
|
||||
{
|
||||
if (area)
|
||||
*area = sram.sram;
|
||||
if (size)
|
||||
*size = 0x10000;
|
||||
}
|
||||
}
|
||||
else if (type == 1)
|
||||
{
|
||||
// bram
|
||||
if (cdd.loaded)
|
||||
{
|
||||
if (area)
|
||||
*area = scd.bram;
|
||||
if (size)
|
||||
*size = 0x2000;
|
||||
}
|
||||
}
|
||||
else if (type == 2)
|
||||
{
|
||||
// external bram
|
||||
if (scd.cartridge.id)
|
||||
{
|
||||
if (area)
|
||||
*area = scd.cartridge.area;
|
||||
if (size)
|
||||
*size = scd.cartridge.mask + 1;
|
||||
// clear and format ebram
|
||||
memset(scd.cartridge.area, 0x00, scd.cartridge.mask + 1);
|
||||
brm_format[0x10] = brm_format[0x12] = brm_format[0x14] = brm_format[0x16] = (((scd.cartridge.mask + 1) / 64) - 3) >> 8;
|
||||
brm_format[0x11] = brm_format[0x13] = brm_format[0x15] = brm_format[0x17] = (((scd.cartridge.mask + 1) / 64) - 3) & 0xff;
|
||||
memcpy(scd.cartridge.area + scd.cartridge.mask + 1 - 0x40, brm_format, 0x40);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// a bit hacky:
|
||||
// in order to present a single memory block to the frontend,
|
||||
// we copy the bram bits next to the ebram bits
|
||||
|
||||
GPGX_EX void gpgx_sram_prepread(void)
|
||||
{
|
||||
if (!sram.on && cdd.loaded && scd.cartridge.id)
|
||||
{
|
||||
void *dest = scd.cartridge.area + scd.cartridge.mask + 1;
|
||||
memcpy(dest, scd.bram, 0x2000);
|
||||
}
|
||||
}
|
||||
|
||||
GPGX_EX void gpgx_sram_commitwrite(void)
|
||||
{
|
||||
if (!sram.on && cdd.loaded && scd.cartridge.id)
|
||||
{
|
||||
void *src = scd.cartridge.area + scd.cartridge.mask + 1;
|
||||
memcpy(scd.bram, src, 0x2000);
|
||||
}
|
||||
}
|
||||
|
||||
GPGX_EX void gpgx_get_sram(void **area, int *size)
|
||||
{
|
||||
if (sram.on)
|
||||
{
|
||||
if (area)
|
||||
*area = sram.sram;
|
||||
if (size)
|
||||
*size = 0x10000;
|
||||
}
|
||||
else if (scd.cartridge.id)
|
||||
{
|
||||
if (area)
|
||||
*area = scd.cartridge.area;
|
||||
if (size)
|
||||
*size = scd.cartridge.mask + 1 + 0x2000;
|
||||
}
|
||||
else if (cdd.loaded)
|
||||
{
|
||||
if (area)
|
||||
*area = scd.bram;
|
||||
if (size)
|
||||
*size = 0x2000;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (area)
|
||||
*area = NULL;
|
||||
if (size)
|
||||
*size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GPGX_EX int gpgx_init(const char *feromextension, int (*feload_archive_cb)(const char *filename, unsigned char *buffer, int maxsize), int sixbutton, char system_a, char system_b)
|
||||
{
|
||||
zap();
|
||||
|
|
|
@ -190,7 +190,9 @@ void cd_cart_init(void)
|
|||
else
|
||||
{
|
||||
/* enable 512K backup RAM cartridge when booting from CD (Mode 2) */
|
||||
scd.cartridge.id = 6;
|
||||
//scd.cartridge.id = 6;
|
||||
scd.cartridge.id = 4; // use 128K instead, which is the size of a real ebram cart
|
||||
// bizhawk doesn't need the extra space because it gives each game its own anyway
|
||||
}
|
||||
|
||||
/* RAM cartridge enabled ? */
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue