This commit is contained in:
Lior Halphon 2019-06-07 19:18:07 +03:00
parent 7fc3de69da
commit 274760746e
3 changed files with 38 additions and 9 deletions

View File

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

View File

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

View File

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