ChannelFHawk: More progress:

* IO now working properly
* Start of mapper implementation
* Additional gamedb entries
This commit is contained in:
Asnivor 2021-11-25 14:52:59 +00:00
parent f32961001e
commit 442e83239d
12 changed files with 260 additions and 126 deletions

View File

@ -1,15 +1,19 @@
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
;;; Type: NO-INTRO
;;; Type: NO-INTRO & TOSEC
;;; Source: Fairchild - Channel F - 20120223-000000
;;; FileGen: 2019-04-16 13:59:49 (UTC)
;;; FileGen: 2021-11-24 09:30:49 (UTC)
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
;;; Bad Dumps
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
C8D5CE90CB1C76C9589711B5029D3421 B Color Organ (19xx)(-)[b] ChannelF
3EF873268F8FC428DA225CADABB4703F B Democart (demo) (1977)(Fairchild)[b] ChannelF
;
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
;;; Hacks
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
02B4A4F523B972C63FEF21BF2E51AE58 Channel F Multi-Cart - Menu (2004)(Riddle, Sean) ChannelF
4B3657594CD1000D08704F4F0FB53C75 Channel F Multi-Cart - Menu (2004)(Riddle, Sean)[a] ChannelF
;
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
;;; Over Dumps
@ -20,21 +24,35 @@
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
;
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
;;; Home Brew
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
CC445080CAA95EA4A48CC013A04F9808 D Full Screen Picture Demo (200x)(e5frog)(PD) ChannelF
4B109AAF9C6896DF4EE4C5A37852DAB2 D Full Screen Picture Demo (200x)(e5frog)(PD)[a] ChannelF
73EEF0F56736E2D8153D6F489DD0BEAD D International Karate Demo (200x)(-)(PD) ChannelF
D337BE6E8F348FB329FBAF44D3C2FA17 D International Karate Demo Test 2 (200x)(-)(PD) ChannelF
A6607B7C30CC4A7695D3112B3271D4E8 D International Karate Demo Test 3 (200x)(-)(PD) ChannelF
7DD3F1040C774FE147FC1D825B353524 D International Karate Demo Test 5 (200x)(-)(PD) ChannelF
F680225A38C3C4A66E30DBCA8D351407 D Test Controls (200x)(e5frog)(PD) ChannelF
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
;;; Believed Good
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
F7BF7D55A7660FFA80D08AD1BA903FF7 Alien Invasion (USA) ChannelF USA
D89B48AE8C906488CAAC2B2AE1D63D88 Backgammon, Acey-Deucey (USA) ChannelF USA
4FA83F734C139963AA02BDBB7A52E500 Baseball (USA) ChannelF USA
25E231E7A464A32B4715BFB47AF89240 Bowling (USA) ChannelF USA
25E231E7A464A32B4715BFB47AF89240 Bowling (USA) ChannelF board=STD USA
BB7F7BBBE21F142591CDCAFA98D7F6E4 Casino Poker (USA) ChannelF USA
35D61D40EF7EC337CBA092AABAC74DBD Checkers (USA) ChannelF USA
94530113A22AE27AF6ED87B98D9AF62A Color Organ (19xx)(-) ChannelF
C44BE208013B82041D01D2BC1834060B Colortest Demo (200x)(Riddle, Sean) ChannelF
54CF17C48707467295749490D458EAFB Democart (demo) (1977)(Fairchild) ChannelF
F6916B665893AA8138CDE57C37E50ADA Democart 2 (demo) (197x)(Fairchild) ChannelF
54CF17C48707467295749490D458EAFB Demonstration Cartridge (USA) ChannelF USA
F6916B665893AA8138CDE57C37E50ADA Demonstration Cartridge 2 (USA) ChannelF USA
4F11F13CBCA685CB20E888F87B3B1586 Desert Fox, Shooting Gallery (USA) ChannelF USA
6FFEDAED3C5CD8BA74D98901849CC451 Dodge It (USA) ChannelF USA
F80AF74B09D058B90E719BB7DFBDD50E Drag Race (USA) ChannelF USA
9E0711B140E22729687DB1E1354980AB Galactic Space Wars, Lunar Lander (USA) ChannelF USA
0124CD0B61DF5502AABD59029CCB6D5A Hangman (USA) ChannelF USA
0124CD0B61DF5502AABD59029CCB6D5A Hangman (USA) ChannelF board=HANG 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
@ -49,6 +67,7 @@ E90339B7068C6227D54F3C0CA637E017 Pinball Challenge (USA) ChannelF USA
913ECBAA30816C6D78DE8651251761FC Rat' Mal (Germany) ChannelF Germany
3783B6AC359E21B99CFA17773AA811C6 Robot War, Torpedo Alley (USA) ChannelF USA
5568205F926333914DEDC8EF8BF16AF2 Schach (Germany) ChannelF Germany
442E362A39018F2D117F43FE013D1D8B Scrolling Mountains (200x)(Curtdawg) ChannelF
DFB66EE145FAB65062FDEADAFC8DC34C Slot Machine (USA) ChannelF USA
4CB12EDAE37DF23851884B82CA410754 Sonar Search (USA) ChannelF USA
32CCA8FF09041A39251D7AADE21EE22F Space War (USA) ChannelF USA
@ -56,3 +75,4 @@ DFB66EE145FAB65062FDEADAFC8DC34C Slot Machine (USA) ChannelF USA
7E5C26A6D1F9A90C68669A9800BA522D Tic-Tac-Toe, Shooting Gallery, Doodle, Quadra-Doodle (USA) ChannelF USA
B074C867F235FB69CED96C6916673B45 Video Blackjack (USA) ChannelF USA
90A9B3952568F91502A7088BFB0AE07E Video Whizball (USA) ChannelF USA
C3C7B3246E50117BD5CDDB2B53E6FBAE Werbetextcassette (198x)(Electronic-Partner)(DE) ChannelF DE

