From 2a67ad625f7727973a193075cfc1634621918339 Mon Sep 17 00:00:00 2001 From: Asnivor Date: Thu, 25 Nov 2021 20:39:03 +0000 Subject: [PATCH] ChannelFHawk: Cart 2102 SRAM Implementation --- Assets/gamedb/gamedb_channelf.txt | 6 +- .../Fairchild/ChannelF/Cart/VesCartBase.cs | 133 +++++++++++++++++- .../Fairchild/ChannelF/Cart/mapper_HANG.cs | 75 ++++++++-- .../Fairchild/ChannelF/Cart/mapper_MAZE.cs | 106 ++++++++++++++ .../Fairchild/ChannelF/Cart/mapper_SCHACH.cs | 68 +++++++++ .../Fairchild/ChannelF/Cart/mapper_STD.cs | 6 - .../Consoles/Fairchild/ChannelF/ChannelF.cs | 1 + 7 files changed, 372 insertions(+), 23 deletions(-) create mode 100644 src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart/mapper_MAZE.cs create mode 100644 src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart/mapper_SCHACH.cs diff --git a/Assets/gamedb/gamedb_channelf.txt b/Assets/gamedb/gamedb_channelf.txt index 18cdc344ac..e8d7681bd9 100644 --- a/Assets/gamedb/gamedb_channelf.txt +++ b/Assets/gamedb/gamedb_channelf.txt @@ -56,8 +56,8 @@ F80AF74B09D058B90E719BB7DFBDD50E Drag Race (USA) ChannelF USA 4C10FA5C7316C59EFA241043FC67DFA8 Magic Numbers - Mind Reader + Nim (USA) ChannelF USA A8E6103FCAE4D0F9E14D9EDCFC3FC493 Math Quiz I - Addition + Subtraction (USA) ChannelF USA 86B77EAFDF7B806E19E01724987E384F Math Quiz II - Multiplication + Division (USA) ChannelF USA -6565DF74539476D66FD78DE1BAC0259C Maze, Jailbreak, Blind-man's-bluff, Trailblazer (USA) ChannelF USA -53E4CC2DA0F2C167E0692B794CB7692C Maze, Jailbreak, Blind-man's-bluff, Trailblazer (USA) (Alt 1) ChannelF USA +6565DF74539476D66FD78DE1BAC0259C Maze, Jailbreak, Blind-man's-bluff, Trailblazer (USA) ChannelF board=MAZE USA +53E4CC2DA0F2C167E0692B794CB7692C Maze, Jailbreak, Blind-man's-bluff, Trailblazer (USA) (Alt 1) ChannelF board=MAZE USA 2B3CA549E27579E4519A765FD8F52D0F Memory Match 1 & 2 (USA) ChannelF USA 1FBD86DCCA0E4619963B902C48AE77F2 Muehle, Tontauben-Schiessen, Kreatives Malspiel, Videoscope (Germany) ChannelF Germany C2A44D22D3865B036479E9311C74D3AD Ordtaevling (Sweden) ChannelF Sweden @@ -66,7 +66,7 @@ E90339B7068C6227D54F3C0CA637E017 Pinball Challenge (USA) ChannelF USA 9A894D745356A050F95410983C3BC54A Pro Football (USA) ChannelF USA 913ECBAA30816C6D78DE8651251761FC Rat' Mal (Germany) ChannelF Germany 3783B6AC359E21B99CFA17773AA811C6 Robot War, Torpedo Alley (USA) ChannelF USA -5568205F926333914DEDC8EF8BF16AF2 Schach (Germany) ChannelF Germany +5568205F926333914DEDC8EF8BF16AF2 Schach (Germany) ChannelF board=SCHACH Germany 442E362A39018F2D117F43FE013D1D8B Scrolling Mountains (200x)(Curtdawg) ChannelF DFB66EE145FAB65062FDEADAFC8DC34C Slot Machine (USA) ChannelF USA 4CB12EDAE37DF23851884B82CA410754 Sonar Search (USA) ChannelF USA diff --git a/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart/VesCartBase.cs b/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart/VesCartBase.cs index d5b9f12aaf..6cf2183516 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart/VesCartBase.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart/VesCartBase.cs @@ -1,12 +1,13 @@ using BizHawk.Common; +using BizHawk.Common.NumberExtensions; using BizHawk.Emulation.Common; +using System.Collections; namespace BizHawk.Emulation.Cores.Consoles.ChannelF { public abstract class VesCartBase { - public abstract string BoardType { get; } - public abstract void SyncState(Serializer ser); + public abstract string BoardType { get; } public virtual void SyncByteArrayDomain(ChannelF sys) { @@ -27,6 +28,15 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF } protected byte[] _ram; + // SRAM config + // taken from https://github.com/mamedev/mame/blob/ee1e4f9683a4953cb9d88f9256017fcbc38e3144/src/devices/bus/chanf/rom.cpp + // (license:BSD-3-Clause - copyright-holders:Fabio Priuli) + protected byte[] m_latch = new byte[2]; + protected ushort m_addr_latch; + protected int m_addr; + protected int m_read_write; + protected int m_data0; + public abstract byte ReadBus(ushort addr); public abstract void WriteBus(ushort addr, byte value); public abstract byte ReadPort(ushort addr); @@ -40,16 +50,131 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF switch (boardStr) { // standard cart layout - default to this - case "STD": - default: + case "STD": // any number of F3851 Program Storage Units (1KB ROM each) or F3856 Program Storage Unit (2KB ROM) // no on-pcb RAM and no extra IO return new mapper_STD(rom); + case "MAZE": + return new mapper_MAZE(rom); + + case "SCHACH": + default: + // F3853 Memory Interface Chip, 6KB of ROM and 2KB of RAM + return new mapper_SCHACH(rom); + case "HANG": return new mapper_HANG(rom); } } + + /// + /// Write method for carts that have an IO-accessible 2102 SRAM chip + /// Taken from: https://github.com/mamedev/mame/blob/ee1e4f9683a4953cb9d88f9256017fcbc38e3144/src/devices/bus/chanf/rom.cpp + /// license:BSD-3-Clause + /// copyright-holders:Fabio Priuli + /// + public void SRAM2102_Write(int index, byte data) + { + switch (index) + { + case 0: + m_latch[0] = data; + + m_read_write = data.Bit(0) ? 1 : 0;// BIT(data, 0); + + //m_addr_latch = (m_addr_latch & 0x3f3) | (BIT(data, 2) << 2) | (BIT(data, 1) << 3); // bits 2,3 come from this write! + m_addr_latch = (ushort)((m_addr_latch & 0x3f3) | (data.Bit(2) ? 1 : 0 << 2) | (data.Bit(1) ? 1 : 0 << 3)); // bits 2,3 come from this write! + + m_addr = m_addr_latch; + + m_data0 = data.Bit(3) ? 1 : 0; // BIT(data, 3); + + if (m_read_write == 1) + RAM[m_addr] = (byte)m_data0; + break; + + case 1: + m_latch[1] = data; + // all bits but 2,3 come from this write, but they are shuffled + // notice that data is 8bits, so when swapping bit8 & bit9 are always 0! + //m_addr_latch = (m_addr_latch & 0x0c) | (bitswap < 16 > ((uint16_t)data, 15, 14, 13, 12, 11, 10, 7, 6, 5, 3, 2, 1, 9, 8, 4, 0)); + + if (m_addr_latch > 0) + { + BitArray b = new BitArray(m_addr_latch); + b[9] = m_addr_latch.Bit(7); + b[8] = m_addr_latch.Bit(6); + b[7] = m_addr_latch.Bit(5); + b[6] = m_addr_latch.Bit(3); + b[5] = m_addr_latch.Bit(2); + b[4] = m_addr_latch.Bit(1); + b[3] = m_addr_latch.Bit(3); + b[2] = m_addr_latch.Bit(2); + b[1] = m_addr_latch.Bit(4); + b[0] = m_addr_latch.Bit(0); + var resBytes = new byte[1]; + b.CopyTo(resBytes, 0); + m_addr_latch = resBytes[0]; + } + + break; + + default: + + break; + } + } + + /// + /// Read method for carts that have an IO-accessible 2102 SRAM chip + /// Taken from: https://github.com/mamedev/mame/blob/ee1e4f9683a4953cb9d88f9256017fcbc38e3144/src/devices/bus/chanf/rom.cpp + /// license:BSD-3-Clause + /// copyright-holders:Fabio Priuli + /// + public byte SRAM2102_Read(int index) + { + switch (index) + { + case 0: + if (m_read_write == 0) + { + m_addr = m_addr_latch; + m_data0 = RAM[m_addr] & 1; + return (byte)((m_latch[0] & 0x7f) | (m_data0 << 7)); + } + + return m_latch[0]; + + case 1: + return m_latch[1]; + + default: + return 0xFF; + } + } + + public void Reset() + { + m_latch[0] = 0; + m_latch[1] = 0; + m_addr = 0; + m_addr_latch = 0; + m_read_write = 0; + m_data0 = 0; + } + + public virtual void SyncState(Serializer ser) + { + ser.BeginSection("Cart"); + ser.Sync(nameof(RAM), ref _ram, false); + ser.Sync(nameof(m_latch), ref m_latch, false); + ser.Sync(nameof(m_addr_latch), ref m_addr_latch); + ser.Sync(nameof(m_addr), ref m_addr); + ser.Sync(nameof(m_read_write), ref m_read_write); + ser.Sync(nameof(m_data0), ref m_data0); + ser.EndSection(); + } } } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart/mapper_HANG.cs b/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart/mapper_HANG.cs index 710d55b1ab..3b472e1cda 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart/mapper_HANG.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart/mapper_HANG.cs @@ -1,6 +1,8 @@  using BizHawk.Common; +using BizHawk.Common.NumberExtensions; using System; +using System.Collections; namespace BizHawk.Emulation.Cores.Consoles.ChannelF { @@ -10,7 +12,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF /// public class mapper_HANG : VesCartBase { - public override string BoardType => "STD"; + public override string BoardType => "HANG"; public mapper_HANG(byte[] rom) { @@ -24,7 +26,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF } } - RAM = new byte[0]; + RAM = new byte[0x400]; } public override byte ReadBus(ushort addr) @@ -40,18 +42,71 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF public override byte ReadPort(ushort addr) { - return 0xFF; + var result = 0xFF; + + switch (addr) + { + case 0x24: + if (m_read_write == 0) + { + m_addr = m_addr_latch; + m_data0 = RAM[m_addr] & 1; + return (byte)((m_latch[0] & 0x7f) | (m_data0 << 7)); + } + + return m_latch[0]; + + case 0x25: + return m_latch[1]; + } + + return (byte)result; } public override void WritePort(ushort addr, byte data) { - // no writeable hardware - } + switch (addr) + { + case 20: + m_latch[0] = data; - public override void SyncState(Serializer ser) - { - ser.BeginSection("Cart"); - ser.EndSection(); + m_read_write = data.Bit(0) ? 1 : 0;// BIT(data, 0); + + //m_addr_latch = (m_addr_latch & 0x3f3) | (BIT(data, 2) a<< 2) | (BIT(data, 1) << 3); // bits 2,3 come from this write! + m_addr_latch = (ushort)((m_addr_latch & 0x3f3) | (data.Bit(2) ? 1 : 0 << 2) | (data.Bit(1) ? 1 : 0 << 3)); // bits 2,3 come from this write! + + m_addr = m_addr_latch; + + m_data0 = data.Bit(3) ? 1 : 0; // BIT(data, 3); + + if (m_read_write == 1) + RAM[m_addr] = (byte)m_data0; + break; + + case 21: + m_latch[1] = data; + // all bits but 2,3 come from this write, but they are shuffled + // notice that data is 8bits, so when swapping bit8 & bit9 are always 0! + //m_addr_latch = (m_addr_latch & 0x0c) | (bitswap < 16 > ((uint16_t)data, 15, 14, 13, 12, 11, 10, 7, 6, 5, 3, 2, 1, 9, 8, 4, 0)); + + BitArray b = new BitArray(m_addr_latch); + b[9] = m_addr_latch.Bit(7); + b[8] = m_addr_latch.Bit(6); + b[7] = m_addr_latch.Bit(5); + b[6] = m_addr_latch.Bit(3); + b[5] = m_addr_latch.Bit(2); + b[4] = m_addr_latch.Bit(1); + b[3] = m_addr_latch.Bit(3); + b[2] = m_addr_latch.Bit(2); + b[1] = m_addr_latch.Bit(4); + b[0] = m_addr_latch.Bit(0); + var resBytes = new byte[1]; + b.CopyTo(resBytes, 0); + m_addr_latch = resBytes[0]; + + break; + + } + } } - } } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart/mapper_MAZE.cs b/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart/mapper_MAZE.cs new file mode 100644 index 0000000000..624c4d40af --- /dev/null +++ b/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart/mapper_MAZE.cs @@ -0,0 +1,106 @@ + +using BizHawk.Common; +using BizHawk.Common.NumberExtensions; +using System; +using System.Collections; + +namespace BizHawk.Emulation.Cores.Consoles.ChannelF +{ + /// + /// ChannelF Cartridge that utilises 2102 SRAM over IO + /// + public class mapper_MAZE : VesCartBase + { + public override string BoardType => "MAZE"; + + public mapper_MAZE(byte[] rom) + { + ROM = new byte[0xFFFF - 0x800]; + for (int i = 0; i < rom.Length; i++) + { + ROM[i] = rom[i]; + } + + RAM = new byte[400]; + } + + public override byte ReadBus(ushort addr) + { + var off = addr - 0x800; + return ROM[off]; + } + + public override void WriteBus(ushort addr, byte value) + { + // no directly writeable memory + } + + public override byte ReadPort(ushort addr) + { + var result = 0xFF; + + switch (addr) + { + case 0x24: + if (m_read_write == 0) + { + m_addr = m_addr_latch; + m_data0 = RAM[m_addr] & 1; + return (byte)((m_latch[0] & 0x7f) | (m_data0 << 7)); + } + + return m_latch[0]; + + case 0x25: + return m_latch[1]; + } + + return (byte)result; + } + + public override void WritePort(ushort addr, byte data) + { + switch (addr) + { + case 24: + m_latch[0] = data; + + m_read_write = data.Bit(0) ? 1 : 0;// BIT(data, 0); + + //m_addr_latch = (m_addr_latch & 0x3f3) | (BIT(data, 2) << 2) | (BIT(data, 1) << 3); // bits 2,3 come from this write! + m_addr_latch = (ushort)((m_addr_latch & 0x3f3) | (data.Bit(2) ? 1 : 0 << 2) | (data.Bit(1) ? 1 : 0 << 3)); // bits 2,3 come from this write! + + m_addr = m_addr_latch; + + m_data0 = data.Bit(3) ? 1 : 0; // BIT(data, 3); + + if (m_read_write == 1) + RAM[m_addr] = (byte)m_data0; + break; + + case 25: + m_latch[1] = data; + // all bits but 2,3 come from this write, but they are shuffled + // notice that data is 8bits, so when swapping bit8 & bit9 are always 0! + //m_addr_latch = (m_addr_latch & 0x0c) | (bitswap < 16 > ((uint16_t)data, 15, 14, 13, 12, 11, 10, 7, 6, 5, 3, 2, 1, 9, 8, 4, 0)); + + BitArray b = new BitArray(m_addr_latch); + b[9] = m_addr_latch.Bit(7); + b[8] = m_addr_latch.Bit(6); + b[7] = m_addr_latch.Bit(5); + b[6] = m_addr_latch.Bit(3); + b[5] = m_addr_latch.Bit(2); + b[4] = m_addr_latch.Bit(1); + b[3] = m_addr_latch.Bit(3); + b[2] = m_addr_latch.Bit(2); + b[1] = m_addr_latch.Bit(4); + b[0] = m_addr_latch.Bit(0); + var resBytes = new byte[1]; + b.CopyTo(resBytes, 0); + m_addr_latch = resBytes[0]; + + break; + } + } + } +} diff --git a/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart/mapper_SCHACH.cs b/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart/mapper_SCHACH.cs new file mode 100644 index 0000000000..afcc274300 --- /dev/null +++ b/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart/mapper_SCHACH.cs @@ -0,0 +1,68 @@ + +using BizHawk.Common; +using System; + +namespace BizHawk.Emulation.Cores.Consoles.ChannelF +{ + /// + /// Saba Schach Mapper + /// 6KB ROM / 2KB RAM + /// Info here: http://www.seanriddle.com/chanfmulti.html + /// + public class mapper_SCHACH : VesCartBase + { + public override string BoardType => "MAZE"; + + public mapper_SCHACH(byte[] rom) + { + ROM = new byte[0xFFFF - 0x800]; + for (int i = 0; i < rom.Length; i++) + { + ROM[i] = rom[i]; + } + + RAM = new byte[0x800 * 3]; + } + + public override byte ReadBus(ushort addr) + { + var result = 0x00; + var off = addr - 0x800; + + if (addr >= 0x2000 && addr < 0x3000) + { + // 2KB RAM + result = RAM[addr - 0x2000]; + } + else + { + result = ROM[off]; + } + + return (byte)result; + } + + public override void WriteBus(ushort addr, byte value) + { + // 2KB writeable memory at 0x2800; + if (addr >= 0x2000 && addr < 0x3000) + { + RAM[addr - 0x2000] = value; + } + else + { + + } + } + + public override byte ReadPort(ushort addr) + { + return 0xFF; + } + + public override void WritePort(ushort addr, byte data) + { + // no writeable hardware + } + } +} diff --git a/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart/mapper_STD.cs b/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart/mapper_STD.cs index 04c8dfd7f5..37be4481e4 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart/mapper_STD.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart/mapper_STD.cs @@ -43,11 +43,5 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF { // no writeable hardware } - - public override void SyncState(Serializer ser) - { - ser.BeginSection("Cart"); - ser.EndSection(); - } } } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.cs b/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.cs index 322be5c37f..22cf9135fd 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.cs @@ -29,6 +29,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF var bios01 = CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("ChannelF", "ChannelF_sl131253")); var bios02 = CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("ChannelF", "ChannelF_sl131254")); + //var bios02 = CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("ChannelF", "ChannelF_sl90025")); Cartridge = VesCartBase.Configure(_gameInfo.First(), _files.First());