From 10038ec76dfb09f4bc753aa3d42037ff65bffb18 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Thu, 18 Jul 2019 23:08:16 +0300 Subject: [PATCH 1/3] Emulate ICD desyncing --- bsnes/gb/Core/display.c | 20 ++++++++++---------- bsnes/sfc/coprocessor/icd/icd.cpp | 7 ++++--- bsnes/sfc/coprocessor/icd/icd.hpp | 5 +++-- bsnes/sfc/coprocessor/icd/interface.cpp | 15 ++++++++------- bsnes/sfc/coprocessor/icd/serialization.cpp | 3 ++- 5 files changed, 27 insertions(+), 23 deletions(-) diff --git a/bsnes/gb/Core/display.c b/bsnes/gb/Core/display.c index 0143f2b1..2bf00ba9 100644 --- a/bsnes/gb/Core/display.c +++ b/bsnes/gb/Core/display.c @@ -127,13 +127,13 @@ static void display_vblank(GB_gameboy_t *gb) if (GB_is_hle_sgb(gb)) { GB_sgb_render(gb); } - + if (gb->turbo) { if (GB_timing_sync_turbo(gb)) { return; } } - + if (!gb->disable_rendering && ((!(gb->io_registers[GB_IO_LCDC] & 0x80) || gb->stopped) || gb->frame_skip_state == GB_FRAMESKIP_LCD_TURNED_ON)) { /* LCD is off, set screen to white or black (if LCD is on in stop mode) */ if (gb->sgb) { @@ -423,8 +423,7 @@ static void render_pixel_if_possible(GB_gameboy_t *gb) gb->screen[gb->position_in_line + gb->current_line * WIDTH] = gb->sprite_palettes_rgb[oam_fifo_item->palette * 4 + pixel]; } } - - /* byuu: gotta do this later so it's only done once ... you'll probably wanna refactor this somehow :/ */ + if (gb->model & GB_MODEL_NO_SFC_BIT) { if (gb->icd_pixel_callback) { gb->icd_pixel_callback(gb, icd_pixel); @@ -770,7 +769,13 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles) fifo_push_bg_row(&gb->bg_fifo, 0, 0, 0, false, false); /* Todo: find out actual access time of SCX */ gb->position_in_line = - (gb->io_registers[GB_IO_SCX] & 7) - 8; - gb->current_lcd_line++; // Todo: unverified timing + + // Todo: unverified timing + gb->current_lcd_line++; + if (gb->icd_hreset_callback) { + gb->icd_hreset_callback(gb); + } + if (gb->current_lcd_line == LINES && GB_is_sgb(gb)) { display_vblank(gb); } @@ -910,11 +915,6 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles) } GB_SLEEP(gb, display, 11, LINE_LENGTH - gb->cycles_for_line); gb->mode_for_interrupt = 2; - - /* TODO: Can this timing even be verified? */ - if (gb->icd_hreset_callback) { - gb->icd_hreset_callback(gb); - } } /* Lines 144 - 152 */ diff --git a/bsnes/sfc/coprocessor/icd/icd.cpp b/bsnes/sfc/coprocessor/icd/icd.cpp index 7d93a4bc..4d9afe85 100644 --- a/bsnes/sfc/coprocessor/icd/icd.cpp +++ b/bsnes/sfc/coprocessor/icd/icd.cpp @@ -16,7 +16,6 @@ namespace SameBoy { static auto vreset(GB_gameboy_t*) -> void { icd.ly = 0; - icd.ppuScanline(); } static auto icd_pixel(GB_gameboy_t*, uint8_t pixel) -> void { @@ -122,7 +121,8 @@ auto ICD::power() -> void { readBank = 0; readAddress = 0; writeBank = 0; - writeAddress = 0; + writeX = 0; + writeY = 0; packetSize = 0; joypID = 3; @@ -148,7 +148,8 @@ auto ICD::reset() -> void { readBank = 0; readAddress = 0; writeBank = 0; - writeAddress = 0; + writeX = 0; + writeY = 0; packetSize = 0; joypID = 3; diff --git a/bsnes/sfc/coprocessor/icd/icd.hpp b/bsnes/sfc/coprocessor/icd/icd.hpp index 4aa6a714..718887f5 100644 --- a/bsnes/sfc/coprocessor/icd/icd.hpp +++ b/bsnes/sfc/coprocessor/icd/icd.hpp @@ -61,7 +61,8 @@ private: uint readBank; uint readAddress; uint writeBank; - uint writeAddress; + uint writeX; + uint writeY; struct Information { uint pathID = 0; @@ -73,7 +74,7 @@ public: //as the offsets of all member variables will be wrong compared to what the C SameBoy code expects. GB_gameboy_t sameboy; uint32_t bitmap[160 * 144]; - uint ly = 0; + uint8_t ly = 0; }; extern ICD icd; diff --git a/bsnes/sfc/coprocessor/icd/interface.cpp b/bsnes/sfc/coprocessor/icd/interface.cpp index 0407649d..b9be5838 100644 --- a/bsnes/sfc/coprocessor/icd/interface.cpp +++ b/bsnes/sfc/coprocessor/icd/interface.cpp @@ -1,18 +1,19 @@ auto ICD::ppuScanline() -> void { - if(ly > 143) return; //Vblank - if((ly & 7) == 0) { + if(++writeY == 8) { writeBank = (writeBank + 1) & 3; - writeAddress = 0; + writeY = 0; } + writeX = 0; } auto ICD::ppuOutput(uint2 color) -> void { - uint y = writeAddress / 160; - uint x = writeAddress % 160; - uint addr = writeBank * 512 + y * 2 + x / 8 * 16; + if(writeX >= 160) return; // Unverified behavior + if(writeY >= 8) return; // Should never happen + + uint addr = writeBank * 512 + writeY * 2 + writeX / 8 * 16; output[addr + 0] = (output[addr + 0] << 1) | !!(color & 1); output[addr + 1] = (output[addr + 1] << 1) | !!(color & 2); - writeAddress = (writeAddress + 1) % 1280; + writeX++; } auto ICD::apuOutput(float left, float right) -> void { diff --git a/bsnes/sfc/coprocessor/icd/serialization.cpp b/bsnes/sfc/coprocessor/icd/serialization.cpp index a0ce490d..75eff3c8 100644 --- a/bsnes/sfc/coprocessor/icd/serialization.cpp +++ b/bsnes/sfc/coprocessor/icd/serialization.cpp @@ -38,5 +38,6 @@ auto ICD::serialize(serializer& s) -> void { s.integer(readBank); s.integer(readAddress); s.integer(writeBank); - s.integer(writeAddress); + s.integer(writeX); + s.integer(writeY); } From 32c781c53123d2fd3a27c94bbbb7109cf571b140 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Fri, 19 Jul 2019 18:19:53 +0300 Subject: [PATCH 2/3] Accuracy fixed, major regression fix --- bsnes/gb/Core/display.c | 7 ++++--- bsnes/sfc/coprocessor/icd/interface.cpp | 3 ++- bsnes/sfc/coprocessor/icd/io.cpp | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/bsnes/gb/Core/display.c b/bsnes/gb/Core/display.c index 2bf00ba9..64c1aeca 100644 --- a/bsnes/gb/Core/display.c +++ b/bsnes/gb/Core/display.c @@ -772,9 +772,6 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles) // Todo: unverified timing gb->current_lcd_line++; - if (gb->icd_hreset_callback) { - gb->icd_hreset_callback(gb); - } if (gb->current_lcd_line == LINES && GB_is_sgb(gb)) { display_vblank(gb); @@ -915,6 +912,10 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles) } GB_SLEEP(gb, display, 11, LINE_LENGTH - gb->cycles_for_line); gb->mode_for_interrupt = 2; + + if (gb->icd_hreset_callback) { + gb->icd_hreset_callback(gb); + } } /* Lines 144 - 152 */ diff --git a/bsnes/sfc/coprocessor/icd/interface.cpp b/bsnes/sfc/coprocessor/icd/interface.cpp index b9be5838..5f2f092a 100644 --- a/bsnes/sfc/coprocessor/icd/interface.cpp +++ b/bsnes/sfc/coprocessor/icd/interface.cpp @@ -1,3 +1,4 @@ + auto ICD::ppuScanline() -> void { if(++writeY == 8) { writeBank = (writeBank + 1) & 3; @@ -10,7 +11,7 @@ auto ICD::ppuOutput(uint2 color) -> void { if(writeX >= 160) return; // Unverified behavior if(writeY >= 8) return; // Should never happen - uint addr = writeBank * 512 + writeY * 2 + writeX / 8 * 16; + uint addr = (writeBank & 3) * 512 + writeY * 2 + writeX / 8 * 16; output[addr + 0] = (output[addr + 0] << 1) | !!(color & 1); output[addr + 1] = (output[addr + 1] << 1) | !!(color & 2); writeX++; diff --git a/bsnes/sfc/coprocessor/icd/io.cpp b/bsnes/sfc/coprocessor/icd/io.cpp index b3a64a47..ccab1785 100644 --- a/bsnes/sfc/coprocessor/icd/io.cpp +++ b/bsnes/sfc/coprocessor/icd/io.cpp @@ -3,7 +3,7 @@ auto ICD::readIO(uint addr, uint8 data) -> uint8 { //LY counter if(addr == 0x6000) { - uint y = min((uint8)143, ly); + uint y = ly; return (y & ~7) | writeBank; } From a0671bc8a9d8586fbcc893bb3b6208e98b58bcc4 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Fri, 19 Jul 2019 19:57:11 +0300 Subject: [PATCH 3/3] Fix SGB save states --- bsnes/sfc/coprocessor/icd/serialization.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/bsnes/sfc/coprocessor/icd/serialization.cpp b/bsnes/sfc/coprocessor/icd/serialization.cpp index 75eff3c8..d3a72770 100644 --- a/bsnes/sfc/coprocessor/icd/serialization.cpp +++ b/bsnes/sfc/coprocessor/icd/serialization.cpp @@ -3,13 +3,17 @@ auto ICD::serialize(serializer& s) -> void { auto size = GB_get_save_state_size(&sameboy); auto data = new uint8_t[size]; - s.array(data, size); - if(s.mode() == serializer::Load) { - GB_load_state_from_buffer(&sameboy, data, size); - } + if(s.mode() == serializer::Save) { GB_save_state_to_buffer(&sameboy, data); } + + s.array(data, size); + + if(s.mode() == serializer::Load) { + GB_load_state_from_buffer(&sameboy, data, size); + } + delete[] data; for(auto n : range(64)) s.array(packet[n].data);