View File

@ -34,8 +34,9 @@ namespace BizHawk.Emulation.Cores.Components.FairchildF8
FlagO = false;
FlagC = false;
// data is complemented between I/O pins and accumulator.
Regs[dest] = (byte)(Regs[src] ^ 0xFF);
// data is complemented between I/O pins and accumulator (because PINs are active-low)
// however for ease we will make them active-high here
Regs[dest] = Regs[src];
FlagS = !Regs[dest].Bit(7);
FlagZ = (Regs[dest] & 0xFF) == 0;
@ -49,8 +50,9 @@ namespace BizHawk.Emulation.Cores.Components.FairchildF8
/// <param name="src"></param>
public void OUT_Func(byte dest, byte src)
{
// data is complemented between accumulator and I/O pins.
WriteHardware(Regs[dest], (byte)(Regs[src] ^ 0xFF));
// data is complemented between accumulator and I/O pins (because PINs are active-low)
// however for ease here we will make them active-high
WriteHardware(Regs[dest], Regs[src]);
}
public void ClearFlags_Func()

View File

@ -5,6 +5,6 @@
/// </summary>
public partial class ChannelF
{
public byte[] Rom = new byte[4096];
//public byte[] Rom = new byte[4096];
}
}

View File

@ -0,0 +1,55 @@
using BizHawk.Common;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.ChannelF
{
public abstract class VesCartBase
{
public abstract string BoardType { get; }
public abstract void SyncState(Serializer ser);
public virtual void SyncByteArrayDomain(ChannelF sys)
{
sys.SyncByteArrayDomain("ROM", _rom);
}
public virtual byte[] ROM
{
get { return _rom; }
protected set { _rom = value; }
}
protected byte[] _rom;
public virtual byte[] RAM
{
get { return _ram; }
protected set { _ram = value; }
}
protected byte[] _ram;
public abstract byte ReadBus(ushort addr);
public abstract void WriteBus(ushort addr, byte value);
public abstract byte ReadPort(ushort addr);
public abstract void WritePort(ushort addr, byte data);
public static VesCartBase Configure(GameInfo gi, byte[] rom)
{
// get board type
string boardStr = gi.OptionPresent("board") ? gi.GetStringValue("board") : "STD";
switch (boardStr)
{
// standard cart layout - default to this
case "STD":
default:
// 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 "HANG":
return new mapper_HANG(rom);
}
}
}
}

