GBHawk: Bug Fixes

This commit is contained in:
alyosha-tas 2017-11-22 11:10:45 -05:00
parent f494b58f3b
commit 0e028a2284
6 changed files with 108 additions and 82 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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