From 78454ea636c448860242043250f074515bba0f7c Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Tue, 25 Feb 2020 13:53:28 -0500 Subject: [PATCH] GBHawk: Start 4x adapter --- .../GBHawkLink4x/GBHawkLink4x.IEmulator.cs | 276 +++++++++++------- .../GBHawkLink4x/GBHawkLink4x.ISettable.cs | 8 +- .../GBHawkLink4x/GBHawkLink4x.IStatable.cs | 11 + .../Nintendo/GBHawkLink4x/GBHawkLink4x.cs | 11 + 4 files changed, 200 insertions(+), 106 deletions(-) diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IEmulator.cs index 44b41eba28..76a90dfa79 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IEmulator.cs @@ -127,6 +127,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x else if (controller.IsPressed("Toggle Cable 4x")) { _cableconnected_4x = true; + is_pinging = false; + is_transmitting = false; } Console.WriteLine("Cable connect status:"); @@ -176,121 +178,191 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x C.do_single_step(); D.do_single_step(); - /* - // the signal to shift out a bit is when serial_clock = 1 - if (((A.serialport.serial_clock == 1) || (A.serialport.serial_clock == 2)) && (A.serialport.clk_rate > 0) && !do_2_next) + if (is_transmitting) { - A.serialport.going_out = (byte)(A.serialport.serial_data >> 7); - if ((C.serialport.clk_rate == -1) && C.serialport.serial_start && A.serialport.can_pulse) - { - C.serialport.serial_clock = A.serialport.serial_clock; - C.serialport.going_out = (byte)(C.serialport.serial_data >> 7); - C.serialport.coming_in = A.serialport.going_out; - } - - A.serialport.coming_in = C.serialport.going_out; - A.serialport.can_pulse = false; } - else if (((C.serialport.serial_clock == 1) || (C.serialport.serial_clock == 2)) && (C.serialport.clk_rate > 0)) + else if (is_pinging) { - do_2_next = false; + x4_clock--; + if (x4_clock == 0) + { + if (ping_byte == 0) + { + // first byte sent is 0xFE + if (ping_player == 1) + { + if ((A.serialport.clk_rate == -1) && A.serialport.serial_start) + { + A.serialport.serial_clock = 1; + A.serialport.going_out = (byte)(A.serialport.serial_data >> 7); + A.serialport.coming_in = (byte)(0xFE >> (7 - ping_bit_count)); + } - C.serialport.going_out = (byte)(C.serialport.serial_data >> 7); + received_byte |= (byte)(A.serialport.going_out << (7 - ping_bit_count)); + } + else if (ping_player == 2) + { + if ((B.serialport.clk_rate == -1) && B.serialport.serial_start) + { + B.serialport.serial_clock = 1; + B.serialport.going_out = (byte)(B.serialport.serial_data >> 7); + B.serialport.coming_in = (byte)(0xFE >> (7 - ping_bit_count)); + } - if ((A.serialport.clk_rate == -1) && A.serialport.serial_start && C.serialport.can_pulse) - { - A.serialport.serial_clock = C.serialport.serial_clock; - A.serialport.going_out = (byte)(A.serialport.serial_data >> 7); - A.serialport.coming_in = C.serialport.going_out; + received_byte |= (byte)(B.serialport.going_out << (7 - ping_bit_count)); + } + else if (ping_player == 3) + { + if ((C.serialport.clk_rate == -1) && C.serialport.serial_start) + { + C.serialport.serial_clock = 1; + C.serialport.going_out = (byte)(C.serialport.serial_data >> 7); + C.serialport.coming_in = (byte)(0xFE >> (7 - ping_bit_count)); + } + + received_byte |= (byte)(C.serialport.going_out << (7 - ping_bit_count)); + } + else + { + if ((D.serialport.clk_rate == -1) && D.serialport.serial_start) + { + D.serialport.serial_clock = 1; + D.serialport.going_out = (byte)(D.serialport.serial_data >> 7); + D.serialport.coming_in = (byte)(0xFE >> (7 - ping_bit_count)); + } + + received_byte |= (byte)(D.serialport.going_out << (7 - ping_bit_count)); + } + + ping_bit_count++; + + if (ping_bit_count == 8) + { + // player one can start the transmission phase + if ((received_byte == 0xAA) && (ping_player == 1)) + { + begin_transmitting_cnt = 1; + } + + ping_bit_count = 0; + received_byte = 0; + + ping_byte++; + } + } + else + { + // the next 3 bytes are the status byte (which may be updated in between each transfer) + if (ping_player == 1) + { + if ((A.serialport.clk_rate == -1) && A.serialport.serial_start) + { + A.serialport.serial_clock = 1; + A.serialport.going_out = (byte)(A.serialport.serial_data >> 7); + A.serialport.coming_in = (byte)(status_byte >> (7 - ping_bit_count)); + } + + received_byte |= (byte)(A.serialport.going_out << (7 - ping_bit_count)); + } + else if (ping_player == 2) + { + if ((B.serialport.clk_rate == -1) && B.serialport.serial_start) + { + B.serialport.serial_clock = 1; + B.serialport.going_out = (byte)(B.serialport.serial_data >> 7); + B.serialport.coming_in = (byte)(status_byte >> (7 - ping_bit_count)); + } + + received_byte |= (byte)(B.serialport.going_out << (7 - ping_bit_count)); + } + else if (ping_player == 3) + { + if ((C.serialport.clk_rate == -1) && C.serialport.serial_start) + { + C.serialport.serial_clock = 1; + C.serialport.going_out = (byte)(C.serialport.serial_data >> 7); + C.serialport.coming_in = (byte)(status_byte >> (7 - ping_bit_count)); + } + + received_byte |= (byte)(C.serialport.going_out << (7 - ping_bit_count)); + } + else + { + if ((D.serialport.clk_rate == -1) && D.serialport.serial_start) + { + D.serialport.serial_clock = 1; + D.serialport.going_out = (byte)(D.serialport.serial_data >> 7); + D.serialport.coming_in = (byte)(status_byte >> (7 - ping_bit_count)); + } + + received_byte |= (byte)(D.serialport.going_out << (7 - ping_bit_count)); + } + + ping_bit_count++; + + if (ping_bit_count == 8) + { + // player one can start the transmission phase + if (((received_byte & 0xAA) == 0xAA) && (ping_player == 1)) + { + begin_transmitting_cnt = 1; + + if (begin_transmitting_cnt == 3) + { + is_transmitting = true; + is_pinging = false; + Console.WriteLine("transmitting"); + } + } + else if (((received_byte & 0x88) == 0x88) && (ping_byte >= 2)) + { + status_byte |= (byte)(1 << (3 + ping_player)); + + + } + + //Console.WriteLine(ping_player + " " + ping_byte + " " + status_byte + " " + received_byte); + + ping_bit_count = 0; + received_byte = 0; + + ping_byte++; + + if (ping_byte == 4) + { + ping_byte = 0; + ping_player++; + + if (ping_player == 5) { ping_player = 1; } + + begin_transmitting_cnt = 0; + + status_byte &= 0xF0; + status_byte |= (byte)ping_player; + } + } + } + + x4_clock = 1024; } - - C.serialport.coming_in = A.serialport.going_out; - C.serialport.can_pulse = false; - - if (C.serialport.serial_clock == 2) { do_2_next = true; } } else { - do_2_next = false; - } - - // the signal to shift out a bit is when serial_clock = 1 - if (((C.serialport.serial_clock == 1) || (C.serialport.serial_clock == 2)) && (C.serialport.clk_rate > 0) && !do_2_next) - { - C.serialport.going_out = (byte)(C.serialport.serial_data >> 7); - - if ((D.serialport.clk_rate == -1) && D.serialport.serial_start && C.serialport.can_pulse) + // initialize the device from master GB + if ((A.serialport.serial_control & 0x81) == 0x80) { - D.serialport.serial_clock = C.serialport.serial_clock; - D.serialport.going_out = (byte)(D.serialport.serial_data >> 7); - D.serialport.coming_in = C.serialport.going_out; + is_pinging = true; + x4_clock = 1024; + ping_player = 1; + ping_byte = 0; + ping_bit_count = 0; + received_byte = 0; + begin_transmitting_cnt = 0; + status_byte = 0x01; // sending to player 1 } - - C.serialport.coming_in = D.serialport.going_out; - C.serialport.can_pulse = false; } - else if (((D.serialport.serial_clock == 1) || (D.serialport.serial_clock == 2)) && (D.serialport.clk_rate > 0)) - { - do_2_next = false; - - D.serialport.going_out = (byte)(D.serialport.serial_data >> 7); - - if ((C.serialport.clk_rate == -1) && C.serialport.serial_start && D.serialport.can_pulse) - { - C.serialport.serial_clock = D.serialport.serial_clock; - C.serialport.going_out = (byte)(C.serialport.serial_data >> 7); - C.serialport.coming_in = D.serialport.going_out; - } - - D.serialport.coming_in = C.serialport.going_out; - D.serialport.can_pulse = false; - - if (D.serialport.serial_clock == 2) { do_2_next = true; } - } - else - { - do_2_next = false; - } - - // the signal to shift out a bit is when serial_clock = 1 - if (((D.serialport.serial_clock == 1) || (D.serialport.serial_clock == 2)) && (D.serialport.clk_rate > 0) && !do_2_next) - { - D.serialport.going_out = (byte)(D.serialport.serial_data >> 7); - - if ((A.serialport.clk_rate == -1) && A.serialport.serial_start && D.serialport.can_pulse) - { - A.serialport.serial_clock = D.serialport.serial_clock; - A.serialport.going_out = (byte)(A.serialport.serial_data >> 7); - A.serialport.coming_in = D.serialport.going_out; - } - - D.serialport.coming_in = A.serialport.going_out; - D.serialport.can_pulse = false; - } - else if (((A.serialport.serial_clock == 1) || (A.serialport.serial_clock == 2)) && (A.serialport.clk_rate > 0)) - { - do_2_next = false; - - A.serialport.going_out = (byte)(A.serialport.serial_data >> 7); - - if ((D.serialport.clk_rate == -1) && D.serialport.serial_start && A.serialport.can_pulse) - { - D.serialport.serial_clock = A.serialport.serial_clock; - D.serialport.going_out = (byte)(D.serialport.serial_data >> 7); - D.serialport.coming_in = A.serialport.going_out; - } - - A.serialport.coming_in = D.serialport.going_out; - A.serialport.can_pulse = false; - - if (A.serialport.serial_clock == 2) { do_2_next = true; } - } - else - { - do_2_next = false; - } - */ + // if we hit a frame boundary, update video if (A.vblank_rise) diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.ISettable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.ISettable.cs index af99fdab41..ea7bb4c9a4 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.ISettable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.ISettable.cs @@ -32,22 +32,22 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x public class GBLink4xSettings { - [DisplayName("Color Mode")] + [DisplayName("Color Mode A")] [Description("Pick Between Green scale and Grey scale colors")] [DefaultValue(GBHawk.GBHawk.GBSettings.PaletteType.BW)] public GBHawk.GBHawk.GBSettings.PaletteType Palette_A { get; set; } - [DisplayName("Color Mode")] + [DisplayName("Color Mode B")] [Description("Pick Between Green scale and Grey scale colors")] [DefaultValue(GBHawk.GBHawk.GBSettings.PaletteType.BW)] public GBHawk.GBHawk.GBSettings.PaletteType Palette_B { get; set; } - [DisplayName("Color Mode")] + [DisplayName("Color Mode C")] [Description("Pick Between Green scale and Grey scale colors")] [DefaultValue(GBHawk.GBHawk.GBSettings.PaletteType.BW)] public GBHawk.GBHawk.GBSettings.PaletteType Palette_C { get; set; } - [DisplayName("Color Mode")] + [DisplayName("Color Mode D")] [Description("Pick Between Green scale and Grey scale colors")] [DefaultValue(GBHawk.GBHawk.GBSettings.PaletteType.BW)] public GBHawk.GBHawk.GBSettings.PaletteType Palette_D { get; set; } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IStatable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IStatable.cs index a4537ea7a9..681efc78de 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IStatable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IStatable.cs @@ -55,6 +55,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x ser.Sync(nameof(B_controller), ref B_controller); ser.Sync(nameof(C_controller), ref C_controller); ser.Sync(nameof(D_controller), ref D_controller); + + ser.Sync(nameof(is_pinging), ref is_pinging); + ser.Sync(nameof(is_transmitting), ref is_transmitting); + ser.Sync(nameof(status_byte), ref status_byte); + ser.Sync(nameof(x4_clock), ref x4_clock); + ser.Sync(nameof(ping_player), ref ping_player); + ser.Sync(nameof(ping_byte), ref ping_byte); + ser.Sync(nameof(ping_bit_count), ref ping_bit_count); + ser.Sync(nameof(received_byte), ref received_byte); + ser.Sync(nameof(begin_transmitting_cnt), ref begin_transmitting_cnt); + _controllerDeck.SyncState(ser); if (ser.IsReader) diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.cs index 3e421eb570..50a5c58c38 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.cs @@ -25,6 +25,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x private bool do_2_next = false; + // 4 player adapter variables + public bool is_pinging, is_transmitting; + public byte status_byte; + public int x4_clock; + public int ping_player; + public int ping_byte; + public int ping_bit_count; + public byte received_byte; + public int begin_transmitting_cnt; + + public byte A_controller, B_controller, C_controller, D_controller; public bool do_frame_fill;