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++;
+ }
+ }
+ }
+ }
+}