diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/LibGBHawk.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/LibGBHawk.cs index ded3c7c0b8..ed5e6d616b 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/LibGBHawk.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/LibGBHawk.cs @@ -35,9 +35,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk /// <param name="core">opaque state pointer</param> /// <param name="romdata_1">the rom data, can be disposed of once this function returns</param> /// <param name="length_1">length of romdata in bytes</param> + /// <param name="MD5">Hash used for mapper loading</param> + /// <param name="RTC_init">Initial RTC time</param> + /// <param name="RTC_offset">Clck offset for RTC</param> /// <returns>0 on success, negative value on failure.</returns> [DllImport("GBHawk.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int GB_load(IntPtr core, byte[] romdata_1, uint length_1, uint RTC_init, uint RTC_offset); + public static extern int GB_load(IntPtr core, byte[] romdata_1, uint length_1, char[] MD5, uint RTC_init, uint RTC_offset); /// <summary> /// Advance a frame and send controller data. @@ -93,12 +96,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk #region Memory Domain Functions /// <summary> - /// Read the system bus + /// Read the RAM /// </summary> /// <param name="core">opaque state pointer</param> - /// <param name="addr">system bus address</param> + /// <param name="addr">ram address</param> [DllImport("GBHawk.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern byte GB_getsysbus(IntPtr core, int addr); + public static extern byte GB_getram(IntPtr core, int addr); /// <summary> /// Read the VRAM @@ -108,13 +111,74 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk [DllImport("GBHawk.dll", CallingConvention = CallingConvention.Cdecl)] public static extern byte GB_getvram(IntPtr core, int addr); + /// <summary> + /// Read the VRAM + /// </summary> + /// <param name="core">opaque state pointer</param> + /// <param name="addr">vram address</param> + [DllImport("GBHawk.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern byte GB_getoam(IntPtr core, int addr); + + /// <summary> + /// Read the VRAM + /// </summary> + /// <param name="core">opaque state pointer</param> + /// <param name="addr">vram address</param> + [DllImport("GBHawk.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern byte GB_gethram(IntPtr core, int addr); + + /// <summary> + /// Read the system bus + /// </summary> + /// <param name="core">opaque state pointer</param> + /// <param name="addr">system bus address</param> + [DllImport("GBHawk.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern byte GB_getsysbus(IntPtr core, int addr); + /// <summary> /// Read the RAM /// </summary> /// <param name="core">opaque state pointer</param> /// <param name="addr">ram address</param> + /// <param name="value">write value</param> [DllImport("GBHawk.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern byte GB_getram(IntPtr core, int addr); + public static extern void GB_setram(IntPtr core, int addr, byte value); + + /// <summary> + /// Read the VRAM + /// </summary> + /// <param name="core">opaque state pointer</param> + /// <param name="addr">vram address</param> + /// <param name="value">write value</param> + [DllImport("GBHawk.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern void GB_setvram(IntPtr core, int addr, byte value); + + /// <summary> + /// Read the VRAM + /// </summary> + /// <param name="core">opaque state pointer</param> + /// <param name="addr">vram address</param> + /// <param name="value">write value</param> + [DllImport("GBHawk.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern void GB_setoam(IntPtr core, int addr, byte value); + + /// <summary> + /// Read the VRAM + /// </summary> + /// <param name="core">opaque state pointer</param> + /// <param name="addr">vram address</param> + /// <param name="value">write value</param> + [DllImport("GBHawk.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern void GB_sethram(IntPtr core, int addr, byte value); + + /// <summary> + /// Read the system bus + /// </summary> + /// <param name="core">opaque state pointer</param> + /// <param name="addr">system bus address</param> + /// <param name="value">write value</param> + [DllImport("GBHawk.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern void GB_setsysbus(IntPtr core, int addr, byte value); #endregion @@ -175,7 +239,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk public static extern void GB_getregisterstate(IntPtr core, StringBuilder h, int t, int l); /// <summary> - /// get the register state from the cpu + /// get the opcode disassembly /// </summary> /// <param name="core">opaque state pointer</param> /// <param name="d">pointer to const char *</param> @@ -184,5 +248,88 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk [DllImport("GBHawk.dll", CallingConvention = CallingConvention.Cdecl)] public static extern void GB_getdisassembly(IntPtr core, StringBuilder h, int t, int l); #endregion + + #region PPU_Viewer + + /// <summary> + /// type of the cpu trace callback + /// </summary> + /// <param name="lcdc">type of event</param> + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void ScanlineCallback(byte lcdc); + + /// <summary> + /// Get PPU Pointers + /// </summary> + /// <param name="core">opaque state pointer</param> + /// <param name="sel">region to get</param> + [DllImport("GBHawk.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr GB_get_ppu_pntrs(IntPtr core, int sel); + + /// <summary> + /// Get PPU Pointers + /// </summary> + /// <param name="core">opaque state pointer</param> + [DllImport("GBHawk.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern byte GB_get_LCDC(IntPtr core); + + /// <summary> + /// set a callback to occur when ly reaches a particular scanline (so at the beginning of the scanline). + /// when the LCD is active, typically 145 will be the first callback after the beginning of frame advance, + /// and 144 will be the last callback right before frame advance returns + /// </summary> + /// <param name="core">opaque state pointer</param> + /// <param name="callback">null to clear</param> + /// <param name="sl">0-153 inclusive</param> + [DllImport("GBHawk.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern void GB_setscanlinecallback(IntPtr core, ScanlineCallback callback, int sl); + + #endregion + + #region debuggable funcitons + + /// <summary> + /// get the current cpu cycle count + /// </summary> + /// <param name="core">opaque state pointer</param> + [DllImport("GBHawk.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern int GB_cpu_cycles(IntPtr core); + + /// <summary> + /// get the registers + /// </summary> + /// <param name="core">opaque state pointer</param> + /// <param name="reg">reg number (see the DLL)</param> + [DllImport("GBHawk.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern byte GB_cpu_get_regs(IntPtr core, int reg); + + /// <summary> + /// get the flags + /// </summary> + /// <param name="core">opaque state pointer</param> + /// <param name="flag">flag number (see the DLL)</param> + [DllImport("GBHawk.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern bool GB_cpu_get_flags(IntPtr core, int flag); + + /// <summary> + /// get the registers + /// </summary> + /// <param name="core">opaque state pointer</param> + /// <param name="reg">reg number (see the DLL)</param> + /// <param name="value">value to set</param> + [DllImport("GBHawk.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern void GB_cpu_set_regs(IntPtr core, int reg, byte value); + + /// <summary> + /// get the flags + /// </summary> + /// <param name="core">opaque state pointer</param> + /// <param name="flag">flag number (see the DLL)</param> + /// <param name="value">value to set</param> + [DllImport("GBHawk.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern void GB_cpu_set_flags(IntPtr core, int flag, bool value); + + #endregion + } } diff --git a/libHawk/GBHawk/GBHawk/Core.h b/libHawk/GBHawk/GBHawk/Core.h index 5baab56200..064c151d7b 100644 --- a/libHawk/GBHawk/GBHawk/Core.h +++ b/libHawk/GBHawk/GBHawk/Core.h @@ -109,6 +109,25 @@ namespace GBHawk MemMap.mapper_pntr->Cart_RAM = &MemMap.Cart_RAM[0]; } + void Reset() + { + MemMap.GB_bios_register = 0; // bios enable + MemMap.GBC_compat = MemMap.is_GBC; + MemMap.in_vblank = true; // we start off in vblank since the LCD is off + MemMap.in_vblank_old = true; + MemMap.double_speed = false; + MemMap.VRAM_Bank = 0; + MemMap.RAM_Bank = 1; // RAM bank always starts as 1 (even writing zero still sets 1) + + MemMap.Register_Reset(); + timer.Reset(); + ppu->Reset(); + psg.Reset(); + serialport.Reset(); + mapper->Reset(); + cpu.Reset(); + } + bool FrameAdvance(uint8_t controller_1, uint8_t controller_2, uint8_t* kb_rows_ptr, bool render, bool rendersound) { @@ -384,19 +403,56 @@ namespace GBHawk #pragma region Memory Domain Functions - uint8_t GetSysBus(uint32_t addr) + + uint8_t GetRAM(uint32_t addr) { - return cpu.PeekMemory(addr); + return MemMap.RAM[addr & 0x7FFF]; } - uint8_t GetVRAM(uint32_t addr) + uint8_t GetVRAM(uint32_t addr) { return MemMap.VRAM[addr & 0x3FFF]; } - uint8_t GetRAM(uint32_t addr) + uint8_t GetOAM(uint32_t addr) { - return MemMap.RAM[addr & 0xFFFF]; + return MemMap.OAM[addr]; + } + + uint8_t GetHRAM(uint32_t addr) + { + return MemMap.ZP_RAM[addr & 0x7F]; + } + + uint8_t GetSysBus(uint32_t addr) + { + return MemMap.PeekMemory(addr); + } + + void SetRAM(uint32_t addr, uint8_t value) + { + MemMap.RAM[addr & 0x7FFF] = value; + } + + void SetVRAM(uint32_t addr, uint8_t value) + { + MemMap.VRAM[addr & 0x3FFF] = value; + } + + void SetOAM(uint32_t addr, uint8_t value) + { + MemMap.OAM[addr] = value; + } + + void SetHRAM(uint32_t addr, uint8_t value) + { + MemMap.ZP_RAM[addr & 0x7F] = value; + } + + void SetSysBus(uint32_t addr, uint8_t value) + { + // make poke? + MemMap.WriteMemory(addr, value); } #pragma endregion @@ -408,6 +464,12 @@ namespace GBHawk cpu.TraceCallback = callback; } + void SetScanlineCallback(void (*callback)(void), int sl) + { + ppu->scanlineCallback = callback; + MemMap._scanlineCallbackLine = sl; + } + int GetHeaderLength() { return 105 + 1; @@ -420,7 +482,7 @@ namespace GBHawk int GetRegStringLength() { - return 86 + 1; + return 74 + 1; } void GetHeader(char* h, int l) diff --git a/libHawk/GBHawk/GBHawk/GBHawk.cpp b/libHawk/GBHawk/GBHawk/GBHawk.cpp index cbe5671bf9..2baa858b45 100644 --- a/libHawk/GBHawk/GBHawk/GBHawk.cpp +++ b/libHawk/GBHawk/GBHawk/GBHawk.cpp @@ -33,13 +33,18 @@ GBHawk_EXPORT void GB_load_bios(GBCore* p, uint8_t* bios, bool GBC_console, bool } // load a rom into the core -GBHawk_EXPORT void GB_load(GBCore* p, uint8_t* rom_1, uint32_t size_1, uint32_t RTC_initial, uint32_t RTC_offset) +GBHawk_EXPORT void GB_load(GBCore* p, uint8_t* rom_1, uint32_t size_1, char* MD5, uint32_t RTC_initial, uint32_t RTC_offset) { - string MD5; + string MD5_s(MD5, 32); - p->Load_ROM(rom_1, size_1, MD5, RTC_initial, RTC_offset); + p->Load_ROM(rom_1, size_1, MD5_s, RTC_initial, RTC_offset); } +// Hard reset (note: does not change RTC, that only happens on load) +GBHawk_EXPORT void GB_Reset(GBCore* p) +{ + p->Reset(); +} // advance a frame GBHawk_EXPORT bool GB_frame_advance(GBCore* p, uint8_t ctrl1, uint8_t ctrl2, uint8_t* kbrows, bool render, bool sound) { @@ -57,6 +62,7 @@ GBHawk_EXPORT uint32_t GB_get_audio(GBCore* p, int32_t* dest_L, int32_t* n_samp_ { return p->GetAudio(dest_L, n_samp_L, dest_R, n_samp_R); } +#pragma endregion #pragma region State Save / Load @@ -76,21 +82,48 @@ GBHawk_EXPORT void GB_load_state(GBCore* p, uint8_t* loader) #pragma region Memory Domain Functions -GBHawk_EXPORT uint8_t GB_getsysbus(GBCore* p, uint32_t addr) { - return p->GetSysBus(addr); +GBHawk_EXPORT uint8_t GB_getram(GBCore* p, uint32_t addr) { + return p->GetRAM(addr); } GBHawk_EXPORT uint8_t GB_getvram(GBCore* p, uint32_t addr) { return p->GetVRAM(addr); } -GBHawk_EXPORT uint8_t GB_getram(GBCore* p, uint32_t addr) { - return p->GetRAM(addr); +GBHawk_EXPORT uint8_t GB_getoam(GBCore* p, uint32_t addr) { + return p->GetOAM(addr); +} + +GBHawk_EXPORT uint8_t GB_gethram(GBCore* p, uint32_t addr) { + return p->GetHRAM(addr); +} + +GBHawk_EXPORT uint8_t GB_getsysbus(GBCore* p, uint32_t addr) { + return p->GetSysBus(addr); +} + +GBHawk_EXPORT void GB_setram(GBCore* p, uint32_t addr, uint8_t value) { + p->SetRAM(addr, value); +} + +GBHawk_EXPORT void GB_setvram(GBCore* p, uint32_t addr, uint8_t value) { + p->SetVRAM(addr, value); +} + +GBHawk_EXPORT void GB_setoam(GBCore* p, uint32_t addr, uint8_t value) { + p->SetOAM(addr, value); +} + +GBHawk_EXPORT void GB_sethram(GBCore* p, uint32_t addr, uint8_t value) { + p->SetHRAM(addr, value); +} + +GBHawk_EXPORT void GB_setsysbus(GBCore* p, uint32_t addr, uint8_t value) { + p->SetSysBus(addr, value); } #pragma endregion - #pragma region Tracer // set tracer callback @@ -128,4 +161,94 @@ GBHawk_EXPORT void GB_getdisassembly(GBCore* p, char* d, int t, int l) { p->GetDisassembly(d, t, l); } +#pragma endregion + +#pragma region PPU Viewer + +// set tracer callback +GBHawk_EXPORT uint8_t* GB_get_ppu_pntrs(GBCore* p, int sel) { + + if (p->MemMap.is_GBC) + { + switch (sel) + { + case 0: return p->MemMap.VRAM; break; + case 1: return p->MemMap.OAM; break; + case 2: return (uint8_t*)p->ppu->OBJ_palette; break; + case 3: return (uint8_t*)p->ppu->BG_palette; break; + } + } + else + { + // need to fix this for GB + switch (sel) + { + case 0: return p->MemMap.VRAM; break; + case 1: return p->MemMap.OAM; break; + case 2: return (uint8_t*)p->ppu->OBJ_palette; break; + case 3: return (uint8_t*)p->ppu->BG_palette; break; + } + } + + return nullptr; +} + +// return LCDC state for the ppu viewer +GBHawk_EXPORT uint8_t GB_get_LCDC(GBCore* p) { + return p->ppu->LCDC; +} + +// set scanline callback +GBHawk_EXPORT void GB_setscanlinecallback(GBCore* p, void (*callback)(void), int sl) { + p->SetScanlineCallback(callback, sl); +} + +#pragma endregion + +#pragma region Debuggable functions + +// return cpu cycle count +GBHawk_EXPORT uint64_t GB_cpu_cycles(GBCore* p) { + return p->cpu.TotalExecutedCycles; +} + +// return cpu registers +GBHawk_EXPORT uint8_t GB_cpu_get_regs(GBCore* p, int reg) { + return p->cpu.Regs[reg]; +} + +// return cpu flags +GBHawk_EXPORT bool GB_cpu_get_flags(GBCore* p, int reg) { + bool ret = false; + + switch (reg) + { + case (0): ret = p->cpu.FlagI; break; + case (1): ret = p->cpu.FlagCget(); break; + case (2): ret = p->cpu.FlagHget(); break; + case (3): ret = p->cpu.FlagNget(); break; + case (4): ret = p->cpu.FlagZget(); break; + } + + return ret; +} + +// set cpu registers +GBHawk_EXPORT void GB_cpu_set_regs(GBCore* p, int reg, uint8_t value) { + p->cpu.Regs[reg] = value; +} + +// set cpu flags +GBHawk_EXPORT void GB_cpu_set_flags(GBCore* p, int reg, bool value) { + + switch (reg) + { + case (0): p->cpu.FlagI = value; break; + case (1): p->cpu.FlagCset(value); break; + case (2): p->cpu.FlagHset(value); break; + case (3): p->cpu.FlagNset(value); break; + case (4): p->cpu.FlagZset(value); break; + } +} + #pragma endregion \ No newline at end of file diff --git a/libHawk/GBHawk/GBHawk/LR35902.h b/libHawk/GBHawk/GBHawk/LR35902.h index 6f8a59a188..a96a999a31 100644 --- a/libHawk/GBHawk/GBHawk/LR35902.h +++ b/libHawk/GBHawk/GBHawk/LR35902.h @@ -166,6 +166,8 @@ namespace GBHawk CB_prefix = false; } + + void Reset() { ResetRegisters(); @@ -2626,12 +2628,12 @@ namespace GBHawk #pragma region Disassemble // disassemblies will also return strings of the same length - const char* TraceHeader = "Z80A: PC, machine code, mnemonic, operands, registers (AF, BC, DE, HL, IX, IY, SP, Cy), flags (CNP3H5ZS)"; + const char* TraceHeader = "LR35902: PC, machine code, mnemonic, operands, registers (A, F, B, C, D, E, H, L, SP), Cy, flags(ZNHCIE)"; const char* Un_halt_event = " ==Un-halted== "; const char* IRQ_event = " ====IRQ==== "; const char* Un_stop_event = " ==Un-stopped== "; const char* No_Reg = " "; - const char* Reg_template = "AF:AAFF BC:BBCC DE:DDEE HL:HHLL Ix:IxIx Iy:IyIy SP:SPSP Cy:FEDCBA9876543210 CNP3H5ZSE"; + const char* Reg_template = "A:AA F:FF B:BB C:CC D:DD E:EE H:HH L:LL SP:SPSP Cy:FEDCBA9876543210 ZNHCIE"; const char* Disasm_template = "PCPC: AA BB CC DD Di Di, XXXXX "; char replacer[32] = {}; @@ -2646,25 +2648,37 @@ namespace GBHawk { val_char_1 = replacer; - string reg_state = "AF:"; - temp_reg = (Regs[A] << 8) + Regs[F]; - sprintf_s(val_char_1, 5, "%04X", temp_reg); - reg_state.append(val_char_1, 4); + string reg_state = "A:"; + sprintf_s(val_char_1, 5, "%02X", Regs[A]); + reg_state.append(val_char_1, 2); - reg_state.append(" BC:"); - temp_reg = (Regs[B] << 8) + Regs[C]; - sprintf_s(val_char_1, 5, "%04X", temp_reg); - reg_state.append(val_char_1, 4); + reg_state = "F:"; + sprintf_s(val_char_1, 5, "%02X", Regs[F]); + reg_state.append(val_char_1, 2); - reg_state.append(" DE:"); - temp_reg = (Regs[D] << 8) + Regs[E]; - sprintf_s(val_char_1, 5, "%04X", temp_reg); - reg_state.append(val_char_1, 4); + reg_state = "B:"; + sprintf_s(val_char_1, 5, "%02X", Regs[B]); + reg_state.append(val_char_1, 2); - reg_state.append(" HL:"); - temp_reg = (Regs[H] << 8) + Regs[L]; - sprintf_s(val_char_1, 5, "%04X", temp_reg); - reg_state.append(val_char_1, 4); + reg_state = "C:"; + sprintf_s(val_char_1, 5, "%02X", Regs[C]); + reg_state.append(val_char_1, 2); + + reg_state = "D:"; + sprintf_s(val_char_1, 5, "%02X", Regs[D]); + reg_state.append(val_char_1, 2); + + reg_state = "E:"; + sprintf_s(val_char_1, 5, "%02X", Regs[E]); + reg_state.append(val_char_1, 2); + + reg_state = "H:"; + sprintf_s(val_char_1, 5, "%02X", Regs[H]); + reg_state.append(val_char_1, 2); + + reg_state = "L:"; + sprintf_s(val_char_1, 5, "%02X", Regs[L]); + reg_state.append(val_char_1, 2); reg_state.append(" SP:"); temp_reg = (Regs[SPh] << 8) + Regs[SPl]; @@ -2679,7 +2693,8 @@ namespace GBHawk reg_state.append(FlagNget() ? "N" : "n"); reg_state.append(FlagHget() ? "H" : "h"); reg_state.append(FlagZget() ? "Z" : "z"); - reg_state.append(FlagI ? "E" : "e"); + reg_state.append(FlagI ? "I" : "i"); + reg_state.append(interrupts_enabled ? "E" : "e"); return reg_state; } @@ -2734,9 +2749,9 @@ namespace GBHawk //n immediate succeeds the opcode and the displacement (if present) //nn immediately succeeds the opcode and the displacement (if present) - if (format.find("nn") != string::npos) + if (format.find("a16") != string::npos) { - size_t str_loc = format.find("nn"); + size_t str_loc = format.find("a16"); val_char_1 = replacer; sprintf_s(val_char_1, 5, "%02X", PeekMemory(addr[0] & 0xFFFF)); @@ -2748,25 +2763,60 @@ namespace GBHawk string val2(val_char_2, 2); addr[0]++; - format.erase(str_loc, 2); + format.erase(str_loc, 3); format.insert(str_loc, val1); format.insert(str_loc, val2); } - - if (format.find("n") != string::npos) + + if (format.find("d16") != string::npos) { - size_t str_loc = format.find("n"); + size_t str_loc = format.find("d16"); val_char_1 = replacer; sprintf_s(val_char_1, 5, "%02X", PeekMemory(addr[0] & 0xFFFF)); string val1(val_char_1, 2); addr[0]++; - format.erase(str_loc, 1); + val_char_2 = replacer; + sprintf_s(val_char_2, 5, "%02X", PeekMemory(addr[0] & 0xFFFF)); + string val2(val_char_2, 2); + addr[0]++; + + format.erase(str_loc, 3); + format.insert(str_loc, val1); + format.insert(str_loc, val2); + } + + if (format.find("d8") != string::npos) + { + size_t str_loc = format.find("d8"); + + val_char_1 = replacer; + sprintf_s(val_char_1, 5, "%02X", PeekMemory(addr[0] & 0xFFFF)); + string val1(val_char_1, 2); + addr[0]++; + + format.erase(str_loc, 2); format.insert(str_loc, val1); } - if (format.find("+d") != string::npos) + if (format.find("a8") != string::npos) + { + size_t str_loc = format.find("a8"); + + val_char_2 = replacer; + sprintf_s(val_char_1, 5, "%02X", PeekMemory(addr[0] & 0xFFFF)); + string val1(val_char_1, 2); + addr[0]++; + + string val2 = "FF"; + + format.erase(str_loc, 2); + format.insert(str_loc, val1); + format.insert(str_loc, val2); + } + + if (format.find("r8") != string::npos) { size_t str_loc = format.find("+d"); @@ -2778,18 +2828,6 @@ namespace GBHawk format.erase(str_loc, 2); format.insert(str_loc, val1); } - if (format.find("d") != string::npos) - { - size_t str_loc = format.find("d"); - - val_char_1 = replacer; - sprintf_s(val_char_1, 5, "%+04d", (int8_t)PeekMemory(addr[0] & 0xFFFF)); - string val1(val_char_1, 4); - addr[0]++; - - format.erase(str_loc, 1); - format.insert(str_loc, val1); - } return format; } diff --git a/libHawk/GBHawk/GBHawk/Memory.h b/libHawk/GBHawk/GBHawk/Memory.h index d58e97d60c..a44c38d09a 100644 --- a/libHawk/GBHawk/GBHawk/Memory.h +++ b/libHawk/GBHawk/GBHawk/Memory.h @@ -56,6 +56,7 @@ namespace GBHawk bool GBC_compat; bool speed_switch, double_speed; bool in_vblank; + bool in_vblank_old; bool GB_bios_register; bool HDMA_transfer; bool _islag; diff --git a/libHawk/GBHawk/GBHawk/PPU.h b/libHawk/GBHawk/GBHawk/PPU.h index fdac6838fa..ce6b117a10 100644 --- a/libHawk/GBHawk/GBHawk/PPU.h +++ b/libHawk/GBHawk/GBHawk/PPU.h @@ -19,6 +19,8 @@ namespace GBHawk } + void (*scanlineCallback)(void); + uint8_t ReadMemory(uint32_t); MemoryManager* mem_ctrl; @@ -725,11 +727,10 @@ namespace GBHawk // scanline callback if ((LY + LY_inc) == _scanlineCallbackLine[0]) { - //if (Core._scanlineCallback != null) - //{ - //Core.GetGPU(); - //Core._scanlineCallback(LCDC); - //} + if (scanlineCallback) + { + scanlineCallback(); + } } cycle = 0; @@ -2146,11 +2147,10 @@ namespace GBHawk // scanline callback if ((LY + LY_inc) == _scanlineCallbackLine[0]) { - //if (Core._scanlineCallback != null) - //{ - // Core.GetGPU(); - // Core._scanlineCallback(LCDC); - //} + if (scanlineCallback) + { + scanlineCallback(); + } } cycle = 0; @@ -3707,11 +3707,10 @@ namespace GBHawk // scanline callback if ((LY + LY_inc) == _scanlineCallbackLine[0]) { - //if (Core._scanlineCallback != null) - //{ - // Core.GetGPU(); - // Core._scanlineCallback(LCDC); - //} + if (scanlineCallback) + { + scanlineCallback(); + } } cycle = 0;