View File

@ -0,0 +1,57 @@

using BizHawk.Common;
using System;
namespace BizHawk.Emulation.Cores.Consoles.ChannelF
{
/// <summary>
/// Hangman ChannelF Cartridge
/// 2KB ROM / NO RAM
/// </summary>
public class mapper_HANG : VesCartBase
{
public override string BoardType => "STD";
public mapper_HANG(byte[] rom)
{
ROM = new byte[0xFFFF - 0x800];
for (int i = 0; i < rom.Length; i++)
{
ROM[i] = rom[i];
if (i > 3000)
{
var test = rom[i];
}
}
RAM = new byte[0];
}
public override byte ReadBus(ushort addr)
{
var off = addr - 0x800;
return ROM[off];
}
public override void WriteBus(ushort addr, byte value)
{
// no writeable memory
}
public override byte ReadPort(ushort addr)
{
return 0xFF;
}
public override void WritePort(ushort addr, byte data)
{
// no writeable hardware
}
public override void SyncState(Serializer ser)
{
ser.BeginSection("Cart");
ser.EndSection();
}
}
}

View File

@ -0,0 +1,53 @@

using BizHawk.Common;
using System;
namespace BizHawk.Emulation.Cores.Consoles.ChannelF
{
/// <summary>
/// Standard ChannelF Cartridge
/// 2KB ROM / NO RAM
/// </summary>
public class mapper_STD : VesCartBase
{
public override string BoardType => "STD";
public mapper_STD(byte[] rom)
{
ROM = new byte[0xFFFF - 0x800];
for (int i = 0; i < rom.Length; i++)
{
ROM[i] = rom[i];
}
RAM = new byte[0];
}
public override byte ReadBus(ushort addr)
{
var off = addr - 0x800;
return ROM[off];
}
public override void WriteBus(ushort addr, byte value)
{
// no writeable memory
}
public override byte ReadPort(ushort addr)
{
return 0xFF;
}
public override void WritePort(ushort addr, byte data)
{
// no writeable hardware
}
public override void SyncState(Serializer ser)
{
ser.BeginSection("Cart");
ser.EndSection();
}
}
}

View File

