ChannelF: Extreme WIP! I promise nothing...
This commit is contained in:
parent
6ea20e9e9b
commit
f0384b7e83
Assets/gamedb
BizHawk.Client.ApiHawk/Classes
BizHawk.Client.Common
BizHawk.Client.DBMan/DATTools
BizHawk.Client.EmuHawk/config
BizHawk.Emulation.Common
BizHawk.Emulation.Cores
BizHawk.Emulation.Cores.csproj
Consoles/Fairchild/ChannelF
|
@ -27,6 +27,7 @@
|
|||
#include gamedb_zxspectrum.txt
|
||||
#include gamedb_amstradcpc.txt
|
||||
#include gamedb_ngp.txt
|
||||
#include gamedb_channelf.txt
|
||||
|
||||
; ************ TI-83 ************
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
|
||||
;;; Type: NO-INTRO
|
||||
;;; Source: Fairchild - Channel F - 20120223-000000
|
||||
;;; FileGen: 2019-04-16 13:59:49 (UTC)
|
||||
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
|
||||
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
|
||||
;;; Bad Dumps
|
||||
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
|
||||
;
|
||||
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
|
||||
;;; Hacks
|
||||
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
|
||||
;
|
||||
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
|
||||
;;; Over Dumps
|
||||
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
|
||||
;
|
||||
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
|
||||
;;; Translated
|
||||
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
|
||||
;
|
||||
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
|
||||
;;; 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
|
||||
BB7F7BBBE21F142591CDCAFA98D7F6E4 Casino Poker (USA) ChannelF USA
|
||||
35D61D40EF7EC337CBA092AABAC74DBD Checkers (USA) ChannelF USA
|
||||
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
|
||||
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
|
||||
2B3CA549E27579E4519A765FD8F52D0F Memory Match 1 & 2 (USA) ChannelF USA
|
||||
1FBD86DCCA0E4619963B902C48AE77F2 Muehle, Tontauben-Schiessen, Kreatives Malspiel, Videoscope (Germany) ChannelF Germany
|
||||
C2A44D22D3865B036479E9311C74D3AD Ordtaevling (Sweden) ChannelF Sweden
|
||||
E90339B7068C6227D54F3C0CA637E017 Pinball Challenge (USA) ChannelF USA
|
||||
5CBCDA1C44F0DAD02B0DFE209B6325D5 Pinball Challenge (USA) (Alt 1) 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
|
||||
DFB66EE145FAB65062FDEADAFC8DC34C Slot Machine (USA) ChannelF USA
|
||||
4CB12EDAE37DF23851884B82CA410754 Sonar Search (USA) ChannelF USA
|
||||
32CCA8FF09041A39251D7AADE21EE22F Space War (USA) ChannelF USA
|
||||
1B409FE1154584F4D1AB76B344A73D99 Spitfire (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
|
|
@ -108,6 +108,9 @@ namespace BizHawk.Client.ApiHawk
|
|||
case "GGL":
|
||||
return CoreSystem.GGL;
|
||||
|
||||
case "ChannelF":
|
||||
return CoreSystem.ChannelF;
|
||||
|
||||
case "VB":
|
||||
case "NGP":
|
||||
case "DNGP":
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
NeoGeoPocket,
|
||||
ZXSpectrum,
|
||||
AmstradCPC,
|
||||
GGL
|
||||
GGL,
|
||||
ChannelF
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,6 +154,8 @@ namespace BizHawk.Client.Common
|
|||
return SystemInfo.ZXSpectrum;
|
||||
case "AmstradCPC":
|
||||
return SystemInfo.AmstradCPC;
|
||||
case "ChannelF":
|
||||
return SystemInfo.ChannelF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ using BizHawk.Emulation.Cores.Consoles.Sega.Saturn;
|
|||
using BizHawk.Emulation.Cores.Consoles.NEC.PCFX;
|
||||
using BizHawk.Emulation.Cores.Computers.AmstradCPC;
|
||||
using BizHawk.Emulation.Cores.Consoles.Vectrex;
|
||||
using BizHawk.Emulation.Cores.Consoles.ChannelF;
|
||||
|
||||
namespace BizHawk.Client.Common
|
||||
{
|
||||
|
@ -1079,6 +1080,9 @@ namespace BizHawk.Client.Common
|
|||
Deterministic);
|
||||
nextEmulator = zx;
|
||||
break;
|
||||
case "ChannelF":
|
||||
nextEmulator = new ChannelF(nextComm, game, rom.FileData, GetCoreSettings<ChannelF>(), GetCoreSyncSettings<ChannelF>());
|
||||
break;
|
||||
case "AmstradCPC":
|
||||
var cpc = new AmstradCPC(nextComm, Enumerable.Repeat(rom.RomData, 1), Enumerable.Repeat(rom.GameInfo, 1).ToList(), GetCoreSettings<AmstradCPC>(), GetCoreSyncSettings<AmstradCPC>());
|
||||
nextEmulator = cpc;
|
||||
|
|
|
@ -204,10 +204,15 @@ namespace BizHawk.Client.Common
|
|||
public static SystemInfo AmstradCPC { get; } = new SystemInfo("Amstrad CPC", CoreSystem.AmstradCPC, 2);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="SystemInfo"/> instance for AmstradCPC
|
||||
/// Gets the <see cref="SystemInfo"/> instance for GGL
|
||||
/// </summary>
|
||||
public static SystemInfo GGL { get; } = new SystemInfo("Game Gear Linked", CoreSystem.GGL, 2);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="SystemInfo"/> instance for ChannelF
|
||||
/// </summary>
|
||||
public static SystemInfo ChannelF { get; } = new SystemInfo("Channel F", CoreSystem.ChannelF, 2);
|
||||
|
||||
#endregion Get SystemInfo
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -382,6 +382,12 @@ namespace BizHawk.Client.Common
|
|||
new PathEntry { System = "PCFX", SystemDisplayName = "PCFX", Type = "Save RAM", Path = Path.Combine(".", "SaveRAM"), Ordinal = 3 },
|
||||
new PathEntry { System = "PCFX", SystemDisplayName = "PCFX", Type = "Screenshots", Path = Path.Combine(".", "Screenshots"), Ordinal = 4 },
|
||||
new PathEntry { System = "PCFX", SystemDisplayName = "PCFX", Type = "Cheats", Path = Path.Combine(".", "Cheats"), Ordinal = 5 },
|
||||
|
||||
new PathEntry { System = "ChannelF", SystemDisplayName = "Fairchild Channel F", Type = "Base", Path = Path.Combine(".", "ZXSpectrum"), Ordinal = 0 },
|
||||
new PathEntry { System = "ChannelF", SystemDisplayName = "Fairchild Channel F", Type = "ROM", Path = ".", Ordinal = 1 },
|
||||
new PathEntry { System = "ChannelF", SystemDisplayName = "Fairchild Channel F", Type = "Savestates", Path = Path.Combine(".", "State"), Ordinal = 2 },
|
||||
new PathEntry { System = "ChannelF", SystemDisplayName = "Fairchild Channel F", Type = "Screenshots", Path = Path.Combine(".", "Screenshots"), Ordinal = 4 },
|
||||
new PathEntry { System = "ChannelF", SystemDisplayName = "Fairchild Channel F", Type = "Cheats", Path = Path.Combine(".", "Cheats"), Ordinal = 5 },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -218,6 +218,7 @@ namespace BizHawk.Client.DBMan
|
|||
Lynx,
|
||||
VB,
|
||||
UZE,
|
||||
NGP
|
||||
NGP,
|
||||
ChannelF
|
||||
}
|
||||
}
|
||||
|
|
|
@ -176,7 +176,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
tt.TabPages[pageidx].Controls.Add(createpanel(settings, cat.Value, tt.Size));
|
||||
|
||||
// zxhawk hack - it uses multiple categoryLabels
|
||||
if (Global.Emulator.SystemId == "ZXSpectrum" || Global.Emulator.SystemId == "AmstradCPC")
|
||||
if (Global.Emulator.SystemId == "ZXSpectrum" || Global.Emulator.SystemId == "AmstradCPC" || Global.Emulator.SystemId == "ChannelF")
|
||||
pageidx++;
|
||||
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
if (buckets[0].Count > 0)
|
||||
{
|
||||
// ZXHawk needs to skip this bit
|
||||
if (Global.Emulator.SystemId == "ZXSpectrum" || Global.Emulator.SystemId == "AmstradCPC")
|
||||
if (Global.Emulator.SystemId == "ZXSpectrum" || Global.Emulator.SystemId == "AmstradCPC" || Global.Emulator.SystemId == "ChannelF")
|
||||
return;
|
||||
|
||||
string tabname = (Global.Emulator.SystemId == "C64") ? "Keyboard" : "Console"; // hack
|
||||
|
@ -275,6 +275,11 @@ namespace BizHawk.Client.EmuHawk
|
|||
tableLayoutPanel1.ColumnStyles[1].Width = Properties.Resources.ZXSpectrumKeyboards.Width;
|
||||
}
|
||||
|
||||
if (controlName == "ChannelF Controller")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (controlName == "AmstradCPC Controller")
|
||||
{
|
||||
/*
|
||||
|
|
|
@ -53,7 +53,8 @@ namespace BizHawk.Client.EmuHawk
|
|||
{ "PCFX", "PC-FX" },
|
||||
{ "32X", "32X" },
|
||||
{ "ZXSpectrum", "ZX Spectrum" },
|
||||
{ "AmstradCPC", "Amstrad CPC" }
|
||||
{ "AmstradCPC", "Amstrad CPC" },
|
||||
{ "ChannelF", "Channel F" }
|
||||
};
|
||||
|
||||
public string TargetSystem = null;
|
||||
|
|
|
@ -61,6 +61,10 @@ namespace BizHawk.Emulation.Common
|
|||
FirmwareAndOption("A584272F21DC82C14B7D4F1ED440E23A976E71F0", 32768, "ZXSpectrum", "PentagonROM", "pentagon.rom", "Russian Pentagon Clone ROM");
|
||||
FirmwareAndOption("282EB7BC819AAD2A12FD954E76F7838A4E1A7929", 16384, "ZXSpectrum", "TRDOSROM", "trdos.rom", "TRDOS ROM");
|
||||
|
||||
// Channel F
|
||||
FirmwareAndOption("81193965A374D77B99B4743D317824B53C3E3C78", 1024, "ChannelF", "ChannelF_sl131253", "ChannelF-SL31253.rom", "Channel F Rom0");
|
||||
FirmwareAndOption("8F70D1B74483BA3A37E86CF16C849D601A8C3D2C", 1024, "ChannelF", "ChannelF_sl131254", "ChannelF-SL31254.rom", "Channel F Rom1");
|
||||
|
||||
// for saturn, we think any bios region can pretty much run any iso
|
||||
// so, we're going to lay this out carefully so that we choose things in a sensible order, but prefer the correct region
|
||||
var ss_100_j = File("2B8CB4F87580683EB4D760E4ED210813D667F0A2", 524288, "saturn-1.00-(J).bin", "Bios v1.00 (J)");
|
||||
|
|
|
@ -34,7 +34,8 @@ namespace BizHawk.Emulation.Common
|
|||
new SystemInfo { SystemId = "AppleII", FullName = "Apple II" },
|
||||
new SystemInfo { SystemId = "INTV", FullName = "Intellivision" },
|
||||
new SystemInfo { SystemId = "ZXSpectrum", FullName = "Sinclair ZX Spectrum" },
|
||||
new SystemInfo { SystemId = "AmstradCPC", FullName = "Amstrad CPC" }
|
||||
new SystemInfo { SystemId = "AmstradCPC", FullName = "Amstrad CPC" },
|
||||
new SystemInfo { SystemId = "ChannelF", FullName = "Fairchild Channel F"},
|
||||
};
|
||||
|
||||
public SystemInfo this[string systemId]
|
||||
|
|
|
@ -595,6 +595,21 @@
|
|||
</Compile>
|
||||
<Compile Include="Consoles\Belogic\LibUzem.cs" />
|
||||
<Compile Include="Consoles\Belogic\Uzem.cs" />
|
||||
<Compile Include="Consoles\Fairchild\ChannelF\ChannelF.IO.cs" />
|
||||
<Compile Include="Consoles\Fairchild\ChannelF\ChannelF.MemoryDomains.cs" />
|
||||
<Compile Include="Consoles\Fairchild\ChannelF\ChannelF.IStatable.cs" />
|
||||
<Compile Include="Consoles\Fairchild\ChannelF\ChannelF.ISettable.cs" />
|
||||
<Compile Include="Consoles\Fairchild\ChannelF\ChannelF.InputPollable.cs" />
|
||||
<Compile Include="Consoles\Fairchild\ChannelF\ChannelF.Controllers.cs" />
|
||||
<Compile Include="Consoles\Fairchild\ChannelF\ChannelF.IEmulator.cs" />
|
||||
<Compile Include="Consoles\Fairchild\ChannelF\ChannelF.IVideoProvider.cs" />
|
||||
<Compile Include="Consoles\Fairchild\ChannelF\ChannelF.cs" />
|
||||
<Compile Include="Consoles\Fairchild\ChannelF\F8\F3850.Disassembler.cs" />
|
||||
<Compile Include="Consoles\Fairchild\ChannelF\F8\F3850.Tables.cs" />
|
||||
<Compile Include="Consoles\Fairchild\ChannelF\F8\F3850.Registers.cs" />
|
||||
<Compile Include="Consoles\Fairchild\ChannelF\F8\F3850.Operations.cs" />
|
||||
<Compile Include="Consoles\Fairchild\ChannelF\F8\F3850.Execute.cs" />
|
||||
<Compile Include="Consoles\Fairchild\ChannelF\F8\F3850.cs" />
|
||||
<Compile Include="Consoles\GCE\Vectrex\Audio.cs" />
|
||||
<Compile Include="Consoles\GCE\Vectrex\VectrexHawk.cs" />
|
||||
<Compile Include="Consoles\GCE\Vectrex\VectrexHawk.ICodeDataLog.cs" />
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using BizHawk.Common.BufferExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.ChannelF
|
||||
{
|
||||
public partial class ChannelF
|
||||
{
|
||||
public ControllerDefinition ChannelFControllerDefinition
|
||||
{
|
||||
get
|
||||
{
|
||||
ControllerDefinition definition = new ControllerDefinition();
|
||||
definition.Name = "ChannelF Controller";
|
||||
|
||||
// sticks
|
||||
List<string> stickL = new List<string>
|
||||
{
|
||||
// P1 (left) stick
|
||||
"P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 Button Up", "P1 Button Down", "P1 Rotate Left", "P1 Rotate Right"
|
||||
};
|
||||
|
||||
foreach (var s in stickL)
|
||||
{
|
||||
definition.BoolButtons.Add(s);
|
||||
definition.CategoryLabels[s] = "Left Controller";
|
||||
}
|
||||
|
||||
List<string> stickR = new List<string>
|
||||
{
|
||||
// P1 (left) stick
|
||||
"P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 Button Up", "P2 Button Down", "P2 Rotate Left", "P2 Rotate Right"
|
||||
};
|
||||
|
||||
foreach (var s in stickR)
|
||||
{
|
||||
definition.BoolButtons.Add(s);
|
||||
definition.CategoryLabels[s] = "Right Controller";
|
||||
}
|
||||
|
||||
// console
|
||||
List<string> consoleButtons = new List<string>
|
||||
{
|
||||
"RESET", "START", "HOLD", "MODE", "TIME"
|
||||
};
|
||||
|
||||
foreach (var s in consoleButtons)
|
||||
{
|
||||
definition.BoolButtons.Add(s);
|
||||
definition.CategoryLabels[s] = "Console";
|
||||
}
|
||||
|
||||
return definition;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
using BizHawk.Common.BufferExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.ChannelF
|
||||
{
|
||||
public partial class ChannelF : IEmulator
|
||||
{
|
||||
public IEmulatorServiceProvider ServiceProvider { get; }
|
||||
|
||||
public ControllerDefinition ControllerDefinition { get; set; }
|
||||
|
||||
public string SystemId => "ChannelF";
|
||||
|
||||
public bool DeterministicEmulation { get; set; }
|
||||
|
||||
private static double cpuFreq = 1.7897725;
|
||||
private static double refreshRate = 60;
|
||||
|
||||
public int ClockPerFrame;
|
||||
public int FrameClock = 0;
|
||||
|
||||
private void CalcClock()
|
||||
{
|
||||
var c = (cpuFreq * 1000000) / refreshRate;
|
||||
ClockPerFrame = (int) c;
|
||||
}
|
||||
|
||||
public bool FrameAdvance(IController controller, bool render, bool renderSound)
|
||||
{
|
||||
while (FrameClock++ < ClockPerFrame)
|
||||
{
|
||||
CPU.ExecuteOne();
|
||||
}
|
||||
|
||||
FrameClock = 0;
|
||||
_frame++;
|
||||
return true;
|
||||
}
|
||||
|
||||
private int _frame;
|
||||
private int _lagcount;
|
||||
private bool _islag;
|
||||
|
||||
public void ResetCounters()
|
||||
{
|
||||
_frame = 0;
|
||||
_lagcount = 0;
|
||||
_islag = false;
|
||||
}
|
||||
|
||||
public int Frame => _frame;
|
||||
|
||||
public CoreComm CoreComm { get; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
using System;
|
||||
using BizHawk.Common.BufferExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.ChannelF
|
||||
{
|
||||
|
||||
public partial class ChannelF
|
||||
{
|
||||
public byte[] BIOS01 = new byte[1024];
|
||||
public byte[] BIOS02 = new byte[1024];
|
||||
|
||||
public byte[] FrameBuffer = new byte[2048];
|
||||
|
||||
public byte[] Cartridge = new byte[0x2000 - 0x800];
|
||||
|
||||
public byte ReadBus(ushort addr)
|
||||
{
|
||||
if (addr < 0x400)
|
||||
{
|
||||
// Rom0
|
||||
return BIOS01[addr];
|
||||
}
|
||||
else if (addr < 0x800)
|
||||
{
|
||||
// Rom1
|
||||
return BIOS02[addr - 0x400];
|
||||
}
|
||||
else if (addr < 0x2000)
|
||||
{
|
||||
// Cart
|
||||
return Cartridge[addr - 0x800];
|
||||
}
|
||||
else if (addr < 0x2000 + 2048)
|
||||
{
|
||||
// Framebuffer
|
||||
return FrameBuffer[addr - 0x2000];
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteBus(ushort addr, byte value)
|
||||
{
|
||||
if (addr < 0x400)
|
||||
{
|
||||
// Rom0
|
||||
}
|
||||
else if (addr < 0x800)
|
||||
{
|
||||
// Rom1
|
||||
}
|
||||
else if (addr < 0x2000)
|
||||
{
|
||||
// Cart
|
||||
}
|
||||
else if (addr < 0x2000 + 2048)
|
||||
{
|
||||
// Framebuffer
|
||||
FrameBuffer[addr - 0x2000] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public byte ReadPort(ushort addr)
|
||||
{
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
public void WritePort(ushort addr, byte value)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Common.BufferExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Cores.Nintendo.NES;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.ChannelF
|
||||
{
|
||||
public partial class ChannelF : ISettable<ChannelF.ChannelFSettings, ChannelF.ChannelFSyncSettings>
|
||||
{
|
||||
internal ChannelFSettings Settings = new ChannelFSettings();
|
||||
internal ChannelFSyncSettings SyncSettings = new ChannelFSyncSettings();
|
||||
|
||||
public ChannelFSettings GetSettings()
|
||||
{
|
||||
return Settings.Clone();
|
||||
}
|
||||
|
||||
public ChannelFSyncSettings GetSyncSettings()
|
||||
{
|
||||
return SyncSettings.Clone();
|
||||
}
|
||||
|
||||
public bool PutSettings(ChannelFSettings o)
|
||||
{
|
||||
Settings = o;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool PutSyncSettings(ChannelFSyncSettings o)
|
||||
{
|
||||
bool ret = ChannelFSyncSettings.NeedsReboot(SyncSettings, o);
|
||||
SyncSettings = o;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public class ChannelFSettings
|
||||
{
|
||||
[DisplayName("Default Background Color")]
|
||||
[Description("The default BG color")]
|
||||
[DefaultValue(0)]
|
||||
public int BackgroundColor { get; set; }
|
||||
|
||||
public ChannelFSettings Clone()
|
||||
{
|
||||
return (ChannelFSettings)MemberwiseClone();
|
||||
}
|
||||
|
||||
public ChannelFSettings()
|
||||
{
|
||||
SettingsUtil.SetDefaultValues(this);
|
||||
}
|
||||
}
|
||||
|
||||
public class ChannelFSyncSettings
|
||||
{
|
||||
[DisplayName("Deterministic Emulation")]
|
||||
[Description("If true, the core agrees to behave in a completely deterministic manner")]
|
||||
[DefaultValue(true)]
|
||||
public bool DeterministicEmulation { get; set; }
|
||||
|
||||
public ChannelFSyncSettings Clone()
|
||||
{
|
||||
return (ChannelFSyncSettings) MemberwiseClone();
|
||||
}
|
||||
|
||||
public ChannelFSyncSettings()
|
||||
{
|
||||
SettingsUtil.SetDefaultValues(this);
|
||||
}
|
||||
|
||||
public static bool NeedsReboot(ChannelFSyncSettings x, ChannelFSyncSettings y)
|
||||
{
|
||||
return !DeepEquality.DeepEquals(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Common.BufferExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.ChannelF
|
||||
{
|
||||
public partial class ChannelF : IStatable
|
||||
{
|
||||
public bool BinarySaveStatesPreferred => true;
|
||||
|
||||
public void SaveStateText(TextWriter writer)
|
||||
{
|
||||
SyncState(new Serializer(writer));
|
||||
}
|
||||
|
||||
public void LoadStateText(TextReader reader)
|
||||
{
|
||||
SyncState(new Serializer(reader));
|
||||
}
|
||||
|
||||
public void SaveStateBinary(BinaryWriter bw)
|
||||
{
|
||||
SyncState(new Serializer(bw));
|
||||
}
|
||||
|
||||
public void LoadStateBinary(BinaryReader br)
|
||||
{
|
||||
SyncState(new Serializer(br));
|
||||
}
|
||||
|
||||
public byte[] SaveStateBinary()
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
BinaryWriter bw = new BinaryWriter(ms);
|
||||
SaveStateBinary(bw);
|
||||
bw.Flush();
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
private void SyncState(Serializer ser)
|
||||
{
|
||||
|
||||
/*
|
||||
|
||||
byte[] core = null;
|
||||
if (ser.IsWriter)
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
ms.Close();
|
||||
core = ms.ToArray();
|
||||
}
|
||||
|
||||
if (ser.IsWriter)
|
||||
{
|
||||
ser.SyncEnum(nameof(_machineType), ref _machineType);
|
||||
|
||||
_cpu.SyncState(ser);
|
||||
ser.BeginSection(nameof(ZXSpectrum));
|
||||
_machine.SyncState(ser);
|
||||
ser.Sync("Frame", ref _machine.FrameCount);
|
||||
ser.Sync("LagCount", ref _lagCount);
|
||||
ser.Sync("IsLag", ref _isLag);
|
||||
ser.EndSection();
|
||||
}
|
||||
|
||||
if (ser.IsReader)
|
||||
{
|
||||
var tmpM = _machineType;
|
||||
ser.SyncEnum(nameof(_machineType), ref _machineType);
|
||||
if (tmpM != _machineType && _machineType.ToString() != "72")
|
||||
{
|
||||
string msg = "SAVESTATE FAILED TO LOAD!!\n\n";
|
||||
msg += "Current Configuration: " + tmpM.ToString();
|
||||
msg += "\n";
|
||||
msg += "Saved Configuration: " + _machineType.ToString();
|
||||
msg += "\n\n";
|
||||
msg += "If you wish to load this SaveState ensure that you have the correct machine configuration selected, reboot the core, then try again.";
|
||||
CoreComm.ShowMessage(msg);
|
||||
_machineType = tmpM;
|
||||
}
|
||||
else
|
||||
{
|
||||
_cpu.SyncState(ser);
|
||||
ser.BeginSection(nameof(ZXSpectrum));
|
||||
_machine.SyncState(ser);
|
||||
ser.Sync("Frame", ref _machine.FrameCount);
|
||||
ser.Sync("LagCount", ref _lagCount);
|
||||
ser.Sync("IsLag", ref _isLag);
|
||||
ser.EndSection();
|
||||
|
||||
SyncAllByteArrayDomains();
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
using BizHawk.Common.BufferExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.ChannelF
|
||||
{
|
||||
public partial class ChannelF : IVideoProvider
|
||||
{
|
||||
public int _frameHz = 60;
|
||||
|
||||
public int[] _vidbuffer = new int[102 * 58];
|
||||
|
||||
public int[] GetVideoBuffer()
|
||||
{
|
||||
return _vidbuffer;
|
||||
}
|
||||
|
||||
public int VirtualWidth => 102 * 2;
|
||||
public int VirtualHeight => 58 * 2;
|
||||
public int BufferWidth => 102;
|
||||
public int BufferHeight => 58;
|
||||
public int BackgroundColor => unchecked((int)0xFF000000);
|
||||
public int VsyncNumerator => _frameHz;
|
||||
public int VsyncDenominator => 1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
using BizHawk.Common.BufferExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.ChannelF
|
||||
{
|
||||
public partial class ChannelF : IInputPollable
|
||||
{
|
||||
public int LagCount
|
||||
{
|
||||
get { return _lagCount; }
|
||||
set { _lagCount = value; }
|
||||
}
|
||||
|
||||
public bool IsLagFrame
|
||||
{
|
||||
get { return _isLag; }
|
||||
set { _isLag = value; }
|
||||
}
|
||||
|
||||
public IInputCallbackSystem InputCallbacks { get; }
|
||||
|
||||
private int _lagCount = 0;
|
||||
private bool _isLag = false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using BizHawk.Common.BufferExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.ChannelF
|
||||
{
|
||||
public partial class ChannelF
|
||||
{
|
||||
internal IMemoryDomains memoryDomains;
|
||||
private readonly Dictionary<string, MemoryDomainByteArray> _byteArrayDomains = new Dictionary<string, MemoryDomainByteArray>();
|
||||
private bool _memoryDomainsInit = false;
|
||||
|
||||
private void SetupMemoryDomains()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void SyncAllByteArrayDomains()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void SyncByteArrayDomain(string name, byte[] data)
|
||||
{
|
||||
if (_memoryDomainsInit || _byteArrayDomains.ContainsKey(name))
|
||||
{
|
||||
var m = _byteArrayDomains[name];
|
||||
m.Data = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
var m = new MemoryDomainByteArray(name, MemoryDomain.Endian.Little, data, true, 1);
|
||||
_byteArrayDomains.Add(name, m);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
using System;
|
||||
using BizHawk.Common.BufferExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.ChannelF
|
||||
{
|
||||
[Core(
|
||||
"ChannelFHawk",
|
||||
"Asnivor",
|
||||
isPorted: false,
|
||||
isReleased: false)]
|
||||
[ServiceNotApplicable(typeof(IDriveLight))]
|
||||
public partial class ChannelF
|
||||
{
|
||||
public ChannelF(CoreComm comm, GameInfo game, byte[] rom, object settings, object syncSettings)
|
||||
{
|
||||
var ser = new BasicServiceProvider(this);
|
||||
ServiceProvider = ser;
|
||||
CoreComm = comm;
|
||||
InputCallbacks = new InputCallbackSystem();
|
||||
|
||||
ControllerDefinition = ChannelFControllerDefinition;
|
||||
|
||||
CPU = new F3850
|
||||
{
|
||||
ReadMemory = ReadBus,
|
||||
WriteMemory = WriteBus,
|
||||
ReadHardware = ReadPort,
|
||||
WriteHardware = WritePort,
|
||||
DummyReadMemory = ReadBus
|
||||
};
|
||||
|
||||
byte[] bios01 = comm.CoreFileProvider.GetFirmware("ChannelF", "ChannelF_sl131253", true);
|
||||
byte[] bios02 = comm.CoreFileProvider.GetFirmware("ChannelF", "ChannelF_sl131254", true);
|
||||
|
||||
BIOS01 = bios01;
|
||||
BIOS02 = bios02;
|
||||
|
||||
Array.Copy(rom, 0, Cartridge, 0, rom.Length);
|
||||
|
||||
CalcClock();
|
||||
|
||||
ser.Register<IVideoProvider>(this);
|
||||
}
|
||||
|
||||
public F3850 CPU;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.ChannelF
|
||||
{
|
||||
/// <summary>
|
||||
/// Disassembler
|
||||
/// </summary>
|
||||
public sealed partial class F3850 : IDisassemblable
|
||||
{
|
||||
|
||||
|
||||
#region IDisassemblable
|
||||
|
||||
public string Cpu
|
||||
{
|
||||
get { return "F3850"; }
|
||||
set { }
|
||||
}
|
||||
|
||||
public string PCRegisterName
|
||||
{
|
||||
get { return "PC"; }
|
||||
}
|
||||
|
||||
public IEnumerable<string> AvailableCpus
|
||||
{
|
||||
get { yield return "F3850"; }
|
||||
}
|
||||
|
||||
public string Disassemble(MemoryDomain m, uint addr, out int length)
|
||||
{
|
||||
length = 0;
|
||||
string ret = "";// Disassemble((ushort)addr, a => m.PeekByte(a), out length);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.ChannelF
|
||||
{
|
||||
public sealed partial class F3850
|
||||
{
|
||||
public const int MaxInstructionLength = 40;
|
||||
|
||||
public long TotalExecutedCycles;
|
||||
|
||||
public int instr_pntr = 0;
|
||||
public ushort[] cur_instr = new ushort[MaxInstructionLength]; // fixed size - do not change at runtime
|
||||
public ushort[] cur_romc = new ushort[MaxInstructionLength]; // fixed size - do not change at runtime
|
||||
public byte opcode;
|
||||
public byte databus;
|
||||
public ushort iobus;
|
||||
|
||||
public void FetchInstruction()
|
||||
{
|
||||
switch (opcode)
|
||||
{
|
||||
case 0x00: LR_A_KU(); break; // LR A, (KU)
|
||||
case 0x01: LR_A_KL(); break; // LR A, (KL)
|
||||
case 0x02: LR_A_QU(); break; // LR A, (QU)
|
||||
case 0x03: LR_A_QL(); break; // LR A, (QL)
|
||||
case 0x04: LR_KU_A(); break; // LR KU, (A)
|
||||
case 0x05: LR_KL_A(); break; // LR KL, (A)
|
||||
case 0x06: LR_QU_A(); break; // LR QU, (A)
|
||||
case 0x07: LR_QL_A(); break; // LR QL, (A)
|
||||
case 0x08: LR_K_P(); break; // LR K, (P)
|
||||
case 0x09: LR_P_K(); break; // LR P, (K)
|
||||
case 0x0A: LR_A_IS(); break; // LR A, (ISAR)
|
||||
case 0x0B: LR_IS_A(); break; // LR ISAR, (A)
|
||||
case 0x0C: LR_PK(); break; // LR PC1, (PC0); LR PC0l <- (r13); LR PC0h, (r12)
|
||||
case 0x0D: LR_P0_Q(); break; // LR PC0l, (r15); LR PC0h <- (r14)
|
||||
case 0x0E: LR_Q_DC(); break; // LR r14, (DC0h); r15 <- (DC0l)
|
||||
case 0x0F: LR_DC_Q(); break; // LR DC0h, (r14); DC0l <- (r15)
|
||||
case 0x10: LR_DC_Q(); break; // LR DC0h, (r10); DC0l <- (r11)
|
||||
case 0x11: LR_H_DC(); break; // LR r10, (DC0h); r11 <- (DC0l)
|
||||
case 0x12: SHIFT_R(1); break; // Shift (A) right one bit position (zero fill)
|
||||
case 0x13: SHIFT_L(1); break; // Shift (A) left one bit position (zero fill)
|
||||
case 0x14: SHIFT_R(4); break; // Shift (A) right four bit positions (zero fill)
|
||||
case 0x15: SHIFT_L(4); break; // Shift (A) left four bit positions (zero fill)
|
||||
case 0x16: LM(); break; // A <- ((DC0))
|
||||
case 0x17: ST(); break; // (DC) <- (A)
|
||||
case 0x18: COM(); break; // A <- A ^ 255
|
||||
case 0x1A: DI(); break; // Clear ICB
|
||||
case 0x1B: EI(); break; // Set ICB
|
||||
case 0x1C: POP(); break; // PC0 <- PC1
|
||||
case 0x1D: LR_W_J(); break; // W <- (r9)
|
||||
case 0x1E: LR_J_W(); break; // r9 <- (W)
|
||||
case 0x1F: INC(); break; // A <- (A) + 1
|
||||
|
||||
default: ILLEGAL(); break; // Illegal Opcode
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Common.NumberExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.ChannelF
|
||||
{
|
||||
public sealed partial class F3850
|
||||
{
|
||||
private void IncrementBySignedByte(ushort dest, byte src)
|
||||
{
|
||||
if (src >= 0x80)
|
||||
{
|
||||
dest -= (ushort)(src & 0x80);
|
||||
}
|
||||
else
|
||||
{
|
||||
dest += (ushort)(src & 0x80);
|
||||
}
|
||||
}
|
||||
|
||||
private void IncrementBySignedByte(byte dest, byte src)
|
||||
{
|
||||
if (src >= 0x80)
|
||||
{
|
||||
dest -= (byte)(src & 0x80);
|
||||
}
|
||||
else
|
||||
{
|
||||
dest += (byte)(src & 0x80);
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadReg_Func(ushort dest, ushort src)
|
||||
{
|
||||
if (dest == DB)
|
||||
{
|
||||
// byte storage
|
||||
Regs[dest] = (ushort)(Regs[src] & 0xFF);
|
||||
}
|
||||
else if (dest == W)
|
||||
{
|
||||
// mask for status register
|
||||
Regs[dest] = (ushort)(Regs[src] & 0x1F);
|
||||
}
|
||||
else
|
||||
{
|
||||
Regs[dest] = Regs[src];
|
||||
}
|
||||
}
|
||||
|
||||
public void ShiftRight_Func(ushort src, ushort index)
|
||||
{
|
||||
int shft = (Regs[src] >> index) & 0xFF;
|
||||
FlagO = false;
|
||||
FlagC = false;
|
||||
FlagZ = shft == 0;
|
||||
FlagS = (~shft & 0x80) != 0;
|
||||
Regs[src] = (ushort)shft;
|
||||
}
|
||||
|
||||
public void ShiftLeft_Func(ushort src, ushort index)
|
||||
{
|
||||
int shft = (Regs[src] << index) & 0xFF;
|
||||
FlagO = false;
|
||||
FlagC = false;
|
||||
FlagZ = shft == 0;
|
||||
FlagS = (~shft & 0x80) != 0;
|
||||
Regs[src] = (ushort)shft;
|
||||
}
|
||||
|
||||
public void COM_Func(ushort src)
|
||||
{
|
||||
byte b = (byte)Regs[src];
|
||||
var r = (byte)~b;
|
||||
FlagO = false;
|
||||
FlagC = false;
|
||||
FlagZ = r == 0;
|
||||
FlagS = (~r & 0x80) != 0;
|
||||
Regs[src] = (ushort)r;
|
||||
}
|
||||
|
||||
public void ADD8_Func(ushort dest, ushort src)
|
||||
{
|
||||
int Reg16_d = Regs[dest];
|
||||
Reg16_d += Regs[src];
|
||||
|
||||
FlagC = Reg16_d.Bit(8);
|
||||
FlagZ = (Reg16_d & 0xFF) == 0;
|
||||
|
||||
ushort ans = (ushort)(Reg16_d & 0xFF);
|
||||
|
||||
FlagO = (Regs[dest].Bit(7) == Regs[src].Bit(7)) && (Regs[dest].Bit(7) != ans.Bit(7));
|
||||
FlagS = ans > 127;
|
||||
|
||||
Regs[dest] = ans;
|
||||
}
|
||||
|
||||
public void INC8_Func(ushort src)
|
||||
{
|
||||
int Reg16_d = Regs[src];
|
||||
Reg16_d += 1;
|
||||
|
||||
FlagC = Reg16_d.Bit(8);
|
||||
FlagZ = (Reg16_d & 0xFF) == 0;
|
||||
|
||||
ushort ans = (ushort)(Reg16_d & 0xFF);
|
||||
|
||||
Regs[src] = ans;
|
||||
|
||||
FlagS = Regs[src].Bit(7);
|
||||
FlagO = Regs[src] == 0x80;
|
||||
}
|
||||
|
||||
public void Read_Func(ushort dest, ushort src)
|
||||
{
|
||||
Regs[dest] = Regs[src];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,231 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms.VisualStyles;
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.ChannelF
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal Registers
|
||||
/// </summary>
|
||||
public sealed partial class F3850
|
||||
{
|
||||
/// <summary>
|
||||
/// Accumulator
|
||||
/// </summary>
|
||||
public ushort A = 0;
|
||||
/// <summary>
|
||||
/// Status Register
|
||||
/// </summary>
|
||||
public ushort W = 1;
|
||||
/// <summary>
|
||||
/// Indirect Scratchpad Address Register
|
||||
/// (6bit)
|
||||
/// </summary>
|
||||
public ushort ISAR = 2;
|
||||
/// <summary>
|
||||
/// Primary Program Counter (low byte)
|
||||
/// </summary>
|
||||
public ushort PC0l = 3;
|
||||
/// <summary>
|
||||
/// Primary Program Counter (high byte)
|
||||
/// </summary>
|
||||
public ushort PC0h = 4;
|
||||
/// <summary>
|
||||
/// Backup Program Counter (low byte)
|
||||
/// </summary>
|
||||
public ushort PC1l = 5;
|
||||
/// <summary>
|
||||
/// Backup Program Counter (high byte)
|
||||
/// </summary>
|
||||
public ushort PC1h = 6;
|
||||
/// <summary>
|
||||
/// Data Counter (low byte)
|
||||
/// </summary>
|
||||
public ushort DC0l = 7;
|
||||
/// <summary>
|
||||
/// Data counter (high byte)
|
||||
/// </summary>
|
||||
public ushort DC0h = 8;
|
||||
/// <summary>
|
||||
/// Temporary Arithmetic Storage
|
||||
/// </summary>
|
||||
public ushort ALU = 9;
|
||||
/// <summary>
|
||||
/// Data Bus
|
||||
/// </summary>
|
||||
public ushort DB = 10;
|
||||
/// <summary>
|
||||
/// IO Bus
|
||||
/// </summary>
|
||||
public ushort IO = 11;
|
||||
|
||||
/// <summary>
|
||||
/// Registers (counters and scratchpad)
|
||||
/// </summary>
|
||||
public ushort[] Regs = new ushort[100];
|
||||
|
||||
// scratchpad registers
|
||||
public ushort SR0 = 20;
|
||||
public ushort SR1 = 21;
|
||||
public ushort SR2 = 22;
|
||||
public ushort SR3 = 23;
|
||||
public ushort SR4 = 24;
|
||||
public ushort SR5 = 25;
|
||||
public ushort SR6 = 26;
|
||||
public ushort SR7 = 27;
|
||||
public ushort SR8 = 28;
|
||||
public ushort SR9 = 29;
|
||||
public ushort SR10 = 30;
|
||||
public ushort SR11 = 31;
|
||||
public ushort SR12 = 32;
|
||||
public ushort SR13 = 33;
|
||||
public ushort SR14 = 34;
|
||||
public ushort SR15 = 35;
|
||||
public ushort SR16 = 36;
|
||||
public ushort SR17 = 37;
|
||||
public ushort SR18 = 38;
|
||||
public ushort SR19 = 39;
|
||||
public ushort SR20 = 40;
|
||||
public ushort SR21 = 41;
|
||||
public ushort SR22 = 42;
|
||||
public ushort SR23 = 43;
|
||||
public ushort SR24 = 44;
|
||||
public ushort SR25 = 45;
|
||||
public ushort SR26 = 46;
|
||||
public ushort SR27 = 47;
|
||||
public ushort SR28 = 48;
|
||||
public ushort SR29 = 49;
|
||||
public ushort SR30 = 50;
|
||||
public ushort SR31 = 51;
|
||||
public ushort SR32 = 52;
|
||||
public ushort SR33 = 53;
|
||||
public ushort SR34 = 54;
|
||||
public ushort SR35 = 55;
|
||||
public ushort SR36 = 56;
|
||||
public ushort SR37 = 57;
|
||||
public ushort SR38 = 58;
|
||||
public ushort SR39 = 59;
|
||||
public ushort SR40 = 60;
|
||||
public ushort SR41 = 61;
|
||||
public ushort SR42 = 62;
|
||||
public ushort SR43 = 63;
|
||||
public ushort SR44 = 64;
|
||||
public ushort SR45 = 65;
|
||||
public ushort SR46 = 66;
|
||||
public ushort SR47 = 67;
|
||||
public ushort SR48 = 68;
|
||||
public ushort SR49 = 69;
|
||||
public ushort SR50 = 70;
|
||||
public ushort SR51 = 71;
|
||||
public ushort SR52 = 72;
|
||||
public ushort SR53 = 73;
|
||||
public ushort SR54 = 74;
|
||||
public ushort SR55 = 75;
|
||||
public ushort SR56 = 76;
|
||||
public ushort SR57 = 77;
|
||||
public ushort SR58 = 78;
|
||||
public ushort SR59 = 79;
|
||||
public ushort SR60 = 80;
|
||||
public ushort SR61 = 81;
|
||||
public ushort SR62 = 82;
|
||||
public ushort SR63 = 83;
|
||||
public ushort SR64 = 84;
|
||||
|
||||
/// <summary>
|
||||
/// Status Register - Sign Flag
|
||||
/// </summary>
|
||||
public bool FlagS
|
||||
{
|
||||
get { return (Regs[W] & 0x01) != 0; }
|
||||
set { Regs[W] = (ushort)((Regs[W] & ~0x01) | (value ? 0x01 : 0x00)); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Status Register - Carry Flag
|
||||
/// </summary>
|
||||
public bool FlagC
|
||||
{
|
||||
get { return (Regs[W] & 0x02) != 0; }
|
||||
set { Regs[W] = (ushort)((Regs[W] & ~0x02) | (value ? 0x02 : 0x00)); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Status Register - Zero Flag
|
||||
/// </summary>
|
||||
public bool FlagZ
|
||||
{
|
||||
get { return (Regs[W] & 0x04) != 0; }
|
||||
set { Regs[W] = (ushort)((Regs[W] & ~0x04) | (value ? 0x04 : 0x00)); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Status Register - Overflow Flag
|
||||
/// </summary>
|
||||
public bool FlagO
|
||||
{
|
||||
get { return (Regs[W] & 0x08) != 0; }
|
||||
set { Regs[W] = (ushort)((Regs[W] & ~0x08) | (value ? 0x08 : 0x00)); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Status Register - Interrupt Master Enable Flag
|
||||
/// </summary>
|
||||
public bool FlagICB
|
||||
{
|
||||
get { return (Regs[W] & 0x10) != 0; }
|
||||
set { Regs[W] = (ushort)((Regs[W] & ~0x10) | (value ? 0x10 : 0x00)); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Access to the full 16-bit Primary Program Counter
|
||||
/// </summary>
|
||||
public ushort RegPC0
|
||||
{
|
||||
get { return (ushort)(Regs[PC0l] | (Regs[PC0h] << 8)); }
|
||||
set
|
||||
{
|
||||
Regs[PC0l] = (ushort)(value & 0xFF);
|
||||
Regs[PC0h] = (ushort)((value >> 8) & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Access to the full 16-bit Backup Program Counter
|
||||
/// </summary>
|
||||
public ushort RegPC1
|
||||
{
|
||||
get { return (ushort)(Regs[PC1l] | (Regs[PC1h] << 8)); }
|
||||
set
|
||||
{
|
||||
Regs[PC1l] = (ushort)(value & 0xFF);
|
||||
Regs[PC1h] = (ushort)((value >> 8) & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Access to the full 16-bit Data Counter
|
||||
/// </summary>
|
||||
public ushort RegDC0
|
||||
{
|
||||
get { return (ushort)(Regs[DC0l] | (Regs[DC0h] << 8)); }
|
||||
set
|
||||
{
|
||||
Regs[DC0l] = (ushort)(value & 0xFF);
|
||||
Regs[DC0h] = (ushort)((value >> 8) & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetRegisters()
|
||||
{
|
||||
for (var i = 0; i < Regs.Length; i++)
|
||||
{
|
||||
Regs[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,420 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.ChannelF
|
||||
{
|
||||
/// <summary>
|
||||
/// Vectors of Instruction Operations
|
||||
/// </summary>
|
||||
public sealed partial class F3850
|
||||
{
|
||||
private void LR_A_KU()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
OP_LR_8, A, SR12, // S
|
||||
ROMC_00_S,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void LR_A_KL()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
OP_LR_8, A, SR13, // S
|
||||
ROMC_00_S,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void LR_A_QU()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
OP_LR_8, A, SR14, // S
|
||||
ROMC_00_S,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void LR_A_QL()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
OP_LR_8, A, SR15, // S
|
||||
ROMC_00_S,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void LR_KU_A()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
OP_LR_8, SR12, A, // S
|
||||
ROMC_00_S,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void LR_KL_A()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
OP_LR_8, SR13, A, // S
|
||||
ROMC_00_S,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void LR_QU_A()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
OP_LR_8, SR14, A, // S
|
||||
ROMC_00_S,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void LR_QL_A()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
OP_LR_8, SR15, A, // S
|
||||
ROMC_00_S,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void LR_K_P()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
ROMC_07, // L
|
||||
IDLE,
|
||||
IDLE,
|
||||
OP_LR_8, SR12, DB,
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_0B, // L
|
||||
IDLE,
|
||||
IDLE,
|
||||
OP_LR_8, SR13, DB,
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_00_S, // S
|
||||
IDLE,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void LR_P_K()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
OP_LR_8, DB, SR12, // L
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_15,
|
||||
IDLE,
|
||||
IDLE,
|
||||
OP_LR_8, DB, SR13, // L
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_18,
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_00_S, // S
|
||||
IDLE,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void LR_A_IS()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
OP_LR_8, A, ISAR, // S
|
||||
ROMC_00_S,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void LR_IS_A()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
OP_LR_8, ISAR, A, // S
|
||||
ROMC_00_S,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void LR_PK()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
OP_LR_8, DB, SR13, // L
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_12,
|
||||
IDLE,
|
||||
IDLE,
|
||||
OP_LR_8, DB, SR12, // L
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_14,
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_00_S, // S
|
||||
IDLE,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void LR_P0_Q()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
OP_LR_8, DB, SR15, // L
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_17,
|
||||
IDLE,
|
||||
IDLE,
|
||||
OP_LR_8, DB, SR14, // L
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_14,
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_00_S, // S
|
||||
IDLE,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void LR_Q_DC()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
ROMC_06, // L
|
||||
IDLE,
|
||||
IDLE,
|
||||
OP_LR_8, SR14, DB,
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_09, // L
|
||||
IDLE,
|
||||
IDLE,
|
||||
OP_LR_8, SR15, DB,
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_00_S, // S
|
||||
IDLE,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void LR_DC_Q()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
OP_LR_8, DB, SR14, // L
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_16,
|
||||
IDLE,
|
||||
IDLE,
|
||||
OP_LR_8, DB, SR15, // L
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_19,
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_00_S, // S
|
||||
IDLE,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void LR_DC_H()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
OP_LR_8, DB, SR10, // L
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_16,
|
||||
IDLE,
|
||||
IDLE,
|
||||
OP_LR_8, DB, SR11, // L
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_19,
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_00_S, // S
|
||||
IDLE,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void LR_H_DC()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
ROMC_06, // L
|
||||
IDLE,
|
||||
IDLE,
|
||||
OP_LR_8, SR10, DB,
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_09, // L
|
||||
IDLE,
|
||||
IDLE,
|
||||
OP_LR_8, SR11, DB,
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_00_S, // S
|
||||
IDLE,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void SHIFT_R(ushort index)
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
OP_SHFT_R, A, index, // S
|
||||
ROMC_00_S,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void SHIFT_L(ushort index)
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
OP_SHFT_L, A, index, // S
|
||||
ROMC_00_S,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void LM()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
ROMC_02, // L
|
||||
IDLE,
|
||||
IDLE,
|
||||
OP_LR_8, DB, A,
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_00_S, // S
|
||||
IDLE,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void ST()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
OP_LR_8, DB, A, // L
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_05,
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_00_S, // S
|
||||
IDLE,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void COM()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
OP_COM, // S
|
||||
ROMC_00_S,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void LNK()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
OP_LNK, // S
|
||||
ROMC_00_S,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void DI()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
ROMC_1C_S, // S
|
||||
OP_DI,
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_00_S, // S
|
||||
IDLE,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void EI()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
ROMC_1C_S, // S
|
||||
OP_EI,
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_00_S, // S
|
||||
IDLE,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void POP()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
ROMC_04, // S
|
||||
IDLE,
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_00_S, // S
|
||||
IDLE,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void LR_W_J()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
ROMC_1C_S, // S
|
||||
IDLE,
|
||||
OP_LR_8, W, SR9,
|
||||
IDLE,
|
||||
ROMC_00_S, // S
|
||||
IDLE,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void LR_J_W()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
OP_LR_8, SR9, W, // S
|
||||
ROMC_00_S,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
private void INC()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
OP_INC8, A, // S
|
||||
ROMC_00_S,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
|
||||
|
||||
private void ILLEGAL()
|
||||
{
|
||||
PopulateCURINSTR(
|
||||
ROMC_00_S, // S
|
||||
IDLE,
|
||||
IDLE,
|
||||
END);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,480 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.ChannelF
|
||||
{
|
||||
/// <summary>
|
||||
/// Fairchild F3850 (F8) CPU (Channel F-specific implementation)
|
||||
///
|
||||
/// The F8 microprocessor is made up of separate interchangeable devices
|
||||
/// The Channel F has:
|
||||
/// * x1 F3850 CPU (central processing unit)
|
||||
/// * x2 F3851 PSU (program storage unit)
|
||||
/// The CPU does not have its own data counters or program counters, rather each F8 component connected to the CPU
|
||||
/// holds their own PCs and SPs and are all connected to the ROMC (ROM control) pins that are serviced by the CPU.
|
||||
/// Every device must respond to changes in the CPU ROMC pins output and they each update their PCs and DCs in the same way.
|
||||
/// e.g. SPs and PCs should always be identical
|
||||
/// Each device has a factory ROM mask applied and with every ROMC change observed is able to know whether it should respond (via the shared data bus)
|
||||
/// or not based on the value within its counters.
|
||||
///
|
||||
/// For this reason we will hold the PCs and SPs within the F3850 implementation.
|
||||
///
|
||||
/// We are currently also *not* using a separate F3851 implementation. In reality the F3851 chip has/does:
|
||||
/// * 1024 byte masked ROM
|
||||
/// * x2 16-bit program counters
|
||||
/// * x1 16-bit data counter
|
||||
/// * Programmable timer
|
||||
/// * Interrupt logic
|
||||
///
|
||||
/// However, the Channel F does not use the timer or interrupt logic at all (as far as I can see) so we can hopefully just
|
||||
/// maintain the PC and DC here in the CPU and move the ROMs into the core.
|
||||
/// </summary>
|
||||
public sealed partial class F3850
|
||||
{
|
||||
// operations that can take place in an instruction
|
||||
|
||||
//public const ushort OP = 1;
|
||||
//public const ushort LR_8 = 2;
|
||||
//public const ushort LR_16 = 3;
|
||||
|
||||
|
||||
public const ushort ROMC_00_S = 40;
|
||||
public const ushort ROMC_00_L = 41;
|
||||
public const ushort ROMC_01 = 1;
|
||||
public const ushort ROMC_02 = 2;
|
||||
public const ushort ROMC_03_S = 3;
|
||||
public const ushort ROMC_03_L = 33;
|
||||
public const ushort ROMC_04 = 4;
|
||||
public const ushort ROMC_05 = 5;
|
||||
public const ushort ROMC_06 = 6;
|
||||
public const ushort ROMC_07 = 7;
|
||||
public const ushort ROMC_08 = 8;
|
||||
public const ushort ROMC_09 = 9;
|
||||
public const ushort ROMC_0A = 10;
|
||||
public const ushort ROMC_0B = 11;
|
||||
public const ushort ROMC_0C = 12;
|
||||
public const ushort ROMC_0D = 13;
|
||||
public const ushort ROMC_0E = 14;
|
||||
public const ushort ROMC_0F = 15;
|
||||
public const ushort ROMC_10 = 16;
|
||||
public const ushort ROMC_11 = 17;
|
||||
public const ushort ROMC_12 = 18;
|
||||
public const ushort ROMC_13 = 19;
|
||||
public const ushort ROMC_14 = 20;
|
||||
public const ushort ROMC_15 = 21;
|
||||
public const ushort ROMC_16 = 22;
|
||||
public const ushort ROMC_17 = 23;
|
||||
public const ushort ROMC_18 = 24;
|
||||
public const ushort ROMC_19 = 25;
|
||||
public const ushort ROMC_1A = 26;
|
||||
public const ushort ROMC_1B = 27;
|
||||
public const ushort ROMC_1C_S = 28;
|
||||
public const ushort ROMC_1C_L = 34;
|
||||
public const ushort ROMC_1D = 29;
|
||||
public const ushort ROMC_1E = 30;
|
||||
public const ushort ROMC_1F = 31;
|
||||
|
||||
public const ushort IDLE = 0;
|
||||
public const ushort END = 51;
|
||||
|
||||
public const ushort OP_LR_8 = 100;
|
||||
public const ushort OP_SHFT_R = 101;
|
||||
public const ushort OP_SHFT_L = 102;
|
||||
public const ushort OP_COM = 103;
|
||||
public const ushort OP_LNK = 104;
|
||||
public const ushort OP_DI = 105;
|
||||
public const ushort OP_EI = 106;
|
||||
public const ushort OP_INC8 = 107;
|
||||
|
||||
|
||||
public F3850()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
ResetRegisters();
|
||||
TotalExecutedCycles = 0;
|
||||
instr_pntr = 0;
|
||||
|
||||
PopulateCURINSTR(
|
||||
ROMC_08, // S
|
||||
IDLE,
|
||||
IDLE,
|
||||
IDLE,
|
||||
IDLE,
|
||||
IDLE,
|
||||
ROMC_00_S,
|
||||
IDLE,
|
||||
IDLE,
|
||||
IDLE,
|
||||
END);
|
||||
|
||||
FlagICB = false;
|
||||
}
|
||||
|
||||
public IMemoryCallbackSystem MemoryCallbacks { get; set; }
|
||||
|
||||
// Memory Access
|
||||
public Func<ushort, byte> ReadMemory;
|
||||
public Action<ushort, byte> WriteMemory;
|
||||
public Func<ushort, byte> PeekMemory;
|
||||
public Func<ushort, byte> DummyReadMemory;
|
||||
|
||||
// Hardware I/O Port Access
|
||||
public Func<ushort, byte> ReadHardware;
|
||||
public Action<ushort, byte> WriteHardware;
|
||||
|
||||
public Action<ushort> OnExecFetch;
|
||||
|
||||
public void SetCallbacks
|
||||
(
|
||||
Func<ushort, byte> ReadMemory,
|
||||
Func<ushort, byte> DummyReadMemory,
|
||||
Func<ushort, byte> PeekMemory,
|
||||
Action<ushort, byte> WriteMemory,
|
||||
Func<ushort, byte> ReadHardware,
|
||||
Action<ushort, byte> WriteHardware
|
||||
)
|
||||
{
|
||||
this.ReadMemory = ReadMemory;
|
||||
this.DummyReadMemory = DummyReadMemory;
|
||||
this.PeekMemory = PeekMemory;
|
||||
this.WriteMemory = WriteMemory;
|
||||
this.ReadHardware = ReadHardware;
|
||||
this.WriteHardware = WriteHardware;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs a single CPU clock cycle
|
||||
/// </summary>
|
||||
public void ExecuteOne()
|
||||
{
|
||||
switch (cur_instr[instr_pntr++])
|
||||
{
|
||||
// always the last tick within an opcode instruction cycle
|
||||
case END:
|
||||
opcode = databus;
|
||||
instr_pntr = 0;
|
||||
FetchInstruction();
|
||||
break;
|
||||
|
||||
// used as timing 'padding'
|
||||
case IDLE:
|
||||
break;
|
||||
|
||||
// load one register into another (or databus)
|
||||
case OP_LR_8:
|
||||
LoadReg_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
|
||||
// Shift register n bit positions to the right (zero fill)
|
||||
case OP_SHFT_R:
|
||||
ShiftRight_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
|
||||
// Shift register n bit positions to the left (zero fill)
|
||||
case OP_SHFT_L:
|
||||
ShiftLeft_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
|
||||
// A <- A ^ 255
|
||||
case OP_COM:
|
||||
COM_Func(A);
|
||||
break;
|
||||
|
||||
// A <- (A) + (C)
|
||||
case OP_LNK:
|
||||
ADD8_Func(Regs[A], (ushort)(FlagC ? 1 : 0));
|
||||
break;
|
||||
|
||||
case OP_DI:
|
||||
FlagICB = false;
|
||||
break;
|
||||
|
||||
case OP_EI:
|
||||
FlagICB = true;
|
||||
break;
|
||||
|
||||
case OP_INC8:
|
||||
INC8_Func(cur_instr[instr_pntr++]);
|
||||
break;
|
||||
|
||||
|
||||
|
||||
// instruction fetch
|
||||
// The device whose address space includes the contents of the PC0 register must place on the data bus the op code addressed by PC0;
|
||||
// then all devices increments the content of PC0.
|
||||
// CYCLE LENGTH: S
|
||||
case ROMC_00_S:
|
||||
databus = ReadMemory(RegPC0++);
|
||||
break;
|
||||
|
||||
// instruction fetch
|
||||
// The device whose address space includes the contents of the PC0 register must place on the data bus the op code addressed by PC0;
|
||||
// then all devices increments the content of PC0.
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_00_L:
|
||||
databus = ReadMemory(RegPC0++);
|
||||
break;
|
||||
|
||||
// The device whose address space includes the contents of the PC0 register must place on the data bus the contents of the memory location
|
||||
// addressed by by PC0; then all devices add the 8-bit value on the data bus, as a signed binary number, to PC0
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_01:
|
||||
databus = ReadMemory(RegPC0);
|
||||
IncrementBySignedByte(RegPC0, databus);
|
||||
break;
|
||||
|
||||
// The device whose DC0 address addresses a memory word within the address space of that device must place on the data bus the contents
|
||||
// of the memory location addressed by DC0; then all devices increment DC0
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_02:
|
||||
databus = ReadMemory(RegDC0++);
|
||||
break;
|
||||
|
||||
// Similar to 0x00, except that it is used for Immediate Operand fetches (using PC0) instead of instruction fetches
|
||||
// CYCLE LENGTH: S
|
||||
case ROMC_03_S:
|
||||
databus = ReadMemory(RegPC0++);
|
||||
iobus = databus;
|
||||
break;
|
||||
|
||||
// Similar to 0x00, except that it is used for Immediate Operand fetches (using PC0) instead of instruction fetches
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_03_L:
|
||||
databus = ReadMemory(RegPC0++);
|
||||
iobus = databus;
|
||||
break;
|
||||
|
||||
// Copy the contents of PC1 into PC0
|
||||
// CYCLE LENGTH: S
|
||||
case ROMC_04:
|
||||
RegPC0 = RegPC1;
|
||||
break;
|
||||
|
||||
// Store the data bus contents into the memory location pointed to by DC0; increment DC0
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_05:
|
||||
WriteMemory(RegDC0++, databus);
|
||||
break;
|
||||
|
||||
// Place the high order byte of DC0 on the data bus
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_06:
|
||||
databus = (byte)Regs[DC0h];
|
||||
break;
|
||||
|
||||
// Place the high order byte of PC1 on the data bus
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_07:
|
||||
databus = (byte)Regs[PC1h];
|
||||
break;
|
||||
|
||||
// All devices copy the contents of PC0 into PC1. The CPU outputs zero on the data bus in this ROMC state.
|
||||
// Load the data bus into both halves of PC0, this clearing the register.
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_08:
|
||||
RegPC1 = RegPC0;
|
||||
databus = 0;
|
||||
Regs[PC0h] = 0;
|
||||
Regs[PC0l] = 0;
|
||||
break;
|
||||
|
||||
// The device whose address space includes the contents of the DC0 register must place the low order byte of DC0 onto the data bus
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_09:
|
||||
databus = (byte)Regs[DC0l];
|
||||
break;
|
||||
|
||||
// All devices add the 8-bit value on the data bus, treated as a signed binary number, to the data counter
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_0A:
|
||||
IncrementBySignedByte(RegDC0, databus);
|
||||
break;
|
||||
|
||||
// The device whose address space includes the value in PC1 must place the low order byte of PC1 on the data bus
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_0B:
|
||||
databus = (byte)Regs[PC1l];
|
||||
break;
|
||||
|
||||
// The device whose address space includes the contents of the PC0 register must place the contents of the memory word addressed by PC0
|
||||
// onto the data bus; then all devices move the value that has just been placed on the data bus into the low order byte of PC0
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_0C:
|
||||
databus = ReadMemory(RegPC0);
|
||||
Regs[PC0l] = databus;
|
||||
break;
|
||||
|
||||
// All devices store in PC1 the current contents of PC0, incremented by 1; PC1 is unaltered
|
||||
// CYCLE LENGTH: S
|
||||
case ROMC_0D:
|
||||
RegPC1 = (ushort)(RegPC0 + 1);
|
||||
break;
|
||||
|
||||
// The device whose address space includes the contents of PC0 must place the contents of the word addressed by PC0 onto the data bus.
|
||||
// The value on the data bus is then moved to the low order byte of DC0 by all devices
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_0E:
|
||||
databus = ReadMemory(RegPC0);
|
||||
Regs[DC0l] = databus;
|
||||
break;
|
||||
|
||||
// The interrupting device with the highest priority must place the low order byte of the interrupt vector on the data bus.
|
||||
// All devices must copy the contents of PC0 into PC1. All devices must move the contents of the data bus into the low order byte of PC0
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_0F:
|
||||
throw new NotImplementedException("ROMC 0x0F not implemented");
|
||||
break;
|
||||
|
||||
// Inhibit any modification to the interrupt priority logic
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_10:
|
||||
throw new NotImplementedException("ROMC 0x10 not implemented");
|
||||
break;
|
||||
|
||||
// The device whose memory space includes the contents of PC0 must place the contents of the addressed memory word on the data bus.
|
||||
// All devices must then move the contents of the data bus to the upper byte of DC0
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_11:
|
||||
databus = ReadMemory(RegPC0);
|
||||
Regs[DC0h] = databus;
|
||||
break;
|
||||
|
||||
// All devices copy the contents of PC0 into PC1. All devices then move the contents of the data bus into the low order byte of PC0
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_12:
|
||||
RegPC1 = RegPC0;
|
||||
Regs[PC0l] = databus;
|
||||
break;
|
||||
|
||||
// The interrupting device with the highest priority must move the high order half of the interrupt vector onto the data bus.
|
||||
// All devices must move the conetnts of the data bus into the high order byte of of PC0. The interrupting device resets its
|
||||
// interrupt circuitry (so that it is no longer requesting CPU servicing and can respond to another interrupt)
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_13:
|
||||
throw new NotImplementedException("ROMC 0x13 not implemented");
|
||||
break;
|
||||
|
||||
// All devices move the contents of the data bus into the high order byte of PC0
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_14:
|
||||
Regs[PC0h] = databus;
|
||||
break;
|
||||
|
||||
// All devices move the contents of the data bus into the high order byte of PC1
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_15:
|
||||
Regs[PC1h] = databus;
|
||||
break;
|
||||
|
||||
// All devices move the contents of the data bus into the high order byte of DC0
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_16:
|
||||
Regs[DC0h] = databus;
|
||||
break;
|
||||
|
||||
// All devices move the contents of the data bus into the low order byte of PC0
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_17:
|
||||
Regs[PC0l] = databus;
|
||||
break;
|
||||
|
||||
// All devices move the contents of the data bus into the low order byte of PC1
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_18:
|
||||
Regs[PC1l] = databus;
|
||||
break;
|
||||
|
||||
// All devices move the contents of the data bus into the low order byte of DC0
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_19:
|
||||
Regs[DC0l] = databus;
|
||||
break;
|
||||
|
||||
// During the prior cycle, an I/O port timer or interrupt control register was addressed; the device containing the addressed
|
||||
// port must move the current contents of the data bus into the addressed port
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_1A:
|
||||
WriteHardware(iobus, databus);
|
||||
break;
|
||||
|
||||
// During the prior cycle, the data bus specified the address of an I/O port. The device containing the addressed I/O port
|
||||
// must place the contents of the I/O port on the data bus. (Note that the contents of the timer and interrupt control
|
||||
// registers cannot be read back onto the data bus)
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_1B:
|
||||
databus = ReadHardware(iobus);
|
||||
break;
|
||||
|
||||
// None
|
||||
// CYCLE LENGTH: S
|
||||
case ROMC_1C_S:
|
||||
break;
|
||||
|
||||
// None
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_1C_L:
|
||||
break;
|
||||
|
||||
// Devices with DC0 and DC1 registers must switch registers. Devices without a DC1 register perform no operation
|
||||
// CYCLE LENGTH: S
|
||||
case ROMC_1D:
|
||||
// we have no DC1 in this implementation
|
||||
break;
|
||||
|
||||
// The device whose address space includes the contents of PC0 must place the low order byte of PC0 onto the data bus
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_1E:
|
||||
databus = (byte)Regs[PC0l];
|
||||
break;
|
||||
|
||||
// The device whose address space includes the contents of PC0 must place the high order byte of PC0 onto the data bus
|
||||
// CYCLE LENGTH: L
|
||||
case ROMC_1F:
|
||||
databus = (byte)Regs[PC0h];
|
||||
break;
|
||||
}
|
||||
|
||||
TotalExecutedCycles++;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Optimization method to set cur_instr
|
||||
/// </summary>
|
||||
private void PopulateCURINSTR(ushort d0 = 0, ushort d1 = 0, ushort d2 = 0, ushort d3 = 0, ushort d4 = 0, ushort d5 = 0, ushort d6 = 0, ushort d7 = 0, ushort d8 = 0,
|
||||
ushort d9 = 0, ushort d10 = 0, ushort d11 = 0, ushort d12 = 0, ushort d13 = 0, ushort d14 = 0, ushort d15 = 0, ushort d16 = 0, ushort d17 = 0, ushort d18 = 0,
|
||||
ushort d19 = 0, ushort d20 = 0, ushort d21 = 0, ushort d22 = 0, ushort d23 = 0, ushort d24 = 0, ushort d25 = 0, ushort d26 = 0, ushort d27 = 0, ushort d28 = 0,
|
||||
ushort d29 = 0, ushort d30 = 0, ushort d31 = 0, ushort d32 = 0, ushort d33 = 0, ushort d34 = 0, ushort d35 = 0, ushort d36 = 0, ushort d37 = 0)
|
||||
{
|
||||
cur_instr[0] = d0; cur_instr[1] = d1; cur_instr[2] = d2;
|
||||
cur_instr[3] = d3; cur_instr[4] = d4; cur_instr[5] = d5;
|
||||
cur_instr[6] = d6; cur_instr[7] = d7; cur_instr[8] = d8;
|
||||
cur_instr[9] = d9; cur_instr[10] = d10; cur_instr[11] = d11;
|
||||
cur_instr[12] = d12; cur_instr[13] = d13; cur_instr[14] = d14;
|
||||
cur_instr[15] = d15; cur_instr[16] = d16; cur_instr[17] = d17;
|
||||
cur_instr[18] = d18; cur_instr[19] = d19; cur_instr[20] = d20;
|
||||
cur_instr[21] = d21; cur_instr[22] = d22; cur_instr[23] = d23;
|
||||
cur_instr[24] = d24; cur_instr[25] = d25; cur_instr[26] = d26;
|
||||
cur_instr[27] = d27; cur_instr[28] = d28; cur_instr[29] = d29;
|
||||
cur_instr[30] = d30; cur_instr[31] = d31; cur_instr[32] = d32;
|
||||
cur_instr[33] = d33; cur_instr[34] = d34; cur_instr[35] = d35;
|
||||
cur_instr[36] = d36; cur_instr[37] = d37;
|
||||
}
|
||||
|
||||
public void SyncState(Serializer ser)
|
||||
{
|
||||
ser.BeginSection(nameof(F3850));
|
||||
|
||||
ser.EndSection();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue