From 47a5ce279804c2c1d152b31b10c5398dbca1ff41 Mon Sep 17 00:00:00 2001 From: Asnivor Date: Tue, 7 May 2019 14:43:36 +0100 Subject: [PATCH] ChannelF: some more changes --- .../BizHawk.Emulation.Cores.csproj | 6 +- .../Computers/SinclairSpectrum/Machine/ULA.cs | 2 +- .../Consoles/Fairchild/ChannelF/Cart.cs | 16 + .../ChannelF/ChannelF.Controllers.cs | 147 ++++++- .../Fairchild/ChannelF/ChannelF.IEmulator.cs | 7 +- .../Fairchild/ChannelF/ChannelF.IO.cs | 85 ---- .../Fairchild/ChannelF/ChannelF.IStatable.cs | 10 +- .../ChannelF/ChannelF.IVideoProvider.cs | 118 ++---- .../ChannelF/ChannelF.MemoryDomains.cs | 4 +- .../Consoles/Fairchild/ChannelF/ChannelF.cs | 4 +- .../Fairchild/ChannelF/F8/F3850.ALU.cs | 111 +---- .../ChannelF/F8/F3850.Disassembler.cs | 92 ++-- .../Fairchild/ChannelF/F8/F3850.Execute.cs | 82 ++-- .../Fairchild/ChannelF/F8/F3850.Operations.cs | 281 +++++++++++++ .../Fairchild/ChannelF/F8/F3850.Registers.cs | 4 + .../Fairchild/ChannelF/F8/F3850.Tables.cs | 192 ++++++--- .../Consoles/Fairchild/ChannelF/F8/F3850.cs | 397 ++++++++++-------- .../Consoles/Fairchild/ChannelF/Memory.cs | 55 +++ .../Consoles/Fairchild/ChannelF/Ports.cs | 188 +++++++++ .../Consoles/Fairchild/ChannelF/Video.cs | 120 ++++++ 20 files changed, 1307 insertions(+), 614 deletions(-) create mode 100644 BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart.cs delete mode 100644 BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.IO.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.Operations.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Memory.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Ports.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Video.cs diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index 375e04e43d..5ed3b20e4f 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -596,7 +596,6 @@ - @@ -605,12 +604,17 @@ + + + + + diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ULA.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ULA.cs index df7541189e..6ab1341a93 100644 --- a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ULA.cs +++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ULA.cs @@ -940,7 +940,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum return croppedBuffer; case ZXSpectrum.BorderType.None: - // all border sizes now 24 + // all border sizes now 0 var lR__ = BorderLeftWidth; var rR__ = BorderRightWidth; var tR__ = BorderTopHeight; diff --git a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart.cs b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart.cs new file mode 100644 index 0000000000..d2d52dda5b --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Cart.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BizHawk.Emulation.Cores.Consoles.ChannelF +{ + /// + /// Cartridge and related functions + /// + public partial class ChannelF + { + public byte[] Rom = new byte[4096]; + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.Controllers.cs b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.Controllers.cs index b0fa1ec6bb..80a2ae7931 100644 --- a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.Controllers.cs +++ b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.Controllers.cs @@ -1,12 +1,127 @@ using System; using System.Collections.Generic; +using System.Windows.Forms; using BizHawk.Common.BufferExtensions; +using BizHawk.Common.NumberExtensions; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Consoles.ChannelF { public partial class ChannelF { + public bool[] StateConsole = new bool[4]; + public string[] ButtonsConsole = new string[] + { + "TIME", "MODE", "HOLD", "START" + }; + public byte DataConsole + { + get + { + int w = 0; + for (int i = 0; i < 4; i++) + { + byte mask = (byte) (1 << i); + w = StateConsole[i] ? w | mask : w & ~mask; + } + + return (byte)(w & 0xFF); + } + } + + public bool[] StateRight = new bool[8]; + public string[] ButtonsRight = new string[] + { + "Right", "Left", "Back", "Forward", "CCW", "CW", "Pull", "Push" + }; + public byte DataRight + { + get + { + int w = 0; + for (int i = 0; i < 8; i++) + { + byte mask = (byte)(1 << i); + w = StateRight[i] ? w | mask : w & ~mask; + } + + return (byte)(w & 0xFF); + } + } + + public bool[] StateLeft = new bool[8]; + public string[] ButtonsLeft = new string[] + { + "Right", "Left", "Back", "Forward", "CCW", "CW", "Pull", "Push" + }; + public byte DataLeft + { + get + { + int w = 0; + for (int i = 0; i < 8; i++) + { + byte mask = (byte)(1 << i); + w = StateLeft[i] ? w | mask : w & ~mask; + } + + return (byte)(w & 0xFF); + } + } + + + /// + /// Cycles through all the input callbacks + /// This should be done once per frame + /// + public bool PollInput() + { + bool noInput = true; + + InputCallbacks.Call(); + + lock (this) + { + for (int i = 0; i < ButtonsConsole.Length; i++) + { + var key = ButtonsConsole[i]; + bool prevState = StateConsole[i]; // CTRLConsole.Bit(i); + bool currState = _controller.IsPressed(key); + if (currState != prevState) + { + StateConsole[i] = currState; + noInput = false; + } + } + + for (int i = 0; i < ButtonsRight.Length; i++) + { + var key = "P1 " + ButtonsRight[i]; + bool prevState = StateRight[i]; + bool currState = _controller.IsPressed(key); + if (currState != prevState) + { + StateRight[i] = currState; + noInput = false; + } + } + + for (int i = 0; i < ButtonsLeft.Length; i++) + { + var key = "P2 " + ButtonsLeft[i]; + bool prevState = StateLeft[i]; + bool currState = _controller.IsPressed(key); + if (currState != prevState) + { + StateLeft[i] = currState; + noInput = false; + } + } + } + + return noInput; + } + public ControllerDefinition ChannelFControllerDefinition { get @@ -14,23 +129,13 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF ControllerDefinition definition = new ControllerDefinition(); definition.Name = "ChannelF Controller"; + string pre = "P1 "; + // sticks - List stickL = new List - { - // 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 stickR = new List { - // P1 (left) stick - "P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 Button Up", "P2 Button Down", "P2 Rotate Left", "P2 Rotate Right" + // P1 (right) stick + pre + "Forward", pre + "Back", pre + "Left", pre + "Right", pre + "CCW", pre + "CW", pre + "Pull", pre + "Push" }; foreach (var s in stickR) @@ -39,6 +144,20 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF definition.CategoryLabels[s] = "Right Controller"; } + pre = "P2 "; + + List stickL = new List + { + // P2 (left) stick + pre + "Forward", pre + "Back", pre + "Left", pre + "Right", pre + "CCW", pre + "CW", pre + "Pull", pre + "Push" + }; + + foreach (var s in stickL) + { + definition.BoolButtons.Add(s); + definition.CategoryLabels[s] = "Left Controller"; + } + // console List consoleButtons = new List { diff --git a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.IEmulator.cs index 026fb361fb..4ce4fcaaa9 100644 --- a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.IEmulator.cs @@ -22,12 +22,15 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF private void CalcClock() { - var c = (cpuFreq * 1000000) / refreshRate; + var c = ((cpuFreq * 1000000) / refreshRate) * 4; ClockPerFrame = (int) c; } public bool FrameAdvance(IController controller, bool render, bool renderSound) { + _controller = controller; + _isLag = false; + if (_tracer.Enabled) { CPU.TraceCallback = s => _tracer.Put(s); @@ -37,6 +40,8 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF CPU.TraceCallback = null; } + _isLag = PollInput(); + while (FrameClock++ < ClockPerFrame) { CPU.ExecuteOne(); diff --git a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.IO.cs b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.IO.cs deleted file mode 100644 index 7aa343ee03..0000000000 --- a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.IO.cs +++ /dev/null @@ -1,85 +0,0 @@ -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[0x2000]; - - public byte[] Cartridge = new byte[0x2000 - 0x800]; - - public byte[] PortLatch = new byte[64]; - - 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 0; - 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 0x00; - } - - public void WritePort(ushort addr, byte value) - { - PortLatch[addr] = value; - - VID_PortIN(addr, value); - } - } -} diff --git a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.IStatable.cs b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.IStatable.cs index d0c2cd3208..101f1fd378 100644 --- a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.IStatable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.IStatable.cs @@ -41,7 +41,15 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF private void SyncState(Serializer ser) { - + ser.BeginSection("ChannelF"); + ser.Sync(nameof(VRAM), ref VRAM, false); + ser.Sync(nameof(_colour), ref _colour); + ser.Sync(nameof(_x), ref _x); + ser.Sync(nameof(_y), ref _y); + ser.Sync(nameof(_arm), ref _arm); + ser.Sync(nameof(ControllersEnabled), ref ControllersEnabled); + CPU.SyncState(ser); + ser.EndSection(); /* byte[] core = null; diff --git a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.IVideoProvider.cs b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.IVideoProvider.cs index 4efe72af28..d67cdd1a94 100644 --- a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.IVideoProvider.cs +++ b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.IVideoProvider.cs @@ -7,95 +7,61 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF { public partial class ChannelF : IVideoProvider, IRegionable { - public static readonly int[] FPalette = - { - Colors.ARGB(0x10, 0x10, 0x10), // Black - Colors.ARGB(0xFD, 0xFD, 0xFD), // White - Colors.ARGB(0xFF, 0x31, 0x53), // Red - Colors.ARGB(0x02, 0xCC, 0x5D), // Green - Colors.ARGB(0x4B, 0x3F, 0xF3), // Blue - Colors.ARGB(0xE0, 0xE0, 0xE0), // Gray - Colors.ARGB(0x91, 0xFF, 0xA6), // BGreen - Colors.ARGB(0xCE, 0xD0, 0xFF), // BBlue - }; - - public static readonly int[] CMap = - { - 0, 1, 1, 1, - 7, 4, 2, 3, - 5, 4, 2, 3, - 6, 4, 2, 3, - }; - public int _frameHz = 60; - public int[] _vidbuffer = new int[108 * 64]; + public int[] CroppedBuffer = new int[(128*64) * 2]; //new int[102 * 58]; - public int[] GetVideoBuffer() - { - int colour; - int a = 0; - int pOff; - - // rows - for (int y = 0; y < 64; y++) - { - pOff = ((FrameBuffer[(y * 128) + 125] & 0x3) & 0x02) | ((FrameBuffer[(y * 128) + 126] & 0x3) >> 1) << 2; - - for (int x = a; x < a + 128; x++) - { - colour = pOff + (FrameBuffer[x | (y << 7)] & 0x03); - var yM = y * 64; - _vidbuffer[yM + x] = FPalette[CMap[colour]]; - } - } - - return _vidbuffer; - } + #region IVideoProvider public int VirtualWidth => BufferWidth * 2; - public int VirtualHeight => BufferHeight * 2; - public int BufferWidth => 108; // 102 - public int BufferHeight => 64; // 58 - public int BackgroundColor => unchecked((int)0xFF000000); + public int VirtualHeight => (int)((double)BufferHeight * 1.5) * 2; + public int BufferWidth => 128;// 102; + public int BufferHeight => 64; // 58; + public int BackgroundColor => Colors.ARGB(0x00, 0x00, 0x00); public int VsyncNumerator => _frameHz; public int VsyncDenominator => 1; - private int row = 0; - private int col = 0; - private byte value = 0; - - public void VID_PortIN(ushort port, byte val) + public int[] GetVideoBuffer() { - switch (port) + BuildFrame(); + /* + for (int i = 0; i < frameBuffer.Length; i++) { - case 0: - - int o; - PortLatch[port] = val; - if ((val & 0x20) != 0) - { - o = (row * 128) + col; - FrameBuffer[o] = value; - } - break; - - case 1: // Set Color (bits 6 and 7) - PortLatch[port] = val; - value = (byte)(((val ^ 0xFF) >> 6) & 0x03); - break; - case 4: // X coordinate, inverted (bits 0-6) - PortLatch[2] = val; - col = (val | 0x80) ^ 0xFF; - break; - case 5: // Y coordinate, inverted (bits 0-5) - PortLatch[3] = val; - //sound TODO - row = (val | 0xC0) ^ 0xFF; - break; + CroppedBuffer[i] = frameBuffer[i]; + CroppedBuffer[i + frameBuffer.Length] = frameBuffer[i]; } + + return CroppedBuffer; + */ + return frameBuffer; + + // crop to visible area + var lR = 4; + var rR = 128 - BufferWidth - lR; + var tR = 4; + var bR = 64 - BufferHeight - tR; + var sW = 128 - lR - rR; + var startP = 128 * tR; + var endP = 128 * bR; + + int index2 = 0; + + // line by line + for (int i = startP; i < CroppedBuffer.Length - endP; i += sW + lR + rR) + { + // each pixel in each line + for (int p = lR; p < sW + lR + rR - rR; p++) + { + if (index2 == CroppedBuffer.Length) + break; + CroppedBuffer[index2++] = frameBuffer[i + p]; + } + } + + return CroppedBuffer; } + #endregion #region IRegionable diff --git a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.MemoryDomains.cs b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.MemoryDomains.cs index af0370f03b..0f62cab512 100644 --- a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.MemoryDomains.cs +++ b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.MemoryDomains.cs @@ -48,8 +48,8 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF { SyncByteArrayDomain("BIOS1", BIOS01); SyncByteArrayDomain("BIOS2", BIOS02); - SyncByteArrayDomain("ROM", Cartridge); - SyncByteArrayDomain("VRAM", FrameBuffer); + SyncByteArrayDomain("ROM", Rom); + SyncByteArrayDomain("VRAM", VRAM); } private void SyncByteArrayDomain(string name, byte[] data) diff --git a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.cs b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.cs index 3c088e0341..7e19c5f260 100644 --- a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.cs +++ b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.cs @@ -1,4 +1,5 @@ using System; +using BizHawk.Common; using BizHawk.Common.BufferExtensions; using BizHawk.Emulation.Common; @@ -39,7 +40,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF BIOS01 = bios01; BIOS02 = bios02; - Array.Copy(rom, 0, Cartridge, 0, rom.Length); + Array.Copy(rom, 0, Rom, 0, rom.Length); CalcClock(); @@ -52,5 +53,6 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF public F3850 CPU; private readonly TraceBuffer _tracer; + public IController _controller; } } diff --git a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.ALU.cs b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.ALU.cs index ccc6d9f234..70858f7576 100644 --- a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.ALU.cs +++ b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.ALU.cs @@ -25,7 +25,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF /// /// Clears all status flags (excluding the ICB flag) /// - public void ALU_ClearFlags() + public void ALU_ClearFlags_() { FlagC = false; FlagO = false; @@ -37,19 +37,19 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF /// Sets the SIGN and ZERO flags based on the supplied byte /// /// - public void ALU_SetFlags_SZ(ushort src) + public void ALU_SetFlags_SZ_(ushort src) { FlagZ = (byte)Regs[src] == 0; FlagS = (~((byte)Regs[src]) & 0x80) != 0; } - + /* /// /// Performs addition and sets the CARRY and OVERFLOW flags accordingly /// /// /// /// - public void ALU_ADD8_Func(ushort dest, ushort src, bool carry = false) + public void ALU_ADD8_Func_(ushort dest, ushort src, bool carry = false) { byte d = (byte)Regs[dest]; byte s = (byte)Regs[src]; @@ -61,6 +61,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF Regs[dest] = (ushort)(result & 0xFF); } + */ /// /// Performs addition and sets the CARRY and OVERFLOW flags accordingly WITHOUT saving to destination @@ -84,49 +85,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF /// /// /// - public void ALU_ADD8D_Func(ushort dest, ushort src) - { - // from MAME f8.cpp (BSD-3) - // https://github.com/mamedev/mame/blob/97b67170277437131adf6ed4d60139c172529e4f/src/devices/cpu/f8/f8.cpp#L264 - byte d = (byte)Regs[dest]; - byte s = (byte)Regs[src]; - byte tmp = (byte)(d + s); - - byte c = 0; // high order carry - byte ic = 0; // low order carry - - if (((d + s) & 0xFF0) > 0xF0) - { - c = 1; - } - - if ((d & 0x0F) + (s & 0x0F) > 0x0F) - { - ic = 1; - } - - ALU_ClearFlags(); - ALU_ADD8_FLAGSONLY_Func(dest, src); - Regs[ALU0] = tmp; - ALU_SetFlags_SZ(ALU0); - - if (c == 0 && ic == 0) - { - tmp = (byte)(((tmp + 0xa0) & 0xf0) + ((tmp + 0x0a) & 0x0f)); - } - - if (c == 0 && ic == 1) - { - tmp = (byte)(((tmp + 0xa0) & 0xf0) + (tmp & 0x0f)); - } - - if (c == 1 && ic == 0) - { - tmp = (byte)((tmp & 0xf0) + ((tmp + 0x0a) & 0x0f)); - } - - Regs[dest] = tmp; - } + public void ALU_SUB8_Func(ushort dest, ushort src) { @@ -169,55 +128,18 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF } */ - /// - /// Right shift 'src' 'shift' positions (zero fill) - /// - /// - /// - public void ALU_SR_Func(ushort src, ushort shift) - { - Regs[src] = (ushort)((Regs[src] >> shift) & 0xFF); - ALU_ClearFlags(); - ALU_SetFlags_SZ(src); - } - - /// - /// Left shit 'src' 'shift' positions (zero fill) - /// - /// - /// - public void ALU_SL_Func(ushort src, ushort shift) - { - Regs[src] = (ushort)((Regs[src] << shift) & 0xFF); - ALU_ClearFlags(); - ALU_SetFlags_SZ(src); - } + /// /// AND /// /// /// - public void ALU_AND8_Func(ushort dest, ushort src) - { - ALU_ClearFlags(); - Regs[dest] = (ushort)(Regs[dest] & Regs[src]); - ALU_SetFlags_SZ(dest); - } + - public void ALU_OR8_Func(ushort dest, ushort src) - { - ALU_ClearFlags(); - Regs[dest] = (ushort)(Regs[dest] | Regs[src]); - ALU_SetFlags_SZ(dest); - } + - public void ALU_XOR8_Func(ushort dest, ushort src) - { - ALU_ClearFlags(); - Regs[dest] = (ushort)(Regs[dest] ^ Regs[src]); - ALU_SetFlags_SZ(dest); - } + /* public void ALU_XOR8C_Func(ushort dest, ushort src) { @@ -264,16 +186,8 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF Regs[dest_h] &= 0xFF; } - public void Read_Func(ushort dest, ushort src_l, ushort src_h) - { - Regs[dest] = ReadMemory((ushort)(Regs[src_l] | (Regs[src_h]) << 8)); - } - - public void Write_Func(ushort dest_l, ushort dest_h, ushort src) - { - WriteMemory((ushort)(Regs[dest_l] | (Regs[dest_h] << 8)), (byte)Regs[src]); - } - + + /* public void LR8_Func(ushort dest, ushort src) { if (dest == DB) @@ -296,6 +210,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF Regs[dest] = Regs[src]; } } + */ /* public void ALU_INC8_Func(ushort src) diff --git a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.Disassembler.cs b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.Disassembler.cs index bba6c4a581..223eba1a51 100644 --- a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.Disassembler.cs +++ b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.Disassembler.cs @@ -19,7 +19,13 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF //n immediate succeeds the opcode and the displacement (if present) //nn immediately succeeds the opcode and the displacement (if present) - if (format.IndexOf("nn") != -1) format = format.Replace("nn", $"{read(addr++) << 8 + (read(addr++)):X4}h"); // MSB is read first + if (format.IndexOf("nn") != -1) + { + format = format.Replace("nn", read(addr++) + .ToString("X2") + read(addr++) + .ToString("X2") + "h"); // MSB is read first + } + if (format.IndexOf("n") != -1) format = format.Replace("n", $"{read(addr++):X2}h"); if (format.IndexOf("+d") != -1) format = format.Replace("+d", "d"); @@ -67,13 +73,13 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF "LR W, J", // 0x1D "LR J, W", // 0x1E "INC", // 0x1F - "LI n", // 0x20 - "NI n", // 0x21 - "IO n", // 0x22 - "XI n", // 0x23 - "AI n", // 0x24 - "CI n", // 0x25 - "IN n", // 0x26 + "LI n", // 0x20 + "NI n", // 0x21 + "OI n", // 0x22 + "XI n", // 0x23 + "AI n", // 0x24 + "CI n", // 0x25 + "IN n", // 0x26 "OUT n", // 0x27 "PI nn", // 0x28 "JMP nn", // 0x29 @@ -111,9 +117,9 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF "LR A, r09", // 0x49 "LR A, r10", // 0x4A "LR A, r11", // 0x4B - "LR A, ISAR", // 0x4C - "LR A, ISAR INC", // 0x4D - "LR A, ISAR DEC", // 0x4E + "LR A, (ISAR)", // 0x4C + "LR A, (ISAR) INC", // 0x4D + "LR A, (ISAR) DEC", // 0x4E "ILLEGAL", // 0x4F "LR r00, A", // 0x50 "LR r01, A", // 0x51 @@ -131,38 +137,38 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF "LR (ISAR), A INC", // 0x5D "LR (ISAR), A DEC", // 0x5E "ILLEGAL", // 0x5F - "LISU 0x00", // 0x60 - "LISU 0x08", // 0x61 - "LISU 0x10", // 0x62 - "LISU 0x18", // 0x63 - "LISU 0x20", // 0x64 - "LISU 0x28", // 0x65 - "LISU 0x30", // 0x66 - "LISU 0x38", // 0x67 - "LISU 0x00", // 0x68 - "LISU 0x01", // 0x69 - "LISU 0x02", // 0x6A - "LISU 0x03", // 0x6B - "LISU 0x04", // 0x6C - "LISU 0x05", // 0x6D - "LISU 0x06", // 0x6E - "LISU 0x07", // 0x6F - "LIS 0x0", // 0x70 - "LIS 0x01", // 0x71 - "LIS 0x2", // 0x72 - "LIS 0x3", // 0x73 - "LIS 0x4", // 0x74 - "LIS 0x5", // 0x75 - "LIS 0x6", // 0x76 - "LIS 0x7", // 0x77 - "LIS 0x8", // 0x78 - "LIS 0x9", // 0x79 - "LIS 0xA", // 0x7A - "LIS 0xB", // 0x7B - "LIS 0xC", // 0x7C - "LIS 0xD", // 0x7D - "LIS 0xE", // 0x7E - "LIS 0xF", // 0x7F + "LISU 0", // 0x60 + "LISU 1", // 0x61 + "LISU 2", // 0x62 + "LISU 3", // 0x63 + "LISU 4", // 0x64 + "LISU 5", // 0x65 + "LISU 6", // 0x66 + "LISU 7", // 0x67 + "LISL 0", // 0x68 + "LISL 1", // 0x69 + "LISL 2", // 0x6A + "LISL 3", // 0x6B + "LISL 4", // 0x6C + "LISL 5", // 0x6D + "LISL 6", // 0x6E + "LISL 7", // 0x6F + "LIS 0", // 0x70 + "LIS 1", // 0x71 + "LIS 2", // 0x72 + "LIS 3", // 0x73 + "LIS 4", // 0x74 + "LIS 5", // 0x75 + "LIS 6", // 0x76 + "LIS 7", // 0x77 + "LIS 8", // 0x78 + "LIS 9", // 0x79 + "LIS A", // 0x7A + "LIS B", // 0x7B + "LIS C", // 0x7C + "LIS D", // 0x7D + "LIS E", // 0x7E + "LIS F", // 0x7F "BT 0", // 0x80 "BT 1", // 0x81 "BT 2", // 0x82 diff --git a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.Execute.cs b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.Execute.cs index f1a5283654..8a2f952e67 100644 --- a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.Execute.cs +++ b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.Execute.cs @@ -119,22 +119,22 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF case 0x5D: LR_ISAR_A_INC(); break; // SR <- (A) (SR pointed to by the ISAR); ISAR incremented case 0x5E: LR_ISAR_A_DEC(); break; // SR <- (A) (SR pointed to by the ISAR); ISAR decremented - case 0x60: LISU(0); break; // ISARU <- 0'e' (octal) - case 0x61: LISU(8); break; // ISARU <- 0'e' (octal) - case 0x62: LISU(16); break; // ISARU <- 0'e' (octal) - case 0x63: LISU(24); break; // ISARU <- 0'e' (octal) - case 0x64: LISU(32); break; // ISARU <- 0'e' (octal) - case 0x65: LISU(40); break; // ISARU <- 0'e' (octal) - case 0x66: LISU(48); break; // ISARU <- 0'e' (octal) - case 0x67: LISU(56); break; // ISARU <- 0'e' (octal) - case 0x68: LISL(0); break; // ISARL <- 0'e' (octal) - case 0x69: LISL(1); break; // ISARL <- 0'e' (octal) - case 0x6A: LISL(2); break; // ISARL <- 0'e' (octal) - case 0x6B: LISL(3); break; // ISARL <- 0'e' (octal) - case 0x6C: LISL(4); break; // ISARL <- 0'e' (octal) - case 0x6D: LISL(5); break; // ISARL <- 0'e' (octal) - case 0x6E: LISL(6); break; // ISARL <- 0'e' (octal) - case 0x6F: LISL(7); break; // ISARL <- 0'e' (octal) + case 0x60: LISU(0); break; // ISARU <- 0'e' (octal) + case 0x61: LISU(1); break; // ISARU <- 0'e' (octal) + case 0x62: LISU(2); break; // ISARU <- 0'e' (octal) + case 0x63: LISU(3); break; // ISARU <- 0'e' (octal) + case 0x64: LISU(4); break; // ISARU <- 0'e' (octal) + case 0x65: LISU(5); break; // ISARU <- 0'e' (octal) + case 0x66: LISU(6); break; // ISARU <- 0'e' (octal) + case 0x67: LISU(7); break; // ISARU <- 0'e' (octal) + case 0x68: LISL(0); break; // ISARL <- 0'e' (octal) + case 0x69: LISL(1); break; // ISARL <- 0'e' (octal) + case 0x6A: LISL(2); break; // ISARL <- 0'e' (octal) + case 0x6B: LISL(3); break; // ISARL <- 0'e' (octal) + case 0x6C: LISL(4); break; // ISARL <- 0'e' (octal) + case 0x6D: LISL(5); break; // ISARL <- 0'e' (octal) + case 0x6E: LISL(6); break; // ISARL <- 0'e' (octal) + case 0x6F: LISL(7); break; // ISARL <- 0'e' (octal) case 0x70: LIS(0); break; // A <- H'0a' case 0x71: LIS(1); break; // A <- H'0a' @@ -152,14 +152,14 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF case 0x7d: LIS(13); break; // A <- H'0a' case 0x7e: LIS(14); break; // A <- H'0a' case 0x7f: LIS(15); break; // A <- H'0a' - case 0x80: BT(0); break; // Test operand against W (Branching instruction) - case 0x81: BT(1); break; // Test operand against W (Branching instruction) - case 0x82: BT(2); break; // Test operand against W (Branching instruction) - case 0x83: BT(3); break; // Test operand against W (Branching instruction) - case 0x84: BT(4); break; // Test operand against W (Branching instruction) - case 0x85: BT(5); break; // Test operand against W (Branching instruction) - case 0x86: BT(6); break; // Test operand against W (Branching instruction) - case 0x87: BT(7); break; // Test operand against W (Branching instruction) + case 0x80: BT(0); break; // Branch on true - test operand against W register + case 0x81: BT(1); break; // Branch if positive (sign bit is set) + case 0x82: BT(2); break; // Branch on carry (carry bit is set) + case 0x83: BT(3); break; // Branch on true - test operand against W register + case 0x84: BT(4); break; // Branch on zero (zero bit is set) + case 0x85: BT(5); break; // Branch on true - test operand against W register + case 0x86: BT(6); break; // Branch on true - test operand against W register + case 0x87: BT(7); break; // Branch on true - test operand against W register case 0x88: AM(); break; // A <- (A) + ((DC0))Binary; DC0 <- (DC0) + 1 case 0x89: AMD(); break; // A <- (A) + ((DC0))Decimal; DC0 <- (DC0) + 1 case 0x8A: NM(); break; // A <- (A) AND ((DC0)); DC0 <- (DC0) + 1 @@ -167,23 +167,23 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF case 0x8C: XM(); break; // A <- (A) XOR ((DC0)); DC0 <- (DC0) + 1 case 0x8D: CM(); break; // Set status flags on basis of: ((DC)) + (A) + 1; DC0 <- (DC0) + 1; DC <- (DC) + (A) case 0x8E: ADC(); break; // DC <- (DC) + (A) - case 0x8F: BR7(); break; // DC <- (DC) + (A) - case 0x90: BF(0); break; // PC0 <- PC0+n+1 - case 0x91: BF(1); break; // PC0 <- PC0+n+1 - case 0x92: BF(2); break; // PC0 <- PC0+n+1 - case 0x93: BF(3); break; // PC0 <- PC0+n+1 - case 0x94: BF(4); break; // PC0 <- PC0+n+1 - case 0x95: BF(5); break; // PC0 <- PC0+n+1 - case 0x96: BF(6); break; // PC0 <- PC0+n+1 - case 0x97: BF(7); break; // PC0 <- PC0+n+1 - case 0x98: BF(8); break; // PC0 <- PC0+n+1 - case 0x99: BF(9); break; // PC0 <- PC0+n+1 - case 0x9A: BF(10); break; // PC0 <- PC0+n+1 - case 0x9B: BF(11); break; // PC0 <- PC0+n+1 - case 0x9C: BF(12); break; // PC0 <- PC0+n+1 - case 0x9D: BF(13); break; // PC0 <- PC0+n+1 - case 0x9E: BF(14); break; // PC0 <- PC0+n+1 - case 0x9F: BF(15); break; // PC0 <- PC0+n+1 + case 0x8F: BR7(); break; // Branch on ISAR (any of the low 3 bits of ISAR are reset) + case 0x90: BF(0); break; // Unconditional branch (always) + case 0x91: BF(1); break; // Branch if negative (sign bit is reset) + case 0x92: BF(2); break; // Branch if no carry (carry bit is reset) + case 0x93: BF(3); break; // Branch on false - test operand against W register + case 0x94: BF(4); break; // Branch on not zero (zero bit is reset) + case 0x95: BF(5); break; // Branch on false - test operand against W register + case 0x96: BF(6); break; // Branch on false - test operand against W register + case 0x97: BF(7); break; // Branch on false - test operand against W register + case 0x98: BF(8); break; // Branch if no overflow (OVF bit is reset) + case 0x99: BF(9); break; // Branch on false - test operand against W register + case 0x9A: BF(10); break; // Branch on false - test operand against W register + case 0x9B: BF(11); break; // Branch on false - test operand against W register + case 0x9C: BF(12); break; // Branch on false - test operand against W register + case 0x9D: BF(13); break; // Branch on false - test operand against W register + case 0x9E: BF(14); break; // Branch on false - test operand against W register + case 0x9F: BF(15); break; // Branch on false - test operand against W register case 0xA0: INS_0(0); break; // A <- (I/O Port 0 or 1) case 0xA1: INS_0(1); break; // A <- (I/O Port 0 or 1) diff --git a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.Operations.cs b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.Operations.cs new file mode 100644 index 0000000000..7698d0060a --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.Operations.cs @@ -0,0 +1,281 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using BizHawk.Common.NumberExtensions; + +namespace BizHawk.Emulation.Cores.Consoles.ChannelF +{ + /// + /// ALU Operations + /// + public sealed partial class F3850 + { + public void Read_Func(ushort dest, ushort src_l, ushort src_h) + { + Regs[dest] = ReadMemory((ushort)(Regs[src_l] | (Regs[src_h]) << 8)); + } + + public void Write_Func(ushort dest_l, ushort dest_h, ushort src) + { + WriteMemory((ushort)(Regs[dest_l] | (Regs[dest_h] << 8)), (byte)Regs[src]); + } + + public void IN_Func(ushort dest, ushort src) + { + Regs[dest] = ReadHardware(Regs[src]); + } + + public void LR_A_IO_Func(ushort dest, ushort src) + { + // helper method that simulates transferring DB to accumulator (as part of an IN operation) + // this sets flags accordingly + // dest should always == A and src should always == DB for this function + + // overflow and carry unconditionally reset + FlagO = false; + FlagC = false; + + Regs[dest] = Regs[src]; + + FlagZ = Regs[dest] == 0; + + // Sign SET if MSB == 0 (positive signed number) + FlagS = Regs[dest].Bit(7) == false; + + // ICB flag not affected + } + + public void ClearFlags_Func() + { + FlagC = false; + FlagO = false; + FlagS = false; + FlagZ = false; + } + + public void LR_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 if (dest == ISAR) + { + // mask for ISAR register + Regs[dest] = (ushort)(Regs[src] & 0x3F); + } + else + { + Regs[dest] = Regs[src]; + } + } + + /// + /// Right shift 'src' 'shift' positions (zero fill) + /// + /// + /// + public void SR_Func(ushort src, ushort shift) + { + // overflow and carry unconditionally reset + FlagO = false; + FlagC = false; + + Regs[src] = (ushort)((Regs[src] >> shift) & 0xFF); + + FlagZ = Regs[src] == 0; + + // Sign SET if MSB == 0 (positive signed number) + FlagS = Regs[src].Bit(7) == false; + + // ICB flag not affected + } + + /// + /// Left shit 'src' 'shift' positions (zero fill) + /// + /// + /// + public void SL_Func(ushort src, ushort shift) + { + // overflow and carry unconditionally reset + FlagO = false; + FlagC = false; + + Regs[src] = (ushort)((Regs[src] << shift) & 0xFF); + + FlagZ = Regs[src] == 0; + + // Sign SET if MSB == 0 (positive signed number) + FlagS = Regs[src].Bit(7) == false; + + // ICB flag not affected + } + + public void ADD_Func(ushort dest, ushort src) + { + // addition of 2 signed bytes + ushort dest16 = Regs[dest]; + + dest16 += Regs[src]; + + FlagC = dest16.Bit(8); + FlagZ = (dest16 & 0xFF) == 0; + + ushort ans = (ushort)(dest16 & 0xFF); + + // Sign SET if MSB == 0 (positive signed number) + FlagS = ans.Bit(7) == false; + + // overflow based on carry out of bit6 XOR carry out of bit7 + var b6c = dest16 >> 7; + var b7c = dest16 >> 8; + FlagO = (b6c ^ b7c) != 0; + + Regs[dest] = ans; + } + + public void SUB_Func(ushort dest, ushort src) + { + Regs[ALU0] = (ushort)((Regs[src] ^ 0xff) + 1); + ADD_Func(dest, ALU0); + } + + public void ADDD_Func(ushort dest, ushort src) + { + var d = Regs[dest]; + var s = Regs[src]; + var bcdRes = d + s; + + var carryIntermediate = ((d & 0x0F) + (s & 0x0F)) > 0x0F; + var carryUpper = bcdRes >= 0x100; + + // temporary storage and set flags + Regs[ALU0] = Regs[dest]; + Regs[ALU1] = Regs[src]; + ADD_Func(ALU0, ALU1); + + if (!carryIntermediate) + { + bcdRes = (bcdRes & 0xF0) | ((bcdRes + 0x0A) & 0x0F); + } + + if (!carryUpper) + { + bcdRes = (bcdRes + 0xA0); + } + + Regs[dest] = (ushort)(bcdRes & 0xFF); + } + + public void CI_Func() + { + // compare immediate + // we need to achieve DB - A + 1 + // flags set - results not stored + var comp = ((Regs[A] ^ 0xFF) + 1); + Regs[ALU0] = (ushort)comp; + ADD_Func(DB, ALU0); + } + + public void ADDD_Func_(ushort dest, ushort src) + { + // from MAME f8.cpp (BSD-3) + // https://github.com/mamedev/mame/blob/97b67170277437131adf6ed4d60139c172529e4f/src/devices/cpu/f8/f8.cpp#L264 + byte d = (byte)Regs[dest]; + byte s = (byte)Regs[src]; + byte tmp = (byte)(d + s); + + byte c = 0; // high order carry + byte ic = 0; // low order carry + + if (((d + s) & 0xFF0) > 0xF0) + { + c = 1; + } + + if ((d & 0x0F) + (s & 0x0F) > 0x0F) + { + ic = 1; + } + + //ALU_ClearFlags(); + ALU_ADD8_FLAGSONLY_Func(dest, src); + Regs[ALU0] = tmp; + //ALU_SetFlags_SZ(ALU0); + + if (c == 0 && ic == 0) + { + tmp = (byte)(((tmp + 0xa0) & 0xf0) + ((tmp + 0x0a) & 0x0f)); + } + + if (c == 0 && ic == 1) + { + tmp = (byte)(((tmp + 0xa0) & 0xf0) + (tmp & 0x0f)); + } + + if (c == 1 && ic == 0) + { + tmp = (byte)((tmp & 0xf0) + ((tmp + 0x0a) & 0x0f)); + } + + Regs[dest] = tmp; + } + + public void AND_Func(ushort dest, ushort src) + { + // overflow and carry unconditionally reset + FlagO = false; + FlagC = false; + + Regs[dest] = (ushort)(Regs[dest] & Regs[src]); + + FlagZ = Regs[src] == 0; + + // Sign SET if MSB == 0 (positive signed number) + FlagS = Regs[src].Bit(7) == false; + + // ICB flag not affected + } + + public void OR_Func(ushort dest, ushort src) + { + // overflow and carry unconditionally reset + FlagO = false; + FlagC = false; + + Regs[dest] = (ushort)(Regs[dest] | Regs[src]); + + FlagZ = Regs[src] == 0; + + // Sign SET if MSB == 0 (positive signed number) + FlagS = Regs[src].Bit(7) == false; + + // ICB flag not affected + } + + public void XOR_Func(ushort dest, ushort src) + { + // overflow and carry unconditionally reset + FlagO = false; + FlagC = false; + + Regs[dest] = (ushort)(Regs[dest] ^ Regs[src]); + + FlagZ = Regs[src] == 0; + + // Sign SET if MSB == 0 (positive signed number) + FlagS = Regs[src].Bit(7) == false; + + // ICB flag not affected + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.Registers.cs b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.Registers.cs index 6e5e057dd4..b426d9d4e4 100644 --- a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.Registers.cs +++ b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.Registers.cs @@ -189,6 +189,10 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF Regs[ONE] = 1; Regs[BYTE] = 0xFF; + + // testing only - fill scratchpad with 0xff + for (int i = 0; i < 64; i++) + Regs[i] = 0xff; } } } diff --git a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.Tables.cs b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.Tables.cs index 7bd4680a4f..ef80c0e7a7 100644 --- a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.Tables.cs +++ b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.Tables.cs @@ -190,8 +190,8 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF { PopulateCURINSTR( // L - OP_LR8, DB, Ql, // DB <- (r15) - IDLE, + OP_LR8, DB, Ql, // DB <- (r15) + OP_EI, // Set ICB Flag IDLE, ROMC_17, // PC0l <- (DB) IDLE, @@ -364,7 +364,8 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF { PopulateCURINSTR( // S - OP_COM, // A <- A XOR 0xFF (compliment accumulator) + OP_XOR8, A, BYTE, // A <- A XOR 0xFF (compliment accumulator) + //OP_COM, // A <- A XOR 0xFF (compliment accumulator) ROMC_00_S, // DB <- ((PC0)); PC0++ IDLE, END); @@ -420,7 +421,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF IDLE, // S ROMC_00_S, // DB <- ((PC0)); PC0++ - IDLE, + OP_EI, // Set ICB Flag IDLE, END); } @@ -435,7 +436,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF IDLE, // S ROMC_00_S, // DB <- ((PC0)); PC0++ - IDLE, + OP_EI, // Set ICB Flag IDLE, END); } @@ -466,9 +467,9 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF // L ROMC_03_L, // DB <- ((PC0)); PC0++ IDLE, - OP_CLEAR_FLAGS, + IDLE, //OP_CLEAR_FLAGS, OP_LR8, A, DB, // A <- (DB) - OP_SET_FLAGS_SZ, A, + IDLE, //OP_SET_FLAGS_SZ, A, IDLE, // S ROMC_00_S, // DB <- ((PC0)); PC0++ @@ -534,9 +535,9 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF // L ROMC_03_L, // DB <- ((PC0)); PC0++ IDLE, - OP_CLEAR_FLAGS, + IDLE, OP_ADD8, A, DB, // A <- (A) + (DB) - OP_SET_FLAGS_SZ, A, + IDLE, IDLE, // S ROMC_00_S, // DB <- ((PC0)); PC0++ @@ -551,8 +552,8 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF // L ROMC_03_L, // DB <- ((PC0)); PC0++ IDLE, - OP_CLEAR_FLAGS, - OP_CI, A, DB, // Set flags for A <- (A) + (DB) + 1 (do not store result in A) + IDLE, + OP_CI, // Set flags for A <- (DB) + (-A) + 1 (do not store result in A) IDLE, IDLE, // S @@ -580,16 +581,16 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF ROMC_03_L, // DB/IO <- ((PC0)); PC0++ IDLE, IDLE, - OP_CLEAR_FLAGS, + IDLE, IDLE, IDLE, // L ROMC_1B, // DB <- ((IO)); IDLE, IDLE, - OP_LR8, A, DB, // A <- (DB) + OP_LR_A_DB_IO, A, DB, // A <- (DB) - flags set as result of IN or INS operation + IDLE, IDLE, - OP_SET_FLAGS_SZ, A, // S ROMC_00_S, // DB <- ((PC0)); PC0++ IDLE, @@ -616,7 +617,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF IDLE, // S ROMC_00_S, // DB <- ((PC0)); PC0++ - IDLE, + OP_EI, // Set ICB Flag IDLE, END); } @@ -652,7 +653,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF IDLE, // S ROMC_00_S, // DB <- ((PC0)); PC0++ - IDLE, + OP_EI, // Set ICB Flag IDLE, END); } @@ -683,7 +684,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF IDLE, // S ROMC_00_S, // DB <- ((PC0)); PC0++ - IDLE, + OP_EI, // Set ICB Flag IDLE, END); } @@ -749,11 +750,15 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF private void DS(ushort rIndex) { + // only scratch registers 0-16 + rIndex = (ushort)(rIndex & 0x0F); + PopulateCURINSTR( // L - OP_CLEAR_FLAGS, - OP_ADD8, rIndex, BYTE, - OP_SET_FLAGS_SZ, rIndex, + IDLE, + OP_SUB8, rIndex, ONE, + //OP_ADD8, rIndex, BYTE, + IDLE, ROMC_00_L, // DB <- ((PC0)); PC0++ IDLE, END); @@ -762,9 +767,9 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF { PopulateCURINSTR( // L - OP_CLEAR_FLAGS, - OP_ADD8, Regs[ISAR], BYTE, // r[ISAR] = r[ISAR] + 0xff - OP_SET_FLAGS_SZ, Regs[ISAR], + IDLE, + OP_SUB8, Regs[ISAR], ONE, // r[ISAR] = r[ISAR] + 0xff + IDLE, ROMC_00_L, // DB <- ((PC0)); PC0++ IDLE, END); @@ -774,9 +779,9 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF { PopulateCURINSTR( // L - OP_CLEAR_FLAGS, - OP_ADD8, Regs[ISAR], BYTE, // r[ISAR] = r[ISAR] + 0xff - OP_SET_FLAGS_SZ, Regs[ISAR], + IDLE, + OP_SUB8, Regs[ISAR], ONE, // r[ISAR] = r[ISAR] + 0xff + IDLE, OP_IS_INC, // Inc ISAR ROMC_00_L, // DB <- ((PC0)); PC0++ END); @@ -786,9 +791,9 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF { PopulateCURINSTR( // L - OP_CLEAR_FLAGS, - OP_ADD8, Regs[ISAR], BYTE, // r[ISAR] = r[ISAR] + 0xff - OP_SET_FLAGS_SZ, Regs[ISAR], + IDLE, + OP_SUB8, Regs[ISAR], ONE, // r[ISAR] = r[ISAR] + 0xff + IDLE, OP_IS_DEC, // Dec ISAR ROMC_00_L, // DB <- ((PC0)); PC0++ END); @@ -796,6 +801,9 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF private void LR_A_R(ushort rIndex) { + // only scratch registers 0-16 + rIndex = (ushort)(rIndex & 0x0F); + PopulateCURINSTR( // S OP_LR8, A, rIndex, // A <- (rIndex) @@ -836,6 +844,9 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF private void LR_R_A(ushort rIndex) { + // only scratch registers 0-16 + rIndex = (ushort)(rIndex & 0x0F); + PopulateCURINSTR( // S OP_LR8, rIndex, A, // rIndex <- (A) @@ -898,7 +909,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF { PopulateCURINSTR( // S - OP_LR8, A, index, // A <- index + OP_LIS, index, // A <- index ROMC_00_S, // DB <- ((PC0)); PC0++ IDLE, END); @@ -918,11 +929,11 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF { PopulateCURINSTR( // L - ROMC_02, // DB <- ((DC0)); DC0++ - OP_CLEAR_FLAGS, + ROMC_02, // DB <- ((DC0)); DC0++ + IDLE, + IDLE, + OP_ADD8, A, DB, // A <- (DB) IDLE, - OP_ADD8, A, DB, // A <- (DB) - OP_SET_FLAGS_SZ, A, IDLE, // S ROMC_00_S, // DB <- ((PC0)); PC0++ @@ -954,9 +965,9 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF // L ROMC_02, // DB <- ((DC0)); DC0++ IDLE, - OP_CLEAR_FLAGS, - OP_AND8, A, DB, // A <- (A) AND (DB) - OP_SET_FLAGS_SZ, A, + IDLE, + OP_AND8, A, DB, // A <- (A) AND (DB) + IDLE, IDLE, // S ROMC_00_S, // DB <- ((PC0)); PC0++ @@ -971,9 +982,9 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF // L ROMC_02, // DB <- ((DC0)); DC0++ IDLE, - OP_CLEAR_FLAGS, - OP_OR8, A, DB, // A <- (A) OR (DB) - OP_SET_FLAGS_SZ, A, + IDLE, + OP_OR8, A, DB, // A <- (A) OR (DB) + IDLE, IDLE, // S ROMC_00_S, // DB <- ((PC0)); PC0++ @@ -988,9 +999,9 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF // L ROMC_02, // DB <- ((DC0)); DC0++ IDLE, - OP_CLEAR_FLAGS, + IDLE, OP_XOR8, A, DB, // A <- (A) XOR (DB) - OP_SET_FLAGS_SZ, A, + IDLE, IDLE, // S ROMC_00_S, // DB <- ((PC0)); PC0++ @@ -1005,7 +1016,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF // L ROMC_02, // DB <- ((DC0)); DC0++ IDLE, - OP_CLEAR_FLAGS, + IDLE, OP_CI, A, IDLE, IDLE, @@ -1054,9 +1065,9 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF PopulateCURINSTR( // S ROMC_1C_S, // Idle - OP_CLEAR_FLAGS, - OP_IN, A, index, // A <- ((Port index - 0/1)) - OP_SET_FLAGS_SZ, A, + IDLE, + OP_IN, A, index, // A <- ((Port index - 0/1)) + OP_LR_A_DB_IO, A, A, // A <- (A) - flags set as result of IN or INS operation // S ROMC_00_S, // DB <- ((PC0)); PC0++ IDLE, @@ -1079,9 +1090,9 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF // L ROMC_1B, // DB <- ((IO)) IDLE, - OP_CLEAR_FLAGS, - OP_LR8, A, DB, // A <- (DB) - OP_SET_FLAGS_SZ, A, + IDLE, + OP_LR_A_DB_IO, A, DB, // A <- (DB) - flags set as result of IN or INS operation + IDLE, IDLE, // S ROMC_00_S, // DB <- ((PC0)); PC0++ @@ -1126,19 +1137,20 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF IDLE, // S ROMC_00_S, // DB <- ((PC0)); PC0++ - IDLE, + OP_EI, // Set ICB Flag IDLE, END); } private void AS(ushort rIndex) { - ALU_ClearFlags(); // clear flags early (as not enough cycle space for commands) + // only scratch registers 0-15 + rIndex = (ushort) (rIndex & 0x0F); PopulateCURINSTR( // S - OP_ADD8, A, rIndex, // A <- (A) + (rIndex) - OP_SET_FLAGS_SZ, A, + OP_ADD8, A, rIndex, // A <- (A) + (rIndex) + IDLE, ROMC_00_S, // DB <- ((PC0)); PC0++ END); } @@ -1147,8 +1159,8 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF { PopulateCURINSTR( // S - OP_CLEAR_FLAGS, - OP_AS_IS, // A <- (A) + ((ISAR)); setSZ + IDLE, + OP_ADD8, A, Regs[ISAR], // A <- (A) + ((ISAR)); IDLE, ROMC_00_S, // DB <- ((PC0)); PC0++ END); @@ -1158,8 +1170,8 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF { PopulateCURINSTR( // S - OP_CLEAR_FLAGS, - OP_AS_IS, // A <- (A) + ((ISAR)); setSZ + IDLE, + OP_ADD8, A, Regs[ISAR], // A <- (A) + ((ISAR)); OP_IS_INC, // Inc ISAR ROMC_00_S, // DB <- ((PC0)); PC0++ END); @@ -1169,8 +1181,8 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF { PopulateCURINSTR( // S - OP_CLEAR_FLAGS, - OP_AS_IS, // A <- (A) + ((ISAR)); setSZ + IDLE, + OP_ADD8, A, Regs[ISAR], // A <- (A) + ((ISAR)); OP_IS_DEC, // Dec ISAR ROMC_00_S, // DB <- ((PC0)); PC0++ END); @@ -1178,6 +1190,9 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF private void ASD(ushort rIndex) { + // only scratch registers 0-15 + rIndex = (ushort)(rIndex & 0x0F); + PopulateCURINSTR( // S ROMC_1C_S, // Idle @@ -1238,11 +1253,14 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF private void XS(ushort rIndex) { + // only scratch registers 0-15 + rIndex = (ushort)(rIndex & 0x0F); + PopulateCURINSTR( // S - OP_CLEAR_FLAGS, - OP_XOR8, A, rIndex, // A <- (A) XOR (reg) - OP_SET_FLAGS_SZ, A, + IDLE, + OP_XOR8, A, rIndex, // A <- (A) XOR (reg) + IDLE, ROMC_00_S, // DB <- ((PC0)); PC0++ END); } @@ -1251,7 +1269,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF { PopulateCURINSTR( // S - OP_XS_IS, // A <- (A) XOR ((ISAR)) + OP_XOR8, A, Regs[ISAR], // A <- (A) XOR ((ISAR)) ROMC_00_S, // DB <- ((PC0)); PC0++ IDLE, END); @@ -1261,7 +1279,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF { PopulateCURINSTR( // S - OP_XS_IS, // A <- (A) XOR ((ISAR)) + OP_XOR8, A, Regs[ISAR], // A <- (A) XOR ((ISAR)) OP_IS_INC, // Inc ISAR ROMC_00_S, // DB <- ((PC0)); PC0++ END); @@ -1271,7 +1289,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF { PopulateCURINSTR( // S - OP_XS_IS, // A <- (A) XOR ((ISAR)) + OP_XOR8, A, Regs[ISAR], // A <- (A) XOR ((ISAR)) OP_IS_DEC, // Dec ISAR ROMC_00_S, // DB <- ((PC0)); PC0++ END); @@ -1279,12 +1297,13 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF private void NS(ushort rIndex) { - ALU_ClearFlags(); // clear flags early (as not enough cycle space for commands) + // only scratch registers 0-15 + rIndex = (ushort)(rIndex & 0x0F); PopulateCURINSTR( // S OP_AND8, A, rIndex, // A <- (A) AND (reg) - OP_SET_FLAGS_SZ, A, + IDLE, ROMC_00_S, // DB <- ((PC0)); PC0++ END); } @@ -1293,7 +1312,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF { PopulateCURINSTR( // S - OP_NS_IS, // A <- (A) AND ((ISAR)) + OP_AND8, A, Regs[ISAR], // A <- (A) AND ((ISAR)) ROMC_00_S, // DB <- ((PC0)); PC0++ IDLE, END); @@ -1303,7 +1322,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF { PopulateCURINSTR( // S - OP_NS_IS, // A <- (A) AND ((ISAR)) + OP_AND8, A, Regs[ISAR], // A <- (A) AND ((ISAR)) OP_IS_INC, // Inc ISAR ROMC_00_S, // DB <- ((PC0)); PC0++ IDLE, @@ -1314,11 +1333,44 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF { PopulateCURINSTR( // S - OP_NS_IS, // A <- (A) AND ((ISAR)) + OP_AND8, A, Regs[ISAR], // A <- (A) AND ((ISAR)) OP_IS_DEC, // Dec ISAR ROMC_00_S, // DB <- ((PC0)); PC0++ IDLE, END); } + + + private void DO_BRANCH() + { + PopulateCURINSTR( + // L + IDLE, + ROMC_01, // forward or backward displacement + IDLE, + IDLE, + IDLE, + IDLE, + // S + ROMC_00_S, // DB <- ((PC0)); PC0++ + IDLE, + IDLE, + END); + } + + private void DONT_BRANCH() + { + PopulateCURINSTR( + // S + IDLE, + ROMC_03_S, // immediate operand fetch + IDLE, + IDLE, + // S + ROMC_00_S, // DB <- ((PC0)); PC0++ + IDLE, + IDLE, + END); + } } } diff --git a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.cs b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.cs index 42d0ac06c2..3e0b240769 100644 --- a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.cs +++ b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using BizHawk.Common; @@ -88,7 +89,8 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF public const ushort OP_AND8 = 107; public const ushort OP_OR8 = 108; public const ushort OP_XOR8 = 109; - public const ushort OP_COM = 110; + //public const ushort OP_COM = 110; + public const ushort OP_SUB8 = 110; public const ushort OP_ADD8 = 111; public const ushort OP_CI = 112; public const ushort OP_IS_INC = 113; @@ -101,11 +103,14 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF public const ushort OP_BF = 120; public const ushort OP_IN = 121; public const ushort OP_OUT = 122; - public const ushort OP_AS_IS = 123; - public const ushort OP_XS_IS = 124; - public const ushort OP_NS_IS = 125; - public const ushort OP_CLEAR_FLAGS = 126; - public const ushort OP_SET_FLAGS_SZ = 127; + //public const ushort OP_AS_IS = 123; + //public const ushort OP_XS_IS = 124; + //public const ushort OP_NS_IS = 125; + public const ushort OP_LR_A_DB_IO = 126; + public const ushort OP_DS = 127; + //public const ushort OP_CLEAR_FLAGS = 126; + //public const ushort OP_SET_FLAGS_SZ = 127; + public const ushort OP_LIS = 128; public F3850() @@ -135,7 +140,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF IDLE, END); - ALU_ClearFlags(); + ClearFlags_Func(); FlagICB = false; } @@ -191,52 +196,51 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF case IDLE: break; - // clears all flags except for ICB - case OP_CLEAR_FLAGS: - ALU_ClearFlags(); - break; - - // sets SIGN and CARRY flags based upon the supplied value - case OP_SET_FLAGS_SZ: - ALU_SetFlags_SZ(cur_instr[instr_pntr++]); - break; - // load one register into another (or databus) case OP_LR8: - LR8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + LR_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + + // load DB into A (as a part of an IN or INS instruction) + case OP_LR_A_DB_IO: + LR_A_IO_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + + // loads supplied index value into register + case OP_LIS: + Regs[ALU1] = (ushort)(cur_instr[instr_pntr++] & 0x0F); + LR_Func(A, ALU1); break; // Shift register n bit positions to the right (zero fill) case OP_SHFT_R: - ALU_SR_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + SR_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); break; // Shift register n bit positions to the left (zero fill) case OP_SHFT_L: - ALU_SL_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + SL_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); break; // x <- (x) ADD y case OP_ADD8: - ALU_ADD8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + ADD_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + + // x <- (x) MINUS y + case OP_SUB8: + SUB_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); break; // x <- (x) ADD y (decimal) case OP_ADD8D: - ALU_ADD8D_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + ADDD_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); break; // A <- (A) + (C) case OP_LNK: - bool fc = FlagC; - ALU_ClearFlags(); - - if (fc) - { - ALU_ADD8_Func(A, ONE); - } - - ALU_SetFlags_SZ(A); + Regs[ALU0] = (ushort)(FlagC ? 1 : 0); + ADD_Func(A, ALU0); break; // Clear ICB status bit @@ -251,38 +255,27 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF // x <- (y) XOR DB case OP_XOR8: - ALU_XOR8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); - break; - - // x <- (y) XOR DB (complement accumulator) - case OP_COM: - Regs[A] = (byte)~Regs[A]; - ALU_ClearFlags(); - ALU_SetFlags_SZ(A); + XOR_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); break; // x <- (x) + 1 case OP_INC8: - ALU_ClearFlags(); - ALU_ADD8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); - ALU_SetFlags_SZ(A); + ADD_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); break; // x <- (y) & DB case OP_AND8: - ALU_AND8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + AND_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); break; // x <- (y) | DB case OP_OR8: - ALU_OR8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + OR_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); break; // DB + (x) + 1 (modify flags without saving result) case OP_CI: - Regs[ALU0] = (byte)~Regs[cur_instr[instr_pntr++]]; - ALU_ADD8_Func(ALU0, DB, true); - ALU_SetFlags_SZ(ALU0); + CI_Func(); break; // ISAR is incremented @@ -297,124 +290,178 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF // set the upper octal ISAR bits (b3,b4,b5) case OP_LISU: - Regs[ISAR] = (ushort) (((Regs[ISAR] & 0x07) | cur_instr[instr_pntr++]) & 0x3F); + Regs[ISAR] = (ushort)((((Regs[ISAR] & 0x07) | (cur_instr[instr_pntr++] & 0x07) << 3)) & 0x3F); break; // set the lower octal ISAR bits (b0,b1,b2) case OP_LISL: - Regs[ISAR] = (ushort) (((Regs[ISAR] & 0x38) | cur_instr[instr_pntr++]) & 0x3F); + Regs[ISAR] = (ushort) (((Regs[ISAR] & 0x38) | (cur_instr[instr_pntr++] & 0x07)) & 0x3F); break; - // test operand against status register + // decrement scratchpad byte + //case OP_DS: + //SUB_Func(cur_instr[instr_pntr++], ONE); + //break; + + // Branch on TRUE case OP_BT: - if ((Regs[W] & cur_instr[instr_pntr++]) != 0) + bool branchBT = false; + switch (cur_instr[instr_pntr++]) { - instr_pntr = 0; - PopulateCURINSTR( - // L - ROMC_01, - IDLE, - IDLE, - IDLE, - IDLE, - IDLE, - // S - ROMC_00_S, // DB <- ((PC0)); PC0++ - IDLE, - IDLE, - END); - } - else - { - instr_pntr = 0; - PopulateCURINSTR( - // S - ROMC_03_S, - IDLE, - IDLE, - IDLE, - // S - ROMC_00_S, // DB < -((PC0)); PC0++ - IDLE, - IDLE, - END); + case 0: + // do not branch + break; + + case 1: + // branch if positive (sign bit is set) + if (FlagS) branchBT = true; + break; + + case 2: + // branch on carry (carry bit is set) + if (FlagC) branchBT = true; + break; + + case 3: + // branch if positive or on carry + if (FlagS || FlagC) branchBT = true; + break; + + case 4: + // branch if zero (zero bit is set) + if (FlagZ) branchBT = true; + break; + + case 5: + // branch if positive (same as t==1) + if (FlagS) branchBT = true; + break; + + case 6: + // branch if zero or on carry + if (FlagZ || FlagC) branchBT = true; + break; + case 7: + // branch if positive or on carry (same as t==3) + if (FlagS || FlagC) branchBT = true; + break; } + + instr_pntr = 0; + if (branchBT) DO_BRANCH(); + else DONT_BRANCH(); break; - // Branch based on ISARL + // Branch on ISARL case OP_BR7: - if ((Regs[ISAR] & 7) == 7) + instr_pntr = 1; // lose a cycle + if (!Regs[ISAR].Bit(0) || !Regs[ISAR].Bit(1) || !Regs[ISAR].Bit(2)) { - instr_pntr = 0; - PopulateCURINSTR( - // S - ROMC_03_S, // DB/IO <- ((PC0)); PC0++ - //IDLE, <- lose a cycle that was stolen in the table - IDLE, - IDLE, - // S - ROMC_00_S, // DB <- ((PC0)); PC0++ - IDLE, - IDLE, - END); + DO_BRANCH(); } else { - instr_pntr = 0; - PopulateCURINSTR( - // L - ROMC_01, - //IDLE, <- lose a cycle that was stolen in the table - IDLE, - IDLE, - IDLE, - IDLE, - ROMC_00_S, // DB <- ((PC0)); PC0++ - IDLE, - IDLE, - END); + DONT_BRANCH(); } break; - // PC0 <- PC0+n+1 + // Branch on FALSE case OP_BF: - if ((Regs[W] & cur_instr[instr_pntr++]) != 0) + bool branchBF = false; + switch (cur_instr[instr_pntr++]) { - instr_pntr = 0; - PopulateCURINSTR( - // S - ROMC_03_S, // DB/IO <- ((PC0)); PC0++ - IDLE, - IDLE, - IDLE, - // S - ROMC_00_S, // DB <- ((PC0)); PC0++ - IDLE, - IDLE, - END); - } - else - { - instr_pntr = 0; - PopulateCURINSTR( - // L - ROMC_01, - IDLE, - IDLE, - IDLE, - IDLE, - IDLE, - // S - ROMC_00_S, // DB <- ((PC0)); PC0++ - IDLE, - IDLE, - END); + case 0: + // unconditional branch relative + branchBF = true; + break; + + case 1: + // branch on negative (sign bit is reset) + if (!FlagS) branchBF = true; + break; + + case 2: + // branch if no carry (carry bit is reset) + if (!FlagC) branchBF = true; + break; + + case 3: + // branch if no carry and negative + if (!FlagC && !FlagS) branchBF = true; + break; + + case 4: + // branch if not zero (zero bit is reset) + if (!FlagZ) branchBF = true; + break; + + case 5: + // same as t==1 + if (!FlagS) branchBF = true; + break; + + case 6: + // branch if no carry and result is no zero + if (!FlagC && !FlagZ) branchBF = true; + break; + + case 7: + // same as t==3 + if (!FlagS && !FlagC) branchBF = true; + break; + + case 8: + // branch if there is no overflow (OVF bit is reset) + if (!FlagO) branchBF = true; + break; + + case 9: + // branch if negative and no overflow + if (!FlagS && !FlagO) branchBF = true; + break; + + case 0xA: + // branch if no overflow and no carry + if (!FlagO && !FlagC) branchBF = true; + break; + + case 0xB: + // branch if no overflow, no carry & negative + if (!FlagO && !FlagC && !FlagS) branchBF = true; + break; + + case 0xC: + // branch if no overflow and not zero + if (!FlagO && !FlagZ) branchBF = true; + break; + + case 0xD: + // same as t==9 + if (!FlagS && !FlagO) branchBF = true; + break; + + case 0xE: + // branch if no overflow, no carry & not zero + if (!FlagO && !FlagC && !FlagZ) branchBF = true; + break; + + case 0xF: + // same as t=0xB + if (!FlagO && !FlagC && !FlagS) branchBF = true; + break; } + + instr_pntr = 0; + if (branchBF) DO_BRANCH(); + else DONT_BRANCH(); break; // A <- (I/O Port 0 or 1) case OP_IN: - Regs[cur_instr[instr_pntr++]] = ReadHardware(cur_instr[instr_pntr++]); + instr_pntr++; // dest == A + Regs[ALU0] = cur_instr[instr_pntr++]; // src + IN_Func(A, ALU0); + //Regs[cur_instr[instr_pntr++]] = ReadHardware(cur_instr[instr_pntr++]); break; // I/O Port 0 or 1 <- (A) @@ -423,28 +470,6 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF //OUT_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); break; - // Add the content of the SR register addressed by ISAR to A (Binary) - case OP_AS_IS: - ALU_ClearFlags(); - ALU_ADD8_Func(A, Regs[ISAR]); - ALU_SetFlags_SZ(A); - break; - - // XOR the content of the SR register addressed by ISAR to A - case OP_XS_IS: - ALU_ClearFlags(); - ALU_XOR8_Func(A, Regs[ISAR]); - ALU_SetFlags_SZ(A); - break; - - // AND the content of the SR register addressed by ISAR to A - case OP_NS_IS: - ALU_ClearFlags(); - ALU_AND8_Func(A, Regs[ISAR]); - ALU_SetFlags_SZ(A); - 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. @@ -650,7 +675,8 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF // registers cannot be read back onto the data bus) // CYCLE LENGTH: L case ROMC_1B: - Regs[DB] = ReadHardware(Regs[IO]); + IN_Func(DB, IO); + //Regs[DB] = ReadHardware(Regs[IO]); break; // None @@ -687,7 +713,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF public Action TraceCallback; - public string TraceHeader => "F3850: PC, machine code, mnemonic, operands, registers (R0, R1, R2, R3, R4, R5, R6, R7, R8, J, HU, HL, KU, KL, QU, QL, Cy), flags (IOZCS)"; + public string TraceHeader => "F3850: PC, machine code, mnemonic, operands, flags (IOZCS), registers (PC1, DC0, A, ISAR, DB, IO, J, H, K, Q, R00-R63), Cycles"; public TraceInfo State(bool disassemble = true) { @@ -713,29 +739,40 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF byte_code.PadRight(12), disasm.PadRight(26)), RegisterInfo = string.Format( - "R0:{0:X2} R1:{1:X2} R2:{2:X2} R3:{3:X2} R4:{4:X2} R5:{5:X2} R6:{6:X2} R7:{7:X2} R8:{8:X2} J:{9:X2} HU:{10:X2} HL:{11:X2} KU:{12:X2} KL:{13:X2} QU:{14:X2} QL:{15:X2} Cy:{16} {17}{18}{19}{20}{21}", - Regs[0], - Regs[1], - Regs[2], - Regs[3], - Regs[4], - Regs[5], - Regs[6], - Regs[7], - Regs[8], + "Flags:{75}{76}{77}{78}{79} " + + "PC1:{0:X4} DC0:{1:X4} A:{2:X2} ISAR:{3:X2} DB:{4:X2} IO:{5:X2} J:{6:X2} H:{7:X4} K:{8:X4} Q:{9:X4} " + + "R0:{10:X2} R1:{11:X2} R2:{12:X2} R3:{13:X2} R4:{14:X2} R5:{15:X2} R6:{16:X2} R7:{17:X2} R8:{18:X2} R9:{19:X2} " + + "R10:{20:X2} R11:{21:X2} R12:{22:X2} R13:{23:X2} R14:{24:X2} R15:{25:X2} R16:{26:X2} R17:{27:X2} R18:{28:X2} R19:{29:X2} " + + "R20:{30:X2} R21:{31:X2} R22:{32:X2} R23:{33:X2} R24:{34:X2} R25:{35:X2} R26:{36:X2} R27:{37:X2} R28:{38:X2} R29:{39:X2} " + + "R30:{40:X2} R31:{41:X2} R32:{42:X2} R33:{43:X2} R34:{44:X2} R35:{45:X2} R36:{46:X2} R37:{47:X2} R38:{48:X2} R39:{49:X2} " + + "R40:{50:X2} R41:{51:X2} R42:{52:X2} R43:{53:X2} R44:{54:X2} R45:{55:X2} R46:{56:X2} R47:{57:X2} R48:{58:X2} R49:{59:X2} " + + "R50:{60:X2} R51:{61:X2} R52:{62:X2} R53:{63:X2} R54:{64:X2} R55:{65:X2} R56:{66:X2} R57:{67:X2} R58:{68:X2} R59:{69:X2} " + + "R60:{70:X2} R61:{71:X2} R62:{72:X2} R63:{73:X2} " + + "Cy:{74}", + RegPC1, + RegDC0, + Regs[A], + Regs[ISAR], + Regs[DB], + Regs[IO], Regs[J], - Regs[Hh], - Regs[Hl], - Regs[Kh], - Regs[Kl], - Regs[Qh], - Regs[Ql], + (ushort)(Regs[Hl] | (Regs[Hh] << 8)), + (ushort)(Regs[Kl] | (Regs[Kh] << 8)), + (ushort)(Regs[Ql] | (Regs[Qh] << 8)), + Regs[0], Regs[1], Regs[2], Regs[3], Regs[4], Regs[5], Regs[6], Regs[7], Regs[8], Regs[9], + Regs[10], Regs[11], Regs[12], Regs[13], Regs[14], Regs[15], Regs[16], Regs[17], Regs[18], Regs[19], + Regs[20], Regs[21], Regs[22], Regs[23], Regs[24], Regs[25], Regs[26], Regs[27], Regs[28], Regs[29], + Regs[30], Regs[31], Regs[32], Regs[33], Regs[34], Regs[35], Regs[36], Regs[37], Regs[38], Regs[39], + Regs[40], Regs[41], Regs[42], Regs[43], Regs[44], Regs[45], Regs[46], Regs[47], Regs[48], Regs[49], + Regs[50], Regs[51], Regs[52], Regs[53], Regs[54], Regs[55], Regs[56], Regs[57], Regs[58], Regs[59], + Regs[60], Regs[61], Regs[62], Regs[63], TotalExecutedCycles, FlagICB ? "I" : "i", FlagO ? "O" : "o", FlagZ ? "Z" : "z", FlagC ? "C" : "c", - FlagS ? "S" : "s") + FlagS ? "S" : "s"), + }; } diff --git a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Memory.cs b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Memory.cs new file mode 100644 index 0000000000..6cf6ced0ca --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Memory.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BizHawk.Emulation.Cores.Consoles.ChannelF +{ + /// + /// Memory and related functions + /// + public partial class ChannelF + { + public byte[] BIOS01 = new byte[1024]; + public byte[] BIOS02 = new byte[1024]; + + /// + /// Simulates reading a byte of data from the address space + /// + /// + /// + 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 0; + return Rom[addr - 0x800]; + } + + return 0xFF; + } + + /// + /// Simulates writing a byte of data to the address space (in its default configuration, there is no writeable RAM in the + /// Channel F addressable through the address space) + /// + /// + /// + public void WriteBus(ushort addr, byte value) + { + + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Ports.cs b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Ports.cs new file mode 100644 index 0000000000..079f952168 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Ports.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Remoting.Messaging; +using System.Text; +using System.Threading.Tasks; +using BizHawk.Common.NumberExtensions; + +namespace BizHawk.Emulation.Cores.Consoles.ChannelF +{ + /// + /// Ports and related functions + /// + public partial class ChannelF + { + /// + /// The Channel F has 4 8-bit IO ports connected. + /// CPU - ports 0 and 1 + /// PSU - ports 4 and 5 + /// (the second PSU has no IO ports wired up) + /// + public byte[] PortLatch = new byte[4]; + + public bool ControllersEnabled; + + public const int PORT0 = 0; + public const int PORT1 = 1; + public const int PORT4 = 2; + public const int PORT5 = 3; + + /// + /// CPU attempts to read data byte from the requested port + /// + /// + /// + public byte ReadPort(ushort addr) + { + byte port = (byte) (addr & 0x07); + + switch (port) + { + // Console buttons + // b0: TIME + // b1: MODE + // b2: HOLD + // b3: START + case 0: + return (byte)((DataConsole ^ 0xFF) & 0x0F); + + // Right controller + // b0: RIGHT + // b1: LEFT + // b2: BACK + // b3: FORWARD + // b4: CCW + // b5: CW + // b6: PULL + // b7: PUSH + case 1: + if (ControllersEnabled) + { + return (byte)((DataRight ^ 0xFF) & 0xFF); + } + return 0; + + // Left controller + // b0: RIGHT + // b1: LEFT + // b2: BACK + // b3: FORWARD + // b4: CCW + // b5: CW + // b6: PULL + // b7: PUSH + case 4: + if (ControllersEnabled) + { + return (byte)((DataLeft ^ 0xFF) & 0xFF); + } + return 0; + } + + return 0xFF; + } + + /// + /// CPU attempts to write data to the requested port (latch) + /// + /// + /// + public void WritePort(ushort addr, byte value) + { + byte port = (byte)(addr & 0x07); + + switch (port) + { + case 0: + + ControllersEnabled = (value & 0x40) == 0; + + var val = value & 0x60; + if (val == 0x40)// && _arm == 0x60) + { + VRAM[(128 * _y) + _x] = (byte)_colour; + } + + /* + + // RAM WRT - A pulse here executes a write to video RAM + bool ramWrt = value.Bit(5); + + // Enable data from controllers (1 equals enable) + // also needs pulse to write to video RAM + bool controllerDataEnable = value.Bit(6); + + if (ramWrt || controllerDataEnable) + { + // triggered write to VRAM + var yxIndex = (_y * 128) + _x; + var byteIndex = yxIndex / 4; + var byteRem = yxIndex % 4; + + switch (byteRem) + { + case 0: + VRAM[byteIndex] |= (byte) _colour; + break; + case 1: + VRAM[byteIndex] |= (byte) (_colour << 2); + break; + case 2: + VRAM[byteIndex] |= (byte)(_colour << 4); + break; + case 3: + VRAM[byteIndex] |= (byte)(_colour << 6); + break; + } + + } + */ + + _arm = value; + + PortLatch[PORT0] = value; + + break; + + case 1: + + // Write Data0 - indicates that valid data is present for both VRAM ODD0 and EVEN0 + bool data0 = value.Bit(6); + // Write Data1 - indicates that valid data is present for both VRAM ODD1 and EVEN1 + bool data1 = value.Bit(7); + + _colour = ((value ^ 0xff) >> 6) & 0x03; + + PortLatch[PORT1] = value; + + break; + + case 4: + + // video horizontal position + // 0 - video select + // 1-6 - horiz A-F + + _x = (value ^ 0xff) & 0x7f; + + PortLatch[PORT4] = value; + + break; + + + case 5: + + // video vertical position and sound + // 0-5 - Vertical A-F + // 6 - Tone AN, 7 - Tone BN + + _y = (value ^ 0xff) & 0x3f; + + PortLatch[PORT5] = value; + + break; + } + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Video.cs b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Video.cs new file mode 100644 index 0000000000..864e228c2a --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Video.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using BizHawk.Common; + +namespace BizHawk.Emulation.Cores.Consoles.ChannelF +{ + /// + /// Video related functions + /// + public partial class ChannelF + { + /// + /// 128x64 pixels - 8192x2bits (2 KB) + /// For the purposes of this core we will use 8192 bytes and just & 0x03 + /// + public byte[] VRAM = new byte[(128 * 64)]; + + public static readonly int[] FPalette = + { + Colors.ARGB(0x10, 0x10, 0x10), // Black + Colors.ARGB(0xFD, 0xFD, 0xFD), // White + Colors.ARGB(0xFF, 0x31, 0x53), // Red + Colors.ARGB(0x02, 0xCC, 0x5D), // Green + Colors.ARGB(0x4B, 0x3F, 0xF3), // Blue + Colors.ARGB(0xE0, 0xE0, 0xE0), // Gray + Colors.ARGB(0x91, 0xFF, 0xA6), // BGreen + Colors.ARGB(0xCE, 0xD0, 0xFF), // BBlue + }; + + public static readonly int[] CMap = + { + 0, 1, 1, 1, + 7, 4, 2, 3, + 5, 4, 2, 3, + 6, 4, 2, 3, + }; + + private int _colour = 2; + private int _x; + private int _y; + private int _arm; + + private int[] frameBuffer = new int[128 * 64]; + + private void BuildFrame() + { + // rows + int counter = 0; + for (int row = 0; row < 64; row++) + { + // columns 125 and 126 hold the palette index modifier for the entire row + var rIndex = 64 * row; + var c125 = (VRAM[rIndex + 125] & 0x02) >> 1; + var c126 = (VRAM[rIndex + 126] & 0x03); + var pModifier = ((c125 | c126) << 2) & 0x0C; + + // columns + for (int col = 0; col < 128; col++, counter++) + { + int colour = (VRAM[rIndex + col]) & 0x03; + var finalColorIndex = pModifier | colour; + var paletteLookup = CMap[finalColorIndex & 0x0f] & 0x07; + frameBuffer[counter] = FPalette[paletteLookup]; + } + } + } + + private void BuildFrame1() + { + int cnt = 0; + // rows + for (int row = 0; row < 64; row++) + { + var yIndex = row * 128; + var yByte = yIndex / 4; + + // last byte for this row contains palette modifier + var pModifier = (byte)(VRAM[yByte + 31] & 0x0C); + + // columns + for (int col = 0; col < 128; col++) + { + var fbIndex = (row * 64) + col; + + var xByte = col / 4; + var xRem = col % 4; + var xyByte = yByte + xByte; + + // each byte contains 4 pixel colour values, b0b1, b2b3, b4b5, b6b7 + int colour = 0; + + switch (xRem) + { + case 0: + colour = VRAM[xyByte] & 0x03; + break; + case 1: + colour = VRAM[xyByte] & 0x0C; + break; + case 2: + colour = VRAM[xyByte] & 0x30; + break; + case 3: + colour = VRAM[xyByte] & 0xC0; + break; + } + + var finalColorIndex = pModifier | colour; + var paletteLookup = CMap[finalColorIndex & 0x0f] & 0x07; + frameBuffer[fbIndex] = FPalette[paletteLookup]; + + cnt++; + } + } + } + } +}