@ -13,6 +13,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
ser.Sync(nameof(latch_y), ref latch_y);
//ser.Sync(nameof(ControllersEnabled), ref ControllersEnabled);
CPU.SyncState(ser);
Cartridge.SyncState(ser);
ser.EndSection();
/*

View File

@ -64,7 +64,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
public int[] CroppedBuffer = new int[102 * 58];
public int VirtualWidth => BufferWidth * 4;
public int VirtualHeight => (int)((double)BufferHeight * 1) * 4;
public int VirtualHeight => (int)((double)BufferHeight * 1.15) * 4;
public int BufferWidth => 102; //128
public int BufferHeight => 58; //64
public int BackgroundColor => Colors.ARGB(0xFF, 0xFF, 0xFF);

View File

@ -47,11 +47,12 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
{
SyncByteArrayDomain("BIOS1", BIOS01);
SyncByteArrayDomain("BIOS2", BIOS02);
SyncByteArrayDomain("ROM", Rom);
Cartridge.SyncByteArrayDomain(this);
//SyncByteArrayDomain("ROM", Rom);
SyncByteArrayDomain("VRAM", VRAM);
}
private void SyncByteArrayDomain(string name, byte[] data)
public void SyncByteArrayDomain(string name, byte[] data)
{
if (_memoryDomainsInit || _byteArrayDomains.ContainsKey(name))
{

View File

@ -27,6 +27,14 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
ControllerDefinition = ChannelFControllerDefinition;
var bios01 = CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("ChannelF", "ChannelF_sl131253"));
var bios02 = CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("ChannelF", "ChannelF_sl131254"));
Cartridge = VesCartBase.Configure(_gameInfo.First(), _files.First());
BIOS01 = bios01;
BIOS02 = bios02;
CPU = new F3850
{
ReadMemory = ReadBus,
@ -36,17 +44,10 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
DummyReadMemory = ReadBus
};
_tracer = new TraceBuffer(CPU.TraceHeader);
_tracer = new TraceBuffer(CPU.TraceHeader);
var bios01 = CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("ChannelF", "ChannelF_sl131253"));
var bios02 = CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("ChannelF", "ChannelF_sl131254"));
BIOS01 = bios01;
BIOS02 = bios02;
var rom = _files.First();
Array.Copy(rom, 0, Rom, 0, rom.Length);
//var rom = _files.First();
//Array.Copy(rom, 0, Rom, 0, rom.Length);
CalcClock();
@ -66,5 +67,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
public F3850 CPU;
private readonly TraceBuffer _tracer;
public IController _controller;
public VesCartBase Cartridge;
}
}

View File

@ -17,26 +17,19 @@
{
if (addr < 0x400)
{
// Rom0
// BIOS ROM 1
return BIOS01[addr];
}
else if (addr < 0x800)
{
// Rom1
// BIOS ROM 2
return BIOS02[addr - 0x400];
}
else if (addr < 0x1800)
{
// Cart
//return 0;
return Rom[addr - 0x800];
}
else
{
// Cartridge Memory Space
return Cartridge.ReadBus(addr);
}
return 0xFF;
}
/// <summary>
@ -46,7 +39,11 @@
/// <param name="addr"></param>
public void WriteBus(ushort addr, byte value)
{
}
// Cartridge Memory Space
if (addr >= 0x800)
{
Cartridge.WriteBus(addr, value);
}
}
}
}

View File

@ -4,9 +4,9 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
{
/// <summary>
/// Ports and related functions
/// Based on the luxor schematic here:
/// https://web.archive.org/web/20210524083634/http://channelf.se/veswiki/images/3/35/Luxor_page2_300dpi.png
/// https://channelf.se/veswiki/images/2/23/Luxor_page3_300dpi.png
/// Based on the schematic here:
/// https://web.archive.org/web/20210524083636/http://channelf.se/veswiki/images/3/31/FVE100_schematic_sheet_1of3.gif
/// https://web.archive.org/web/20160313115333/http://channelf.se/veswiki/images/0/04/FVE_schematic_sheet_2_of_3.png
/// </summary>
public partial class ChannelF
{
@ -15,55 +15,34 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
/// CPU (3850) - ports 0 and 1
/// PSU (3851) - ports 4 and 5
/// (the second PSU has no IO ports wired up)
/// Depending on the attached cartridge, there may be additional hardware on the IO bus
/// All CPU and PSU I/O ports are active-low with output-latches
/// </summary>
public byte[] OutputLatch = new byte[4];
public byte[] OutputLatch = new byte[0xFF];
public bool LS368Disabled;
public const int PORT0 = 0;
public const int PORT1 = 1;
public const int PORT4 = 2;
public const int PORT5 = 3;
public bool LS368Enable;
/// <summary>
/// CPU is attempting to read from a port
/// </summary>
/// <param name="addr"></param>
/// <returns></returns>
public byte ReadPort(ushort addr)
{
byte result = 0xFF;
var result = 0xFF;
switch (addr)
{
default:
break;
case 0:
// Console Buttons - these are connected to pins 0-3 (bits 0-3) through a 7404 Hex Inverter
// b0: TIME
// b1: MODE
// b2: HOLD
// b3: START
// b3: START
// RESET button is connected directly to the RST pin on the CPU (this is handled here in the PollInput() method)
// get the 4 console buttons state
var cButtons = DataConsole & 0x0F;
// hex inverter
var cButtonsInverted = (byte)(DataConsole ^ 0xFF);
// AND latched output (pins 4 and 7 not connected)
result = (byte)((OutputLatch[PORT0] & 0x6F) | cButtonsInverted);
result = ~(DataConsole & 0x0F) | OutputLatch[addr];
break;
case 1:
// right controller (player 1)
// connected through 7404 Hex Inverter
// b0: RIGHT
// b1: LEFT
@ -71,26 +50,12 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
// b3: FORWARD
// b4: CCW
// b5: CW
var rButtons = DataRight & 0x3F;
// connected through LS368 Hex Interting 3-State Buffer
// the enable pin of this IC is driven by a CPU write to pin 6 on port 0
// b6: PULL
// b7: PUSH
var rButtons2 = LS368Disabled ? 0 : DataRight & 0xC0;
// hex inverters
var rbuttonsInverted = (byte)((rButtons | rButtons2) ^ 0xFF);
// AND latched output
result = (byte)(OutputLatch[PORT1] | rbuttonsInverted);
var v1 = LS368Enable ? DataRight : DataRight | 0xC0;
result = (~v1) | OutputLatch[addr];
break;
case 4:
// left controller (player 2)
// connected through LS368 Hex Interting 3-State Buffer
// the enable pin of this IC is driven by a CPU write to pin 6 on port 0
// b0: RIGHT
@ -101,25 +66,22 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
// b5: CW
// b6: PULL
// b7: PUSH
var lButtons = LS368Disabled ? 0 : DataLeft & 0xFF;
// hex inverter
var lButtonsInverted = (byte)(lButtons ^ 0xFF);
// AND latched output
result = (byte)(OutputLatch[PORT4] | lButtonsInverted);
var v2 = LS368Enable ? DataLeft : 0xFF;
result = (~v2) | OutputLatch[addr];
break;
case 5:
result = OutputLatch[addr];
break;
// output only IO port - return the last latched output
result = OutputLatch[PORT5];
default:
// possible cartridge hardware IO space
result = ~(Cartridge.ReadPort(addr)) | OutputLatch[addr];
break;
}
return result;
return (byte)result;
}
/// <summary>
@ -130,51 +92,30 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
switch (addr)
{
case 0:
OutputLatch[PORT0] = value;
// LS368 enable pin on bit 6
LS368Disabled = !value.Bit(6);
if (!value.Bit(5))
OutputLatch[addr] = value;
LS368Enable = !value.Bit(6);
if (value.Bit(5))
{
// WRT pulse
// pulse clocks the 74195 parallel access shift register which feeds inputs of 2 NAND gates
// writing data to both sets of even and odd VRAM chips (based on the row and column addresses latched into the 7493 ICs
VRAM[((latch_y) * 0x80) + latch_x] = (byte)latch_colour;
VRAM[((latch_y) * 0x80) + latch_x] = (byte)latch_colour;
}
break;
case 1:
// latch pixel colour
OutputLatch[PORT1] = value;
// write data 0 = bit6
// write data 1 = bit7
latch_colour = ((value) >> 6) & 0x03;
OutputLatch[addr] = value;
latch_colour = ((value ^ 0xFF) >> 6) & 0x03;
break;
case 4:
// latch horiztonal column address
OutputLatch[PORT4] = value;
// bit7 is not sent to the 7493s (IO47N)
latch_x = value & 0x7F;
OutputLatch[addr] = value;
latch_x = (value | 0x80) ^ 0xFF;
break;
case 5:
// latch vertical row address and sound bits
OutputLatch[PORT5] = value;
// ignore the sound bits
latch_y = value & 0x3F;
// bits 6 (ToneAN) and 7 (ToneBN) are sound generation
OutputLatch[addr] = value;
latch_y = (value | 0xC0) ^ 0xFF;
var audio = (value >> 6) & 0x03;
if (audio != tone)
{
@ -183,9 +124,13 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
amplitude = 1;
AudioChange();
}
break;
default:
// possible write to cartridge hardware
Cartridge.WritePort(addr, (byte)(value ^ 0xFF));
break;
}
}
}
}
}