diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.IEmulator.cs index 54f009a9b3..19c04a4312 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.IEmulator.cs @@ -10,6 +10,8 @@ namespace BizHawk.Emulation.Cores.Sega.GGHawkLink public ControllerDefinition ControllerDefinition => _controllerDeck.Definition; + public int L_NMI_CD, R_NMI_CD; + public bool FrameAdvance(IController controller, bool render, bool rendersound) { //Console.WriteLine("-----------------------FRAME-----------------------"); @@ -62,6 +64,33 @@ namespace BizHawk.Emulation.Cores.Sega.GGHawkLink L.FrameAdvancePrep(); R.FrameAdvancePrep(); + if (!_cableconnected) + { + if ((L.Port05 & 0x38) == 0x38) + { + L.Port05 |= 4; + L.Cpu.NonMaskableInterrupt = true; + } + + if ((R.Port05 & 0x38) == 0x38) + { + R.Port05 |= 4; + R.Cpu.NonMaskableInterrupt = true; + } + } + else + { + if ((L.Port05 & 0x38) == 0x38) + { + L.Port05 &= 0xFB; + } + + if ((R.Port05 & 0x38) == 0x38) + { + R.Port05 &= 0xFB; + } + } + int scanlinesPerFrame = 262; L.Vdp.ScanLine = 0; @@ -84,11 +113,92 @@ namespace BizHawk.Emulation.Cores.Sega.GGHawkLink L.Cpu.ExecuteOne(); R.Cpu.ExecuteOne(); - /* - * - * Linking code goes here - * - */ + // linking code + if (L.p3_write) + { + L.p3_write = false; + + if (((L.Port05 & 0x38) == 0x38) && _cableconnected) + { + L.Port05 |= 1; + + if ((R.Port05 & 0x38) == 0x38) + { + R.Port05 |= 2; + R.Port04 = L.Port03; + R_NMI_CD = 256; + //R.Cpu.NonMaskableInterrupt = true; + } + } + } + + if (L.p4_read) + { + L.p4_read = false; + L.Cpu.NonMaskableInterrupt = false; + + if (((L.Port05 & 0x38) == 0x38) && _cableconnected) + { + L.Port05 &= 0xFD; + + if ((R.Port05 & 0x38) == 0x38) + { + R.Port05 &= 0xFE; + } + } + } + + if (R.p3_write) + { + R.p3_write = false; + + if (((R.Port05 & 0x38) == 0x38) && _cableconnected) + { + R.Port05 |= 1; + + if ((L.Port05 & 0x38) == 0x38) + { + L.Port05 |= 2; + L.Port04 = R.Port03; + L_NMI_CD = 256; + //L.Cpu.NonMaskableInterrupt = true; + } + } + } + + if (R.p4_read) + { + R.p4_read = false; + R.Cpu.NonMaskableInterrupt = false; + + if (((R.Port05 & 0x38) == 0x38) && _cableconnected) + { + R.Port05 &= 0xFD; + + if ((L.Port05 & 0x38) == 0x38) + { + L.Port05 &= 0xFE; + } + } + } + + if (L_NMI_CD > 0) + { + L_NMI_CD--; + if (L_NMI_CD == 0) + { + L.Cpu.NonMaskableInterrupt = true; + } + } + + if (R_NMI_CD > 0) + { + R_NMI_CD--; + if (R_NMI_CD == 0) + { + R.Cpu.NonMaskableInterrupt = true; + } + } L.PSG.generate_sound(); R.PSG.generate_sound(); diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.IStatable.cs b/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.IStatable.cs index 5da5d644d7..920fa985f6 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.IStatable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.IStatable.cs @@ -59,6 +59,8 @@ namespace BizHawk.Emulation.Cores.Sega.GGHawkLink ser.Sync(nameof(_cableconnected), ref _cableconnected); ser.Sync(nameof(_cablediscosignal), ref _cablediscosignal); ser.Sync(nameof(do_r_next), ref do_r_next); + ser.Sync(nameof(L_NMI_CD), ref L_NMI_CD); + ser.Sync(nameof(L_NMI_CD), ref R_NMI_CD); _controllerDeck.SyncState(ser); } } diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IStatable.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IStatable.cs index ac07eeac62..1ba1712d05 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IStatable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IStatable.cs @@ -64,6 +64,8 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem ser.Sync(nameof(Bios_bank), ref Bios_bank); ser.Sync(nameof(Port01), ref Port01); ser.Sync(nameof(Port02), ref Port02); + ser.Sync(nameof(Port03), ref Port03); + ser.Sync(nameof(Port04), ref Port04); ser.Sync(nameof(Port05), ref Port05); ser.Sync(nameof(Port3E), ref Port3E); ser.Sync(nameof(Port3F), ref Port3F); @@ -74,6 +76,8 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem ser.Sync(nameof(cntr_rd_0), ref cntr_rd_0); ser.Sync(nameof(cntr_rd_1), ref cntr_rd_1); ser.Sync(nameof(cntr_rd_2), ref cntr_rd_2); + ser.Sync(nameof(p3_write), ref p3_write); + ser.Sync(nameof(p4_read), ref p4_read); ser.Sync(nameof(stand_alone), ref stand_alone); ser.Sync(nameof(disablePSG), ref disablePSG); ser.Sync(nameof(sampleclock), ref sampleclock); diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs index ba12a7c4c1..68d48916a4 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs @@ -245,8 +245,10 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem private int _frame = 0; private byte Port01 = 0xFF; - private byte Port02 = 0xFF; - private byte Port05 = 0x00; + public byte Port02 = 0xFF; + public byte Port03 = 0x00; + public byte Port04 = 0xFF; + public byte Port05 = 0x00; private byte Port3E = 0xAF; private byte Port3F = 0xFF; private byte PortDE = 0x00; @@ -260,6 +262,8 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem public byte cntr_rd_1; public byte cntr_rd_2; public bool stand_alone = true; + public bool p3_write; + public bool p4_read; public DisplayType Region { get; set; } @@ -345,8 +349,8 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem case 0x00: if (stand_alone) { return ReadPort0(); } else { _lagged = false; return cntr_rd_0; } case 0x01: return Port01; case 0x02: return Port02; - case 0x03: return 0x00; - case 0x04: return 0xFF; + case 0x03: return Port03; + case 0x04: p4_read = true; return Port04; case 0x05: return Port05; case 0x06: return 0xFF; case 0x3E: return Port3E; @@ -388,7 +392,9 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem { case 0x01: Port01 = value; break; case 0x02: Port02 = value; break; - case 0x05: Port05 = value; break; + case 0x03: p3_write = true; Port03 = value; break; + case 0x04: /*Port04 = value*/; break; // receive port, not sure what writing does + case 0x05: Port05 = (byte)(value & 0xF8); break; case 0x06: PSG.Set_Panning(value); break; case 0x3E: Port3E = value; break; case 0x3F: Port3F = value; break;