ChannelFHawk: Cart 2102 SRAM Implementation

This commit is contained in:
Asnivor 2021-11-25 20:39:03 +00:00
parent ddf07ebe27
commit 2a67ad625f
7 changed files with 372 additions and 23 deletions

View File

@ -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

View File

@ -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);
}
}
/// <summary>
/// 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
/// </summary>
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;
}
}
/// <summary>
/// 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
/// </summary>
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();
}
}
}

View File

@ -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
/// </summary>
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;
}
}
}
}
}

View File

@ -0,0 +1,106 @@

using BizHawk.Common;
using BizHawk.Common.NumberExtensions;
using System;
using System.Collections;
namespace BizHawk.Emulation.Cores.Consoles.ChannelF
{
/// <summary>
/// ChannelF Cartridge that utilises 2102 SRAM over IO
/// </summary>
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;
}
}
}
}

View File

@ -0,0 +1,68 @@

using BizHawk.Common;
using System;
namespace BizHawk.Emulation.Cores.Consoles.ChannelF
{
/// <summary>
/// Saba Schach Mapper
/// 6KB ROM / 2KB RAM
/// Info here: http://www.seanriddle.com/chanfmulti.html
/// </summary>
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
}
}
}

View File

@ -43,11 +43,5 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
{
// no writeable hardware
}
public override void SyncState(Serializer ser)
{
ser.BeginSection("Cart");
ser.EndSection();
}
}
}

View File

@ -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());