diff --git a/bsnes/emulator/emulator.hpp b/bsnes/emulator/emulator.hpp index 91881723..03d99998 100644 --- a/bsnes/emulator/emulator.hpp +++ b/bsnes/emulator/emulator.hpp @@ -32,7 +32,7 @@ using namespace nall; namespace Emulator { static const string Name = "bsnes"; - static const string Version = "107.9"; + static const string Version = "107.10"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "https://byuu.org/"; diff --git a/bsnes/gb/Core/display.c b/bsnes/gb/Core/display.c index 64c1aeca..bc251206 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,7 +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]; } } - + if (gb->model & GB_MODEL_NO_SFC_BIT) { if (gb->icd_pixel_callback) { gb->icd_pixel_callback(gb, icd_pixel); @@ -769,10 +769,7 @@ 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; - - // Todo: unverified timing - gb->current_lcd_line++; - + gb->current_lcd_line++; // Todo: unverified timing if (gb->current_lcd_line == LINES && GB_is_sgb(gb)) { display_vblank(gb); } @@ -912,7 +909,7 @@ 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); } diff --git a/bsnes/sfc/coprocessor/icd/icd.cpp b/bsnes/sfc/coprocessor/icd/icd.cpp index 4d9afe85..9e673117 100644 --- a/bsnes/sfc/coprocessor/icd/icd.cpp +++ b/bsnes/sfc/coprocessor/icd/icd.cpp @@ -10,16 +10,15 @@ ICD icd; namespace SameBoy { static auto hreset(GB_gameboy_t*) -> void { - icd.ly++; - icd.ppuScanline(); + icd.ppuHreset(); } static auto vreset(GB_gameboy_t*) -> void { - icd.ly = 0; + icd.ppuVreset(); } static auto icd_pixel(GB_gameboy_t*, uint8_t pixel) -> void { - icd.ppuOutput(pixel); + icd.ppuWrite(pixel); } static auto joyp_write(GB_gameboy_t*, uint8_t value) -> void { @@ -35,7 +34,7 @@ namespace SameBoy { static auto sample(GB_gameboy_t*, GB_sample_t* sample) -> void { float left = sample->left / 32768.0f; float right = sample->right / 32768.0f; - icd.apuOutput(left, right); + icd.apuWrite(left, right); } static auto vblank(GB_gameboy_t*) -> void { @@ -63,7 +62,8 @@ auto ICD::main() -> void { auto ICD::load() -> bool { information = {}; - GB_random_set_enabled(false); +//todo: connect to SFC random enable setting +//GB_random_set_enabled(false); if(Frequency == 0) { GB_init(&sameboy, GB_MODEL_SGB_NO_SFC); GB_load_boot_rom_from_buffer(&sameboy, (const unsigned char*)&SGB1BootROM[0], 256); @@ -96,7 +96,6 @@ auto ICD::load() -> bool { fp->read(data, size); GB_load_rom_from_buffer(&sameboy, data, size); } else return unload(), false; - ly = 0; return true; } @@ -104,10 +103,31 @@ auto ICD::unload() -> void { GB_free(&sameboy); } -auto ICD::power() -> void { +auto ICD::power(bool reset) -> void { //SGB1 uses CPU oscillator; SGB2 uses dedicated oscillator create(ICD::Enter, (Frequency ? Frequency : system.cpuFrequency()) / 5.0); - stream = Emulator::audio.createStream(2, uint((Frequency ? Frequency : system.cpuFrequency()) / 5.0 / 128.0)); + if(!reset) { + stream = Emulator::audio.createStream(2, uint((Frequency ? Frequency : system.cpuFrequency()) / 5.0 / 128.0)); + } + + for(auto& packet : this->packet) packet = {}; + packetSize = 0; + + joypID = 3; + joyp14Lock = 0; + joyp15Lock = 0; + pulseLock = 1; + strobeLock = 0; + packetLock = 0; + joypPacket = {}; + packetOffset = 0; + bitData = 0; + bitOffset = 0; + + for(auto& n : output) n = 0xff; + readBank = 0; + readAddress = 0; + writeBank = 0; r6003 = 0x00; r6004 = 0xff; @@ -117,45 +137,8 @@ auto ICD::power() -> void { for(auto& r : r7000) r = 0x00; mltReq = 0; - for(auto& n : output) n = 0xff; - readBank = 0; - readAddress = 0; - writeBank = 0; - writeX = 0; - writeY = 0; - - packetSize = 0; - joypID = 3; - joyp15Lock = 0; - joyp14Lock = 0; - pulseLock = true; - - GB_reset(&sameboy); -} - -auto ICD::reset() -> void { - create(ICD::Enter, (Frequency ? Frequency : system.cpuFrequency()) / 5.0); - - r6003 = 0x00; - r6004 = 0xff; - r6005 = 0xff; - r6006 = 0xff; - r6007 = 0xff; - for(auto& r : r7000) r = 0x00; - mltReq = 0; - - for(auto& n : output) n = 0xff; - readBank = 0; - readAddress = 0; - writeBank = 0; - writeX = 0; - writeY = 0; - - packetSize = 0; - joypID = 3; - joyp15Lock = 0; - joyp14Lock = 0; - pulseLock = true; + hcounter = 0; + vcounter = 0; GB_reset(&sameboy); } diff --git a/bsnes/sfc/coprocessor/icd/icd.hpp b/bsnes/sfc/coprocessor/icd/icd.hpp index 718887f5..0863f638 100644 --- a/bsnes/sfc/coprocessor/icd/icd.hpp +++ b/bsnes/sfc/coprocessor/icd/icd.hpp @@ -8,13 +8,13 @@ struct ICD : Emulator::Platform, Thread { auto load() -> bool; auto unload() -> void; - auto power() -> void; - auto reset() -> void; //software reset + auto power(bool reset = false) -> void; //interface.cpp - auto ppuScanline() -> void; - auto ppuOutput(uint2 color) -> void; - auto apuOutput(float left, float right) -> void; + auto ppuHreset() -> void; + auto ppuVreset() -> void; + auto ppuWrite(uint2 color) -> void; + auto apuWrite(float left, float right) -> void; auto joypWrite(bool p14, bool p15) -> void; //io.cpp @@ -33,21 +33,27 @@ struct ICD : Emulator::Platform, Thread { private: struct Packet { - auto operator[](uint addr) -> uint8& { return data[addr & 15]; } + auto operator[](uint4 address) -> uint8& { return data[address]; } uint8 data[16]; }; Packet packet[64]; - uint packetSize; + uint7 packetSize; - uint joypID; - bool joyp15Lock; - bool joyp14Lock; - bool pulseLock; - bool strobeLock; - bool packetLock; + uint2 joypID; + uint1 joyp14Lock; + uint1 joyp15Lock; + uint1 pulseLock; + uint1 strobeLock; + uint1 packetLock; Packet joypPacket; - uint8 packetOffset; - uint8 bitData, bitOffset; + uint4 packetOffset; + uint8 bitData; + uint3 bitOffset; + + uint8 output[4 * 512]; + uint2 readBank; + uint9 readAddress; + uint2 writeBank; uint8 r6003; //control port uint8 r6004; //joypad 1 @@ -57,12 +63,8 @@ private: uint8 r7000[16]; //JOYP packet data uint8 mltReq; //number of active joypads - uint8 output[4 * 512]; - uint readBank; - uint readAddress; - uint writeBank; - uint writeX; - uint writeY; + uint8 hcounter; + uint8 vcounter; struct Information { uint pathID = 0; @@ -74,7 +76,6 @@ 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]; - uint8_t ly = 0; }; extern ICD icd; diff --git a/bsnes/sfc/coprocessor/icd/interface.cpp b/bsnes/sfc/coprocessor/icd/interface.cpp index 5f2f092a..859c14d3 100644 --- a/bsnes/sfc/coprocessor/icd/interface.cpp +++ b/bsnes/sfc/coprocessor/icd/interface.cpp @@ -1,33 +1,35 @@ - -auto ICD::ppuScanline() -> void { - if(++writeY == 8) { - writeBank = (writeBank + 1) & 3; - writeY = 0; - } - writeX = 0; +auto ICD::ppuHreset() -> void { + hcounter = 0; + vcounter++; + if((uint3)vcounter == 0) writeBank++; } -auto ICD::ppuOutput(uint2 color) -> void { - if(writeX >= 160) return; // Unverified behavior - if(writeY >= 8) return; // Should never happen - - 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++; +auto ICD::ppuVreset() -> void { + hcounter = 0; + vcounter = 0; } -auto ICD::apuOutput(float left, float right) -> void { +auto ICD::ppuWrite(uint2 color) -> void { + auto x = (uint8)hcounter++; + auto y = (uint3)vcounter; + if(x >= 160) return; //unverified behavior + + uint11 address = writeBank * 512 + y * 2 + x / 8 * 16; + output[address + 0] = (output[address + 0] << 1) | !!(color & 1); + output[address + 1] = (output[address + 1] << 1) | !!(color & 2); +} + +auto ICD::apuWrite(float left, float right) -> void { float samples[] = {left, right}; stream->write(samples); } auto ICD::joypWrite(bool p14, bool p15) -> void { //joypad handling - if(p15 == 1 && p14 == 1) { - if(joyp15Lock == 0 && joyp14Lock == 0) { - joyp15Lock = 1; + if(p14 == 1 && p15 == 1) { + if(joyp14Lock == 0 && joyp15Lock == 0) { joyp14Lock = 1; + joyp15Lock = 1; joypID++; if(mltReq == 0) joypID &= 0; //1-player mode if(mltReq == 1) joypID &= 1; //2-player mode @@ -43,17 +45,17 @@ auto ICD::joypWrite(bool p14, bool p15) -> void { if(joypID == 3) joypad = r6007; uint4 input = 0xf; - if(p15 == 1 && p14 == 1) input = 0xf - joypID; + if(p14 == 1 && p15 == 1) input = 0xf - joypID; if(p14 == 0) input &= bits(joypad,0-3); //d-pad if(p15 == 0) input &= bits(joypad,4-7); //buttons GB_icd_set_joyp(&sameboy, input); - if(p15 == 0 && p14 == 1) joyp15Lock = 0; - if(p15 == 1 && p14 == 0) joyp14Lock = 0; + if(p14 == 0 && p15 == 1) joyp14Lock = 0; + if(p14 == 1 && p15 == 0) joyp15Lock = 0; //packet handling - if(p15 == 0 && p14 == 0) { //pulse + if(p14 == 0 && p15 == 0) { //pulse pulseLock = false; packetOffset = 0; bitOffset = 0; @@ -64,13 +66,13 @@ auto ICD::joypWrite(bool p14, bool p15) -> void { if(pulseLock) return; - if(p15 == 1 && p14 == 1) { + if(p14 == 1 && p15 == 1) { strobeLock = false; return; } if(strobeLock) { - if(p15 == 1 || p14 == 1) { //malformed packet + if(p14 == 1 || p15 == 1) { //malformed packet packetLock = false; pulseLock = true; bitOffset = 0; @@ -80,13 +82,13 @@ auto ICD::joypWrite(bool p14, bool p15) -> void { } } - //p15:1, p14:0 = 0 - //p15:0, p14:1 = 1 - bool bit = (p15 == 0); + //p14:0, p15:1 = 0 + //p14:1, p15:0 = 1 + bool bit = p15 == 0; strobeLock = true; if(packetLock) { - if(p15 == 1 && p14 == 0) { + if(p14 == 0 && p15 == 1) { if((joypPacket[0] >> 3) == 0x11) { mltReq = joypPacket[1] & 3; joypID = 3; //required: the next time P14==1 && P15==1; increment and start from ID=0 (Joypad 1) @@ -99,11 +101,11 @@ auto ICD::joypWrite(bool p14, bool p15) -> void { return; } - bitData = (bit << 7) | (bitData >> 1); - if(++bitOffset < 8) return; + bitData = bit << 7 | bitData >> 1; + if(++bitOffset) return; - bitOffset = 0; joypPacket[packetOffset] = bitData; - if(++packetOffset < 16) return; + if(++packetOffset) return; + packetLock = true; } diff --git a/bsnes/sfc/coprocessor/icd/io.cpp b/bsnes/sfc/coprocessor/icd/io.cpp index ccab1785..069b0fec 100644 --- a/bsnes/sfc/coprocessor/icd/io.cpp +++ b/bsnes/sfc/coprocessor/icd/io.cpp @@ -3,8 +3,7 @@ auto ICD::readIO(uint addr, uint8 data) -> uint8 { //LY counter if(addr == 0x6000) { - uint y = ly; - return (y & ~7) | writeBank; + return vcounter & ~7 | writeBank; } //command ready port @@ -54,7 +53,7 @@ auto ICD::writeIO(uint addr, uint8 data) -> void { //d1,d0: 0 = frequency divider (clock rate adjust) if(addr == 0x6003) { if((r6003 & 0x80) == 0x00 && (data & 0x80) == 0x80) { - reset(); + power(true); //soft reset } auto frequency = system.cpuFrequency(); switch(data & 3) { diff --git a/bsnes/sfc/coprocessor/icd/serialization.cpp b/bsnes/sfc/coprocessor/icd/serialization.cpp index d3a72770..f75b47f9 100644 --- a/bsnes/sfc/coprocessor/icd/serialization.cpp +++ b/bsnes/sfc/coprocessor/icd/serialization.cpp @@ -3,25 +3,21 @@ auto ICD::serialize(serializer& s) -> void { auto size = GB_get_save_state_size(&sameboy); auto data = new uint8_t[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); s.integer(packetSize); s.integer(joypID); - s.integer(joyp15Lock); s.integer(joyp14Lock); + s.integer(joyp15Lock); s.integer(pulseLock); s.integer(strobeLock); s.integer(packetLock); @@ -30,6 +26,11 @@ auto ICD::serialize(serializer& s) -> void { s.integer(bitData); s.integer(bitOffset); + s.array(output); + s.integer(readBank); + s.integer(readAddress); + s.integer(writeBank); + s.integer(r6003); s.integer(r6004); s.integer(r6005); @@ -38,10 +39,6 @@ auto ICD::serialize(serializer& s) -> void { s.array(r7000); s.integer(mltReq); - s.array(output); - s.integer(readBank); - s.integer(readAddress); - s.integer(writeBank); - s.integer(writeX); - s.integer(writeY); + s.integer(hcounter); + s.integer(vcounter); }