diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs index 5902b22337..2bac7a73e8 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs @@ -12,11 +12,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk public ControllerDefinition ControllerDefinition => _controllerDeck.Definition; public byte controller_state; - public byte controller_state_old; public bool in_vblank_old; public bool in_vblank; public bool vblank_rise; - bool contr_check_once; public void FrameAdvance(IController controller, bool render, bool rendersound) { @@ -57,7 +55,43 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk // gameboy frames can be variable lengths // we want to end a frame when VBlank turns from false to true int ticker = 0; - contr_check_once = true; + + // check if new input changed the input register and triggered IRQ + byte contr_prev = input_register; + + input_register &= 0xF0; + if ((input_register & 0x30) == 0x20) + { + input_register |= (byte)(controller_state & 0xF); + } + else if ((input_register & 0x30) == 0x10) + { + input_register |= (byte)((controller_state & 0xF0) >> 4); + } + else if ((input_register & 0x30) == 0x00) + { + // if both polls are set, then a bit is zero if either or both pins are zero + byte temp = (byte)((controller_state & 0xF) & ((controller_state & 0xF0) >> 4)); + input_register |= temp; + } + else + { + input_register |= 0xF; + } + + // check for interrupts + + + if (((contr_prev & 8) > 0) && ((input_register & 8) == 0) || + ((contr_prev & 4) > 0) && ((input_register & 4) == 0) || + ((contr_prev & 2) > 0) && ((input_register & 2) == 0) || + ((contr_prev & 1) > 0) && ((input_register & 1) == 0)) + { + if (REG_FFFF.Bit(4)) { cpu.FlagI = true; } + REG_FF0F |= 0x10; + } + + while (!vblank_rise && (ticker < 100000)) { audio.tick(); @@ -69,43 +103,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk timer.tick_2(); - // check for controller interrupts somewhere around the middle of the frame - if ((cpu.LY == 50) && contr_check_once) - { - byte contr_prev = input_register; - - input_register &= 0xF0; - if ((input_register & 0x30) == 0x20) - { - input_register |= (byte)(controller_state & 0xF); - } - else if ((input_register & 0x30) == 0x10) - { - input_register |= (byte)((controller_state & 0xF0) >> 4); - } - else if ((input_register & 0x30) == 0x00) - { - // if both polls are set, then a bit is zero if either or both pins are zero - byte temp = (byte)((controller_state & 0xF) & ((controller_state & 0xF0) >> 4)); - input_register |= temp; - } - else - { - input_register |= 0xF; - } - - // check for interrupts - if (((contr_prev & 8) > 0) && ((input_register & 8) == 0) || - ((contr_prev & 4) > 0) && ((input_register & 4) == 0) || - ((contr_prev & 2) > 0) && ((input_register & 2) == 0) || - ((contr_prev & 2) > 0) && ((input_register & 1) == 0)) - { - if (REG_FFFF.Bit(4)) { cpu.FlagI = true; } - REG_FF0F |= 0x10; - } - } - - if (in_vblank && !in_vblank_old) { vblank_rise = true; @@ -126,15 +123,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk { InputCallbacks.Call(); controller_state = _controllerDeck.ReadPort1(controller); - - // set interrupt flag if a pin went from high to low - if (controller_state < controller_state_old) - { - if (REG_FFFF.Bit(4)) { cpu.FlagI = true; } - REG_FF0F |= 0x10; - } - - controller_state_old = controller_state; } public int Frame => _frame; diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IStatable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IStatable.cs index 6fe619718d..6a6c3cf872 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IStatable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IStatable.cs @@ -62,7 +62,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk _controllerDeck.SyncState(ser); ser.Sync("controller_state", ref controller_state); - ser.Sync("controller_state_old", ref controller_state_old); ser.Sync("in_vblank", ref in_vblank); ser.Sync("in_vblank_old", ref in_vblank_old); ser.Sync("vblank_rise", ref vblank_rise); diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/HW_Registers.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/HW_Registers.cs index e24acbe22d..daf9161210 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/HW_Registers.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/HW_Registers.cs @@ -16,26 +16,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk // Read Input case 0xFF00: _islag = false; - - input_register &= 0xF0; - if ((input_register & 0x30) == 0x20) - { - input_register |= (byte)(controller_state & 0xF); - } - else if ((input_register & 0x30) == 0x10) - { - input_register |= (byte)((controller_state & 0xF0) >> 4); - } - else if ((input_register & 0x30) == 0x00) - { - // if both polls are set, then a bit is zero if either or both pins are zero - byte temp = (byte)((controller_state & 0xF) & ((controller_state & 0xF0) >> 4)); - input_register |= temp; - } - else - { - input_register |= 0xF; - } ret = input_register; break; @@ -143,7 +123,42 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk { // select input case 0xFF00: - input_register = (byte)(0xC0 | (value & 0x3F)); // top 2 bits always 1 + input_register &= 0xCF; + input_register |= (byte)(value & 0x30); // top 2 bits always 1 + + // check for high to low transitions that trigger IRQs + byte contr_prev = input_register; + + input_register &= 0xF0; + if ((input_register & 0x30) == 0x20) + { + input_register |= (byte)(controller_state & 0xF); + } + else if ((input_register & 0x30) == 0x10) + { + input_register |= (byte)((controller_state & 0xF0) >> 4); + } + else if ((input_register & 0x30) == 0x00) + { + // if both polls are set, then a bit is zero if either or both pins are zero + byte temp = (byte)((controller_state & 0xF) & ((controller_state & 0xF0) >> 4)); + input_register |= temp; + } + else + { + input_register |= 0xF; + } + + // check for interrupts + if (((contr_prev & 8) > 0) && ((input_register & 8) == 0) || + ((contr_prev & 4) > 0) && ((input_register & 4) == 0) || + ((contr_prev & 2) > 0) && ((input_register & 2) == 0) || + ((contr_prev & 1) > 0) && ((input_register & 1) == 0)) + { + if (REG_FFFF.Bit(4)) { cpu.FlagI = true; } + REG_FF0F |= 0x10; + } + break; // Serial data port diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Mappers/Mapper_MBC2.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Mappers/Mapper_MBC2.cs index 6327d00491..dfda342323 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Mappers/Mapper_MBC2.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Mappers/Mapper_MBC2.cs @@ -32,7 +32,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk } else if ((addr >= 0xA000) && (addr < 0xA200)) { - return Core.cart_RAM[addr - 0xA000]; + if (RAM_enable) + { + return Core.cart_RAM[addr - 0xA000]; + } + return 0xFF; } else { @@ -49,13 +53,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk { if (addr < 0x2000) { - RAM_enable = (addr & 0x100) > 0; + if ((addr & 0x100) == 0) + { + RAM_enable = ((value & 0xA) == 0xA) ? true : false; + } } else if (addr < 0x4000) { if ((addr & 0x100) > 0) { ROM_bank = value & 0xF; + if (ROM_bank==0) { ROM_bank = 1; } } } else if ((addr >= 0xA000) && (addr < 0xA200)) diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/PPU.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/PPU.cs index 53c90c41b8..02de5b6d7d 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/PPU.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/PPU.cs @@ -428,8 +428,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk else { // screen disable sets STAT as though it were vblank, but there is no Stat IRQ asserted - STAT &= 0xFC; - STAT |= 0x01; + //STAT &= 0xFC; + //STAT |= 0x01; + + STAT &= 0xF8; VBL_INT = LYC_INT = HBL_INT = OAM_INT = false; diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/SerialPort.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/SerialPort.cs index cbdc837a36..64de7f5457 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/SerialPort.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/SerialPort.cs @@ -19,8 +19,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk public byte ReadReg(int addr) { - byte ret = 0; - switch (addr) { case 0xFF01: @@ -29,7 +27,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk return serial_control; } - return ret; + return 0xFF; + } public void WriteReg(int addr, byte value) @@ -58,6 +57,21 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk serial_clock = clk_rate; } } + else if (serial_start) + { + if ((value & 1) > 0) + { + clk_internal = true; + clk_rate = 512; + serial_clock = clk_rate; + } + else + { + clk_internal = false; + clk_rate = get_external_clock(); + serial_clock = clk_rate; + } + } serial_control = (byte)(0x7E | (value & 0x81)); // middle six bits always 1 break; @@ -69,7 +83,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk { if (serial_start) { - serial_clock--; + if (serial_clock > 0) { serial_clock--; } if (serial_clock == 0) { if (serial_bits > 0) @@ -98,10 +112,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk } // call this function to get the clock rate of a connected device - // internal rate is 512 + // if no external device, the clocking doesn't occur public int get_external_clock() { - return 512; + return -1; } // call this function to get the next bit from the connected device @@ -120,7 +134,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk { serial_control = 0x7E; serial_start = false; - serial_data = 0xFF; + serial_data = 0x00; } public void SyncState(Serializer ser)