GBHawk: FiX serial port emulation (somewhat) and cleanup some minor bugs

This commit is contained in:
alyosha-tas 2020-10-01 15:17:58 -04:00
parent 60da770532
commit 7ebc3a3058
10 changed files with 88 additions and 26 deletions

View File

@ -21,8 +21,8 @@ namespace BizHawk.Emulation.Cores.Components.LR35902
DEC16, SPl, SPh,
INT_GET, 1, W,
WR, SPl, SPh, PCl,
IRQ_CLEAR,
IDLE,
IRQ_CLEAR,
TR, PCl, W,
OP };
}
@ -50,8 +50,8 @@ namespace BizHawk.Emulation.Cores.Components.LR35902
DEC16, SPl, SPh,
INT_GET, 1, W,
WR, SPl, SPh, PCl,
IRQ_CLEAR,
IDLE,
IRQ_CLEAR,
TR, PCl, W,
OP };
}

View File

@ -600,7 +600,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902
// interrupt src = 5 sets the PC to zero as observed
// also the triggering interrupt seems like it is held low (i.e. cannot trigger I flag) until the interrupt is serviced
ushort bit_check = instr_table[instr_pntr++];
//Console.WriteLine(interrupt_src + " " + interrupt_enable + " " + TotalExecutedCycles);
//Console.WriteLine("int " + TotalExecutedCycles);
interrupt_src_reg = GetIntRegs(0);
interrupt_enable_reg = GetIntRegs(1);

View File

@ -20,5 +20,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
public void Step(StepType type) => throw new NotImplementedException();
public long TotalExecutedCycles => (long)cpu.TotalExecutedCycles;
//public long TotalExecutedCycles => CycleCount;
}
}

View File

@ -20,6 +20,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
public bool controller_was_checked;
public bool delays_to_process;
public int controller_delay_cd;
//public long CycleCount;
public bool FrameAdvance(IController controller, bool render, bool rendersound)
{
@ -112,8 +113,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
cpu.ExecuteOne();
timer.divider_reg++;
if (delays_to_process) { process_delays(); }
REG_FF0F_OLD = REG_FF0F;
}
if (ppu.DMA_start && !cpu.halted && !cpu.stopped) { ppu.DMA_tick(); }
serialport.serial_transfer_tick();
timer.tick();
@ -130,6 +133,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
cpu.TotalExecutedCycles++;
timer.divider_reg++;
if (delays_to_process) { process_delays(); }
REG_FF0F_OLD = REG_FF0F;
}
timer.tick();
@ -139,6 +144,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
if (delays_to_process) { process_delays(); }
}
//CycleCount++;
if (in_vblank && !in_vblank_old)
{
_islag = false;
@ -194,14 +201,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
if (!HDMA_transfer)
{
// These things all tick twice as fast in GBC double speed mode
if (ppu.DMA_start && !cpu.halted && !cpu.stopped) { ppu.DMA_tick(); }
serialport.serial_transfer_tick();
timer.tick();
cpu.ExecuteOne();
timer.divider_reg++;
if (delays_to_process) { process_delays(); }
// Note that DMA is halted when the CPU is halted
if (double_speed)
{
if (ppu.DMA_start && !cpu.halted && !cpu.stopped) { ppu.DMA_tick(); }
@ -209,26 +209,36 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
timer.tick();
cpu.ExecuteOne();
timer.divider_reg++;
if (delays_to_process) { process_delays(); }
REG_FF0F_OLD = REG_FF0F;
}
}
else
{
if (ppu.DMA_start && !cpu.halted && !cpu.stopped) { ppu.DMA_tick(); }
serialport.serial_transfer_tick();
timer.tick();
cpu.TotalExecutedCycles++;
cpu.ExecuteOne();
timer.divider_reg++;
if (delays_to_process) { process_delays(); }
}
else
{
if (double_speed)
{
timer.tick();
cpu.TotalExecutedCycles++;
timer.divider_reg++;
if (delays_to_process) { process_delays(); }
REG_FF0F_OLD = REG_FF0F;
}
timer.tick();
cpu.TotalExecutedCycles++;
timer.divider_reg++;
if (delays_to_process) { process_delays(); }
}
if (in_vblank && !in_vblank_old)
@ -314,7 +324,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
else
{
// reset the divider (only way for speed_change_timing_fine.gbc and speed_change_cancel.gbc to both work)
timer.divider_reg = 1;
//Console.WriteLine("at stop " + timer.divider_reg);
timer.divider_reg = 0x1;
// TODO: resetting the divider causes an increment, but exact timing unclear
//timer.tick();
double_speed = !double_speed;
return 0;
}
@ -343,7 +358,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 clear wins on GB but the set wins on GBC
if (((REG_FF0F & 4) == 4) && ((r & 4) == 0) && timer.IRQ_block && !is_GBC) { r |= 4; }
if (((REG_FF0F & 8) == 8) && ((r & 8) == 0) && serialport.IRQ_block && !is_GBC) { r |= 8; }
REG_FF0F = r;
}

