GBHawk: work on double speed mode

This commit is contained in:
alyosha-tas 2020-11-21 13:49:28 -05:00
parent 7596b97218
commit cd7cc7f939
3 changed files with 37 additions and 11 deletions

View File

@ -10,7 +10,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902
// variables for executing instructions
public int instr_pntr = 0;
public ushort[] cur_instr = new ushort [60];
public ushort[] instr_table = new ushort[256 * 2 * 60 + 60 * 9];
public ushort[] instr_table = new ushort[256 * 2 * 60 + 60 * 10];
public bool CB_prefix;
public bool halted;
public bool stopped;
@ -622,6 +622,12 @@ namespace BizHawk.Emulation.Cores.Components.LR35902
// wait state during HDMA
instr_table[256 * 60 * 2 + 60 * 8] = WAIT;
// Speed Change Loop
instr_table[256 * 60 * 2 + 60 * 9] = IDLE;
instr_table[256 * 60 * 2 + 60 * 9 + 1] = DIV_RST;
instr_table[256 * 60 * 2 + 60 * 9 + 2] = HALT_CHK;
instr_table[256 * 60 * 2 + 60 * 9 + 3] = STOP;
}
}
}

View File

@ -60,6 +60,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902
public const ushort COND_CHECK = 48;
public const ushort HALT_FUNC = 49;
public const ushort WAIT = 50; // set cpu to wait state during HDMA
public const ushort DIV_RST = 51; // change speed mode
// test conditions
public const ushort ALWAYS_T = 0;
@ -512,9 +513,13 @@ namespace BizHawk.Emulation.Cores.Components.LR35902
break;
}
if (stop_time == (32769))
if (stop_time == 32770)
{
// point to speed cange loop
SpeedFunc(1);
instr_pntr = 256 * 60 * 2 + 60 * 9;
stop_time--;
break;
}
stop_time--;
@ -730,6 +735,9 @@ namespace BizHawk.Emulation.Cores.Components.LR35902
case WAIT:
instr_pntr--;
break;
case DIV_RST:
SpeedFunc(2);
break;
}
TotalExecutedCycles++;
}

View File

@ -287,7 +287,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
speed_switch = false;
Console.WriteLine("Speed Switch: " + cpu.TotalExecutedCycles);
int ret = double_speed ? 32769 : 32769; // actual time needs checking
int ret = double_speed ? 32770 : 32770; // actual time needs checking
return ret;
}
@ -298,16 +298,27 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
// if we are in GB mode, return 0, cannot switch speed
return 0;
}
else if (temp == 1)
{
double_speed = !double_speed;
return 0;
}
else
{
// reset the divider (only way for speed_change_timing_fine.gbc and speed_change_cancel.gbc to both work)
//Console.WriteLine("at stop " + timer.divider_reg);
timer.divider_reg = 0x1;
// Console.WriteLine("at stop " + timer.divider_reg + " " + timer.timer_control);
// TODO: resetting the divider causes an increment, but exact timing unclear
//timer.tick();
// only if the timer mode is 1, an extra tick of the timer is counted before the reset
// this varies between console revisions
if ((timer.timer_control & 3) == 1)
{
if((timer.divider_reg & 0x7) == 7)
{
timer.old_state = true;
}
}
double_speed = !double_speed;
timer.divider_reg = 0xFFFF;
return 0;
}
}
@ -341,9 +352,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
public void SetIntRegs(byte r)
{
// For timer interrupts or serial interrupts that occur on the same cycle as the IRQ clear
// the cear wins on GB and GBA (tested on GBP.) Assuming true for GBC E too.
if (((REG_FF0F & 4) == 4) && ((r & 4) == 0) && timer.IRQ_block) { r |= 4; }
if (((REG_FF0F & 8) == 8) && ((r & 8) == 0) && serialport.IRQ_block) { r |= 8; }
// the clear wins on GB and GBA (tested on GBP.) Assuming true for GBC E too.
// but only in single speed
if (((REG_FF0F & 4) == 4) && ((r & 4) == 0) && timer.IRQ_block && !double_speed) { r |= 4; }
if (((REG_FF0F & 8) == 8) && ((r & 8) == 0) && serialport.IRQ_block && !double_speed) { r |= 8; }
REG_FF0F = r;
}