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;