mirror of https://github.com/bsnes-emu/bsnes.git
Fix #165
This commit is contained in:
parent
7fc3de69da
commit
274760746e
|
@ -95,7 +95,7 @@ void GB_init(GB_gameboy_t *gb, GB_model_t model)
|
||||||
memset(gb, 0, sizeof(*gb));
|
memset(gb, 0, sizeof(*gb));
|
||||||
gb->model = model;
|
gb->model = model;
|
||||||
if (GB_is_cgb(gb)) {
|
if (GB_is_cgb(gb)) {
|
||||||
gb->ram = malloc(gb->ram_size = 0x2000 * 8);
|
gb->ram = malloc(gb->ram_size = 0x1000 * 8);
|
||||||
gb->vram = malloc(gb->vram_size = 0x2000 * 2);
|
gb->vram = malloc(gb->vram_size = 0x2000 * 2);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -632,7 +632,7 @@ void GB_reset(GB_gameboy_t *gb)
|
||||||
gb->io_registers[GB_IO_JOYP] = 0xF;
|
gb->io_registers[GB_IO_JOYP] = 0xF;
|
||||||
gb->mbc_ram_size = mbc_ram_size;
|
gb->mbc_ram_size = mbc_ram_size;
|
||||||
if (GB_is_cgb(gb)) {
|
if (GB_is_cgb(gb)) {
|
||||||
gb->ram_size = 0x2000 * 8;
|
gb->ram_size = 0x1000 * 8;
|
||||||
gb->vram_size = 0x2000 * 2;
|
gb->vram_size = 0x2000 * 2;
|
||||||
memset(gb->vram, 0, gb->vram_size);
|
memset(gb->vram, 0, gb->vram_size);
|
||||||
gb->cgb_mode = true;
|
gb->cgb_mode = true;
|
||||||
|
@ -703,7 +703,7 @@ void GB_switch_model_and_reset(GB_gameboy_t *gb, GB_model_t model)
|
||||||
{
|
{
|
||||||
gb->model = model;
|
gb->model = model;
|
||||||
if (GB_is_cgb(gb)) {
|
if (GB_is_cgb(gb)) {
|
||||||
gb->ram = realloc(gb->ram, gb->ram_size = 0x2000 * 8);
|
gb->ram = realloc(gb->ram, gb->ram_size = 0x1000 * 8);
|
||||||
gb->vram = realloc(gb->vram, gb->vram_size = 0x2000 * 2);
|
gb->vram = realloc(gb->vram, gb->vram_size = 0x2000 * 2);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -333,6 +333,7 @@ struct GB_gameboy_internal_s {
|
||||||
bool infrared_input;
|
bool infrared_input;
|
||||||
GB_printer_t printer;
|
GB_printer_t printer;
|
||||||
uint8_t extra_oam[0xff00 - 0xfea0];
|
uint8_t extra_oam[0xff00 - 0xfea0];
|
||||||
|
uint32_t ram_size; // Different between CGB and DMG
|
||||||
);
|
);
|
||||||
|
|
||||||
/* DMA and HDMA */
|
/* DMA and HDMA */
|
||||||
|
@ -593,7 +594,6 @@ struct GB_gameboy_internal_s {
|
||||||
bool turbo;
|
bool turbo;
|
||||||
bool turbo_dont_skip;
|
bool turbo_dont_skip;
|
||||||
bool disable_rendering;
|
bool disable_rendering;
|
||||||
uint32_t ram_size; // Different between CGB and DMG
|
|
||||||
uint8_t boot_rom[0x900];
|
uint8_t boot_rom[0x900];
|
||||||
bool vblank_just_occured; // For slow operations involving syscalls; these should only run once per vblank
|
bool vblank_just_occured; // For slow operations involving syscalls; these should only run once per vblank
|
||||||
uint8_t cycles_since_run; // How many cycles have passed since the last call to GB_run(), in 8MHz units
|
uint8_t cycles_since_run; // How many cycles have passed since the last call to GB_run(), in 8MHz units
|
||||||
|
|
|
@ -156,11 +156,6 @@ static bool verify_state_compatibility(GB_gameboy_t *gb, GB_gameboy_t *save)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gb->ram_size != save->ram_size) {
|
|
||||||
GB_log(gb, "The save state has non-matching RAM size. Try changing the emulated model.\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gb->vram_size != save->vram_size) {
|
if (gb->vram_size != save->vram_size) {
|
||||||
GB_log(gb, "The save state has non-matching VRAM size. Try changing the emulated model.\n");
|
GB_log(gb, "The save state has non-matching VRAM size. Try changing the emulated model.\n");
|
||||||
return false;
|
return false;
|
||||||
|
@ -171,6 +166,17 @@ static bool verify_state_compatibility(GB_gameboy_t *gb, GB_gameboy_t *save)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gb->ram_size != save->ram_size) {
|
||||||
|
if (gb->ram_size == 0x1000 * 8 && save->ram_size == 0x2000 * 8) {
|
||||||
|
/* A bug in versions prior to 0.12 made CGB instances allocate twice the ammount of RAM.
|
||||||
|
Ignore this issue to retain compatibility with older, 0.11, save states. */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
GB_log(gb, "The save state has non-matching RAM size. Try changing the emulated model.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,6 +188,8 @@ int GB_load_state(GB_gameboy_t *gb, const char *path)
|
||||||
|
|
||||||
/* Every unread value should be kept the same. */
|
/* Every unread value should be kept the same. */
|
||||||
memcpy(&save, gb, sizeof(save));
|
memcpy(&save, gb, sizeof(save));
|
||||||
|
/* ...Except ram size, we use it to detect old saves with incorrect ram sizes */
|
||||||
|
save.ram_size = 0;
|
||||||
|
|
||||||
FILE *f = fopen(path, "rb");
|
FILE *f = fopen(path, "rb");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
|
@ -199,6 +207,17 @@ int GB_load_state(GB_gameboy_t *gb, const char *path)
|
||||||
if (!READ_SECTION(&save, f, rtc )) goto error;
|
if (!READ_SECTION(&save, f, rtc )) goto error;
|
||||||
if (!READ_SECTION(&save, f, video )) goto error;
|
if (!READ_SECTION(&save, f, video )) goto error;
|
||||||
|
|
||||||
|
if (save.ram_size == 0) {
|
||||||
|
/* Save doesn't have ram size specified, it's a pre 0.12 save state with potentially
|
||||||
|
incorrect RAM amount if it's a CGB instance */
|
||||||
|
if (GB_is_cgb(&save)) {
|
||||||
|
save.ram_size = 0x2000 * 8; // Incorrect RAM size
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
save.ram_size = gb->ram_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!verify_state_compatibility(gb, &save)) {
|
if (!verify_state_compatibility(gb, &save)) {
|
||||||
errno = -1;
|
errno = -1;
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -218,13 +237,19 @@ int GB_load_state(GB_gameboy_t *gb, const char *path)
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return EIO;
|
return EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fix for 0.11 save states that allocate twice the amount of RAM in CGB instances */
|
||||||
|
fseek(f, save.ram_size - gb->ram_size, SEEK_CUR);
|
||||||
|
|
||||||
if (fread(gb->vram, 1, gb->vram_size, f) != gb->vram_size) {
|
if (fread(gb->vram, 1, gb->vram_size, f) != gb->vram_size) {
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return EIO;
|
return EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t orig_ram_size = gb->ram_size;
|
||||||
memcpy(gb, &save, sizeof(save));
|
memcpy(gb, &save, sizeof(save));
|
||||||
|
gb->ram_size = orig_ram_size;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
if (gb->cartridge_type->has_rumble && gb->rumble_callback) {
|
if (gb->cartridge_type->has_rumble && gb->rumble_callback) {
|
||||||
|
@ -324,6 +349,10 @@ int GB_load_state_from_buffer(GB_gameboy_t *gb, const uint8_t *buffer, size_t le
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fix for 0.11 save states that allocate twice the amount of RAM in CGB instances */
|
||||||
|
buffer += save.ram_size - gb->ram_size;
|
||||||
|
length -= save.ram_size - gb->ram_size;
|
||||||
|
|
||||||
memcpy(gb, &save, sizeof(save));
|
memcpy(gb, &save, sizeof(save));
|
||||||
|
|
||||||
if (gb->cartridge_type->has_rumble && gb->rumble_callback) {
|
if (gb->cartridge_type->has_rumble && gb->rumble_callback) {
|
||||||
|
|
Loading…
Reference in New Issue