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:
goyuken 2013-12-18 01:58:18 +00:00
parent 8bd8af15fe
commit adc3df41bd
5 changed files with 101 additions and 116 deletions

View File

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

View File

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

View File

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

View File

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