ChannelFHawk: CPU mostly there. It's running games now. Still need to work on input.

This commit is contained in:
ASNiVOR 2021-11-19 19:09:04 +00:00
parent c86691bfb1
commit c74b47315f
12 changed files with 1900 additions and 700 deletions

View File

@ -5,10 +5,10 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
{
public partial class ChannelF
{
public bool[] StateConsole = new bool[4];
public bool[] StateConsole = new bool[5];
public string[] ButtonsConsole =
{
"TIME", "MODE", "HOLD", "START"
"TIME", "MODE", "HOLD", "START", "RESET"
};
public byte DataConsole
@ -16,7 +16,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
get
{
int w = 0;
for (int i = 0; i < 4; i++)
for (int i = 0; i < 5; i++)
{
byte mask = (byte) (1 << i);
w = StateConsole[i] ? w | mask : w & ~mask;

View File

@ -8,11 +8,10 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
{
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);
ser.Sync(nameof(latch_colour), ref latch_colour);
ser.Sync(nameof(latch_x), ref latch_x);
ser.Sync(nameof(latch_y), ref latch_y);
//ser.Sync(nameof(ControllersEnabled), ref ControllersEnabled);
CPU.SyncState(ser);
ser.EndSection();
/*

View File

@ -5,15 +5,70 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
{
public partial class ChannelF : IVideoProvider, IRegionable
{
public int _frameHz = 60;
/// <summary>
/// 128x64 pixels - 8192x2bits (2 KB)
/// For the purposes of this core we will use 8192 bytes and just &amp; 0x03
/// </summary>
public byte[] VRAM = new byte[(128 * 64)];
public static readonly int[] FPalette =
{
//0x101010, 0xFDFDFD, 0x5331FF, 0x5DCC02, 0xF33F4B, 0xE0E0E0, 0xA6FF91, 0xD0CEFF
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 latch_colour = 2; //2;
private int latch_x;
private int latch_y;
private readonly int[] frameBuffer = new int[128 * 64];
private void BuildFrame()
{
for (int r = 0; r < 64; r++)
{
// lines
var p1 = (VRAM[(r * 0x80) + 125]) & 0x03;
var p2 = (VRAM[(r * 0x80) + 126]) & 0x03;
var pOffset = ((p2 & 0x02) | (p1 >> 1)) << 2;
for (int c = 0; c < 128; c++)
{
// columns
var colourIndex = pOffset + (VRAM[c | (r << 7)] & 0x03);
frameBuffer[(r << 7) + c] = CMap[colourIndex];
//frameBuffer[(r << 7) + c + 1] = CMap[colourIndex];
}
}
}
public int _frameHz = 60;
public int[] CroppedBuffer = new int[102 * 58];
public int VirtualWidth => BufferWidth * 2;
public int VirtualHeight => (int)((double)BufferHeight * 1.3) * 2;
public int BufferWidth => 102; //128
public int BufferHeight => 58; //64
public int BackgroundColor => Colors.ARGB(0x00, 0x00, 0x00);
public int BackgroundColor => Colors.ARGB(0xFF, 0xFF, 0xFF);
public int VsyncNumerator => _frameHz;
public int VsyncDenominator => 1;
@ -42,10 +97,6 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
}
return CroppedBuffer;
//return frameBuffer;
}
public DisplayType Region => DisplayType.NTSC;

View File

@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.ChannelF
@ -8,10 +10,18 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
public partial class ChannelF
{
[CoreConstructor(VSystemID.Raw.ChannelF)]
public ChannelF(CoreComm comm, GameInfo game, byte[] rom)
public ChannelF(CoreLoadParameters<ChannelFSettings, ChannelFSyncSettings> lp)
{
var ser = new BasicServiceProvider(this);
ServiceProvider = ser;
CoreComm = lp.Comm;
_gameInfo = lp.Roms.Select(r => r.Game).ToList();
_files = lp.Roms.Select(r => r.RomData).ToList();
var settings = lp.Settings ?? new ChannelFSettings();
var syncSettings = lp.SyncSettings ?? new ChannelFSyncSettings();
MemoryCallbacks = new MemoryCallbackSystem(new[] { "System Bus" });
ControllerDefinition = ChannelFControllerDefinition;
@ -27,12 +37,14 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
_tracer = new TraceBuffer(CPU.TraceHeader);
var bios01 = comm.CoreFileProvider.GetFirmwareOrThrow(new("ChannelF", "ChannelF_sl131253"));
var bios02 = comm.CoreFileProvider.GetFirmwareOrThrow(new("ChannelF", "ChannelF_sl131254"));
var bios01 = CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("ChannelF", "ChannelF_sl131253"));
var bios02 = CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("ChannelF", "ChannelF_sl131254"));
BIOS01 = bios01;
BIOS02 = bios02;
var rom = _files.First();
Array.Copy(rom, 0, Rom, 0, rom.Length);
CalcClock();
@ -45,6 +57,11 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
SetupMemoryDomains();
}
internal CoreComm CoreComm { get; }
public List<GameInfo> _gameInfo;
private readonly List<byte[]> _files;
public F3850 CPU;
private readonly TraceBuffer _tracer;
public IController _controller;

View File

@ -2,7 +2,7 @@
{
public sealed partial class F3850
{
public const int MaxInstructionLength = 40;
public const int MaxInstructionLength = 48;
public long TotalExecutedCycles;
@ -15,264 +15,268 @@
{
switch (opcode)
{
case 0x00: LR_A_KU(); break; // LR A, (KU)
case 0x01: LR_A_KL(); break; // LR A, (KL)
case 0x02: LR_A_QU(); break; // LR A, (QU)
case 0x03: LR_A_QL(); break; // LR A, (QL)
case 0x04: LR_KU_A(); break; // LR KU, (A)
case 0x05: LR_KL_A(); break; // LR KL, (A)
case 0x06: LR_QU_A(); break; // LR QU, (A)
case 0x07: LR_QL_A(); break; // LR QL, (A)
case 0x08: LR_K_P(); break; // LR K, (P)
case 0x09: LR_P_K(); break; // LR P, (K)
case 0x0A: LR_A_IS(); break; // LR A, (ISAR)
case 0x0B: LR_IS_A(); break; // LR ISAR, (A)
case 0x0C: PK(); break; // LR PC1, (PC0); LR PC0l <- (r13); LR PC0h, (r12)
case 0x0D: LR_P0_Q(); break; // LR PC0l, (r15); LR PC0h <- (r14)
case 0x0E: LR_Q_DC(); break; // LR r14, (DC0h); r15 <- (DC0l)
case 0x0F: LR_DC_Q(); break; // LR DC0h, (r14); DC0l <- (r15)
case 0x10: LR_DC_H(); break; // LR DC0h, (r10); DC0l <- (r11)
case 0x11: LR_H_DC(); break; // LR r10, (DC0h); r11 <- (DC0l)
case 0x12: SHIFT_R(1); break; // Shift (A) right one bit position (zero fill)
case 0x13: SHIFT_L(1); break; // Shift (A) left one bit position (zero fill)
case 0x14: SHIFT_R(4); break; // Shift (A) right four bit positions (zero fill)
case 0x15: SHIFT_L(4); break; // Shift (A) left four bit positions (zero fill)
case 0x16: LM(); break; // A <- ((DC0))
case 0x17: ST(); break; // (DC) <- (A)
case 0x18: COM(); break; // A <- A XOR 255 (complement A)
case 0x19: LNK(); break; // A <- (A) + (C)
case 0x1A: DI(); break; // Clear ICB
case 0x1B: EI(); break; // Set ICB
case 0x1C: POP(); break; // PC0 <- PC1
case 0x1D: LR_W_J(); break; // W <- (r9)
case 0x1E: LR_J_W(); break; // r9 <- (W)
case 0x1F: INC(); break; // A <- (A) + 1
case 0x20: LI(); break; // A <- H'aa'
case 0x21: NI(); break; // A <- (A) AND H'aa'
case 0x22: OI(); break; // A <- (A) OR H'aa'
case 0x23: XI(); break; // A <- (A) XOR H'aa'
case 0x24: AI(); break; // A <- (A) + H'aa'
case 0x25: CI(); break; // H'aa' + (A) + 1 (modify flags without saving result)
case 0x26: IN(); break; // DB <- PP; A <- (I/O Port PP)
case 0x27: OUT(); break; // DB <- PP; I/O Port PP <- (A)
case 0x28: PI(); break; // A <- H'ii'; PC1 <- (PC0) + 1; PC0l <- H'jj'; PC0h <- (A)
case 0x29: JMP(); break; // A <- H'ii'; PC0l <- H'jj'; PC0h <- (A)
case 0x2A: DCI(); break; // DC0h <- ii; increment PC0; DC0l <- jj; increment PC0
case 0x2B: NOP(); break; // No operation (4 cycles - fetch next opcode)
case 0x2C: XDC(); break; // DC0 <-> DC1
case 0x00: LR_A_KU(); break; // LR A, (KU)
case 0x01: LR_A_KL(); break; // LR A, (KL)
case 0x02: LR_A_QU(); break; // LR A, (QU)
case 0x03: LR_A_QL(); break; // LR A, (QL)
case 0x04: LR_KU_A(); break; // LR KU, (A)
case 0x05: LR_KL_A(); break; // LR KL, (A)
case 0x06: LR_QU_A(); break; // LR QU, (A)
case 0x07: LR_QL_A(); break; // LR QL, (A)
case 0x08: LR_K_P(); break; // LR K, (P)
case 0x09: LR_P_K(); break; // LR P, (K)
case 0x0A: LR_A_IS(); break; // LR A, (ISAR)
case 0x0B: LR_IS_A(); break; // LR ISAR, (A)
case 0x0C: PK(); break; // LR PC1, (PC0); LR PC0l <- (r13); LR PC0h, (r12)
case 0x0D: LR_P0_Q(); break; // LR PC0l, (r15); LR PC0h <- (r14)
case 0x0E: LR_Q_DC(); break; // LR r14, (DC0h); r15 <- (DC0l)
case 0x0F: LR_DC_Q(); break; // LR DC0h, (r14); DC0l <- (r15)
case 0x10: LR_DC_H(); break; // LR DC0h, (r10); DC0l <- (r11)
case 0x11: LR_H_DC(); break; // LR r10, (DC0h); r11 <- (DC0l)
case 0x12: SR(1); break; // Shift (A) right one bit position (zero fill)
case 0x13: SL(1); break; // Shift (A) left one bit position (zero fill)
case 0x14: SR(4); break; // Shift (A) right four bit positions (zero fill)
case 0x15: SL(4); break; // Shift (A) left four bit positions (zero fill)
case 0x16: LM(); break; // A <- ((DC0))
case 0x17: ST(); break; // (DC) <- (A)
case 0x18: COM(); break; // A <- A XOR 255 (complement A)
case 0x19: LNK(); break; // A <- (A) + (C)
case 0x1A: DI(); break; // Clear ICB
case 0x1B: EI(); break; // Set ICB
case 0x1C: POP(); break; // PC0 <- PC1
case 0x1D: LR_W_J(); break; // W <- (r9)
case 0x1E: LR_J_W(); break; // r9 <- (W)
case 0x1F: INC(); break; // A <- (A) + 1
case 0x20: LI(); break; // A <- H'aa'
case 0x21: NI(); break; // A <- (A) AND H'aa'
case 0x22: OI(); break; // A <- (A) OR H'aa'
case 0x23: XI(); break; // A <- (A) XOR H'aa'
case 0x24: AI(); break; // A <- (A) + H'aa'
case 0x25: CI(); break; // H'aa' + (A) + 1 (modify flags without saving result)
case 0x26: IN(); break; // DB <- PP; A <- (I/O Port PP)
case 0x27: OUT(); break; // DB <- PP; I/O Port PP <- (A)
case 0x28: PI(); break; // A <- H'ii'; PC1 <- (PC0) + 1; PC0l <- H'jj'; PC0h <- (A)
case 0x29: JMP(); break; // A <- H'ii'; PC0l <- H'jj'; PC0h <- (A)
case 0x2A: DCI(); break; // DC0h <- ii; increment PC0; DC0l <- jj; increment PC0
case 0x2B: NOP(); break; // No operation (4 cycles - fetch next opcode)
case 0x2C: XDC(); break; // DC0 <-> DC1
case 0x30: DS(0); break; // SR <- (SR) + H'FF'
case 0x31: DS(1); break; // SR <- (SR) + H'FF'
case 0x32: DS(2); break; // SR <- (SR) + H'FF'
case 0x33: DS(3); break; // SR <- (SR) + H'FF'
case 0x34: DS(4); break; // SR <- (SR) + H'FF'
case 0x35: DS(5); break; // SR <- (SR) + H'FF'
case 0x36: DS(6); break; // SR <- (SR) + H'FF'
case 0x37: DS(7); break; // SR <- (SR) + H'FF'
case 0x38: DS(8); break; // SR <- (SR) + H'FF'
case 0x39: DS(9); break; // SR <- (SR) + H'FF'
case 0x3A: DS(10); break; // SR <- (SR) + H'FF'
case 0x3B: DS(11); break; // SR <- (SR) + H'FF'
case 0x3C: DS_ISAR(); break; // SR <- (SR) + H'FF' (SR pointed to by the ISAR)
case 0x3D: DS_ISAR_INC(); break; // SR <- (SR) + H'FF' (SR pointed to by the ISAR); ISAR incremented
case 0x3E: DS_ISAR_DEC(); break; // SR <- (SR) + H'FF' (SR pointed to by the ISAR); ISAR decremented
case 0x30: DS(0); break; // SR <- (SR) + H'FF'
case 0x31: DS(1); break; // SR <- (SR) + H'FF'
case 0x32: DS(2); break; // SR <- (SR) + H'FF'
case 0x33: DS(3); break; // SR <- (SR) + H'FF'
case 0x34: DS(4); break; // SR <- (SR) + H'FF'
case 0x35: DS(5); break; // SR <- (SR) + H'FF'
case 0x36: DS(6); break; // SR <- (SR) + H'FF'
case 0x37: DS(7); break; // SR <- (SR) + H'FF'
case 0x38: DS(8); break; // SR <- (SR) + H'FF'
case 0x39: DS(9); break; // SR <- (SR) + H'FF'
case 0x3A: DS(10); break; // SR <- (SR) + H'FF'
case 0x3B: DS(11); break; // SR <- (SR) + H'FF'
case 0x3C: DS_ISAR(); break; // SR <- (SR) + H'FF' (SR pointed to by the ISAR)
case 0x3D: DS_ISAR_INC(); break; // SR <- (SR) + H'FF' (SR pointed to by the ISAR); ISAR incremented
case 0x3E: DS_ISAR_DEC(); break; // SR <- (SR) + H'FF' (SR pointed to by the ISAR); ISAR decremented
case 0x40: LR_A_R(0); break; // A <- (SR)
case 0x41: LR_A_R(1); break; // A <- (SR)
case 0x42: LR_A_R(2); break; // A <- (SR)
case 0x43: LR_A_R(3); break; // A <- (SR)
case 0x44: LR_A_R(4); break; // A <- (SR)
case 0x45: LR_A_R(5); break; // A <- (SR)
case 0x46: LR_A_R(6); break; // A <- (SR)
case 0x47: LR_A_R(7); break; // A <- (SR)
case 0x48: LR_A_R(8); break; // A <- (SR)
case 0x49: LR_A_R(9); break; // A <- (SR)
case 0x4A: LR_A_R(10); break; // A <- (SR)
case 0x4B: LR_A_R(11); break; // A <- (SR)
case 0x4C: LR_A_ISAR(); break; // A <- (SR) (SR pointed to by the ISAR)
case 0x4D: LR_A_ISAR_INC(); break; // A <- (SR) (SR pointed to by the ISAR); ISAR incremented
case 0x4E: LR_A_ISAR_DEC(); break; // A <- (SR) (SR pointed to by the ISAR); ISAR decremented
case 0x40: LR_A_R(0); break; // A <- (SR)
case 0x41: LR_A_R(1); break; // A <- (SR)
case 0x42: LR_A_R(2); break; // A <- (SR)
case 0x43: LR_A_R(3); break; // A <- (SR)
case 0x44: LR_A_R(4); break; // A <- (SR)
case 0x45: LR_A_R(5); break; // A <- (SR)
case 0x46: LR_A_R(6); break; // A <- (SR)
case 0x47: LR_A_R(7); break; // A <- (SR)
case 0x48: LR_A_R(8); break; // A <- (SR)
case 0x49: LR_A_R(9); break; // A <- (SR)
case 0x4A: LR_A_R(10); break; // A <- (SR)
case 0x4B: LR_A_R(11); break; // A <- (SR)
case 0x4C: LR_A_ISAR(); break; // A <- (SR) (SR pointed to by the ISAR)
case 0x4D: LR_A_ISAR_INC(); break; // A <- (SR) (SR pointed to by the ISAR); ISAR incremented
case 0x4E: LR_A_ISAR_DEC(); break; // A <- (SR) (SR pointed to by the ISAR); ISAR decremented
case 0x50: LR_R_A(0); break; // SR <- (A)
case 0x51: LR_R_A(1); break; // SR <- (A)
case 0x52: LR_R_A(2); break; // SR <- (A)
case 0x53: LR_R_A(3); break; // SR <- (A)
case 0x54: LR_R_A(4); break; // SR <- (A)
case 0x55: LR_R_A(5); break; // SR <- (A)
case 0x56: LR_R_A(6); break; // SR <- (A)
case 0x57: LR_R_A(7); break; // SR <- (A)
case 0x58: LR_R_A(8); break; // SR <- (A)
case 0x59: LR_R_A(9); break; // SR <- (A)
case 0x5A: LR_R_A(10); break; // SR <- (A)
case 0x5B: LR_R_A(11); break; // SR <- (A)
case 0x5C: LR_ISAR_A(); break; // SR <- (A) (SR pointed to by the ISAR)
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 0x50: LR_R_A(0); break; // SR <- (A)
case 0x51: LR_R_A(1); break; // SR <- (A)
case 0x52: LR_R_A(2); break; // SR <- (A)
case 0x53: LR_R_A(3); break; // SR <- (A)
case 0x54: LR_R_A(4); break; // SR <- (A)
case 0x55: LR_R_A(5); break; // SR <- (A)
case 0x56: LR_R_A(6); break; // SR <- (A)
case 0x57: LR_R_A(7); break; // SR <- (A)
case 0x58: LR_R_A(8); break; // SR <- (A)
case 0x59: LR_R_A(9); break; // SR <- (A)
case 0x5A: LR_R_A(10); break; // SR <- (A)
case 0x5B: LR_R_A(11); break; // SR <- (A)
case 0x5C: LR_ISAR_A(); break; // SR <- (A) (SR pointed to by the ISAR)
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(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 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'
case 0x72: LIS(2); break; // A <- H'0a'
case 0x73: LIS(3); break; // A <- H'0a'
case 0x74: LIS(4); break; // A <- H'0a'
case 0x75: LIS(5); break; // A <- H'0a'
case 0x76: LIS(6); break; // A <- H'0a'
case 0x77: LIS(7); break; // A <- H'0a'
case 0x78: LIS(8); break; // A <- H'0a'
case 0x79: LIS(9); break; // A <- H'0a'
case 0x7a: LIS(10); break; // A <- H'0a'
case 0x7b: LIS(11); break; // A <- H'0a'
case 0x7c: LIS(12); break; // A <- H'0a'
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; // 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
case 0x8B: OM(); break; // A <- (A) OR ((DC0)); DC0 <- (DC0) + 1
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; // 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)
case 0x70: LIS(0); break; // A <- H'0a' (CLR)
case 0x71: LIS(1); break; // A <- H'0a'
case 0x72: LIS(2); break; // A <- H'0a'
case 0x73: LIS(3); break; // A <- H'0a'
case 0x74: LIS(4); break; // A <- H'0a'
case 0x75: LIS(5); break; // A <- H'0a'
case 0x76: LIS(6); break; // A <- H'0a'
case 0x77: LIS(7); break; // A <- H'0a'
case 0x78: LIS(8); break; // A <- H'0a'
case 0x79: LIS(9); break; // A <- H'0a'
case 0x7a: LIS(10); break; // A <- H'0a'
case 0x7b: LIS(11); break; // A <- H'0a'
case 0x7c: LIS(12); break; // A <- H'0a'
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: BTN(); break; // Branch on true - no branch (3 cycle effective NOP)
case 0x81: BP(); break; // Branch if positive (sign bit is set)
case 0x82: BC(); break; // Branch on carry (carry bit is set)
case 0x83: BT_CS(); break; // Branch on carry or positive
case 0x84: BZ(); break; // Branch on zero (zero bit is set)
case 0x85: BT_ZS(); break; // Branch on zero or positive
case 0x86: BT_ZC(); break; // Branch if zero or on carry
case 0x87: BT_ZCS(); break; // Branch if zero or positive or on carry
case 0xA4: INS_1(4); break; // DB <- Port Address (4 thru 15)
case 0xA5: INS_1(5); break; // DB <- Port Address (4 thru 15)
case 0xA6: INS_1(6); break; // DB <- Port Address (4 thru 15)
case 0xA7: INS_1(7); break; // DB <- Port Address (4 thru 15)
case 0xA8: INS_1(8); break; // DB <- Port Address (4 thru 15)
case 0xA9: INS_1(9); break; // DB <- Port Address (4 thru 15)
case 0xAA: INS_1(10); break; // DB <- Port Address (4 thru 15)
case 0xAB: INS_1(11); break; // DB <- Port Address (4 thru 15)
case 0xAC: INS_1(12); break; // DB <- Port Address (4 thru 15)
case 0xAD: INS_1(13); break; // DB <- Port Address (4 thru 15)
case 0xAE: INS_1(14); break; // DB <- Port Address (4 thru 15)
case 0xAF: INS_1(15); break; // DB <- Port Address (4 thru 15)
case 0xB0: OUTS_0(0); break; // I/O Port 0 or 1 <- (A)
case 0xB1: OUTS_0(1); break; // I/O Port 0 or 1 <- (A)
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
case 0x8B: OM(); break; // A <- (A) OR ((DC0)); DC0 <- (DC0) + 1
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; // Branch on ISAR (any of the low 3 bits of ISAR are reset)
case 0x90: BR(); break; // Unconditional branch relative (always)
case 0x91: BM(); break; // Branch on negative (sign bit is reset)
case 0x92: BNC(); break; // Branch if no carry (carry bit is reset)
case 0x93: BF_CS(); break; // Branch on false - negative and no carry
case 0x94: BNZ(); break; // Branch on not zero (zero bit is reset)
case 0x95: BF_ZS(); break; // Branch on false - negative and not zero
case 0x96: BF_ZC(); break; // Branch on false - no carry and not zero
case 0x97: BF_ZCS(); break; // Branch on false - no carry and not zero and negative
case 0x98: BNO(); break; // Branch if no overflow (OVF bit is reset)
case 0x99: BF_OS(); break; // Branch on false - no overflow and negative
case 0x9A: BF_OC(); break; // Branch on false - no overflow and no carry
case 0x9B: BF_OCS(); break; // Branch on false - no overflow and no carry and negative
case 0x9C: BF_OZ(); break; // Branch on false - no overflow and not zero
case 0x9D: BF_OZS(); break; // Branch on false - no overflow and not zero and negative
case 0x9E: BF_OZC(); break; // Branch on false - no overflow and not zero and no carry
case 0x9F: BF_OZCS(); break; // Branch on false - no overflow and not zero and no carry and negative
case 0xB4: OUTS_1(4); break; // DB <- Port Address (4 thru 15)
case 0xB5: OUTS_1(5); break; // DB <- Port Address (4 thru 15)
case 0xB6: OUTS_1(6); break; // DB <- Port Address (4 thru 15)
case 0xB7: OUTS_1(7); break; // DB <- Port Address (4 thru 15)
case 0xB8: OUTS_1(8); break; // DB <- Port Address (4 thru 15)
case 0xB9: OUTS_1(9); break; // DB <- Port Address (4 thru 15)
case 0xBA: OUTS_1(10); break; // DB <- Port Address (4 thru 15)
case 0xBB: OUTS_1(11); break; // DB <- Port Address (4 thru 15)
case 0xBC: OUTS_1(12); break; // DB <- Port Address (4 thru 15)
case 0xBD: OUTS_1(13); break; // DB <- Port Address (4 thru 15)
case 0xBE: OUTS_1(14); break; // DB <- Port Address (4 thru 15)
case 0xBF: OUTS_1(15); break; // DB <- Port Address (4 thru 15)
case 0xC0: AS(0); break; // A <- (A) + (r) Binary
case 0xC1: AS(1); break; // A <- (A) + (r) Binary
case 0xC2: AS(2); break; // A <- (A) + (r) Binary
case 0xC3: AS(3); break; // A <- (A) + (r) Binary
case 0xC4: AS(4); break; // A <- (A) + (r) Binary
case 0xC5: AS(5); break; // A <- (A) + (r) Binary
case 0xC6: AS(6); break; // A <- (A) + (r) Binary
case 0xC7: AS(7); break; // A <- (A) + (r) Binary
case 0xC8: AS(8); break; // A <- (A) + (r) Binary
case 0xC9: AS(9); break; // A <- (A) + (r) Binary
case 0xCA: AS(10); break; // A <- (A) + (r) Binary
case 0xCB: AS(11); break; // A <- (A) + (r) Binary
case 0xCC: AS_IS(); break; // A <- (A) + (r addressed via ISAR) Binary
case 0xCD: AS_IS_INC(); break; // A <- (A) + (r addressed via ISAR) Binary; Increment ISAR
case 0xCE: AS_IS_DEC(); break; // A <- (A) + (r addressed via ISAR) Binary; Decrement ISAR
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)
case 0xD0: ASD(0); break; // A <- (A) + (r) Decimal
case 0xD1: ASD(1); break; // A <- (A) + (r) Decimal
case 0xD2: ASD(2); break; // A <- (A) + (r) Decimal
case 0xD3: ASD(3); break; // A <- (A) + (r) Decimal
case 0xD4: ASD(4); break; // A <- (A) + (r) Decimal
case 0xD5: ASD(5); break; // A <- (A) + (r) Decimal
case 0xD6: ASD(6); break; // A <- (A) + (r) Decimal
case 0xD7: ASD(7); break; // A <- (A) + (r) Decimal
case 0xD8: ASD(8); break; // A <- (A) + (r) Decimal
case 0xD9: ASD(9); break; // A <- (A) + (r) Decimal
case 0xDA: ASD(10); break; // A <- (A) + (r) Decimal
case 0xDB: ASD(11); break; // A <- (A) + (r) Decimal
case 0xDC: ASD_IS(); break; // A <- (A) + (r addressed via ISAR) Decimal
case 0xDD: ASD_IS_INC(); break; // A <- (A) + (r addressed via ISAR) Decimal; Increment ISAR
case 0xDE: ASD_IS_DEC(); break; // A <- (A) + (r addressed via ISAR) Decimal; Decrement ISAR
case 0xA4: INS_1(4); break; // DB <- Port Address (4 thru 15)
case 0xA5: INS_1(5); break; // DB <- Port Address (4 thru 15)
case 0xA6: INS_1(6); break; // DB <- Port Address (4 thru 15)
case 0xA7: INS_1(7); break; // DB <- Port Address (4 thru 15)
case 0xA8: INS_1(8); break; // DB <- Port Address (4 thru 15)
case 0xA9: INS_1(9); break; // DB <- Port Address (4 thru 15)
case 0xAA: INS_1(10); break; // DB <- Port Address (4 thru 15)
case 0xAB: INS_1(11); break; // DB <- Port Address (4 thru 15)
case 0xAC: INS_1(12); break; // DB <- Port Address (4 thru 15)
case 0xAD: INS_1(13); break; // DB <- Port Address (4 thru 15)
case 0xAE: INS_1(14); break; // DB <- Port Address (4 thru 15)
case 0xAF: INS_1(15); break; // DB <- Port Address (4 thru 15)
case 0xE0: XS(0); break; // A <- (A) XOR (r)
case 0xE1: XS(1); break; // A <- (A) XOR (r)
case 0xE2: XS(2); break; // A <- (A) XOR (r)
case 0xE3: XS(3); break; // A <- (A) XOR (r)
case 0xE4: XS(4); break; // A <- (A) XOR (r)
case 0xE5: XS(5); break; // A <- (A) XOR (r)
case 0xE6: XS(6); break; // A <- (A) XOR (r)
case 0xE7: XS(7); break; // A <- (A) XOR (r)
case 0xE8: XS(8); break; // A <- (A) XOR (r)
case 0xE9: XS(9); break; // A <- (A) XOR (r)
case 0xEA: XS(10); break; // A <- (A) XOR (r)
case 0xEB: XS(11); break; // A <- (A) XOR (r)
case 0xEC: XS_IS(); break; // A <- (A) XOR (r addressed via ISAR)
case 0xED: XS_IS_INC(); break; // A <- (A) XOR (r addressed via ISAR); Increment ISAR
case 0xEE: XS_IS_DEC(); break; // A <- (A) XOR (r addressed via ISAR); Decrement ISAR
case 0xB0: OUTS_0(0); break; // I/O Port 0 or 1 <- (A)
case 0xB1: OUTS_0(1); break; // I/O Port 0 or 1 <- (A)
case 0xF0: NS(0); break; // A <- (A) XOR (r)
case 0xF1: NS(1); break; // A <- (A) XOR (r)
case 0xF2: NS(2); break; // A <- (A) XOR (r)
case 0xF3: NS(3); break; // A <- (A) XOR (r)
case 0xF4: NS(4); break; // A <- (A) XOR (r)
case 0xF5: NS(5); break; // A <- (A) XOR (r)
case 0xF6: NS(6); break; // A <- (A) XOR (r)
case 0xF7: NS(7); break; // A <- (A) XOR (r)
case 0xF8: NS(8); break; // A <- (A) XOR (r)
case 0xF9: NS(9); break; // A <- (A) XOR (r)
case 0xFA: NS(10); break; // A <- (A) XOR (r)
case 0xFB: NS(11); break; // A <- (A) XOR (r)
case 0xFC: NS_IS(); break; // A <- (A) XOR (r addressed via ISAR)
case 0xFD: NS_IS_INC(); break; // A <- (A) XOR (r addressed via ISAR); Increment ISAR
case 0xFE: NS_IS_DEC(); break; // A <- (A) XOR (r addressed via ISAR); Decrement ISAR
case 0xB4: OUTS_1(4); break; // DB <- Port Address (4 thru 15)
case 0xB5: OUTS_1(5); break; // DB <- Port Address (4 thru 15)
case 0xB6: OUTS_1(6); break; // DB <- Port Address (4 thru 15)
case 0xB7: OUTS_1(7); break; // DB <- Port Address (4 thru 15)
case 0xB8: OUTS_1(8); break; // DB <- Port Address (4 thru 15)
case 0xB9: OUTS_1(9); break; // DB <- Port Address (4 thru 15)
case 0xBA: OUTS_1(10); break; // DB <- Port Address (4 thru 15)
case 0xBB: OUTS_1(11); break; // DB <- Port Address (4 thru 15)
case 0xBC: OUTS_1(12); break; // DB <- Port Address (4 thru 15)
case 0xBD: OUTS_1(13); break; // DB <- Port Address (4 thru 15)
case 0xBE: OUTS_1(14); break; // DB <- Port Address (4 thru 15)
case 0xBF: OUTS_1(15); break; // DB <- Port Address (4 thru 15)
default: ILLEGAL(); break; // Illegal Opcode
case 0xC0: AS(0); break; // A <- (A) + (r) Binary
case 0xC1: AS(1); break; // A <- (A) + (r) Binary
case 0xC2: AS(2); break; // A <- (A) + (r) Binary
case 0xC3: AS(3); break; // A <- (A) + (r) Binary
case 0xC4: AS(4); break; // A <- (A) + (r) Binary
case 0xC5: AS(5); break; // A <- (A) + (r) Binary
case 0xC6: AS(6); break; // A <- (A) + (r) Binary
case 0xC7: AS(7); break; // A <- (A) + (r) Binary
case 0xC8: AS(8); break; // A <- (A) + (r) Binary
case 0xC9: AS(9); break; // A <- (A) + (r) Binary
case 0xCA: AS(10); break; // A <- (A) + (r) Binary
case 0xCB: AS(11); break; // A <- (A) + (r) Binary
case 0xCC: AS_IS(); break; // A <- (A) + (r addressed via ISAR) Binary
case 0xCD: AS_IS_INC(); break; // A <- (A) + (r addressed via ISAR) Binary; Increment ISAR
case 0xCE: AS_IS_DEC(); break; // A <- (A) + (r addressed via ISAR) Binary; Decrement ISAR
case 0xD0: ASD(0); break; // A <- (A) + (r) Decimal
case 0xD1: ASD(1); break; // A <- (A) + (r) Decimal
case 0xD2: ASD(2); break; // A <- (A) + (r) Decimal
case 0xD3: ASD(3); break; // A <- (A) + (r) Decimal
case 0xD4: ASD(4); break; // A <- (A) + (r) Decimal
case 0xD5: ASD(5); break; // A <- (A) + (r) Decimal
case 0xD6: ASD(6); break; // A <- (A) + (r) Decimal
case 0xD7: ASD(7); break; // A <- (A) + (r) Decimal
case 0xD8: ASD(8); break; // A <- (A) + (r) Decimal
case 0xD9: ASD(9); break; // A <- (A) + (r) Decimal
case 0xDA: ASD(10); break; // A <- (A) + (r) Decimal
case 0xDB: ASD(11); break; // A <- (A) + (r) Decimal
case 0xDC: ASD_IS(); break; // A <- (A) + (r addressed via ISAR) Decimal
case 0xDD: ASD_IS_INC(); break; // A <- (A) + (r addressed via ISAR) Decimal; Increment ISAR
case 0xDE: ASD_IS_DEC(); break; // A <- (A) + (r addressed via ISAR) Decimal; Decrement ISAR
case 0xE0: XS(0); break; // A <- (A) XOR (r)
case 0xE1: XS(1); break; // A <- (A) XOR (r)
case 0xE2: XS(2); break; // A <- (A) XOR (r)
case 0xE3: XS(3); break; // A <- (A) XOR (r)
case 0xE4: XS(4); break; // A <- (A) XOR (r)
case 0xE5: XS(5); break; // A <- (A) XOR (r)
case 0xE6: XS(6); break; // A <- (A) XOR (r)
case 0xE7: XS(7); break; // A <- (A) XOR (r)
case 0xE8: XS(8); break; // A <- (A) XOR (r)
case 0xE9: XS(9); break; // A <- (A) XOR (r)
case 0xEA: XS(10); break; // A <- (A) XOR (r)
case 0xEB: XS(11); break; // A <- (A) XOR (r)
case 0xEC: XS_IS(); break; // A <- (A) XOR (r addressed via ISAR)
case 0xED: XS_IS_INC(); break; // A <- (A) XOR (r addressed via ISAR); Increment ISAR
case 0xEE: XS_IS_DEC(); break; // A <- (A) XOR (r addressed via ISAR); Decrement ISAR
case 0xF0: NS(0); break; // A <- (A) AND (r)
case 0xF1: NS(1); break; // A <- (A) AND (r)
case 0xF2: NS(2); break; // A <- (A) AND (r)
case 0xF3: NS(3); break; // A <- (A) AND (r)
case 0xF4: NS(4); break; // A <- (A) AND (r)
case 0xF5: NS(5); break; // A <- (A) AND (r)
case 0xF6: NS(6); break; // A <- (A) AND (r)
case 0xF7: NS(7); break; // A <- (A) AND (r)
case 0xF8: NS(8); break; // A <- (A) AND (r)
case 0xF9: NS(9); break; // A <- (A) AND (r)
case 0xFA: NS(10); break; // A <- (A) AND (r)
case 0xFB: NS(11); break; // A <- (A) AND (r)
case 0xFC: NS_IS(); break; // A <- (A) AND (r addressed via ISAR)
case 0xFD: NS_IS_INC(); break; // A <- (A) AND (r addressed via ISAR); Increment ISAR
case 0xFE: NS_IS_DEC(); break; // A <- (A) AND (r addressed via ISAR); Decrement ISAR
default: ILLEGAL(); break; // Illegal Opcode
}
}
}

View File

@ -22,24 +22,22 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
Regs[dest] = ReadHardware(Regs[src]);
}
/// <summary>
/// Helper method moving from IO to A and setting flags accordingly
/// </summary>
/// <param name="dest"></param>
/// <param name="src"></param>
public void LR_A_IO_Func(byte dest, byte 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];
// data is complemented between I/O pin and accumulator.
Regs[dest] = (byte)(Regs[src] ^ 0xFF);
FlagZ = Regs[dest] == 0;
// Sign SET if MSB == 0 (positive signed number)
FlagS = Regs[dest].Bit(7) == false;
// ICB flag not affected
FlagS = Regs[dest].Bit(7);
FlagZ = (Regs[dest] & 0xFF) == 0;
}
public void ClearFlags_Func()
@ -50,6 +48,11 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
FlagZ = false;
}
/// <summary>
/// Helper function for transferring data between registers
/// </summary>
/// <param name="dest"></param>
/// <param name="src"></param>
public void LR_Func(byte dest, byte src)
{
if (dest == DB)
@ -86,16 +89,12 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
Regs[src] = (byte)((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
FlagS = !Regs[src].Bit(7);
FlagZ = (Regs[src] & 0xFF) == 0;
}
/// <summary>
/// Left shit 'src' 'shift' positions (zero fill)
/// Left shift 'src' 'shift' positions (zero fill)
/// </summary>
/// <param name="src"></param>
/// <param name="shift"></param>
@ -107,51 +106,25 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
Regs[src] = (byte)((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_(byte dest, byte 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] = (byte)ans;
FlagS = !Regs[src].Bit(7);
FlagZ = (Regs[src] & 0xFF) == 0;
}
/// <summary>
/// Binary addition
/// Statuses modified: OVF, ZERO, CARRY, SIGN
/// Statuses unaffected: ICB
/// </summary>
/// <param name="dest"></param>
/// <param name="src"></param>
public void ADD_Func(byte dest, byte src)
{
// addition of 2 signed bytes
var sD = Regs[dest] & 0x80;
var sS = Regs[src] & 0x80;
var res = Regs[dest] + Regs[src];
var sR = res & 0x80;
FlagS = !((res & 0x80) > 0);
FlagZ = (res & 0xff) == 0;
FlagO = (sD == sS && sD != sR);
FlagC = (res & 0x100) > 0;
Regs[dest] = (byte) (res & 0xff);
FlagS = !res.Bit(7);
FlagC = res.Bit(8);
FlagZ = (res & 0xFF) == 0;
FlagO = (Regs[dest].Bit(7) == Regs[src].Bit(7)) && (Regs[dest].Bit(7) != res.Bit(7));
Regs[dest] = (byte)(res & 0xFF);
}
public void SUB_Func(byte dest, byte src)
@ -160,89 +133,95 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
ADD_Func(dest, ALU0);
}
/// <summary>
/// Decimal Add
/// http://www.bitsavers.org/components/fairchild/f8/67095664_F8_Guide_To_Programming_1976.pdf - page 40
/// </summary>
/// <param name="dest"></param>
/// <param name="src"></param>
public void ADDD_Func(byte dest, byte src)
{
var d = Regs[dest];
var s = Regs[src];
var bcdRes = d + s;
// The accumulator and the memory location addressed by the DCO registers are assumed to contain two BCD digits.
// The content of the address memory byte is added to the contents of the accumulator to give a BCD result in the accumulator
// providing these steps are followed:
//
// Decimal addition is, in reality, three binary events. Consider 8-bit decimal addition.
// Assume two BCD digit augend XY is added to two BCD digit addend l).N, to give a BCD result PQ:
// XY
// +ZW
// --
// =PQ
//
// Two carries are important: any intermediate carry (IC) out of the low order answer digit (Q), and any overall carry (C) out of the high order digit (P).
// The three binary steps required to perform BCD addition are as follows:
var carryIntermediate = ((d & 0x0F) + (s & 0x0F)) > 0x0F;
var carryUpper = bcdRes >= 0x100;
// STEP 1: Binary add H'66' to the augend. (this should happen before this function is called)
// STEP 2: Binary add the addend to the sum from Step 1. Record the status of the carry (C) and intermediate carry (IC).
// temporary storage and set flags
Regs[ALU0] = Regs[dest];
Regs[ALU1] = Regs[src];
ADD_Func(ALU0, ALU1);
var augend = Regs[dest];
var addend = Regs[src];
var working = (byte)(augend + addend);
if (!carryIntermediate)
bool highCarry;
bool lowCarry;
highCarry = ((augend + addend) & 0xFF0) > 0xF0;
lowCarry = (augend & 0x0F) + (addend & 0x0F) > 0x0F;
var res = augend + addend;
FlagC = res.Bit(8);
FlagO = (Regs[dest].Bit(7) == Regs[src].Bit(7)) && (Regs[dest].Bit(7) != res.Bit(7));
FlagS = !working.Bit(7);
FlagZ = (working & 0xFF) == 0;
// STEP 3: Add a factor to the sum from Step 2, based on the status of C and IC. The factor to be added is given by the following table:
// C IC Sum to be added
// ------------------------
// 0 0 0xAA
// 0 1 0xA0
// 1 0 0x0A
// 1 1 0x00
//
// In Step 3, any carry from the low order digit to the high order digit is suppressed.
if (!highCarry && !lowCarry)
{
bcdRes = (bcdRes & 0xF0) | ((bcdRes + 0x0A) & 0x0F);
working = (byte)(((working + 0xa0) & 0xf0) + ((working + 0x0a) & 0x0f));
}
else if (!highCarry && lowCarry)
{
working = (byte)(((working + 0xa0) & 0xf0) + (working & 0x0f));
}
else if (highCarry && !lowCarry)
{
working = (byte)((working & 0xf0) + ((working + 0x0a) & 0x0f));
}
else
{
// add nothing (0x00)
}
if (!carryUpper)
{
bcdRes = (bcdRes + 0xA0);
}
Regs[dest] = (byte)(bcdRes & 0xFF);
Regs[dest] = (byte)(working & 0xFF);
}
/// <summary>
/// Binary add the two's compliment of the accumulator to the value on the databus
/// Set flags accordingly but accumlator is not touched
/// </summary>
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] = (byte)comp;
var twosComp = (byte)((Regs[A] ^ 0xFF) + 1);
Regs[ALU0] = twosComp;
Regs[ALU1] = Regs[DB];
ADD_Func(ALU1, 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;
}
*/
ADD_Func(ALU0, ALU1);
}
/// <summary>
/// Logical AND regs[dest] with regs[src] and store the result in regs[dest]
/// </summary>
/// <param name="dest"></param>
/// <param name="src"></param>
public void AND_Func(byte dest, byte src)
{
// overflow and carry unconditionally reset
@ -251,14 +230,15 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
Regs[dest] = (byte)(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
FlagS = !Regs[dest].Bit(7);
FlagZ = (Regs[dest] & 0xFF) == 0;
}
/// <summary>
/// Logical OR regs[dest] with regs[src] and store the result in regs[dest]
/// </summary>
/// <param name="dest"></param>
/// <param name="src"></param>
public void OR_Func(byte dest, byte src)
{
// overflow and carry unconditionally reset
@ -267,14 +247,15 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
Regs[dest] = (byte)(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
FlagS = !Regs[dest].Bit(7);
FlagZ = (Regs[dest] & 0xFF) == 0;
}
/// <summary>
/// The destination (regs[dest]) is XORed with (regs[src]).
/// </summary>
/// <param name="dest"></param>
/// <param name="src"></param>
public void XOR_Func(byte dest, byte src)
{
// overflow and carry unconditionally reset
@ -283,12 +264,8 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
Regs[dest] = (byte)(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
FlagZ = (Regs[dest] & 0xFF) == 0;
FlagS = !Regs[dest].Bit(7);
}
}
}

View File

@ -93,6 +93,8 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
/// <summary>
/// Status Register - Sign Flag
/// When the results of an ALU operation are being interpreted as a signed binary number, the high oidei bit (bit 7) represents the sign of the number
/// At the conclusion of instructions that may modify the Accumulator bit 7, the S bit (W register bit 0) is set to the complement of the Accumulator bit 7.
/// </summary>
public bool FlagS
{
@ -102,6 +104,8 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
/// <summary>
/// Status Register - Carry Flag
/// The C bit (W register bit 1) may be visualized as an extension of an 8-bit data unit; i.e., bit 8 of a 9-bit data unit.
/// When two bytes are added and the sum is greater than 255, the carry out of bit 7 appears in the C bit.
/// </summary>
public bool FlagC
{
@ -111,6 +115,8 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
/// <summary>
/// Status Register - Zero Flag
/// The Z bit (W Register bit 2) is set whenever an arithmetic or logical operation generates a zero result.
/// The Z bit is reset to 0 when an arithmetic or logical operation could have generated a zero result, but did not.
/// </summary>
public bool FlagZ
{
@ -120,6 +126,9 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
/// <summary>
/// Status Register - Overflow Flag
/// The high order Accumulator bit (bit 7) represents the sign of the number.
/// When the Accumulator contents are being interpreted as a signed binary number, some method must be provided for indicating carries out of the highest numeric bit (bit 6 of the Accumulator).
/// This is done using the 0 bit (W register bit 3). After arithmetic operations, the 0 bit is set to the EXCLUSIVE-OR of Carry Out of bits 6 and bits 7. This simplifies signed binary arithmetic.
/// </summary>
public bool FlagO
{
@ -129,6 +138,8 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
/// <summary>
/// Status Register - Interrupt Master Enable Flag
/// External logic can alter the operations sequence within the CPU by interrupting ongoing operations.
/// However, interrupts are allowed only when t (W register bit 4) is set to 1; interrupts are disallowed when the ICB bit is reset to O.
/// </summary>
public bool FlagICB
{

View File

@ -83,7 +83,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
public const byte OP_AND8 = 107;
public const byte OP_OR8 = 108;
public const byte OP_XOR8 = 109;
//public const byte OP_COM = 110;
public const byte OP_COM = 99;
public const byte OP_SUB8 = 110;
public const byte OP_ADD8 = 111;
public const byte OP_CI = 112;
@ -94,17 +94,50 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
public const byte OP_BT = 117;
public const byte OP_ADD8D = 118;
public const byte OP_BR7 = 119;
public const byte OP_BF = 120;
public const byte OP_IN = 121;
public const byte OP_OUT = 122;
public const byte OP_BR = 120;
public const byte OP_BM = 121;
public const byte OP_BNC = 122;
public const byte OP_BF_CS = 123;
public const byte OP_BNZ = 124;
public const byte OP_BF_ZS = 125;
public const byte OP_BF_ZC = 126;
public const byte OP_BF_ZCS = 127;
public const byte OP_BNO = 128;
public const byte OP_BF_OS = 129;
public const byte OP_BF_OC = 130;
public const byte OP_BF_OCS = 131;
public const byte OP_BF_OZ = 132;
public const byte OP_BF_OZS = 133;
public const byte OP_BF_OZC = 134;
public const byte OP_BF_OZCS = 135;
public const byte OP_BTN = 136;
public const byte OP_BP = 137;
public const byte OP_BC = 138;
public const byte OP_BT_CS = 139;
public const byte OP_BZ = 140;
public const byte OP_BT_ZS = 141;
public const byte OP_BT_ZC = 142;
public const byte OP_BT_ZCS = 143;
public const byte OP_BF = 141;
public const byte OP_IN = 151;
public const byte OP_OUT = 152;
//public const byte OP_AS_IS = 123;
//public const byte OP_XS_IS = 124;
//public const byte OP_NS_IS = 125;
public const byte OP_LR_A_DB_IO = 126;
public const byte OP_DS = 127;
public const byte OP_LR_A_DB_IO = 156;
public const byte OP_DS = 157;
//public const byte OP_CLEAR_FLAGS = 126;
//public const byte OP_SET_FLAGS_SZ = 127;
public const byte OP_LIS = 128;
public const byte OP_LIS = 158;
public F3850()
@ -200,7 +233,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
LR_A_IO_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
// loads supplied index value into register
// loads supplied index value into the bottom 4 bits of a register (upper bits are set to 0)
case OP_LIS:
Regs[ALU1] = (byte)(cur_instr[instr_pntr++] & 0x0F);
LR_Func(A, ALU1);
@ -252,6 +285,13 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
XOR_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
// The accumulator is loaded with its one's complement
case OP_COM:
XOR_Func(A, BYTE);
//Regs[A] = (byte)(Regs[A] ^ 0xFF);
break;
// x <- (x) + 1
case OP_INC8:
ADD_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
@ -274,7 +314,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
// ISAR is incremented
case OP_IS_INC:
Regs[ISAR] = (byte)((Regs[ISAR]& 0x38) | ((Regs[ISAR] + 1) & 0x07));
Regs[ISAR] = (byte)((Regs[ISAR] & 0x38) | ((Regs[ISAR] + 1) & 0x07));
break;
// ISAR is decremented
@ -282,184 +322,223 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
Regs[ISAR] = (byte)((Regs[ISAR] & 0x38) | ((Regs[ISAR] - 1) & 0x07));
break;
// set the upper octal ISAR bits (b3,b4,b5)
// set the upper octal ISAR bits (b3,b4,b5) but do not alter the three least significant bits
case OP_LISU:
Regs[ISAR] = (byte)((((Regs[ISAR] & 0x07) | (cur_instr[instr_pntr++] & 0x07) << 3)) & 0x3F);
break;
// set the lower octal ISAR bits (b0,b1,b2)
// set the lower octal ISAR bits (b0,b1,b2) but do not alter the three most significant bits
case OP_LISL:
Regs[ISAR] = (byte) (((Regs[ISAR] & 0x38) | (cur_instr[instr_pntr++] & 0x07)) & 0x3F);
break;
// decrement scratchpad byte
//case OP_DS:
//SUB_Func(cur_instr[instr_pntr++], ONE);
//break;
// Branch on TRUE
case OP_BT:
bool branchBT = false;
switch (cur_instr[instr_pntr++])
{
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 and zero
if (FlagS || FlagZ) 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 or zero
if (FlagS || FlagC || FlagZ) branchBT = true;
break;
}
instr_pntr = 0;
if (branchBT) DO_BRANCH();
else DONT_BRANCH();
// Unconditional Branch (relative)
case OP_BR:
DO_BF_BRANCH(0);
break;
// Branch on ISARL
case OP_BR7:
instr_pntr = 1; // lose a cycle
if (Regs[ISAR].Bit(0) && Regs[ISAR].Bit(1) && Regs[ISAR].Bit(2))
{
DONT_BRANCH();
}
// Branch on Negative
case OP_BM:
if (!FlagS)
DO_BF_BRANCH(0);
else
{
DO_BRANCH();
}
DONT_BF_BRANCH(0);
break;
// Branch on FALSE
case OP_BF:
bool branchBF = false;
switch (cur_instr[instr_pntr++])
{
case 0:
// unconditional branch relative
branchBF = true;
break;
// Branch if no carry
case OP_BNC:
if (!FlagC)
DO_BF_BRANCH(0);
else
DONT_BF_BRANCH(0);
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:
// branch if not zero and negative
if (!FlagS && !FlagZ) branchBF = true;
break;
case 6:
// branch if no carry and result is no zero
if (!FlagC && !FlagZ) branchBF = true;
break;
case 7:
// branch if not zero, carry and sign
if (!FlagS && !FlagC && !FlagZ) 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:
// branch if no overflow, not zero and neg
if (!FlagS && !FlagO && !FlagZ) branchBF = true;
break;
case 0xE:
// branch if no overflow, no carry & not zero
if (!FlagO && !FlagC && !FlagZ) branchBF = true;
break;
case 0xF:
// all neg
if (!FlagO && !FlagC && !FlagS && FlagZ) branchBF = true;
break;
}
// Branch if negative and no carry
case OP_BF_CS:
if (!FlagS && !FlagC)
DO_BF_BRANCH(0);
else
DONT_BF_BRANCH(0);
break;
// Branch if not zero
case OP_BNZ:
instr_pntr = 0;
if (branchBF) DO_BRANCH();
else DONT_BRANCH();
if (!FlagZ)
DO_BF_BRANCH(0);
else
DONT_BF_BRANCH(0);
break;
// Branch on Negative and not Zero (same thing as branch on negative)
case OP_BF_ZS:
if (!FlagS && !FlagZ)
DO_BF_BRANCH(0);
else
DONT_BF_BRANCH(0);
break;
// Branch on no Carry and not Zero
case OP_BF_ZC:
if (!FlagC && !FlagZ)
DO_BF_BRANCH(0);
else
DONT_BF_BRANCH(0);
break;
// Branch on no Carry and not Zero and Negative
case OP_BF_ZCS:
if (!FlagC && !FlagZ && !FlagS)
DO_BF_BRANCH(0);
else
DONT_BF_BRANCH(0);
break;
// Branch on no Overflow
case OP_BNO:
if (!FlagO)
DO_BF_BRANCH(0);
else
DONT_BF_BRANCH(0);
break;
// Branch on no overflow and Negative
case OP_BF_OS:
if (!FlagO && !FlagS)
DO_BF_BRANCH(0);
else
DONT_BF_BRANCH(0);
break;
// Branch on no overflow and Negative
case OP_BF_OC:
if (!FlagO && !FlagC)
DO_BF_BRANCH(0);
else
DONT_BF_BRANCH(0);
break;
// Branch on no overflow and no carry and Negative
case OP_BF_OCS:
if (!FlagO && !FlagC && !FlagS)
DO_BF_BRANCH(0);
else
DONT_BF_BRANCH(0);
break;
// Branch on no overflow and not zero
case OP_BF_OZ:
if (!FlagO && !FlagZ)
DO_BF_BRANCH(0);
else
DONT_BF_BRANCH(0);
break;
// Branch on no overflow and not zero and negative
case OP_BF_OZS:
if (!FlagO && !FlagZ && !FlagS)
DO_BF_BRANCH(0);
else
DONT_BF_BRANCH(0);
break;
// Branch on no overflow and not zero and no carry
case OP_BF_OZC:
if (!FlagO && !FlagZ && !FlagC)
DO_BF_BRANCH(0);
else
DONT_BF_BRANCH(0);
break;
// Branch on no overflow and not zero and no carry and negative
case OP_BF_OZCS:
if (!FlagO && !FlagZ && !FlagC && FlagS)
DO_BF_BRANCH(0);
else
DONT_BF_BRANCH(0);
break;
// Branch on true - no branch
case OP_BTN:
DONT_BT_BRANCH(0);
break;
// Branch if positive
case OP_BP:
if (FlagS)
DO_BT_BRANCH(0);
else
DONT_BT_BRANCH(0);
break;
// Branch on carry
case OP_BC:
if (FlagC)
DO_BT_BRANCH(0);
else
DONT_BT_BRANCH(0);
break;
// Branch on carry or positive
case OP_BT_CS:
if (FlagC || FlagS)
DO_BT_BRANCH(0);
else
DONT_BT_BRANCH(0);
break;
// Branch if zero
case OP_BZ:
if (FlagZ)
DO_BT_BRANCH(0);
else
DONT_BT_BRANCH(0);
break;
// Branch if zero or positive
case OP_BT_ZS:
if (FlagZ || FlagS)
DO_BT_BRANCH(0);
else
DONT_BT_BRANCH(0);
break;
// Branch if zero or carry
case OP_BT_ZC:
if (FlagZ || FlagC)
DO_BT_BRANCH(0);
else
DONT_BT_BRANCH(0);
break;
// Branch if zero or carry or positive
case OP_BT_ZCS:
if (FlagZ || FlagC || FlagS)
DO_BT_BRANCH(0);
else
DONT_BT_BRANCH(0);
break;
// Branch on ISARL - if any of the low 3 bits of ISAR are reset
case OP_BR7:
if (!Regs[ISAR].Bit(0) || !Regs[ISAR].Bit(1) || !Regs[ISAR].Bit(2))
DO_BF_BRANCH(1);
else
DONT_BF_BRANCH(1);
break;
// A <- (I/O Port 0 or 1)
case OP_IN:
instr_pntr++; // dest == A
Regs[ALU0] = cur_instr[instr_pntr++]; // src
IN_Func(A, ALU0);
IN_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
//instr_pntr++; // dest == A
//Regs[ALU0] = cur_instr[instr_pntr++]; // src
//IN_Func(A, ALU0);
break;
// I/O Port 0 or 1 <- (A)
case OP_OUT:
WriteHardware(cur_instr[instr_pntr++], (byte)Regs[cur_instr[instr_pntr++]]);
//OUT_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
break;
// instruction fetch
@ -485,7 +564,22 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
// CYCLE LENGTH: L
case ROMC_01:
Read_Func(DB, PC0l, PC0h);
RegPC0 += (ushort)((sbyte) Regs[DB]);
RegPC0 = Regs[DB].Bit(7) ? (ushort)(RegPC0 - (byte)((Regs[DB] ^ 0xFF) + 1)) : (ushort)(RegPC0 + Regs[DB]);
/*
if (Regs[DB].Bit(7))
{
// sign bit set
var cN = (byte)((Regs[DB] ^ 0xFF) + 1);
// subtract
RegPC0 -= cN;
}
else
{
// positive signed number
RegPC0 += Regs[DB];
}
//RegPC0 += (ushort)((sbyte) Regs[DB]);
*/
break;
// The device whose DC0 address addresses a memory word within the address space of that device must place on the data bus the contents
@ -522,6 +616,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
// CYCLE LENGTH: L
case ROMC_05:
Write_Func(DC0l, DC0h, DB);
RegDC0++;
break;
// Place the high order byte of DC0 on the data bus
@ -555,7 +650,24 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
// All devices add the 8-bit value on the data bus, treated as a signed binary number, to the data counter
// CYCLE LENGTH: L
case ROMC_0A:
RegDC0 += (ushort) ((sbyte) Regs[DB]);
// The contents of the accumulator are treated as a signed binary number, and are added to the contents of every DCO register.
RegDC0 = Regs[DB].Bit(7) ? (ushort)(RegDC0 - (byte)((Regs[DB] ^ 0xFF) + 1)) : (ushort)(RegDC0 + Regs[DB]);
/*
if (Regs[DB].Bit(7))
{
// sign bit set
var cN = (byte)((Regs[DB] ^ 0xFF) + 1);
// subtract
RegDC0 -= cN;
}
else
{
// positive signed number
RegDC0 += Regs[DB];
}
*/
//RegDC0 += (ushort) ((sbyte) Regs[DB]);
break;
// The device whose address space includes the value in PC1 must place the low order byte of PC1 on the data bus
@ -771,7 +883,8 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
private void PopulateCURINSTR(byte d0 = 0, byte d1 = 0, byte d2 = 0, byte d3 = 0, byte d4 = 0, byte d5 = 0, byte d6 = 0, byte d7 = 0, byte d8 = 0,
byte d9 = 0, byte d10 = 0, byte d11 = 0, byte d12 = 0, byte d13 = 0, byte d14 = 0, byte d15 = 0, byte d16 = 0, byte d17 = 0, byte d18 = 0,
byte d19 = 0, byte d20 = 0, byte d21 = 0, byte d22 = 0, byte d23 = 0, byte d24 = 0, byte d25 = 0, byte d26 = 0, byte d27 = 0, byte d28 = 0,
byte d29 = 0, byte d30 = 0, byte d31 = 0, byte d32 = 0, byte d33 = 0, byte d34 = 0, byte d35 = 0, byte d36 = 0, byte d37 = 0)
byte d29 = 0, byte d30 = 0, byte d31 = 0, byte d32 = 0, byte d33 = 0, byte d34 = 0, byte d35 = 0, byte d36 = 0, byte d37 = 0,
byte d38 = 0, byte d39 = 0, byte d40 = 0, byte d41 = 0, byte d42 = 0, byte d43 = 0, byte d44 = 0, byte d45 = 0, byte d46 = 0, byte d47 = 0)
{
cur_instr[0] = d0; cur_instr[1] = d1; cur_instr[2] = d2;
cur_instr[3] = d3; cur_instr[4] = d4; cur_instr[5] = d5;
@ -785,7 +898,10 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
cur_instr[27] = d27; cur_instr[28] = d28; cur_instr[29] = d29;
cur_instr[30] = d30; cur_instr[31] = d31; cur_instr[32] = d32;
cur_instr[33] = d33; cur_instr[34] = d34; cur_instr[35] = d35;
cur_instr[36] = d36; cur_instr[37] = d37;
cur_instr[36] = d36; cur_instr[37] = d37; cur_instr[37] = d38;
cur_instr[39] = d36; cur_instr[40] = d37; cur_instr[41] = d38;
cur_instr[42] = d36; cur_instr[43] = d37; cur_instr[44] = d38;
cur_instr[45] = d36; cur_instr[46] = d37; cur_instr[47] = d38;
}
public void SyncState(Serializer ser)

View File

@ -31,6 +31,10 @@
//return 0;
return Rom[addr - 0x800];
}
else
{
}
return 0xFF;
}

View File

@ -4,18 +4,22 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
{
/// <summary>
/// Ports and related functions
/// Based on the luxor schematic here:
/// https://web.archive.org/web/20210524083634/http://channelf.se/veswiki/images/3/35/Luxor_page2_300dpi.png
/// https://channelf.se/veswiki/images/2/23/Luxor_page3_300dpi.png
/// </summary>
public partial class ChannelF
{
/// <summary>
/// The Channel F has 4 8-bit IO ports connected.
/// CPU - ports 0 and 1
/// PSU - ports 4 and 5
/// CPU (3850) - ports 0 and 1
/// PSU (3851) - ports 4 and 5
/// (the second PSU has no IO ports wired up)
/// All CPU and PSU I/O ports are active-low with output-latches
/// </summary>
public byte[] PortLatch = new byte[4];
public byte[] OutputLatch = new byte[4];
public bool ControllersEnabled;
public bool LS368Disabled;
public const int PORT0 = 0;
public const int PORT1 = 1;
@ -23,34 +27,204 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
public const int PORT5 = 3;
/// <summary>
/// CPU attempts to read data byte from the requested port
/// CPU is attempting to read from a port
/// </summary>
/// <param name="addr"></param>
/// <returns></returns>
public byte ReadPort(ushort addr)
{
byte result = 1;
switch (addr)
{
// Console buttons
// b0: TIME
// b1: MODE
// b2: HOLD
// b3: START
default:
break;
case 0:
return (byte)((DataConsole ^ 0xff) | PortLatch[PORT0]);
// Right controller
// b0: RIGHT
// b1: LEFT
// b2: BACK
// b3: FORWARD
// b4: CCW
// b5: CW
// b6: PULL
// b7: PUSH
// Console Buttons - these are connected to pins 0-3 (bits 0-3) through a 7404 Hex Inverter
// sample RESET state first - this is connected directly to the RESET pin on the CPU
if (DataConsole.Bit(5))
{
CPU.Reset();
}
// get the 4 console buttons state
var cButtons = DataConsole & 0x0F;
// hex inverter
var cButtonsInverted = (byte)(DataConsole ^ 0xFF);
// AND latched output (pins 4 and 7 not connected)
result = (byte)((OutputLatch[PORT0] & 0x6F) | cButtonsInverted);
break;
case 1:
// right controller (player 1)
// connected through 7404 Hex Inverter
// b0: RIGHT
// b1: LEFT
// b2: BACK
// b3: FORWARD
// b4: CCW
// b5: CW
var rButtons = DataRight & 0x3F;
// connected through LS368 Hex Interting 3-State Buffer
// the enable pin of this IC is driven by a CPU write to pin 6 on port 0
// b6: PULL
// b7: PUSH
var rButtons2 = LS368Disabled ? 0 : DataRight & 0xC0;
// hex inverters
var rbuttonsInverted = (byte)((rButtons | rButtons2) ^ 0xFF);
// AND latched output
result = (byte)(OutputLatch[PORT1] | rbuttonsInverted);
break;
case 4:
// left controller (player 2)
// connected through LS368 Hex Interting 3-State Buffer
// the enable pin of this IC is driven by a CPU write to pin 6 on port 0
// b0: RIGHT
// b1: LEFT
// b2: BACK
// b3: FORWARD
// b4: CCW
// b5: CW
// b6: PULL
// b7: PUSH
var lButtons = LS368Disabled ? 0 : DataLeft & 0xFF;
// hex inverter
var lButtonsInverted = (byte)(lButtons ^ 0xFF);
// AND latched output
result = (byte)(OutputLatch[PORT4] | lButtonsInverted);
break;
case 5:
// output only IO port - return the last latched output
result = OutputLatch[PORT5];
break;
}
return result;
}
/// <summary>
/// CPU is attempting to write to the specified IO port
/// </summary>
/// <param name="addr"></param>
/// <returns></returns>
public void WritePort(ushort addr, byte value)
{
switch (addr)
{
case 0:
OutputLatch[PORT0] = value;
// LS368 enable pin on bit 6
LS368Disabled = value.Bit(6);
if (value.Bit(5))
{
// pulse clocks the 74195 parallel access shift register which feeds inputs of 2 NAND gates
// writing data to both sets of even and odd VRAM chips (based on the row and column addresses latched into the 7493 ICs
VRAM[(latch_y * 0x80) + latch_x] = (byte)latch_colour;
}
break;
case 1:
OutputLatch[PORT1] = value;
// set pixel colour
// write data 0 = bit6
// write data 1 = bit7
latch_colour = ((value ^ 0xFF) >> 6) & 0x03;
break;
case 4:
OutputLatch[PORT4] = value;
// latch horiztonal column address
// these are hex inverted along the way
// bit7 is not sent to the 7493s (IO47N) - make it logical 1 before hex inversion
var p1Data = value | 0x80;
latch_x = (p1Data ^ 0xFF) & 0xFF;
break;
case 5:
OutputLatch[PORT5] = value;
// bits 6 (ToneAN) and 7 (ToneBN) are sound generation
var audio = (value >> 6) & 0x03;
if (audio != tone)
{
tone = audio;
time = 0;
amplitude = 1;
AudioChange();
}
// remaining bits latch vertical row address
var vert = (value | 0xC0) & 0xFF;
latch_y = (vert ^ 0xFF) & 0xFF;
break;
}
}
/*
/// <summary>
/// CPU attempts to read data byte from the requested port
/// </summary>
/// <param name="addr"></param>
/// <returns></returns>
public byte ReadPort1(ushort addr)
{
switch (addr)
{
// CPU Port 0
case 0:
// Console buttons
// b0: TIME
// b1: MODE
// b2: HOLD
// b3: START
return (byte)((DataConsole ^ 0xff) | OutputLatch[PORT0]);
// CPU Port 1
case 1:
// Right controller
// b0: RIGHT
// b1: LEFT
// b2: BACK
// b3: FORWARD
// b4: CCW
// b5: CW
// b6: PULL
// b7: PUSH
byte ed1;
if ((PortLatch[PORT0] & 0x40) == 0)
if ((OutputLatch[PORT0] & 0x40) == 0)
{
ed1 = DataRight;
}
@ -58,20 +232,21 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
{
ed1 = (byte) (0xC0 | DataRight);
}
return (byte) ((ed1 ^ 0xff) | PortLatch[PORT1]);
return (byte) ((ed1 ^ 0xff) | OutputLatch[PORT1]);
// Left controller
// b0: RIGHT
// b1: LEFT
// b2: BACK
// b3: FORWARD
// b4: CCW
// b5: CW
// b6: PULL
// b7: PUSH
// PSU Port 4
case 4:
// Left controller
// b0: RIGHT
// b1: LEFT
// b2: BACK
// b3: FORWARD
// b4: CCW
// b5: CW
// b6: PULL
// b7: PUSH
byte ed4;
if ((PortLatch[PORT0] & 0x40) == 0)
if ((OutputLatch[PORT0] & 0x40) == 0)
{
ed4 = DataLeft;
}
@ -79,10 +254,11 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
{
ed4 = 0xff;
}
return (byte)((ed4 ^ 0xff) | PortLatch[PORT4]);
return (byte)((ed4 ^ 0xff) | OutputLatch[PORT4]);
// PSU Port 5
case 5:
return (byte) (0 | PortLatch[PORT5]);
return (byte) (0 | OutputLatch[PORT5]);
default:
return 0;
@ -94,34 +270,50 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
/// </summary>
/// <param name="addr"></param>
/// <param name="value"></param>
public void WritePort(ushort addr, byte value)
public void WritePort1(ushort addr, byte value)
{
switch (addr)
{
// CPU Port 0
case 0:
PortLatch[PORT0] = value;
// b5: Executes a write to VRAM
// b6: Enable controllers data
OutputLatch[PORT0] = value;
if ((value & 0x20) != 0)
{
// write to VRAM
var offset = _x + (_y * 128);
VRAM[offset] = (byte)(_colour);
}
if ((value & 0x40) != 0)
{
//ControllersEnabled = false;
}
break;
// CPU Port 1
case 1:
// bits 6 and 7 decide pixel colour (this is not inverted)
PortLatch[PORT1] = value;
OutputLatch[PORT1] = value;
// Write Data0 - indicates that valid data is present for both VRAM ODD0 and EVEN0
bool data0 = value.Bit(6);
//bool data0 = value.Bit(6);
// Write Data1 - indicates that valid data is present for both VRAM ODD1 and EVEN1
bool data1 = value.Bit(7);
//bool data1 = value.Bit(7);
//_colour = ((value) >> 6) & 3;
_colour = ((value ^ 0xff) >> 6) & 0x3;
_colour = (value >> 6) & 0x3;
break;
// PSU Port 4
case 4:
PortLatch[PORT4] = value;
//
OutputLatch[PORT4] = value;
_x = (value ^ 0xff) & 0x7f;
//_x = (value | 0x80) ^ 0xFF;
/*
@ -132,14 +324,14 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
*/
break;
// PSU port 5
case 5:
PortLatch[PORT5] = value;
OutputLatch[PORT5] = value;
//_y = (value & 31); // ^ 0xff;
//_y = (value | 0xC0) ^ 0xff;
@ -163,5 +355,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
break;
}
}
*/
}
}

View File

@ -7,45 +7,7 @@ namespace BizHawk.Emulation.Cores.Consoles.ChannelF
/// </summary>
public partial class ChannelF
{
/// <summary>
/// 128x64 pixels - 8192x2bits (2 KB)
/// For the purposes of this core we will use 8192 bytes and just &amp; 0x03
/// </summary>
public byte[] VRAM = new byte[(128 * 64)];
public static readonly int[] FPalette =
{
/*
0x101010, 0xFDFDFD, 0x5331FF, 0x5DCC02, 0xF33F4B, 0xE0E0E0, 0xA6FF91, 0xD0CEFF
*/
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 readonly int[] frameBuffer = new int[128 * 64];
private void BuildFrame()
private void BuildFrame1()
{
// rows
int counter = 0;