View File

@ -220,6 +220,18 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
iptr3 = Marshal.AllocHGlobal(ppu.color_palette.Length * 8 * 8 + 1);
_scanlineCallback = null;
/*
for (int i = 0; i < ZP_RAM.Length; i++)
{
ZP_RAM[i] = 0xFF;
}
for (int i = 0; i < RAM.Length; i++)
{
RAM[i] = 0xFF;
}
*/
}
public bool IsCGBMode() => is_GBC;

View File

@ -50,6 +50,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
blank_frame = true;
}
LCDC = value;
//Console.WriteLine(LY + " " + cycle);
break;
case 0xFF41: // STAT
// writing to STAT during mode 0 or 1 causes a STAT IRQ

View File

@ -38,6 +38,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
// Interrupt flags
case 0xFF0F:
// TODO: Maybe some PPU bits are immediately visible, see 10spritesPrLine_10xposA7_m0irq_2_dmg08_cgb04c_out2.gbc
//Console.WriteLine("FF0F " + cpu.TotalExecutedCycles);
ret = REG_FF0F_OLD;
break;

View File

@ -25,6 +25,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
{
public partial class GBHawk
{
//public byte[] RAM_read = new byte[0x8000];
//public byte[] ZP_RAM_read = new byte[0x80];
public byte ReadMemory(ushort addr)
{
if (MemoryCallbacks.HasReads)
@ -61,6 +64,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
if (addr >= 0xF000 && addr < 0xFE00)
{
//if (RAM_read[(RAM_Bank * 0x1000) + (addr - 0xF000)] == 0) { Console.WriteLine("RAM: " + addr + " " + cpu.TotalExecutedCycles); }
return RAM[(RAM_Bank * 0x1000) + (addr - 0xF000)];
}
@ -85,6 +89,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
{
if (addr != 0xFFFF)
{
//if (ZP_RAM_read[addr - 0xFF80] == 0) { Console.WriteLine("ZP: " + (addr - 0xFF80) + " " + cpu.TotalExecutedCycles); }
return ZP_RAM[addr - 0xFF80];
}
else
@ -158,6 +163,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
if (addr < 0xFE00)
{
addr = (ushort)(RAM_Bank * (addr & 0x1000) + (addr & 0xFFF));
//if (RAM_read[addr] == 0) { Console.WriteLine("RAM: " + addr + " " + cpu.TotalExecutedCycles); }
return RAM[addr];
}
@ -215,6 +221,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
if (addr < 0xFFFF)
{
//if (ZP_RAM_read[addr - 0xFF80] == 0) { Console.WriteLine("ZP: " + (addr - 0xFF80) + " " + cpu.TotalExecutedCycles); }
return ZP_RAM[addr - 0xFF80];
}
@ -234,7 +241,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
if (ppu.DMA_start)
{
// some of gekkio's tests require this to be accessible during DMA
if (addr >= 0xA000 && addr < 0xC000 && is_GBC)
{
// on GBC only, cart is accessible during DMA
@ -243,10 +249,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
if (addr >= 0xE000 && addr < 0xF000)
{
//RAM_read[addr - 0xE000] = 1;
RAM[addr - 0xE000] = value;
}
else if (addr >= 0xF000 && addr < 0xFE00)
{
//RAM_read[RAM_Bank * 0x1000 + (addr - 0xF000)] = 1;
RAM[RAM_Bank * 0x1000 + (addr - 0xF000)] = value;
}
else if (addr >= 0xFE00 && addr < 0xFEA0 && ppu.DMA_OAM_access)
@ -261,6 +269,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
{
if (addr != 0xFFFF)
{
//ZP_RAM_read[addr - 0xFF80] = 1;
ZP_RAM[addr - 0xFF80] = value;
}
else
@ -281,6 +290,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
}
else if (addr < 0xFFFF)
{
//ZP_RAM_read[addr - 0xFF80] = 1;
ZP_RAM[addr - 0xFF80] = value;
}
else
@ -294,7 +304,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
{
if (ppu.OAM_access_write) { OAM[addr - 0xFE00] = value; }
}
// unmapped memory writes depend on console
// unmapped memory writes depend on console
else
{
if (is_GBC)
@ -318,6 +328,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
else if (addr >= 0xC000)
{
addr = (ushort)(RAM_Bank * (addr & 0x1000) + (addr & 0xFFF));
//RAM_read[addr] = 1;
RAM[addr] = value;
}
else if (addr >= 0xA000)
@ -326,7 +337,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
}
else if (addr >= 0x8000)
{
if (ppu.VRAM_access_write) { VRAM[(VRAM_Bank * 0x2000) + (addr - 0x8000)] = value; }
if (ppu.VRAM_access_write)
{
VRAM[(VRAM_Bank * 0x2000) + (addr - 0x8000)] = value;
}
}
else
{

View File

@ -1,5 +1,6 @@
using BizHawk.Common.NumberExtensions;
using BizHawk.Common;
using System;
namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
{
@ -15,6 +16,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
public int clk_rate;
public byte going_out;
public byte coming_in;
public int serial_bits_old;
public bool IRQ_block;
public byte ReadReg(int addr)
{
@ -40,20 +43,24 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
case 0xFF02:
if ((value & 0x1) == 1)
{
serial_bits = 8;
if (((value & 2) > 0) && Core.GBC_compat)
{
clk_rate = 16;
serial_clock = (16 - (int)(Core.cpu.TotalExecutedCycles % 8)) + 1;
serial_clock = 16 - (int)(Core.timer.divider_reg % 8) - 1;
// if the clock rate is changing and it's on a GBA/C, the parity of (cpu.totalexecutedcycles & 512) effects the first bit
// Not sure exactly how yet
}
else
{
clk_rate = 512;
serial_clock = 512 - (int)(Core.cpu.TotalExecutedCycles % 256) + 1;
serial_clock = 512 - (int)(Core.timer.divider_reg % 256) - 1;
// there seems to be some clock inverting happening on some transfers
// not sure of the exact nature of it, here is one methor that gives correct result on one test rom but not others
// not sure of the exact nature of it, here is one method that gives correct result on one test rom but not others
/*
if (Core._syncSettings.GBACGB && Core.is_GBC)
{
@ -68,10 +75,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
}
else
{
serial_bits_old = serial_bits;
serial_bits = 8;
clk_rate = -1;
serial_clock = clk_rate;
can_pulse = false;
}
if (Core.GBC_compat)
@ -90,6 +99,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
public void serial_transfer_tick()
{
IRQ_block = false;
if (serial_clock > 0)
{
serial_clock--;
@ -108,6 +119,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
if (Core.REG_FFFF.Bit(3)) { Core.cpu.FlagI = true; }
Core.REG_FF0F |= 0x08;
//Console.WriteLine("SIRQ " + Core.cpu.TotalExecutedCycles);
IRQ_block = true;
}
else
{
@ -141,6 +154,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
ser.Sync(nameof(going_out), ref going_out);
ser.Sync(nameof(coming_in), ref coming_in);
ser.Sync(nameof(can_pulse), ref can_pulse);
ser.Sync(nameof(IRQ_block), ref IRQ_block);
}
}
}

View File

@ -204,6 +204,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
// set interrupts
if (Core.REG_FFFF.Bit(2)) { Core.cpu.FlagI = true; }
//Console.WriteLine("timer " + Core.cpu.TotalExecutedCycles);
Core.REG_FF0F |= 0x04;
IRQ_block = true;
}