Vectrex Initial Commit
This commit is contained in:
parent
31237e0c92
commit
ba4ec02cb5
|
@ -597,6 +597,39 @@
|
|||
</Compile>
|
||||
<Compile Include="Consoles\Belogic\LibUzem.cs" />
|
||||
<Compile Include="Consoles\Belogic\Uzem.cs" />
|
||||
<Compile Include="Consoles\GCE\Vectrex\Audio.cs" />
|
||||
<Compile Include="Consoles\GCE\Vectrex\Vectrex.CpuLink.cs" />
|
||||
<Compile Include="Consoles\GCE\Vectrex\VectrexHawk.cs" />
|
||||
<Compile Include="Consoles\GCE\Vectrex\VectrexHawk.ICodeDataLog.cs" />
|
||||
<Compile Include="Consoles\GCE\Vectrex\VectrexHawk.IDebuggable.cs">
|
||||
<DependentUpon>VectrexHawk.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\GCE\Vectrex\VectrexHawk.IEmulator.cs">
|
||||
<DependentUpon>VectrexHawk.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\GCE\Vectrex\VectrexHawk.IInputPollable.cs">
|
||||
<DependentUpon>VectrexHawk.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\GCE\Vectrex\VectrexHawk.IMemoryDomains.cs">
|
||||
<DependentUpon>VectrexHawk.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\GCE\Vectrex\VectrexHawk.ISaveRam.cs">
|
||||
<DependentUpon>VectrexHawk.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\GCE\Vectrex\VectrexHawk.ISettable.cs">
|
||||
<DependentUpon>VectrexHawk.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\GCE\Vectrex\VectrexHawk.IStatable.cs">
|
||||
<DependentUpon>VectrexHawk.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\GCE\Vectrex\VectrexHawkControllerDeck.cs" />
|
||||
<Compile Include="Consoles\GCE\Vectrex\VectrexHawkControllers.cs" />
|
||||
<Compile Include="Consoles\GCE\Vectrex\HW_Registers.cs" />
|
||||
<Compile Include="Consoles\GCE\Vectrex\Mappers\MapperBase.cs" />
|
||||
<Compile Include="Consoles\GCE\Vectrex\Mappers\Mapper_Default.cs" />
|
||||
<Compile Include="Consoles\GCE\Vectrex\MemoryMap.cs" />
|
||||
<Compile Include="Consoles\GCE\Vectrex\PPU.cs" />
|
||||
<Compile Include="Consoles\GCE\Vectrex\SerialPort.cs" />
|
||||
<Compile Include="Consoles\Coleco\ColecoVision.cs" />
|
||||
<Compile Include="Consoles\Coleco\ColecoVision.IDebuggable.cs">
|
||||
<DependentUpon>ColecoVision.cs</DependentUpon>
|
||||
|
@ -1493,6 +1526,13 @@
|
|||
<Compile Include="CPUs\CP1610\CP1610.Disassembler.cs" />
|
||||
<Compile Include="CPUs\CP1610\CP1610.Execute.cs" />
|
||||
<Compile Include="CPUs\HuC6280\HuC6280_CDL.cs" />
|
||||
<Compile Include="CPUs\MC6809\Execute.cs" />
|
||||
<Compile Include="CPUs\MC6809\Interrupts.cs" />
|
||||
<Compile Include="CPUs\MC6809\MC6809.cs" />
|
||||
<Compile Include="CPUs\MC6809\NewDisassembler.cs" />
|
||||
<Compile Include="CPUs\MC6809\Operations.cs" />
|
||||
<Compile Include="CPUs\MC6809\Registers.cs" />
|
||||
<Compile Include="CPUs\MC6809\Tables_Direct.cs" />
|
||||
<Compile Include="CPUs\LR35902\Execute.cs" />
|
||||
<Compile Include="CPUs\LR35902\Interrupts.cs" />
|
||||
<Compile Include="CPUs\LR35902\LR35902.cs" />
|
||||
|
|
|
@ -0,0 +1,303 @@
|
|||
using System;
|
||||
|
||||
namespace BizHawk.Emulation.Common.Components.MC6809
|
||||
{
|
||||
public partial class MC6809
|
||||
{
|
||||
private ulong totalExecutedCycles;
|
||||
public ulong TotalExecutedCycles { get { return totalExecutedCycles; } set { totalExecutedCycles = value; } }
|
||||
|
||||
private int EI_pending;
|
||||
private bool interrupts_enabled;
|
||||
|
||||
// variables for executing instructions
|
||||
public int instr_pntr = 0;
|
||||
public ushort[] cur_instr;
|
||||
public int opcode;
|
||||
public bool halted;
|
||||
public bool stopped;
|
||||
public bool jammed;
|
||||
public int LY;
|
||||
|
||||
public void FetchInstruction(byte opcode)
|
||||
{
|
||||
switch (opcode)
|
||||
{
|
||||
case 0x00: DIRECT_MEM(NEG); break; // NEG (Direct)
|
||||
case 0x01: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x02: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x03: DIRECT_MEM(COM); break; // COM (Direct)
|
||||
case 0x04: DIRECT_MEM(LSR); break; // LSR (Direct)
|
||||
case 0x05: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x06: DIRECT_MEM(ROR); break; // ROR (Direct)
|
||||
case 0x07: DIRECT_MEM(ASR); break; // ASR (Direct)
|
||||
case 0x08: DIRECT_MEM(ASL); break; // ASL , LSL (Direct)
|
||||
case 0x09: DIRECT_MEM(ROL); break; // ROL (Direct)
|
||||
case 0x0A: DIRECT_MEM(DEC8); break; // DEC (Direct)
|
||||
case 0x0B: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x0C: DIRECT_MEM(INC8); break; // INC (Direct)
|
||||
case 0x0D: DIRECT_MEM(TST); break; // TST (Direct)
|
||||
case 0x0E: JMP_DIR_(); break; // JMP (Direct)
|
||||
case 0x0F: DIRECT_MEM(CLR); break; // CLR (Direct)
|
||||
case 0x10: PAGE_2(); break; // Page 2
|
||||
case 0x11: PAGE_3(); break; // Page 3
|
||||
case 0x12: NOP_(); break; // NOP (Inherent)
|
||||
case 0x13: SYNC_(); break; // SYNC (Inherent)
|
||||
case 0x14: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x15: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x16: LBR_(true); break; // LBRA (Relative)
|
||||
case 0x17: LBSR_(); break; // LBSR (Relative)
|
||||
case 0x18: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x19: REG_OP(DA, A); break; // DAA (Inherent)
|
||||
case 0x1A: REG_OP_IMD_CC(OR8); break; // ORCC (Immediate)
|
||||
case 0x1B: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x1C: REG_OP_IMD_CC(AND8); break; // ANDCC (Immediate)
|
||||
case 0x1D: REG_OP(SEX, A); break; // SEX (Inherent)
|
||||
case 0x1E: EXG_(); break; // EXG (Immediate)
|
||||
case 0x1F: TFR_(); break; // TFR (Immediate)
|
||||
case 0x20: BR_(true); break; // BRA (Relative)
|
||||
case 0x21: BR_(false); break; // BRN (Relative)
|
||||
case 0x22: BR_(!(FlagC | FlagZ)); break; // BHI (Relative)
|
||||
case 0x23: BR_(FlagC | FlagZ); break; // BLS (Relative)
|
||||
case 0x24: BR_(!FlagC); break; // BHS , BCC (Relative)
|
||||
case 0x25: BR_(FlagC); break; // BLO , BCS (Relative)
|
||||
case 0x26: BR_(!FlagZ); break; // BNE (Relative)
|
||||
case 0x27: BR_(FlagZ); break; // BEQ (Relative)
|
||||
case 0x28: BR_(!FlagV); break; // BVC (Relative)
|
||||
case 0x29: BR_(FlagV); break; // BVS (Relative)
|
||||
case 0x2A: BR_(!FlagN); break; // BPL (Relative)
|
||||
case 0x2B: BR_(FlagN); break; // BMI (Relative)
|
||||
case 0x2C: BR_(FlagN == FlagV); break; // BGE (Relative)
|
||||
case 0x2D: BR_(FlagN ^ FlagV); break; // BLT (Relative)
|
||||
case 0x2E: BR_((!FlagZ) & (FlagN == FlagV)); break; // BGT (Relative)
|
||||
case 0x2F: BR_(FlagZ | (FlagN ^ FlagV)); break; // BLE (Relative)
|
||||
case 0x30: JR_COND(!FlagC); break; // LEAX (Indexed)
|
||||
case 0x31: ; break; // LEAY (Indexed)
|
||||
case 0x32: ; break; // LEAS (Indexed)
|
||||
case 0x33: ; break; // LEAU (Indexed)
|
||||
case 0x34: ; break; // PSHS (Immediate)
|
||||
case 0x35: ; break; // PULS (Immediate)
|
||||
case 0x36: ; break; // PSHU (Immediate)
|
||||
case 0x37: ; break; // PULU (Immediate)
|
||||
case 0x38: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x39: ; break; // RTS (Inherent)
|
||||
case 0x3A: ; break; // ABX (Inherent)
|
||||
case 0x3B: ; break; // RTI (Inherent)
|
||||
case 0x3C: ; break; // CWAI (Inherent)
|
||||
case 0x3D: ; break; // MUL (Inherent)
|
||||
case 0x3E: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x3F: ; break; // SWI (Inherent)
|
||||
case 0x40: REG_OP(NEG, A); break; // NEGA (Inherent)
|
||||
case 0x41: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x42: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x43: REG_OP(COM, A); break; // COMA (Inherent)
|
||||
case 0x44: REG_OP(LSR, A); break; // LSRA (Inherent)
|
||||
case 0x45: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x46: REG_OP(ROR, A); break; // RORA (Inherent)
|
||||
case 0x47: REG_OP(ASR, A); break; // ASRA (Inherent)
|
||||
case 0x48: REG_OP(ASL, A); break; // ASLA , LSLA (Inherent)
|
||||
case 0x49: REG_OP(ROL, A); break; // ROLA (Inherent)
|
||||
case 0x4A: REG_OP(DEC8, A); break; // DECA (Inherent)
|
||||
case 0x4B: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x4C: REG_OP(INC8, A); break; // INCA (Inherent)
|
||||
case 0x4D: REG_OP(TST, A); break; // TSTA (Inherent)
|
||||
case 0x4E: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x4F: REG_OP(CLR, A); break; // CLRA (Inherent)
|
||||
case 0x50: REG_OP(NEG, B); break; // NEGB (Inherent)
|
||||
case 0x51: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x52: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x53: REG_OP(COM, B); break; // COMB (Inherent)
|
||||
case 0x54: REG_OP(LSR, B); break; // LSRB (Inherent)
|
||||
case 0x55: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x56: REG_OP(ROR, B); break; // RORB (Inherent)
|
||||
case 0x57: REG_OP(ASR, B); break; // ASRB (Inherent)
|
||||
case 0x58: REG_OP(ASL, B); break; // ASLB , LSLB (Inherent)
|
||||
case 0x59: REG_OP(ROL, B); break; // ROLB (Inherent)
|
||||
case 0x5A: REG_OP(DEC8, B); break; // DECB (Inherent)
|
||||
case 0x5B: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x5C: REG_OP(INC8, B); break; // INCB (Inherent)
|
||||
case 0x5D: REG_OP(TST, B); break; // TSTB (Inherent)
|
||||
case 0x5E: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x5F: REG_OP(CLR, B); break; // CLRB (Inherent)
|
||||
case 0x60: REG_OP(TR, B); break; // NEG (Indexed)
|
||||
case 0x61: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x62: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x63: REG_OP(TR, B); break; // COM (Indexed)
|
||||
case 0x64: REG_OP(TR, B); break; // LSR (Indexed)
|
||||
case 0x65: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x66: REG_OP(TR, B); break; // ROR (Indexed)
|
||||
case 0x67: REG_OP(TR, A); break; // ASR (Indexed)
|
||||
case 0x68: REG_OP(TR, A); break; // ASL , LSL (Indexed)
|
||||
case 0x69: REG_OP(TR, A); break; // ROL (Indexed)
|
||||
case 0x6A: REG_OP(TR, A); break; // DEC (Indexed)
|
||||
case 0x6B: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x6C: REG_OP(TR, A); break; // INC (Indexed)
|
||||
case 0x6D: REG_OP(TR, A); break; // TST (Indexed)
|
||||
case 0x6E: REG_OP(TR, A); break; // JMP (Indexed)
|
||||
case 0x6F: REG_OP(TR, A); break; // CLR (Indexed)
|
||||
case 0x70: REG_OP(TR, A); break; // NEG (Extended)
|
||||
case 0x71: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x72: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x73: REG_OP(TR, A); break; // COM (Extended)
|
||||
case 0x74: REG_OP(TR, A); break; // LSR (Extended)
|
||||
case 0x75: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x76: REG_OP(TR, A); break; // ROR (Extended)
|
||||
case 0x77: REG_OP(TR, A); break; // ASR (Extended)
|
||||
case 0x78: REG_OP(TR, A); break; // ASL , LSL (Extended)
|
||||
case 0x79: REG_OP(TR, A); break; // ROL (Extended)
|
||||
case 0x7A: REG_OP(TR, A); break; // DEC (Extended)
|
||||
case 0x7B: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x7C: REG_OP(TR, A); break; // INC (Extended)
|
||||
case 0x7D: REG_OP(TR, A); break; // TST (Extended)
|
||||
case 0x7E: REG_OP(TR, A); break; // JMP (Extended)
|
||||
case 0x7F: REG_OP(TR, A); break; // CLR (Extended)
|
||||
case 0x80: REG_OP(ADD8, A); break; // SUBA (Immediate)
|
||||
case 0x81: REG_OP(ADD8, A); break; // CMPA (Immediate)
|
||||
case 0x82: REG_OP(ADD8, A); break; // SBCA (Immediate)
|
||||
case 0x83: REG_OP(ADD8, A); break; // SUBD (Immediate)
|
||||
case 0x84: REG_OP(ADD8, A); break; // ANDA (Immediate)
|
||||
case 0x85: REG_OP(ADD8, A); break; // BITA (Immediate)
|
||||
case 0x86: REG_OP(ADD8, A); break; // LDA (Immediate)
|
||||
case 0x87: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x88: REG_OP(ADC8, A); break; // EORA (Immediate)
|
||||
case 0x89: REG_OP(ADC8, A); break; // ADCA (Immediate)
|
||||
case 0x8A: REG_OP(ADC8, A); break; // ORA (Immediate)
|
||||
case 0x8B: REG_OP(ADC8, A); break; // ADDA (Immediate)
|
||||
case 0x8C: REG_OP(ADC8, A); break; // CMPX (Immediate)
|
||||
case 0x8D: REG_OP(ADC8, A); break; // BSR (Relative)
|
||||
case 0x8E: REG_OP(ADC8, A); break; // LDX (Immediate)
|
||||
case 0x8F: ILLEGAL(); break; // ILLEGAL
|
||||
case 0x90: REG_OP(ADD8, A); break; // SUBA (Direct)
|
||||
case 0x91: REG_OP(ADD8, A); break; // CMPA (Direct)
|
||||
case 0x92: REG_OP(ADD8, A); break; // SBCA (Direct)
|
||||
case 0x93: REG_OP(ADD8, A); break; // SUBD (Direct)
|
||||
case 0x94: REG_OP(ADD8, A); break; // ANDA (Direct)
|
||||
case 0x95: REG_OP(ADD8, A); break; // BITA (Direct)
|
||||
case 0x96: REG_OP(ADD8, A); break; // LDA (Direct)
|
||||
case 0x97: REG_OP(ADD8, A); break; // STA (Direct)
|
||||
case 0x98: REG_OP(ADC8, A); break; // EORA (Direct)
|
||||
case 0x99: REG_OP(ADC8, A); break; // ADCA (Direct)
|
||||
case 0x9A: REG_OP(ADC8, A); break; // ORA (Direct)
|
||||
case 0x9B: REG_OP(ADC8, A); break; // ADDA (Direct)
|
||||
case 0x9C: REG_OP(ADC8, A); break; // CMPX (Direct)
|
||||
case 0x9D: REG_OP(ADC8, A); break; // JSR (Direct)
|
||||
case 0x9E: REG_OP(ADC8, A); break; // LDX (Direct)
|
||||
case 0x9F: REG_OP(ADC8, A); break; // STX (Direct)
|
||||
case 0xA0: REG_OP(AND8, A); break; // SUBA (Indexed)
|
||||
case 0xA1: REG_OP(AND8, A); break; // CMPA (Indexed)
|
||||
case 0xA2: REG_OP(AND8, A); break; // SBCA (Indexed)
|
||||
case 0xA3: REG_OP(AND8, A); break; // SUBD (Indexed)
|
||||
case 0xA4: REG_OP(AND8, A); break; // ANDA (Indexed)
|
||||
case 0xA5: REG_OP(AND8, A); break; // BITA (Indexed)
|
||||
case 0xA6: REG_OP(AND8, A); break; // LDA (Indexed)
|
||||
case 0xA7: REG_OP(AND8, A); break; // STA (Indexed)
|
||||
case 0xA8: REG_OP(XOR8, A); break; // EORA (Indexed)
|
||||
case 0xA9: REG_OP(XOR8, A); break; // ADCA (Indexed)
|
||||
case 0xAA: REG_OP(XOR8, A); break; // ORA (Indexed)
|
||||
case 0xAB: REG_OP(XOR8, A); break; // ADDA (Indexed)
|
||||
case 0xAC: REG_OP(XOR8, A); break; // CMPX (Indexed)
|
||||
case 0xAD: REG_OP(XOR8, A); break; // JSR (Indexed)
|
||||
case 0xAE: REG_OP(XOR8, A); break; // LDX (Indexed)
|
||||
case 0xAF: REG_OP(XOR8, A); break; // STX (Indexed)
|
||||
case 0xB0: REG_OP(AND8, A); break; // SUBA (Extended)
|
||||
case 0xB1: REG_OP(AND8, A); break; // CMPA (Extended)
|
||||
case 0xB2: REG_OP(AND8, A); break; // SBCA (Extended)
|
||||
case 0xB3: REG_OP(AND8, A); break; // SUBD (Extended)
|
||||
case 0xB4: REG_OP(AND8, A); break; // ANDA (Extended)
|
||||
case 0xB5: REG_OP(AND8, A); break; // BITA (Extended)
|
||||
case 0xB6: REG_OP(AND8, A); break; // LDA (Extended)
|
||||
case 0xB7: REG_OP(AND8, A); break; // STA (Extended)
|
||||
case 0xB8: REG_OP(XOR8, A); break; // EORA (Extended)
|
||||
case 0xB9: REG_OP(XOR8, A); break; // ADCA (Extended)
|
||||
case 0xBA: REG_OP(XOR8, A); break; // ORA (Extended)
|
||||
case 0xBB: REG_OP(XOR8, A); break; // ADDA (Extended)
|
||||
case 0xBC: REG_OP(XOR8, A); break; // CMPX (Extended)
|
||||
case 0xBD: REG_OP(XOR8, A); break; // JSR (Extended)
|
||||
case 0xBE: REG_OP(XOR8, A); break; // LDX (Extended)
|
||||
case 0xBF: REG_OP(XOR8, A); break; // STX (Extended)
|
||||
case 0xC0: REG_OP(ADD8, A); break; // SUBB (Immediate)
|
||||
case 0xC1: REG_OP(ADD8, A); break; // CMPB (Immediate)
|
||||
case 0xC2: REG_OP(ADD8, A); break; // SBCB (Immediate)
|
||||
case 0xC3: REG_OP(ADD8, A); break; // ADDD (Immediate)
|
||||
case 0xC4: REG_OP(ADD8, A); break; // ANDB (Immediate)
|
||||
case 0xC5: REG_OP(ADD8, A); break; // BITB (Immediate)
|
||||
case 0xC6: REG_OP(ADD8, A); break; // LDB (Immediate)
|
||||
case 0xC7: ILLEGAL(); break; // ILLEGAL
|
||||
case 0xC8: REG_OP(ADC8, A); break; // EORB (Immediate)
|
||||
case 0xC9: REG_OP(ADC8, A); break; // ADCB (Immediate)
|
||||
case 0xCA: REG_OP(ADC8, A); break; // ORB (Immediate)
|
||||
case 0xCB: REG_OP(ADC8, A); break; // ADDB (Immediate)
|
||||
case 0xCC: REG_OP(ADC8, A); break; // LDD (Immediate)
|
||||
case 0xCD: ILLEGAL(); break; // ILLEGAL
|
||||
case 0xCE: REG_OP(ADC8, A); break; // LDU (Immediate)
|
||||
case 0xCF: ILLEGAL(); break; // ILLEGAL
|
||||
case 0xD0: REG_OP(ADD8, B); break; // SUBB (Direct)
|
||||
case 0xD1: REG_OP(ADD8, B); break; // CMPB (Direct)
|
||||
case 0xD2: REG_OP(ADD8, B); break; // SBCB (Direct)
|
||||
case 0xD3: REG_OP(ADD8, B); break; // ADDD (Direct)
|
||||
case 0xD4: REG_OP(ADD8, B); break; // ANDB (Direct)
|
||||
case 0xD5: REG_OP(ADD8, B); break; // BITB (Direct)
|
||||
case 0xD6: REG_OP(ADD8, B); break; // LDB (Direct)
|
||||
case 0xD7: REG_OP(ADD8, B); break; // STB (Direct)
|
||||
case 0xD8: REG_OP(ADC8, B); break; // EORB (Direct)
|
||||
case 0xD9: REG_OP(ADC8, B); break; // ADCB (Direct)
|
||||
case 0xDA: REG_OP(ADC8, B); break; // ORB (Direct)
|
||||
case 0xDB: REG_OP(ADC8, B); break; // ADDB (Direct)
|
||||
case 0xDC: REG_OP(ADC8, B); break; // LDD (Direct)
|
||||
case 0xDD: REG_OP(ADC8, B); break; // STD (Direct)
|
||||
case 0xDE: REG_OP(ADC8, B); break; // LDU (Direct)
|
||||
case 0xDF: REG_OP(ADC8, B); break; // STU (Direct)
|
||||
case 0xE0: REG_OP(AND8, B); break; // SUBB (Indexed)
|
||||
case 0xE1: REG_OP(AND8, B); break; // CMPB (Indexed)
|
||||
case 0xE2: REG_OP(AND8, B); break; // SBCB (Indexed)
|
||||
case 0xE3: REG_OP(AND8, B); break; // ADDD (Indexed)
|
||||
case 0xE4: REG_OP(AND8, B); break; // ANDB (Indexed)
|
||||
case 0xE5: REG_OP(AND8, B); break; // BITB (Indexed)
|
||||
case 0xE6: REG_OP(AND8, B); break; // LDB (Indexed)
|
||||
case 0xE7: REG_OP(AND8, B); break; // STB (Indexed)
|
||||
case 0xE8: REG_OP(XOR8, B); break; // EORB (Indexed)
|
||||
case 0xE9: REG_OP(XOR8, B); break; // ADCB (Indexed)
|
||||
case 0xEA: REG_OP(XOR8, B); break; // ORB (Indexed)
|
||||
case 0xEB: REG_OP(XOR8, B); break; // ADDB (Indexed)
|
||||
case 0xEC: REG_OP(XOR8, B); break; // LDD (Indexed)
|
||||
case 0xED: REG_OP(XOR8, B); break; // STD (Indexed)
|
||||
case 0xEE: REG_OP(XOR8, B); break; // LDU (Indexed)
|
||||
case 0xEF: REG_OP(XOR8, B); break; // STU (Indexed)
|
||||
case 0xF0: REG_OP(AND8, B); break; // SUBB (Extended)
|
||||
case 0xF1: REG_OP(AND8, B); break; // CMPB (Extended)
|
||||
case 0xF2: REG_OP(AND8, B); break; // SBCB (Extended)
|
||||
case 0xF3: REG_OP(AND8, B); break; // ADDD (Extended)
|
||||
case 0xF4: REG_OP(AND8, B); break; // ANDB (Extended)
|
||||
case 0xF5: REG_OP(AND8, B); break; // BITB (Extended)
|
||||
case 0xF6: REG_OP(AND8, B); break; // LDB (Extended)
|
||||
case 0xF7: REG_OP(AND8, B); break; // STB (Extended)
|
||||
case 0xF8: REG_OP(XOR8, B); break; // EORB (Extended)
|
||||
case 0xF9: REG_OP(XOR8, B); break; // ADCB (Extended)
|
||||
case 0xFA: REG_OP(XOR8, B); break; // ORB (Extended)
|
||||
case 0xFB: REG_OP(XOR8, B); break; // ADDB (Extended)
|
||||
case 0xFC: REG_OP(XOR8, B); break; // LDD (Extended)
|
||||
case 0xFD: REG_OP(XOR8, B); break; // STD (Extended)
|
||||
case 0xFE: REG_OP(XOR8, B); break; // LDU (Extended)
|
||||
case 0xFF: REG_OP(XOR8, B); break; // STU (Extended)
|
||||
}
|
||||
}
|
||||
|
||||
public void FetchInstruction2(byte opcode)
|
||||
{
|
||||
switch (opcode)
|
||||
{
|
||||
|
||||
default: ILLEGAL(); break;
|
||||
}
|
||||
}
|
||||
|
||||
public void FetchInstruction3(byte opcode)
|
||||
{
|
||||
switch (opcode)
|
||||
{
|
||||
|
||||
default: ILLEGAL(); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
using System;
|
||||
|
||||
namespace BizHawk.Emulation.Common.Components.MC6809
|
||||
{
|
||||
public partial class MC6809
|
||||
{
|
||||
private void INTERRUPT_()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void INTERRUPT_GBC_NOP()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private static ushort[] INT_vectors = new ushort[] {0x40, 0x48, 0x50, 0x58, 0x60, 0x00};
|
||||
|
||||
public ushort int_src;
|
||||
public int stop_time;
|
||||
public bool stop_check;
|
||||
public bool is_GBC; // GBC automatically adds a NOP to avoid the HALT bug (according to Sinimas)
|
||||
public bool I_use; // in halt mode, the I flag is checked earlier then when deicision to IRQ is taken
|
||||
public bool skip_once;
|
||||
public bool Halt_bug_2;
|
||||
public bool Halt_bug_3;
|
||||
|
||||
private void ResetInterrupts()
|
||||
{
|
||||
I_use = false;
|
||||
skip_once = false;
|
||||
Halt_bug_2 = false;
|
||||
Halt_bug_3 = false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,461 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Common.NumberExtensions;
|
||||
|
||||
// Motorola Corp 6809
|
||||
namespace BizHawk.Emulation.Common.Components.MC6809
|
||||
{
|
||||
public sealed partial class MC6809
|
||||
{
|
||||
// operations that can take place in an instruction
|
||||
public const ushort IDLE = 0;
|
||||
public const ushort OP = 1;
|
||||
public const ushort RD = 2;
|
||||
public const ushort WR = 3;
|
||||
public const ushort TR = 4;
|
||||
public const ushort ADD16BR = 5;
|
||||
public const ushort ADD8 = 6;
|
||||
public const ushort SUB8 = 7;
|
||||
public const ushort ADC8 = 8;
|
||||
public const ushort SBC8 = 9;
|
||||
public const ushort INC16 = 10;
|
||||
public const ushort INC8 = 11;
|
||||
public const ushort DEC16 = 12;
|
||||
public const ushort DEC8 = 13;
|
||||
public const ushort RLC = 14;
|
||||
public const ushort ROL = 15;
|
||||
public const ushort RRC = 16;
|
||||
public const ushort ROR = 17;
|
||||
public const ushort COM = 18;
|
||||
public const ushort DA = 19;
|
||||
public const ushort SCF = 20;
|
||||
public const ushort CCF = 21;
|
||||
public const ushort AND8 = 22;
|
||||
public const ushort XOR8 = 23;
|
||||
public const ushort OR8 = 24;
|
||||
public const ushort CP8 = 25;
|
||||
public const ushort ASL = 26;
|
||||
public const ushort ASR = 27;
|
||||
public const ushort LSR = 28;
|
||||
public const ushort SWAP = 29;
|
||||
public const ushort BIT = 30;
|
||||
public const ushort RES = 31;
|
||||
public const ushort SET = 32;
|
||||
public const ushort EI = 33;
|
||||
public const ushort DI = 34;
|
||||
public const ushort HALT = 35;
|
||||
public const ushort STOP = 36;
|
||||
public const ushort ASGN = 38;
|
||||
public const ushort ADDS = 39; // signed 16 bit operation used in 2 instructions
|
||||
public const ushort OP_G = 40; // glitchy opcode read performed by halt when interrupts disabled
|
||||
public const ushort JAM = 41; // all undocumented opcodes jam the machine
|
||||
public const ushort RD_F = 42; // special read case to pop value into F
|
||||
public const ushort EI_RETI = 43; // reti has no delay in interrupt enable
|
||||
public const ushort INT_GET = 44;
|
||||
public const ushort HALT_CHK = 45; // when in halt mode, actually check I Flag here
|
||||
public const ushort RD_INC = 46;
|
||||
public const ushort SET_ADDR = 47;
|
||||
public const ushort NEG = 48;
|
||||
public const ushort TST = 49;
|
||||
public const ushort CLR = 50;
|
||||
public const ushort OP_PG_2 = 51;
|
||||
public const ushort OP_PG_3 = 52;
|
||||
public const ushort SEX = 53;
|
||||
public const ushort RD_INC_OP = 54;
|
||||
public const ushort EXG = 55;
|
||||
public const ushort TFR = 56;
|
||||
public const ushort WR_DEC_LO = 57;
|
||||
public const ushort WR_HI = 58;
|
||||
public const ushort ADD8BR = 59;
|
||||
|
||||
public MC6809()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
ResetRegisters();
|
||||
ResetInterrupts();
|
||||
TotalExecutedCycles = 8;
|
||||
stop_check = false;
|
||||
cur_instr = new ushort[] { IDLE, IDLE, HALT_CHK, OP };
|
||||
}
|
||||
|
||||
// Memory Access
|
||||
|
||||
public Func<ushort, byte> ReadMemory;
|
||||
public Action<ushort, byte> WriteMemory;
|
||||
public Func<ushort, byte> PeekMemory;
|
||||
public Func<ushort, byte> DummyReadMemory;
|
||||
|
||||
// Special Function for Speed switching executed on a STOP
|
||||
public Func<int, int> SpeedFunc;
|
||||
|
||||
//this only calls when the first byte of an instruction is fetched.
|
||||
public Action<ushort> OnExecFetch;
|
||||
|
||||
public void UnregisterMemoryMapper()
|
||||
{
|
||||
ReadMemory = null;
|
||||
ReadMemory = null;
|
||||
PeekMemory = null;
|
||||
DummyReadMemory = null;
|
||||
}
|
||||
|
||||
public void SetCallbacks
|
||||
(
|
||||
Func<ushort, byte> ReadMemory,
|
||||
Func<ushort, byte> DummyReadMemory,
|
||||
Func<ushort, byte> PeekMemory,
|
||||
Action<ushort, byte> WriteMemory
|
||||
)
|
||||
{
|
||||
this.ReadMemory = ReadMemory;
|
||||
this.DummyReadMemory = DummyReadMemory;
|
||||
this.PeekMemory = PeekMemory;
|
||||
this.WriteMemory = WriteMemory;
|
||||
}
|
||||
|
||||
//a little CDL related stuff
|
||||
public delegate void DoCDLCallbackType(ushort addr, MC6809.eCDLogMemFlags flags);
|
||||
|
||||
public DoCDLCallbackType CDLCallback;
|
||||
|
||||
public enum eCDLogMemFlags
|
||||
{
|
||||
FetchFirst = 1,
|
||||
FetchOperand = 2,
|
||||
Data = 4,
|
||||
Write = 8
|
||||
};
|
||||
|
||||
// Execute instructions
|
||||
public void ExecuteOne(ref byte interrupt_src, byte interrupt_enable)
|
||||
{
|
||||
switch (cur_instr[instr_pntr++])
|
||||
{
|
||||
case IDLE:
|
||||
// do nothing
|
||||
break;
|
||||
case OP:
|
||||
// Read the opcode of the next instruction
|
||||
if (EI_pending > 0)
|
||||
{
|
||||
EI_pending--;
|
||||
if (EI_pending == 0)
|
||||
{
|
||||
interrupts_enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (I_use && interrupts_enabled && !jammed)
|
||||
{
|
||||
interrupts_enabled = false;
|
||||
|
||||
if (TraceCallback != null)
|
||||
{
|
||||
TraceCallback(new TraceInfo
|
||||
{
|
||||
Disassembly = "====IRQ====",
|
||||
RegisterInfo = ""
|
||||
});
|
||||
}
|
||||
|
||||
// call interrupt processor
|
||||
// lowest bit set is highest priority
|
||||
INTERRUPT_();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (OnExecFetch != null) OnExecFetch(PC);
|
||||
if (TraceCallback != null) TraceCallback(State());
|
||||
if (CDLCallback != null) CDLCallback(PC, eCDLogMemFlags.FetchFirst);
|
||||
FetchInstruction(ReadMemory(Regs[PC]++));
|
||||
}
|
||||
instr_pntr = 0;
|
||||
I_use = false;
|
||||
break;
|
||||
|
||||
case OP_PG_2:
|
||||
FetchInstruction2(ReadMemory(Regs[PC]++));
|
||||
break;
|
||||
case OP_PG_3:
|
||||
FetchInstruction3(ReadMemory(Regs[PC]++));
|
||||
break;
|
||||
case RD:
|
||||
Read_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case RD_INC:
|
||||
Read_Inc_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case RD_INC_OP:
|
||||
Read_Inc_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
switch (cur_instr[instr_pntr++])
|
||||
{
|
||||
case AND8:
|
||||
AND8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case OR8:
|
||||
OR8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case SUB8:
|
||||
SUB8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case WR:
|
||||
Write_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case WR_DEC_LO:
|
||||
Write_Dec_Lo_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case WR_HI:
|
||||
Write_Hi_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case TR:
|
||||
TR_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case EXG:
|
||||
EXG_Func(cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case TFR:
|
||||
TFR_Func(cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case SET_ADDR:
|
||||
Regs[cur_instr[instr_pntr++]] = (ushort)((Regs[cur_instr[instr_pntr++]] << 8) | Regs[cur_instr[instr_pntr++]]);
|
||||
break;
|
||||
case NEG:
|
||||
NEG_8_Func(cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case TST:
|
||||
TST_Func(cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case CLR:
|
||||
CLR_Func(cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case SEX:
|
||||
SEX_Func(cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case ADD16BR:
|
||||
ADD16BR_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case ADD8BR:
|
||||
ADD8BR_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case ADD8:
|
||||
ADD8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case SUB8:
|
||||
SUB8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case ADC8:
|
||||
ADC8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case SBC8:
|
||||
SBC8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case INC16:
|
||||
INC16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case INC8:
|
||||
INC8_Func(cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case DEC16:
|
||||
DEC16_Func(cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case DEC8:
|
||||
DEC8_Func(cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case RLC:
|
||||
RLC_Func(cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case ROL:
|
||||
ROL_Func(cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case RRC:
|
||||
RRC_Func(cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case ROR:
|
||||
ROR_Func(cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case COM:
|
||||
COM_Func(cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case DA:
|
||||
DA_Func(cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case SCF:
|
||||
SCF_Func(cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case CCF:
|
||||
CCF_Func(cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case AND8:
|
||||
AND8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case XOR8:
|
||||
XOR8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case OR8:
|
||||
OR8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case CP8:
|
||||
CP8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case ASL:
|
||||
ASL_Func(cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case ASR:
|
||||
ASR_Func(cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case LSR:
|
||||
LSR_Func(cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case SWAP:
|
||||
SWAP_Func(cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case BIT:
|
||||
BIT_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case RES:
|
||||
RES_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case SET:
|
||||
SET_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case EI:
|
||||
if (EI_pending == 0) { EI_pending = 2; }
|
||||
break;
|
||||
case DI:
|
||||
interrupts_enabled = false;
|
||||
EI_pending = 0;
|
||||
break;
|
||||
case HALT:
|
||||
|
||||
break;
|
||||
case STOP:
|
||||
|
||||
break;
|
||||
case ASGN:
|
||||
ASGN_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case ADDS:
|
||||
ADDS_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case OP_G:
|
||||
if (OnExecFetch != null) OnExecFetch(PC);
|
||||
if (TraceCallback != null) TraceCallback(State());
|
||||
if (CDLCallback != null) CDLCallback(PC, eCDLogMemFlags.FetchFirst);
|
||||
|
||||
FetchInstruction(ReadMemory(PC)); // note no increment
|
||||
|
||||
instr_pntr = 0;
|
||||
break;
|
||||
case JAM:
|
||||
jammed = true;
|
||||
instr_pntr--;
|
||||
break;
|
||||
case RD_F:
|
||||
Read_Func_F(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
|
||||
break;
|
||||
case EI_RETI:
|
||||
EI_pending = 1;
|
||||
break;
|
||||
case INT_GET:
|
||||
|
||||
break;
|
||||
case HALT_CHK:
|
||||
|
||||
break;
|
||||
}
|
||||
totalExecutedCycles++;
|
||||
}
|
||||
|
||||
// tracer stuff
|
||||
|
||||
public Action<TraceInfo> TraceCallback;
|
||||
|
||||
public string TraceHeader
|
||||
{
|
||||
get { return "MC6809: PC, machine code, mnemonic, operands, registers (A, F, B, C, D, E, H, L, SP), Cy, flags (ZNHCI)"; }
|
||||
}
|
||||
|
||||
public TraceInfo State(bool disassemble = true)
|
||||
{
|
||||
ushort notused;
|
||||
|
||||
return new TraceInfo
|
||||
{
|
||||
Disassembly = string.Format(
|
||||
"{0} ",
|
||||
disassemble ? Disassemble(PC, ReadMemory, out notused) : "---").PadRight(40),
|
||||
RegisterInfo = string.Format(
|
||||
"A:{0:X2} F:{1:X2} B:{2:X2} C:{3:X2} D:{4:X2} E:{5:X2} H:{6:X2} L:{7:X2}",
|
||||
|
||||
TotalExecutedCycles,
|
||||
LY,
|
||||
FlagZ ? "Z" : "z",
|
||||
FlagN ? "N" : "n",
|
||||
FlagH ? "H" : "h",
|
||||
FlagC ? "C" : "c",
|
||||
FlagI ? "I" : "i",
|
||||
interrupts_enabled ? "E" : "e")
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Optimization method to set cur_instr
|
||||
/// </summary>
|
||||
private void PopulateCURINSTR(ushort d0 = 0, ushort d1 = 0, ushort d2 = 0, ushort d3 = 0, ushort d4 = 0, ushort d5 = 0, ushort d6 = 0, ushort d7 = 0, ushort d8 = 0,
|
||||
ushort d9 = 0, ushort d10 = 0, ushort d11 = 0, ushort d12 = 0, ushort d13 = 0, ushort d14 = 0, ushort d15 = 0, ushort d16 = 0, ushort d17 = 0, ushort d18 = 0,
|
||||
ushort d19 = 0, ushort d20 = 0, ushort d21 = 0, ushort d22 = 0, ushort d23 = 0, ushort d24 = 0, ushort d25 = 0, ushort d26 = 0, ushort d27 = 0, ushort d28 = 0,
|
||||
ushort d29 = 0, ushort d30 = 0, ushort d31 = 0, ushort d32 = 0, ushort d33 = 0, ushort d34 = 0, ushort d35 = 0, ushort d36 = 0, ushort d37 = 0)
|
||||
{
|
||||
cur_instr[0] = d0; cur_instr[1] = d1; cur_instr[2] = d2;
|
||||
cur_instr[3] = d3; cur_instr[4] = d4; cur_instr[5] = d5;
|
||||
cur_instr[6] = d6; cur_instr[7] = d7; cur_instr[8] = d8;
|
||||
cur_instr[9] = d9; cur_instr[10] = d10; cur_instr[11] = d11;
|
||||
cur_instr[12] = d12; cur_instr[13] = d13; cur_instr[14] = d14;
|
||||
cur_instr[15] = d15; cur_instr[16] = d16; cur_instr[17] = d17;
|
||||
cur_instr[18] = d18; cur_instr[19] = d19; cur_instr[20] = d20;
|
||||
cur_instr[21] = d21; cur_instr[22] = d22; cur_instr[23] = d23;
|
||||
cur_instr[24] = d24; cur_instr[25] = d25; cur_instr[26] = d26;
|
||||
cur_instr[27] = d27; cur_instr[28] = d28; cur_instr[29] = d29;
|
||||
cur_instr[30] = d30; cur_instr[31] = d31; cur_instr[32] = d32;
|
||||
cur_instr[33] = d33; cur_instr[34] = d34; cur_instr[35] = d35;
|
||||
cur_instr[36] = d36; cur_instr[37] = d37;
|
||||
}
|
||||
|
||||
// State Save/Load
|
||||
public void SyncState(Serializer ser)
|
||||
{
|
||||
ser.BeginSection("MC6809");
|
||||
ser.Sync("IRQ", ref interrupts_enabled);
|
||||
ser.Sync("I_use", ref I_use);
|
||||
ser.Sync("skip_once", ref skip_once);
|
||||
ser.Sync("Halt_bug_2", ref Halt_bug_2);
|
||||
ser.Sync("Halt_bug_3", ref Halt_bug_3);
|
||||
ser.Sync("Halted", ref halted);
|
||||
ser.Sync("ExecutedCycles", ref totalExecutedCycles);
|
||||
ser.Sync("EI_pending", ref EI_pending);
|
||||
ser.Sync("int_src", ref int_src);
|
||||
ser.Sync("stop_time", ref stop_time);
|
||||
ser.Sync("stop_check", ref stop_check);
|
||||
ser.Sync("is_GBC", ref is_GBC);
|
||||
|
||||
ser.Sync("instr_pntr", ref instr_pntr);
|
||||
ser.Sync("cur_instr", ref cur_instr, false);
|
||||
ser.Sync("Stopped", ref stopped);
|
||||
ser.Sync("opcode", ref opcode);
|
||||
ser.Sync("jammped", ref jammed);
|
||||
ser.Sync("LY", ref LY);
|
||||
|
||||
ser.EndSection();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,587 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BizHawk.Emulation.Common.Components.MC6809
|
||||
{
|
||||
// adapted from the information at http://www.pastraiser.com/cpu/gameboy/gameboy_opcodes.html
|
||||
public sealed partial class MC6809
|
||||
{
|
||||
static string[] table =
|
||||
{
|
||||
"NOP", // 00
|
||||
"LD BC,d16", // 01
|
||||
"LD (BC),A", // 02
|
||||
"INC BC", // 03
|
||||
"INC B", // 04
|
||||
"DEC B", // 05
|
||||
"LD B,d8", // 06
|
||||
"RLCA", // 07
|
||||
"LD (a16),SP", // 08
|
||||
"ADD HL,BC", // 09
|
||||
"LD A,(BC)", // 0a
|
||||
"DEC BC", // 0b
|
||||
"INC C", // 0c
|
||||
"DEC C", // 0d
|
||||
"LD C,d8", // 0e
|
||||
"RRCA", // 0f
|
||||
"STOP 0", // 10
|
||||
"LD DE,d16", // 11
|
||||
"LD (DE),A", // 12
|
||||
"INC DE", // 13
|
||||
"INC D", // 14
|
||||
"DEC D", // 15
|
||||
"LD D,d8", // 16
|
||||
"RLA", // 17
|
||||
"JR r8", // 18
|
||||
"ADD HL,DE", // 19
|
||||
"LD A,(DE)", // 1a
|
||||
"DEC DE", // 1b
|
||||
"INC E", // 1c
|
||||
"DEC E", // 1d
|
||||
"LD E,d8", // 1e
|
||||
"RRA", // 1f
|
||||
"JR NZ,r8", // 20
|
||||
"LD HL,d16", // 21
|
||||
"LD (HL+),A", // 22
|
||||
"INC HL", // 23
|
||||
"INC H", // 24
|
||||
"DEC H", // 25
|
||||
"LD H,d8", // 26
|
||||
"DAA", // 27
|
||||
"JR Z,r8", // 28
|
||||
"ADD HL,HL", // 29
|
||||
"LD A,(HL+)", // 2a
|
||||
"DEC HL", // 2b
|
||||
"INC L", // 2c
|
||||
"DEC L", // 2d
|
||||
"LD L,d8", // 2e
|
||||
"CPL", // 2f
|
||||
"JR NC,r8", // 30
|
||||
"LD SP,d16", // 31
|
||||
"LD (HL-),A", // 32
|
||||
"INC SP", // 33
|
||||
"INC (HL)", // 34
|
||||
"DEC (HL)", // 35
|
||||
"LD (HL),d8", // 36
|
||||
"SCF", // 37
|
||||
"JR C,r8", // 38
|
||||
"ADD HL,SP", // 39
|
||||
"LD A,(HL-)", // 3a
|
||||
"DEC SP", // 3b
|
||||
"INC A", // 3c
|
||||
"DEC A", // 3d
|
||||
"LD A,d8", // 3e
|
||||
"CCF", // 3f
|
||||
"LD B,B", // 40
|
||||
"LD B,C", // 41
|
||||
"LD B,D", // 42
|
||||
"LD B,E", // 43
|
||||
"LD B,H", // 44
|
||||
"LD B,L", // 45
|
||||
"LD B,(HL)", // 46
|
||||
"LD B,A", // 47
|
||||
"LD C,B", // 48
|
||||
"LD C,C", // 49
|
||||
"LD C,D", // 4a
|
||||
"LD C,E", // 4b
|
||||
"LD C,H", // 4c
|
||||
"LD C,L", // 4d
|
||||
"LD C,(HL)", // 4e
|
||||
"LD C,A", // 4f
|
||||
"LD D,B", // 50
|
||||
"LD D,C", // 51
|
||||
"LD D,D", // 52
|
||||
"LD D,E", // 53
|
||||
"LD D,H", // 54
|
||||
"LD D,L", // 55
|
||||
"LD D,(HL)", // 56
|
||||
"LD D,A", // 57
|
||||
"LD E,B", // 58
|
||||
"LD E,C", // 59
|
||||
"LD E,D", // 5a
|
||||
"LD E,E", // 5b
|
||||
"LD E,H", // 5c
|
||||
"LD E,L", // 5d
|
||||
"LD E,(HL)", // 5e
|
||||
"LD E,A", // 5f
|
||||
"LD H,B", // 60
|
||||
"LD H,C", // 61
|
||||
"LD H,D", // 62
|
||||
"LD H,E", // 63
|
||||
"LD H,H", // 64
|
||||
"LD H,L", // 65
|
||||
"LD H,(HL)", // 66
|
||||
"LD H,A", // 67
|
||||
"LD L,B", // 68
|
||||
"LD L,C", // 69
|
||||
"LD L,D", // 6a
|
||||
"LD L,E", // 6b
|
||||
"LD L,H", // 6c
|
||||
"LD L,L", // 6d
|
||||
"LD L,(HL)", // 6e
|
||||
"LD L,A", // 6f
|
||||
"LD (HL),B", // 70
|
||||
"LD (HL),C", // 71
|
||||
"LD (HL),D", // 72
|
||||
"LD (HL),E", // 73
|
||||
"LD (HL),H", // 74
|
||||
"LD (HL),L", // 75
|
||||
"HALT", // 76
|
||||
"LD (HL),A", // 77
|
||||
"LD A,B", // 78
|
||||
"LD A,C", // 79
|
||||
"LD A,D", // 7a
|
||||
"LD A,E", // 7b
|
||||
"LD A,H", // 7c
|
||||
"LD A,L", // 7d
|
||||
"LD A,(HL)", // 7e
|
||||
"LD A,A", // 7f
|
||||
"ADD A,B", // 80
|
||||
"ADD A,C", // 81
|
||||
"ADD A,D", // 82
|
||||
"ADD A,E", // 83
|
||||
"ADD A,H", // 84
|
||||
"ADD A,L", // 85
|
||||
"ADD A,(HL)", // 86
|
||||
"ADD A,A", // 87
|
||||
"ADC A,B", // 88
|
||||
"ADC A,C", // 89
|
||||
"ADC A,D", // 8a
|
||||
"ADC A,E", // 8b
|
||||
"ADC A,H", // 8c
|
||||
"ADC A,L", // 8d
|
||||
"ADC A,(HL)", // 8e
|
||||
"ADC A,A", // 8f
|
||||
"SUB B", // 90
|
||||
"SUB C", // 91
|
||||
"SUB D", // 92
|
||||
"SUB E", // 93
|
||||
"SUB H", // 94
|
||||
"SUB L", // 95
|
||||
"SUB (HL)", // 96
|
||||
"SUB A", // 97
|
||||
"SBC A,B", // 98
|
||||
"SBC A,C", // 99
|
||||
"SBC A,D", // 9a
|
||||
"SBC A,E", // 9b
|
||||
"SBC A,H", // 9c
|
||||
"SBC A,L", // 9d
|
||||
"SBC A,(HL)", // 9e
|
||||
"SBC A,A", // 9f
|
||||
"AND B", // a0
|
||||
"AND C", // a1
|
||||
"AND D", // a2
|
||||
"AND E", // a3
|
||||
"AND H", // a4
|
||||
"AND L", // a5
|
||||
"AND (HL)", // a6
|
||||
"AND A", // a7
|
||||
"XOR B", // a8
|
||||
"XOR C", // a9
|
||||
"XOR D", // aa
|
||||
"XOR E", // ab
|
||||
"XOR H", // ac
|
||||
"XOR L", // ad
|
||||
"XOR (HL)", // ae
|
||||
"XOR A", // af
|
||||
"OR B", // b0
|
||||
"OR C", // b1
|
||||
"OR D", // b2
|
||||
"OR E", // b3
|
||||
"OR H", // b4
|
||||
"OR L", // b5
|
||||
"OR (HL)", // b6
|
||||
"OR A", // b7
|
||||
"CP B", // b8
|
||||
"CP C", // b9
|
||||
"CP D", // ba
|
||||
"CP E", // bb
|
||||
"CP H", // bc
|
||||
"CP L", // bd
|
||||
"CP (HL)", // be
|
||||
"CP A", // bf
|
||||
"RET NZ", // c0
|
||||
"POP BC", // c1
|
||||
"JP NZ,a16", // c2
|
||||
"JP a16", // c3
|
||||
"CALL NZ,a16", // c4
|
||||
"PUSH BC", // c5
|
||||
"ADD A,d8", // c6
|
||||
"RST 00H", // c7
|
||||
"RET Z", // c8
|
||||
"RET", // c9
|
||||
"JP Z,a16", // ca
|
||||
"PREFIX CB", // cb
|
||||
"CALL Z,a16", // cc
|
||||
"CALL a16", // cd
|
||||
"ADC A,d8", // ce
|
||||
"RST 08H", // cf
|
||||
"RET NC", // d0
|
||||
"POP DE", // d1
|
||||
"JP NC,a16", // d2
|
||||
"???", // d3
|
||||
"CALL NC,a16", // d4
|
||||
"PUSH DE", // d5
|
||||
"SUB d8", // d6
|
||||
"RST 10H", // d7
|
||||
"RET C", // d8
|
||||
"RETI", // d9
|
||||
"JP C,a16", // da
|
||||
"???", // db
|
||||
"CALL C,a16", // dc
|
||||
"???", // dd
|
||||
"SBC A,d8", // de
|
||||
"RST 18H", // df
|
||||
"LDH (a8),A", // e0
|
||||
"POP HL", // e1
|
||||
"LD (C),A", // e2
|
||||
"???", // e3
|
||||
"???", // e4
|
||||
"PUSH HL", // e5
|
||||
"AND d8", // e6
|
||||
"RST 20H", // e7
|
||||
"ADD SP,r8", // e8
|
||||
"JP (HL)", // e9
|
||||
"LD (a16),A", // ea
|
||||
"???", // eb
|
||||
"???", // ec
|
||||
"???", // ed
|
||||
"XOR d8", // ee
|
||||
"RST 28H", // ef
|
||||
"LDH A,(a8)", // f0
|
||||
"POP AF", // f1
|
||||
"LD A,(C)", // f2
|
||||
"DI", // f3
|
||||
"???", // f4
|
||||
"PUSH AF", // f5
|
||||
"OR d8", // f6
|
||||
"RST 30H", // f7
|
||||
"LD HL,SP+r8", // f8
|
||||
"LD SP,HL", // f9
|
||||
"LD A,(a16)", // fa
|
||||
"EI ", // fb
|
||||
"???", // fc
|
||||
"???", // fd
|
||||
"CP d8", // fe
|
||||
"RST 38H", // ff
|
||||
"RLC B", // 00
|
||||
"RLC C", // 01
|
||||
"RLC D", // 02
|
||||
"RLC E", // 03
|
||||
"RLC H", // 04
|
||||
"RLC L", // 05
|
||||
"RLC (HL)", // 06
|
||||
"RLC A", // 07
|
||||
"RRC B", // 08
|
||||
"RRC C", // 09
|
||||
"RRC D", // 0a
|
||||
"RRC E", // 0b
|
||||
"RRC H", // 0c
|
||||
"RRC L", // 0d
|
||||
"RRC (HL)", // 0e
|
||||
"RRC A", // 0f
|
||||
"RL B", // 10
|
||||
"RL C", // 11
|
||||
"RL D", // 12
|
||||
"RL E", // 13
|
||||
"RL H", // 14
|
||||
"RL L", // 15
|
||||
"RL (HL)", // 16
|
||||
"RL A", // 17
|
||||
"RR B", // 18
|
||||
"RR C", // 19
|
||||
"RR D", // 1a
|
||||
"RR E", // 1b
|
||||
"RR H", // 1c
|
||||
"RR L", // 1d
|
||||
"RR (HL)", // 1e
|
||||
"RR A", // 1f
|
||||
"SLA B", // 20
|
||||
"SLA C", // 21
|
||||
"SLA D", // 22
|
||||
"SLA E", // 23
|
||||
"SLA H", // 24
|
||||
"SLA L", // 25
|
||||
"SLA (HL)", // 26
|
||||
"SLA A", // 27
|
||||
"SRA B", // 28
|
||||
"SRA C", // 29
|
||||
"SRA D", // 2a
|
||||
"SRA E", // 2b
|
||||
"SRA H", // 2c
|
||||
"SRA L", // 2d
|
||||
"SRA (HL)", // 2e
|
||||
"SRA A", // 2f
|
||||
"SWAP B", // 30
|
||||
"SWAP C", // 31
|
||||
"SWAP D", // 32
|
||||
"SWAP E", // 33
|
||||
"SWAP H", // 34
|
||||
"SWAP L", // 35
|
||||
"SWAP (HL)", // 36
|
||||
"SWAP A", // 37
|
||||
"SRL B", // 38
|
||||
"SRL C", // 39
|
||||
"SRL D", // 3a
|
||||
"SRL E", // 3b
|
||||
"SRL H", // 3c
|
||||
"SRL L", // 3d
|
||||
"SRL (HL)", // 3e
|
||||
"SRL A", // 3f
|
||||
"BIT 0,B", // 40
|
||||
"BIT 0,C", // 41
|
||||
"BIT 0,D", // 42
|
||||
"BIT 0,E", // 43
|
||||
"BIT 0,H", // 44
|
||||
"BIT 0,L", // 45
|
||||
"BIT 0,(HL)", // 46
|
||||
"BIT 0,A", // 47
|
||||
"BIT 1,B", // 48
|
||||
"BIT 1,C", // 49
|
||||
"BIT 1,D", // 4a
|
||||
"BIT 1,E", // 4b
|
||||
"BIT 1,H", // 4c
|
||||
"BIT 1,L", // 4d
|
||||
"BIT 1,(HL)", // 4e
|
||||
"BIT 1,A", // 4f
|
||||
"BIT 2,B", // 50
|
||||
"BIT 2,C", // 51
|
||||
"BIT 2,D", // 52
|
||||
"BIT 2,E", // 53
|
||||
"BIT 2,H", // 54
|
||||
"BIT 2,L", // 55
|
||||
"BIT 2,(HL)", // 56
|
||||
"BIT 2,A", // 57
|
||||
"BIT 3,B", // 58
|
||||
"BIT 3,C", // 59
|
||||
"BIT 3,D", // 5a
|
||||
"BIT 3,E", // 5b
|
||||
"BIT 3,H", // 5c
|
||||
"BIT 3,L", // 5d
|
||||
"BIT 3,(HL)", // 5e
|
||||
"BIT 3,A", // 5f
|
||||
"BIT 4,B", // 60
|
||||
"BIT 4,C", // 61
|
||||
"BIT 4,D", // 62
|
||||
"BIT 4,E", // 63
|
||||
"BIT 4,H", // 64
|
||||
"BIT 4,L", // 65
|
||||
"BIT 4,(HL)", // 66
|
||||
"BIT 4,A", // 67
|
||||
"BIT 5,B", // 68
|
||||
"BIT 5,C", // 69
|
||||
"BIT 5,D", // 6a
|
||||
"BIT 5,E", // 6b
|
||||
"BIT 5,H", // 6c
|
||||
"BIT 5,L", // 6d
|
||||
"BIT 5,(HL)", // 6e
|
||||
"BIT 5,A", // 6f
|
||||
"BIT 6,B", // 70
|
||||
"BIT 6,C", // 71
|
||||
"BIT 6,D", // 72
|
||||
"BIT 6,E", // 73
|
||||
"BIT 6,H", // 74
|
||||
"BIT 6,L", // 75
|
||||
"BIT 6,(HL)", // 76
|
||||
"BIT 6,A", // 77
|
||||
"BIT 7,B", // 78
|
||||
"BIT 7,C", // 79
|
||||
"BIT 7,D", // 7a
|
||||
"BIT 7,E", // 7b
|
||||
"BIT 7,H", // 7c
|
||||
"BIT 7,L", // 7d
|
||||
"BIT 7,(HL)", // 7e
|
||||
"BIT 7,A", // 7f
|
||||
"RES 0,B", // 80
|
||||
"RES 0,C", // 81
|
||||
"RES 0,D", // 82
|
||||
"RES 0,E", // 83
|
||||
"RES 0,H", // 84
|
||||
"RES 0,L", // 85
|
||||
"RES 0,(HL)", // 86
|
||||
"RES 0,A", // 87
|
||||
"RES 1,B", // 88
|
||||
"RES 1,C", // 89
|
||||
"RES 1,D", // 8a
|
||||
"RES 1,E", // 8b
|
||||
"RES 1,H", // 8c
|
||||
"RES 1,L", // 8d
|
||||
"RES 1,(HL)", // 8e
|
||||
"RES 1,A", // 8f
|
||||
"RES 2,B", // 90
|
||||
"RES 2,C", // 91
|
||||
"RES 2,D", // 92
|
||||
"RES 2,E", // 93
|
||||
"RES 2,H", // 94
|
||||
"RES 2,L", // 95
|
||||
"RES 2,(HL)", // 96
|
||||
"RES 2,A", // 97
|
||||
"RES 3,B", // 98
|
||||
"RES 3,C", // 99
|
||||
"RES 3,D", // 9a
|
||||
"RES 3,E", // 9b
|
||||
"RES 3,H", // 9c
|
||||
"RES 3,L", // 9d
|
||||
"RES 3,(HL)", // 9e
|
||||
"RES 3,A", // 9f
|
||||
"RES 4,B", // a0
|
||||
"RES 4,C", // a1
|
||||
"RES 4,D", // a2
|
||||
"RES 4,E", // a3
|
||||
"RES 4,H", // a4
|
||||
"RES 4,L", // a5
|
||||
"RES 4,(HL)", // a6
|
||||
"RES 4,A", // a7
|
||||
"RES 5,B", // a8
|
||||
"RES 5,C", // a9
|
||||
"RES 5,D", // aa
|
||||
"RES 5,E", // ab
|
||||
"RES 5,H", // ac
|
||||
"RES 5,L", // ad
|
||||
"RES 5,(HL)", // ae
|
||||
"RES 5,A", // af
|
||||
"RES 6,B", // b0
|
||||
"RES 6,C", // b1
|
||||
"RES 6,D", // b2
|
||||
"RES 6,E", // b3
|
||||
"RES 6,H", // b4
|
||||
"RES 6,L", // b5
|
||||
"RES 6,(HL)", // b6
|
||||
"RES 6,A", // b7
|
||||
"RES 7,B", // b8
|
||||
"RES 7,C", // b9
|
||||
"RES 7,D", // ba
|
||||
"RES 7,E", // bb
|
||||
"RES 7,H", // bc
|
||||
"RES 7,L", // bd
|
||||
"RES 7,(HL)", // be
|
||||
"RES 7,A", // bf
|
||||
"SET 0,B", // c0
|
||||
"SET 0,C", // c1
|
||||
"SET 0,D", // c2
|
||||
"SET 0,E", // c3
|
||||
"SET 0,H", // c4
|
||||
"SET 0,L", // c5
|
||||
"SET 0,(HL)", // c6
|
||||
"SET 0,A", // c7
|
||||
"SET 1,B", // c8
|
||||
"SET 1,C", // c9
|
||||
"SET 1,D", // ca
|
||||
"SET 1,E", // cb
|
||||
"SET 1,H", // cc
|
||||
"SET 1,L", // cd
|
||||
"SET 1,(HL)", // ce
|
||||
"SET 1,A", // cf
|
||||
"SET 2,B", // d0
|
||||
"SET 2,C", // d1
|
||||
"SET 2,D", // d2
|
||||
"SET 2,E", // d3
|
||||
"SET 2,H", // d4
|
||||
"SET 2,L", // d5
|
||||
"SET 2,(HL)", // d6
|
||||
"SET 2,A", // d7
|
||||
"SET 3,B", // d8
|
||||
"SET 3,C", // d9
|
||||
"SET 3,D", // da
|
||||
"SET 3,E", // db
|
||||
"SET 3,H", // dc
|
||||
"SET 3,L", // dd
|
||||
"SET 3,(HL)", // de
|
||||
"SET 3,A", // df
|
||||
"SET 4,B", // e0
|
||||
"SET 4,C", // e1
|
||||
"SET 4,D", // e2
|
||||
"SET 4,E", // e3
|
||||
"SET 4,H", // e4
|
||||
"SET 4,L", // e5
|
||||
"SET 4,(HL)", // e6
|
||||
"SET 4,A", // e7
|
||||
"SET 5,B", // e8
|
||||
"SET 5,C", // e9
|
||||
"SET 5,D", // ea
|
||||
"SET 5,E", // eb
|
||||
"SET 5,H", // ec
|
||||
"SET 5,L", // ed
|
||||
"SET 5,(HL)", // ee
|
||||
"SET 5,A", // ef
|
||||
"SET 6,B", // f0
|
||||
"SET 6,C", // f1
|
||||
"SET 6,D", // f2
|
||||
"SET 6,E", // f3
|
||||
"SET 6,H", // f4
|
||||
"SET 6,L", // f5
|
||||
"SET 6,(HL)", // f6
|
||||
"SET 6,A", // f7
|
||||
"SET 7,B", // f8
|
||||
"SET 7,C", // f9
|
||||
"SET 7,D", // fa
|
||||
"SET 7,E", // fb
|
||||
"SET 7,H", // fc
|
||||
"SET 7,L", // fd
|
||||
"SET 7,(HL)", // fe
|
||||
"SET 7,A", // ff
|
||||
};
|
||||
|
||||
public static string Disassemble(ushort addr, Func<ushort, byte> reader, out ushort size)
|
||||
{
|
||||
ushort origaddr = addr;
|
||||
List<byte> bytes = new List<byte>();
|
||||
bytes.Add(reader(addr++));
|
||||
|
||||
string result = table[bytes[0]];
|
||||
if (bytes[0] == 0xcb)
|
||||
{
|
||||
bytes.Add(reader(addr++));
|
||||
result = table[bytes[1] + 256];
|
||||
}
|
||||
|
||||
if (result.Contains("d8"))
|
||||
{
|
||||
byte d = reader(addr++);
|
||||
bytes.Add(d);
|
||||
result = result.Replace("d8", string.Format("#{0:X2}h", d));
|
||||
}
|
||||
else if (result.Contains("d16"))
|
||||
{
|
||||
byte dlo = reader(addr++);
|
||||
byte dhi = reader(addr++);
|
||||
bytes.Add(dlo);
|
||||
bytes.Add(dhi);
|
||||
result = result.Replace("d16", string.Format("#{0:X2}{1:X2}h", dhi, dlo));
|
||||
}
|
||||
else if (result.Contains("a16"))
|
||||
{
|
||||
byte dlo = reader(addr++);
|
||||
byte dhi = reader(addr++);
|
||||
bytes.Add(dlo);
|
||||
bytes.Add(dhi);
|
||||
result = result.Replace("a16", string.Format("#{0:X2}{1:X2}h", dhi, dlo));
|
||||
}
|
||||
else if (result.Contains("a8"))
|
||||
{
|
||||
byte d = reader(addr++);
|
||||
bytes.Add(d);
|
||||
result = result.Replace("a8", string.Format("#FF{0:X2}h", d));
|
||||
}
|
||||
else if (result.Contains("r8"))
|
||||
{
|
||||
byte d = reader(addr++);
|
||||
bytes.Add(d);
|
||||
int offs = d;
|
||||
if (offs >= 128)
|
||||
offs -= 256;
|
||||
result = result.Replace("r8", string.Format("{0:X4}h", (ushort)(addr + offs)));
|
||||
}
|
||||
StringBuilder ret = new StringBuilder();
|
||||
ret.Append(string.Format("{0:X4}: ", origaddr));
|
||||
foreach (var b in bytes)
|
||||
ret.Append(string.Format("{0:X2} ", b));
|
||||
while (ret.Length < 17)
|
||||
ret.Append(' ');
|
||||
ret.Append(result);
|
||||
size = (ushort)(addr - origaddr);
|
||||
return ret.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,666 @@
|
|||
using BizHawk.Common.NumberExtensions;
|
||||
using System;
|
||||
|
||||
namespace BizHawk.Emulation.Common.Components.MC6809
|
||||
{
|
||||
public partial class MC6809
|
||||
{
|
||||
public void Read_Func(ushort dest, ushort src)
|
||||
{
|
||||
if (CDLCallback != null)
|
||||
{
|
||||
if (src == PC) CDLCallback(Regs[src], eCDLogMemFlags.FetchOperand);
|
||||
else CDLCallback(Regs[src], eCDLogMemFlags.Data);
|
||||
}
|
||||
Regs[dest] = ReadMemory(Regs[src]);
|
||||
}
|
||||
|
||||
public void Read_Inc_Func(ushort dest, ushort src)
|
||||
{
|
||||
if (CDLCallback != null)
|
||||
{
|
||||
if (src == PC) CDLCallback(Regs[src], eCDLogMemFlags.FetchOperand);
|
||||
else CDLCallback(Regs[src], eCDLogMemFlags.Data);
|
||||
}
|
||||
Regs[dest] = ReadMemory(Regs[src]);
|
||||
|
||||
Regs[src] = Regs[src]++;
|
||||
}
|
||||
|
||||
public void Write_Func(ushort dest_l, ushort dest_h, ushort src)
|
||||
{
|
||||
ushort addr = (ushort)(Regs[dest_l] | (Regs[dest_h]) << 8);
|
||||
if (CDLCallback != null) CDLCallback(addr, eCDLogMemFlags.Write | eCDLogMemFlags.Data);
|
||||
WriteMemory(addr, (byte)Regs[src]);
|
||||
}
|
||||
|
||||
public void NEG_8_Func(ushort src)
|
||||
{
|
||||
int Reg16_d = 0;
|
||||
Reg16_d -= Regs[src];
|
||||
|
||||
FlagC = Regs[src] != 0x0;
|
||||
FlagZ = (Reg16_d & 0xFF) == 0;
|
||||
FlagV = Regs[src] == 0x80;
|
||||
FlagN = (Reg16_d & 0xFF) > 127;
|
||||
|
||||
ushort ans = (ushort)(Reg16_d & 0xFF);
|
||||
// redo for half carry flag
|
||||
Reg16_d = 0;
|
||||
Reg16_d -= (Regs[src] & 0xF);
|
||||
FlagH = Reg16_d.Bit(4);
|
||||
Regs[src] = ans;
|
||||
}
|
||||
|
||||
// speical read for POP AF that always clears the lower 4 bits of F
|
||||
public void Read_Func_F(ushort dest, ushort src_l, ushort src_h)
|
||||
{
|
||||
Regs[dest] = (ushort)(ReadMemory((ushort)(Regs[src_l] | (Regs[src_h]) << 8)) & 0xF0);
|
||||
}
|
||||
|
||||
public void Write_Dec_Lo_Func(ushort dest, ushort src)
|
||||
{
|
||||
if (CDLCallback != null) CDLCallback(Regs[dest], eCDLogMemFlags.Write | eCDLogMemFlags.Data);
|
||||
WriteMemory(Regs[dest], (byte)Regs[src]);
|
||||
Regs[dest] -= 1;
|
||||
}
|
||||
|
||||
public void Write_Hi_Func(ushort dest, ushort src)
|
||||
{
|
||||
if (CDLCallback != null) CDLCallback(Regs[dest], eCDLogMemFlags.Write | eCDLogMemFlags.Data);
|
||||
WriteMemory(Regs[dest], (byte)(Regs[src] >> 8));
|
||||
}
|
||||
|
||||
public void TR_Func(ushort dest, ushort src)
|
||||
{
|
||||
Regs[dest] = Regs[src];
|
||||
}
|
||||
|
||||
public void TST_Func(ushort src)
|
||||
{
|
||||
FlagZ = Regs[src] == 0;
|
||||
FlagV = false;
|
||||
FlagN = (Regs[src] & 0xFF) > 127;
|
||||
}
|
||||
|
||||
public void CLR_Func(ushort src)
|
||||
{
|
||||
Regs[src] = 0;
|
||||
|
||||
FlagZ = true;
|
||||
FlagV = false;
|
||||
FlagC = false;
|
||||
FlagN = false;
|
||||
}
|
||||
|
||||
// source is considered a 16 bit signed value, used for long relative branch
|
||||
// no flags used
|
||||
public void ADD16BR_Func(ushort dest, ushort src)
|
||||
{
|
||||
Regs[dest] = (ushort)(Regs[dest] + (short)Regs[src]);
|
||||
}
|
||||
|
||||
public void ADD8BR_Func(ushort dest, ushort src)
|
||||
{
|
||||
if (Regs[src] > 127) { Regs[src] |= 0xFF00; }
|
||||
Regs[dest] = (ushort)(Regs[dest] + (short)Regs[src]);
|
||||
}
|
||||
|
||||
public void ADD8_Func(ushort dest, ushort src)
|
||||
{
|
||||
int Reg16_d = Regs[dest];
|
||||
Reg16_d += Regs[src];
|
||||
|
||||
FlagC = Reg16_d.Bit(8);
|
||||
FlagZ = (Reg16_d & 0xFF) == 0;
|
||||
|
||||
ushort ans = (ushort)(Reg16_d & 0xFF);
|
||||
|
||||
// redo for half carry flag
|
||||
Reg16_d = Regs[dest] & 0xF;
|
||||
Reg16_d += (Regs[src] & 0xF);
|
||||
|
||||
FlagH = Reg16_d.Bit(4);
|
||||
|
||||
FlagN = false;
|
||||
|
||||
Regs[dest] = ans;
|
||||
}
|
||||
|
||||
public void SUB8_Func(ushort dest, ushort src)
|
||||
{
|
||||
int Reg16_d = Regs[dest];
|
||||
Reg16_d -= Regs[src];
|
||||
|
||||
FlagC = Reg16_d.Bit(8);
|
||||
FlagZ = (Reg16_d & 0xFF) == 0;
|
||||
|
||||
ushort ans = (ushort)(Reg16_d & 0xFF);
|
||||
|
||||
// redo for half carry flag
|
||||
Reg16_d = Regs[dest] & 0xF;
|
||||
Reg16_d -= (Regs[src] & 0xF);
|
||||
|
||||
FlagH = Reg16_d.Bit(4);
|
||||
FlagN = true;
|
||||
|
||||
Regs[dest] = ans;
|
||||
}
|
||||
|
||||
public void BIT_Func(ushort bit, ushort src)
|
||||
{
|
||||
FlagZ = !Regs[src].Bit(bit);
|
||||
FlagH = true;
|
||||
FlagN = false;
|
||||
}
|
||||
|
||||
public void SET_Func(ushort bit, ushort src)
|
||||
{
|
||||
Regs[src] |= (ushort)(1 << bit);
|
||||
}
|
||||
|
||||
public void RES_Func(ushort bit, ushort src)
|
||||
{
|
||||
Regs[src] &= (ushort)(0xFF - (1 << bit));
|
||||
}
|
||||
|
||||
public void ASGN_Func(ushort src, ushort val)
|
||||
{
|
||||
Regs[src] = val;
|
||||
}
|
||||
|
||||
public void SWAP_Func(ushort src)
|
||||
{
|
||||
ushort temp = (ushort)((Regs[src] << 4) & 0xF0);
|
||||
Regs[src] = (ushort)(temp | (Regs[src] >> 4));
|
||||
|
||||
FlagZ = Regs[src] == 0;
|
||||
FlagH = false;
|
||||
FlagN = false;
|
||||
FlagC = false;
|
||||
}
|
||||
|
||||
public void ASL_Func(ushort src)
|
||||
{
|
||||
FlagC = Regs[src].Bit(7);
|
||||
FlagV = Regs[src].Bit(7) ^ Regs[src].Bit(6);
|
||||
|
||||
Regs[src] = (ushort)((Regs[src] << 1) & 0xFF);
|
||||
|
||||
FlagZ = Regs[src] == 0;
|
||||
FlagH = false;
|
||||
FlagN = (Regs[src] & 0xFF) > 127;
|
||||
|
||||
}
|
||||
|
||||
public void ASR_Func(ushort src)
|
||||
{
|
||||
FlagC = Regs[src].Bit(0);
|
||||
|
||||
ushort temp = (ushort)(Regs[src] & 0x80); // MSB doesn't change in this operation
|
||||
|
||||
Regs[src] = (ushort)((Regs[src] >> 1) | temp);
|
||||
|
||||
FlagZ = Regs[src] == 0;
|
||||
FlagH = false;
|
||||
FlagN = (Regs[src] & 0xFF) > 127;
|
||||
}
|
||||
|
||||
public void LSR_Func(ushort src)
|
||||
{
|
||||
FlagC = Regs[src].Bit(0);
|
||||
|
||||
Regs[src] = (ushort)(Regs[src] >> 1);
|
||||
|
||||
FlagZ = Regs[src] == 0;
|
||||
FlagN = false;
|
||||
}
|
||||
|
||||
public void COM_Func(ushort src)
|
||||
{
|
||||
Regs[src] = (ushort)((~Regs[src]) & 0xFF);
|
||||
|
||||
FlagC = true;
|
||||
FlagZ = Regs[src] == 0;
|
||||
FlagV = false;
|
||||
FlagN = (Regs[src] & 0xFF) > 127;
|
||||
}
|
||||
|
||||
public void SEX_Func(ushort src)
|
||||
{
|
||||
if (Regs[B] > 127)
|
||||
{
|
||||
Regs[A] = 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
Regs[A] = 0;
|
||||
}
|
||||
|
||||
FlagZ = D == 0;
|
||||
FlagN = Regs[B] > 127;
|
||||
}
|
||||
|
||||
public void CCF_Func(ushort src)
|
||||
{
|
||||
FlagC = !FlagC;
|
||||
FlagH = false;
|
||||
FlagN = false;
|
||||
}
|
||||
|
||||
public void SCF_Func(ushort src)
|
||||
{
|
||||
FlagC = true;
|
||||
FlagH = false;
|
||||
FlagN = false;
|
||||
}
|
||||
|
||||
public void AND8_Func(ushort dest, ushort src)
|
||||
{
|
||||
Regs[dest] = (ushort)(Regs[dest] & Regs[src]);
|
||||
|
||||
FlagZ = Regs[dest] == 0;
|
||||
FlagV = false;
|
||||
FlagN = Regs[B] > 127;
|
||||
}
|
||||
|
||||
public void OR8_Func(ushort dest, ushort src)
|
||||
{
|
||||
Regs[dest] = (ushort)(Regs[dest] | Regs[src]);
|
||||
|
||||
FlagZ = Regs[dest] == 0;
|
||||
FlagV = false;
|
||||
FlagN = Regs[B] > 127;
|
||||
}
|
||||
|
||||
public void XOR8_Func(ushort dest, ushort src)
|
||||
{
|
||||
Regs[dest] = (ushort)(Regs[dest] ^ Regs[src]);
|
||||
|
||||
FlagZ = Regs[dest] == 0;
|
||||
FlagC = false;
|
||||
FlagH = false;
|
||||
FlagN = false;
|
||||
}
|
||||
|
||||
public void CP8_Func(ushort dest, ushort src)
|
||||
{
|
||||
int Reg16_d = Regs[dest];
|
||||
Reg16_d -= Regs[src];
|
||||
|
||||
FlagC = Reg16_d.Bit(8);
|
||||
FlagZ = (Reg16_d & 0xFF) == 0;
|
||||
|
||||
// redo for half carry flag
|
||||
Reg16_d = Regs[dest] & 0xF;
|
||||
Reg16_d -= (Regs[src] & 0xF);
|
||||
|
||||
FlagH = Reg16_d.Bit(4);
|
||||
|
||||
FlagN = true;
|
||||
}
|
||||
|
||||
public void RRC_Func(ushort src)
|
||||
{
|
||||
FlagC = Regs[src].Bit(0);
|
||||
|
||||
Regs[src] = (ushort)((FlagC ? 0x80 : 0) | (Regs[src] >> 1));
|
||||
|
||||
FlagZ = (Regs[src] == 0);
|
||||
FlagH = false;
|
||||
FlagN = false;
|
||||
}
|
||||
|
||||
public void ROR_Func(ushort src)
|
||||
{
|
||||
ushort c = (ushort)(FlagC ? 0x80 : 0);
|
||||
|
||||
FlagC = Regs[src].Bit(0);
|
||||
|
||||
Regs[src] = (ushort)(c | (Regs[src] >> 1));
|
||||
|
||||
FlagZ = Regs[src] == 0;
|
||||
FlagN = (Regs[src] & 0xFF) > 127;
|
||||
}
|
||||
|
||||
public void RLC_Func(ushort src)
|
||||
{
|
||||
bool imm = false;
|
||||
if (imm) { src = A; }
|
||||
|
||||
ushort c = (ushort)(Regs[src].Bit(7) ? 1 : 0);
|
||||
FlagC = Regs[src].Bit(7);
|
||||
|
||||
Regs[src] = (ushort)(((Regs[src] << 1) & 0xFF) | c);
|
||||
|
||||
FlagZ = imm ? false : (Regs[src] == 0);
|
||||
FlagH = false;
|
||||
FlagN = false;
|
||||
}
|
||||
|
||||
public void ROL_Func(ushort src)
|
||||
{
|
||||
ushort c = (ushort)(FlagC ? 1 : 0);
|
||||
FlagC = Regs[src].Bit(7);
|
||||
FlagV = Regs[src].Bit(7) ^ Regs[src].Bit(6);
|
||||
|
||||
|
||||
Regs[src] = (ushort)(((Regs[src] << 1) & 0xFF) | c);
|
||||
|
||||
FlagZ = Regs[src] == 0;
|
||||
FlagN = (Regs[src] & 0xFF) > 127;
|
||||
}
|
||||
|
||||
public void INC8_Func(ushort src)
|
||||
{
|
||||
FlagV = Regs[src] == 0x7F;
|
||||
|
||||
Regs[src] = (ushort)((Regs[src] + 1) & 0xFF);
|
||||
|
||||
FlagZ = Regs[src] == 0;
|
||||
FlagN = (Regs[src] & 0xFF) > 127;
|
||||
}
|
||||
|
||||
public void DEC8_Func(ushort src)
|
||||
{
|
||||
FlagV = Regs[src] == 0x80;
|
||||
|
||||
Regs[src] = (ushort)((Regs[src] - 1) & 0xFF);
|
||||
|
||||
FlagZ = Regs[src] == 0;
|
||||
FlagN = (Regs[src] & 0xFF) > 127;
|
||||
}
|
||||
|
||||
public void INC16_Func(ushort src_l, ushort src_h)
|
||||
{
|
||||
int Reg16_d = Regs[src_l] | (Regs[src_h] << 8);
|
||||
|
||||
Reg16_d += 1;
|
||||
|
||||
Regs[src_l] = (ushort)(Reg16_d & 0xFF);
|
||||
Regs[src_h] = (ushort)((Reg16_d & 0xFF00) >> 8);
|
||||
}
|
||||
|
||||
public void DEC16_Func(ushort src)
|
||||
{
|
||||
Regs[src] -= 1;
|
||||
}
|
||||
|
||||
public void ADC8_Func(ushort dest, ushort src)
|
||||
{
|
||||
int Reg16_d = Regs[dest];
|
||||
int c = FlagC ? 1 : 0;
|
||||
|
||||
Reg16_d += (Regs[src] + c);
|
||||
|
||||
FlagC = Reg16_d.Bit(8);
|
||||
FlagZ = (Reg16_d & 0xFF) == 0;
|
||||
|
||||
ushort ans = (ushort)(Reg16_d & 0xFF);
|
||||
|
||||
// redo for half carry flag
|
||||
Reg16_d = Regs[dest] & 0xF;
|
||||
Reg16_d += ((Regs[src] & 0xF) + c);
|
||||
|
||||
FlagH = Reg16_d.Bit(4);
|
||||
FlagN = false;
|
||||
|
||||
Regs[dest] = ans;
|
||||
}
|
||||
|
||||
public void SBC8_Func(ushort dest, ushort src)
|
||||
{
|
||||
int Reg16_d = Regs[dest];
|
||||
int c = FlagC ? 1 : 0;
|
||||
|
||||
Reg16_d -= (Regs[src] + c);
|
||||
|
||||
FlagC = Reg16_d.Bit(8);
|
||||
FlagZ = (Reg16_d & 0xFF) == 0;
|
||||
|
||||
ushort ans = (ushort)(Reg16_d & 0xFF);
|
||||
|
||||
// redo for half carry flag
|
||||
Reg16_d = Regs[dest] & 0xF;
|
||||
Reg16_d -= ((Regs[src] & 0xF) + c);
|
||||
|
||||
FlagH = Reg16_d.Bit(4);
|
||||
FlagN = true;
|
||||
|
||||
Regs[dest] = ans;
|
||||
}
|
||||
|
||||
// DA code courtesy of AWJ: http://forums.nesdev.com/viewtopic.php?f=20&t=15944
|
||||
public void DA_Func(ushort src)
|
||||
{
|
||||
byte a = (byte)Regs[src];
|
||||
|
||||
if (!FlagN)
|
||||
{ // after an addition, adjust if (half-)carry occurred or if result is out of bounds
|
||||
if (FlagC || a > 0x99) { a += 0x60; FlagC = true; }
|
||||
if (FlagH || (a & 0x0f) > 0x09) { a += 0x6; }
|
||||
}
|
||||
else
|
||||
{ // after a subtraction, only adjust if (half-)carry occurred
|
||||
if (FlagC) { a -= 0x60; }
|
||||
if (FlagH) { a -= 0x6; }
|
||||
}
|
||||
|
||||
a &= 0xFF;
|
||||
|
||||
Regs[src] = a;
|
||||
|
||||
FlagZ = a == 0;
|
||||
FlagH = false;
|
||||
}
|
||||
|
||||
// used for signed operations
|
||||
public void ADDS_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
|
||||
{
|
||||
int Reg16_d = Regs[dest_l];
|
||||
int Reg16_s = Regs[src_l];
|
||||
|
||||
Reg16_d += Reg16_s;
|
||||
|
||||
ushort temp = 0;
|
||||
|
||||
// since this is signed addition, calculate the high byte carry appropriately
|
||||
if (Reg16_s.Bit(7))
|
||||
{
|
||||
if (((Reg16_d & 0xFF) >= Regs[dest_l]))
|
||||
{
|
||||
temp = 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = (ushort)(Reg16_d.Bit(8) ? 1 : 0);
|
||||
}
|
||||
|
||||
ushort ans_l = (ushort)(Reg16_d & 0xFF);
|
||||
|
||||
// JR operations do not effect flags
|
||||
if (dest_l != PC)
|
||||
{
|
||||
FlagC = Reg16_d.Bit(8);
|
||||
|
||||
// redo for half carry flag
|
||||
Reg16_d = Regs[dest_l] & 0xF;
|
||||
Reg16_d += Regs[src_l] & 0xF;
|
||||
|
||||
FlagH = Reg16_d.Bit(4);
|
||||
FlagN = false;
|
||||
FlagZ = false;
|
||||
}
|
||||
|
||||
Regs[dest_l] = ans_l;
|
||||
Regs[dest_h] += temp;
|
||||
Regs[dest_h] &= 0xFF;
|
||||
|
||||
}
|
||||
|
||||
public void EXG_Func(ushort sel)
|
||||
{
|
||||
ushort src = 0;
|
||||
ushort dest = 0;
|
||||
ushort temp = 0;
|
||||
if ((Regs[sel] & 0x8) == 0)
|
||||
{
|
||||
switch (Regs[sel] & 0xF)
|
||||
{
|
||||
case 0: src = Dr; break;
|
||||
case 1: src = X; break;
|
||||
case 2: src = Y; break;
|
||||
case 3: src = US; break;
|
||||
case 4: src = SP; break;
|
||||
case 5: src = PC; break;
|
||||
case 6: src = 0xFF; break;
|
||||
case 7: src = 0xFF; break;
|
||||
}
|
||||
|
||||
switch ((Regs[sel] >> 4) & 0xF)
|
||||
{
|
||||
case 0: dest = Dr; break;
|
||||
case 1: dest = X; break;
|
||||
case 2: dest = Y; break;
|
||||
case 3: dest = US; break;
|
||||
case 4: dest = SP; break;
|
||||
case 5: dest = PC; break;
|
||||
case 6: dest = 0xFF; break;
|
||||
case 7: dest = 0xFF; break;
|
||||
default: dest = 0xFF; break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (Regs[sel] & 0xF)
|
||||
{
|
||||
case 8: src = A; break;
|
||||
case 9: src = B; break;
|
||||
case 10: src = CC; break;
|
||||
case 11: src = DP; break;
|
||||
case 12: src = 0xFF; break;
|
||||
case 13: src = 0xFF; break;
|
||||
case 14: src = 0xFF; break;
|
||||
case 15: src = 0xFF; break;
|
||||
}
|
||||
|
||||
switch ((Regs[sel] >> 4) & 0xF)
|
||||
{
|
||||
case 8: dest = A; break;
|
||||
case 9: dest = B; break;
|
||||
case 10: dest = CC; break;
|
||||
case 11: dest = DP; break;
|
||||
case 12: dest = 0xFF; break;
|
||||
case 13: dest = 0xFF; break;
|
||||
case 14: dest = 0xFF; break;
|
||||
case 15: dest = 0xFF; break;
|
||||
default: dest = 0xFF; break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((src != 0xFF) && (dest != 0xFF))
|
||||
{
|
||||
if (src == Dr)
|
||||
{
|
||||
temp = D;
|
||||
D = Regs[dest];
|
||||
Regs[dest] = temp;
|
||||
}
|
||||
else if (dest == Dr)
|
||||
{
|
||||
temp = D;
|
||||
D = Regs[src];
|
||||
Regs[src] = temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = Regs[src];
|
||||
Regs[src] = Regs[dest];
|
||||
Regs[dest] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void TFR_Func(ushort sel)
|
||||
{
|
||||
ushort src = 0;
|
||||
ushort dest = 0;
|
||||
|
||||
if ((Regs[sel] & 0x8) == 0)
|
||||
{
|
||||
switch (Regs[sel] & 0xF)
|
||||
{
|
||||
case 0: dest = Dr; break;
|
||||
case 1: dest = X; break;
|
||||
case 2: dest = Y; break;
|
||||
case 3: dest = US; break;
|
||||
case 4: dest = SP; break;
|
||||
case 5: dest = PC; break;
|
||||
case 6: dest = 0xFF; break;
|
||||
case 7: dest = 0xFF; break;
|
||||
}
|
||||
|
||||
switch ((Regs[sel] >> 4) & 0xF)
|
||||
{
|
||||
case 0: src = Dr; break;
|
||||
case 1: src = X; break;
|
||||
case 2: src = Y; break;
|
||||
case 3: src = US; break;
|
||||
case 4: src = SP; break;
|
||||
case 5: src = PC; break;
|
||||
case 6: src = 0xFF; break;
|
||||
case 7: src = 0xFF; break;
|
||||
default: src = 0xFF; break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (Regs[sel] & 0xF)
|
||||
{
|
||||
case 8: dest = A; break;
|
||||
case 9: dest = B; break;
|
||||
case 10: dest = CC; break;
|
||||
case 11: dest = DP; break;
|
||||
case 12: dest = 0xFF; break;
|
||||
case 13: dest = 0xFF; break;
|
||||
case 14: dest = 0xFF; break;
|
||||
case 15: dest = 0xFF; break;
|
||||
}
|
||||
|
||||
switch ((Regs[sel] >> 4) & 0xF)
|
||||
{
|
||||
case 8: src = A; break;
|
||||
case 9: src = B; break;
|
||||
case 10: src = CC; break;
|
||||
case 11: src = DP; break;
|
||||
case 12: src = 0xFF; break;
|
||||
case 13: src = 0xFF; break;
|
||||
case 14: src = 0xFF; break;
|
||||
case 15: src = 0xFF; break;
|
||||
default: src = 0xFF; break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((src != 0xFF) && (dest != 0xFF))
|
||||
{
|
||||
if (src == Dr)
|
||||
{
|
||||
Regs[dest] = D;
|
||||
}
|
||||
else if (dest == Dr)
|
||||
{
|
||||
D = Regs[src];
|
||||
}
|
||||
else
|
||||
{
|
||||
Regs[dest] = Regs[dest];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
TODO: STOP for second byte nonzero
|
|
@ -0,0 +1,87 @@
|
|||
using System.Runtime.InteropServices;
|
||||
using System;
|
||||
|
||||
namespace BizHawk.Emulation.Common.Components.MC6809
|
||||
{
|
||||
public partial class MC6809
|
||||
{
|
||||
// registers
|
||||
public ushort[] Regs = new ushort[12];
|
||||
|
||||
public const ushort PC = 0;
|
||||
public const ushort US = 1;
|
||||
public const ushort SP = 2;
|
||||
public const ushort X = 3;
|
||||
public const ushort Y = 4;
|
||||
public const ushort A = 5;
|
||||
public const ushort B = 6;
|
||||
public const ushort ADDR = 7; // internal
|
||||
public const ushort ALU = 8; // internal
|
||||
public const ushort ALU2 = 9; // internal
|
||||
public const ushort DP = 10;
|
||||
public const ushort CC = 11;
|
||||
public const ushort Dr = 12;
|
||||
|
||||
public ushort D
|
||||
{
|
||||
get { return (ushort)(Regs[B] | (Regs[A] << 8)); }
|
||||
set { Regs[B] = (ushort)(value & 0xFF); Regs[A] = (ushort)((value >> 8) & 0xFF); }
|
||||
}
|
||||
|
||||
public bool FlagC
|
||||
{
|
||||
get { return (Regs[CC] & 0x01) != 0; }
|
||||
set { Regs[CC] = (byte)((Regs[CC] & ~0x01) | (value ? 0x01 : 0x00)); }
|
||||
}
|
||||
|
||||
public bool FlagV
|
||||
{
|
||||
get { return (Regs[CC] & 0x02) != 0; }
|
||||
set { Regs[CC] = (byte)((Regs[CC] & ~0x02) | (value ? 0x02 : 0x00)); }
|
||||
}
|
||||
|
||||
public bool FlagZ
|
||||
{
|
||||
get { return (Regs[CC] & 0x04) != 0; }
|
||||
set { Regs[CC] = (byte)((Regs[CC] & ~0x04) | (value ? 0x04 : 0x00)); }
|
||||
}
|
||||
|
||||
public bool FlagN
|
||||
{
|
||||
get { return (Regs[CC] & 0x08) != 0; }
|
||||
set { Regs[CC] = (byte)((Regs[CC] & ~0x08) | (value ? 0x08 : 0x00)); }
|
||||
}
|
||||
|
||||
public bool FlagI
|
||||
{
|
||||
get { return (Regs[CC] & 0x10) != 0; }
|
||||
set { Regs[CC] = (byte)((Regs[CC] & ~0x10) | (value ? 0x10 : 0x00)); }
|
||||
}
|
||||
|
||||
public bool FlagH
|
||||
{
|
||||
get { return (Regs[CC] & 0x20) != 0; }
|
||||
set { Regs[CC] = (byte)((Regs[CC] & ~0x20) | (value ? 0x20 : 0x00)); }
|
||||
}
|
||||
|
||||
public bool FlagF
|
||||
{
|
||||
get { return (Regs[CC] & 0x40) != 0; }
|
||||
set { Regs[CC] = (byte)((Regs[CC] & ~0x40) | (value ? 0x40 : 0x00)); }
|
||||
}
|
||||
|
||||
public bool FlagE
|
||||
{
|
||||
get { return (Regs[CC] & 0x80) != 0; }
|
||||
set { Regs[CC] = (byte)((Regs[CC] & ~0x80) | (value ? 0x80 : 0x00)); }
|
||||
}
|
||||
|
||||
private void ResetRegisters()
|
||||
{
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
Regs[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,268 @@
|
|||
using System;
|
||||
|
||||
namespace BizHawk.Emulation.Common.Components.MC6809
|
||||
{
|
||||
public partial class MC6809
|
||||
{
|
||||
// this contains the vectors of instrcution operations
|
||||
// NOTE: This list is NOT confirmed accurate for each individual cycle
|
||||
|
||||
private void NOP_()
|
||||
{
|
||||
PopulateCURINSTR(IDLE);
|
||||
}
|
||||
|
||||
private void ILLEGAL()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void SYNC_()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void DIRECT_MEM(ushort oper)
|
||||
{
|
||||
PopulateCURINSTR(RD_INC, ALU, PC,
|
||||
SET_ADDR, ADDR, DP, ALU,
|
||||
RD, ADDR,
|
||||
oper, ALU,
|
||||
WR, ADDR);
|
||||
}
|
||||
|
||||
private void REG_OP_IMD_CC(ushort oper)
|
||||
{
|
||||
Regs[ALU2] = Regs[CC];
|
||||
PopulateCURINSTR(RD_INC_OP, ALU, PC, oper, ALU2, ALU,
|
||||
TR, CC, ALU2);
|
||||
}
|
||||
|
||||
private void EXG_()
|
||||
{
|
||||
PopulateCURINSTR(RD_INC, ALU,
|
||||
EXG, ALU,
|
||||
IDLE,
|
||||
IDLE,
|
||||
IDLE,
|
||||
IDLE,
|
||||
IDLE);
|
||||
}
|
||||
|
||||
private void TFR_()
|
||||
{
|
||||
PopulateCURINSTR(RD_INC, ALU,
|
||||
TFR, ALU,
|
||||
IDLE,
|
||||
IDLE,
|
||||
IDLE);
|
||||
}
|
||||
|
||||
private void REG_OP(ushort oper, ushort src)
|
||||
{
|
||||
PopulateCURINSTR(oper, src);
|
||||
}
|
||||
|
||||
private void JMP_DIR_()
|
||||
{
|
||||
PopulateCURINSTR(RD_INC, ALU, PC,
|
||||
SET_ADDR, PC, DP, ALU);
|
||||
}
|
||||
|
||||
private void LBR_(bool cond)
|
||||
{
|
||||
if (cond)
|
||||
{
|
||||
PopulateCURINSTR(RD_INC, ALU, PC,
|
||||
RD_INC, ALU2, PC,
|
||||
SET_ADDR, ADDR, ALU, ALU2,
|
||||
ADD16BR, PC, ADDR);
|
||||
}
|
||||
else
|
||||
{
|
||||
PopulateCURINSTR(RD_INC, ALU, PC,
|
||||
RD_INC, ALU2, PC,
|
||||
SET_ADDR, PC, ALU, ALU2);
|
||||
}
|
||||
}
|
||||
|
||||
private void BR_(bool cond)
|
||||
{
|
||||
if (cond)
|
||||
{
|
||||
PopulateCURINSTR(RD_INC, ALU, PC,
|
||||
ADD8BR, PC, ALU);
|
||||
}
|
||||
else
|
||||
{
|
||||
PopulateCURINSTR(RD_INC, ALU, PC,
|
||||
IDLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void LBSR_()
|
||||
{
|
||||
PopulateCURINSTR(RD_INC, ALU, PC,
|
||||
RD_INC, ALU2, PC,
|
||||
SET_ADDR, ADDR, ALU, ALU2,
|
||||
ADD16BR, PC, ADDR,
|
||||
TR, ADDR, PC,
|
||||
DEC16, SP,
|
||||
WR_DEC_LO, SP, ADDR,
|
||||
WR_HI, SP, ADDR);
|
||||
}
|
||||
|
||||
private void PAGE_2()
|
||||
{
|
||||
|
||||
PopulateCURINSTR(OP_PG_2);
|
||||
}
|
||||
|
||||
private void PAGE_3()
|
||||
{
|
||||
|
||||
PopulateCURINSTR(OP_PG_3);
|
||||
}
|
||||
|
||||
private void INC_16(ushort src_l, ushort src_h)
|
||||
{
|
||||
cur_instr = new ushort[]
|
||||
{IDLE,
|
||||
IDLE,
|
||||
IDLE,
|
||||
INC16, src_l, src_h,
|
||||
IDLE,
|
||||
IDLE,
|
||||
HALT_CHK,
|
||||
OP };
|
||||
}
|
||||
|
||||
|
||||
private void DEC_16(ushort src_l, ushort src_h)
|
||||
{
|
||||
cur_instr = new ushort[]
|
||||
{IDLE,
|
||||
IDLE,
|
||||
IDLE,
|
||||
DEC16, src_l, src_h,
|
||||
IDLE,
|
||||
IDLE,
|
||||
HALT_CHK,
|
||||
OP };
|
||||
}
|
||||
|
||||
private void ADD_16(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void STOP_()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void HALT_()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void JR_COND(bool cond)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void JP_COND(bool cond)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void RET_()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void RETI_()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void RET_COND(bool cond)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void CALL_COND(bool cond)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void INT_OP(ushort operation, ushort src)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void BIT_OP(ushort operation, ushort bit, ushort src)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void PUSH_(ushort src_l, ushort src_h)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// NOTE: this is the only instruction that can write to F
|
||||
// but the bottom 4 bits of F are always 0, so instead of putting a special check for every read op
|
||||
// let's just put a special operation here specifically for F
|
||||
private void POP_(ushort src_l, ushort src_h)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void RST_(ushort n)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void PREFIX_()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void DI_()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void EI_()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void JP_HL()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void ADD_SP()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void LD_SP_HL()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void LD_HL_SPn()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void JAM_()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,379 @@
|
|||
using System;
|
||||
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Common.BufferExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Common.NumberExtensions;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Vectrex
|
||||
{
|
||||
// An AY_3_8912
|
||||
|
||||
public class Audio : ISoundProvider
|
||||
{
|
||||
public VectrexHawk Core { get; set; }
|
||||
|
||||
private BlipBuffer _blip_L = new BlipBuffer(15000);
|
||||
private BlipBuffer _blip_R = new BlipBuffer(15000);
|
||||
|
||||
public uint master_audio_clock;
|
||||
|
||||
private short current_sample;
|
||||
|
||||
public byte[] Register = new byte[16];
|
||||
|
||||
public byte port_sel;
|
||||
|
||||
public short Sample()
|
||||
{
|
||||
return current_sample;
|
||||
}
|
||||
|
||||
private static readonly int[] VolumeTable =
|
||||
{
|
||||
0x0000, 0x0055, 0x0079, 0x00AB, 0x00F1, 0x0155, 0x01E3, 0x02AA,
|
||||
0x03C5, 0x0555, 0x078B, 0x0AAB, 0x0F16, 0x1555, 0x1E2B, 0x2AAA
|
||||
};
|
||||
|
||||
private int psg_clock;
|
||||
private int sq_per_A, sq_per_B, sq_per_C;
|
||||
private int clock_A, clock_B, clock_C;
|
||||
private int vol_A, vol_B, vol_C;
|
||||
private bool A_on, B_on, C_on;
|
||||
private bool A_up, B_up, C_up;
|
||||
private bool A_noise, B_noise, C_noise;
|
||||
|
||||
private int env_per;
|
||||
private int env_clock;
|
||||
private int env_shape;
|
||||
private int env_E;
|
||||
private int E_up_down;
|
||||
private int env_vol_A, env_vol_B, env_vol_C;
|
||||
|
||||
private int noise_clock;
|
||||
private int noise_per;
|
||||
private int noise = 0x1;
|
||||
|
||||
public void SyncState(Serializer ser)
|
||||
{
|
||||
ser.BeginSection("PSG");
|
||||
|
||||
ser.Sync("Register", ref Register, false);
|
||||
|
||||
ser.Sync("psg_clock", ref psg_clock);
|
||||
ser.Sync("clock_A", ref clock_A);
|
||||
ser.Sync("clock_B", ref clock_B);
|
||||
ser.Sync("clock_C", ref clock_C);
|
||||
ser.Sync("noise_clock", ref noise_clock);
|
||||
ser.Sync("env_clock", ref env_clock);
|
||||
ser.Sync("A_up", ref A_up);
|
||||
ser.Sync("B_up", ref B_up);
|
||||
ser.Sync("C_up", ref C_up);
|
||||
ser.Sync("noise", ref noise);
|
||||
ser.Sync("env_E", ref env_E);
|
||||
ser.Sync("E_up_down", ref E_up_down);
|
||||
ser.Sync("port_sel", ref port_sel);
|
||||
|
||||
sync_psg_state();
|
||||
|
||||
ser.EndSection();
|
||||
}
|
||||
|
||||
public byte ReadReg(int addr)
|
||||
{
|
||||
return Register[port_sel];
|
||||
}
|
||||
|
||||
private void sync_psg_state()
|
||||
{
|
||||
sq_per_A = (Register[0] & 0xFF) | (((Register[1] & 0xF) << 8));
|
||||
if (sq_per_A == 0)
|
||||
{
|
||||
sq_per_A = 0x1000;
|
||||
}
|
||||
|
||||
sq_per_B = (Register[2] & 0xFF) | (((Register[3] & 0xF) << 8));
|
||||
if (sq_per_B == 0)
|
||||
{
|
||||
sq_per_B = 0x1000;
|
||||
}
|
||||
|
||||
sq_per_C = (Register[4] & 0xFF) | (((Register[5] & 0xF) << 8));
|
||||
if (sq_per_C == 0)
|
||||
{
|
||||
sq_per_C = 0x1000;
|
||||
}
|
||||
|
||||
env_per = (Register[11] & 0xFF) | (((Register[12] & 0xFF) << 8));
|
||||
if (env_per == 0)
|
||||
{
|
||||
env_per = 0x10000;
|
||||
}
|
||||
|
||||
env_per *= 2;
|
||||
|
||||
A_on = Register[7].Bit(0);
|
||||
B_on = Register[7].Bit(1);
|
||||
C_on = Register[7].Bit(2);
|
||||
A_noise = Register[7].Bit(3);
|
||||
B_noise = Register[7].Bit(4);
|
||||
C_noise = Register[7].Bit(5);
|
||||
|
||||
noise_per = Register[6] & 0x1F;
|
||||
if (noise_per == 0)
|
||||
{
|
||||
noise_per = 0x20;
|
||||
}
|
||||
|
||||
var shape_select = Register[13] & 0xF;
|
||||
|
||||
if (shape_select < 4)
|
||||
env_shape = 0;
|
||||
else if (shape_select < 8)
|
||||
env_shape = 1;
|
||||
else
|
||||
env_shape = 2 + (shape_select - 8);
|
||||
|
||||
vol_A = Register[8] & 0xF;
|
||||
env_vol_A = (Register[8] >> 4) & 0x1;
|
||||
|
||||
vol_B = Register[9] & 0xF;
|
||||
env_vol_B = (Register[9] >> 4) & 0x1;
|
||||
|
||||
vol_C = Register[10] & 0xF;
|
||||
env_vol_C = (Register[10] >> 4) & 0x1;
|
||||
}
|
||||
|
||||
public void WriteReg(int addr, byte value)
|
||||
{
|
||||
value &= 0xFF;
|
||||
|
||||
Register[port_sel] = value;
|
||||
|
||||
sync_psg_state();
|
||||
|
||||
if (port_sel == 13)
|
||||
{
|
||||
env_clock = env_per;
|
||||
|
||||
if (env_shape == 0 || env_shape == 2 || env_shape == 3 || env_shape == 4 || env_shape == 5)
|
||||
{
|
||||
env_E = 15;
|
||||
E_up_down = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
env_E = 0;
|
||||
E_up_down = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void tick()
|
||||
{
|
||||
// there are 8 cpu cycles for every psg cycle
|
||||
bool sound_out_A;
|
||||
bool sound_out_B;
|
||||
bool sound_out_C;
|
||||
|
||||
psg_clock++;
|
||||
|
||||
if (psg_clock == 8)
|
||||
{
|
||||
psg_clock = 0;
|
||||
|
||||
clock_A--;
|
||||
clock_B--;
|
||||
clock_C--;
|
||||
|
||||
noise_clock--;
|
||||
env_clock--;
|
||||
|
||||
// clock noise
|
||||
if (noise_clock == 0)
|
||||
{
|
||||
noise = (noise >> 1) ^ (noise.Bit(0) ? 0x10004 : 0);
|
||||
noise_clock = noise_per;
|
||||
}
|
||||
|
||||
if (env_clock == 0)
|
||||
{
|
||||
env_clock = env_per;
|
||||
|
||||
env_E += E_up_down;
|
||||
|
||||
if (env_E == 16 || env_E == -1)
|
||||
{
|
||||
|
||||
// we just completed a period of the envelope, determine what to do now based on the envelope shape
|
||||
if (env_shape == 0 || env_shape == 1 || env_shape == 3 || env_shape == 9)
|
||||
{
|
||||
E_up_down = 0;
|
||||
env_E = 0;
|
||||
}
|
||||
else if (env_shape == 5 || env_shape == 7)
|
||||
{
|
||||
E_up_down = 0;
|
||||
env_E = 15;
|
||||
}
|
||||
else if (env_shape == 4 || env_shape == 8)
|
||||
{
|
||||
if (env_E == 16)
|
||||
{
|
||||
env_E = 15;
|
||||
E_up_down = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
env_E = 0;
|
||||
E_up_down = 1;
|
||||
}
|
||||
}
|
||||
else if (env_shape == 2)
|
||||
{
|
||||
env_E = 15;
|
||||
}
|
||||
else
|
||||
{
|
||||
env_E = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (clock_A == 0)
|
||||
{
|
||||
A_up = !A_up;
|
||||
clock_A = sq_per_A;
|
||||
}
|
||||
|
||||
if (clock_B == 0)
|
||||
{
|
||||
B_up = !B_up;
|
||||
clock_B = sq_per_B;
|
||||
}
|
||||
|
||||
if (clock_C == 0)
|
||||
{
|
||||
C_up = !C_up;
|
||||
clock_C = sq_per_C;
|
||||
}
|
||||
|
||||
|
||||
sound_out_A = (noise.Bit(0) | A_noise) & (A_on | A_up);
|
||||
sound_out_B = (noise.Bit(0) | B_noise) & (B_on | B_up);
|
||||
sound_out_C = (noise.Bit(0) | C_noise) & (C_on | C_up);
|
||||
|
||||
// now calculate the volume of each channel and add them together
|
||||
int v;
|
||||
|
||||
if (env_vol_A == 0)
|
||||
{
|
||||
v = (short)(sound_out_A ? VolumeTable[vol_A] : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
v = (short)(sound_out_A ? VolumeTable[vol_A] : 0);
|
||||
}
|
||||
|
||||
if (env_vol_B == 0)
|
||||
{
|
||||
v += (short)(sound_out_B ? VolumeTable[vol_B] : 0);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
v += (short)(sound_out_B ? VolumeTable[env_E] : 0);
|
||||
}
|
||||
|
||||
if (env_vol_C == 0)
|
||||
{
|
||||
v += (short)(sound_out_C ? VolumeTable[vol_C] : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
v += (short)(sound_out_C ? VolumeTable[env_E] : 0);
|
||||
}
|
||||
|
||||
current_sample = (short)v;
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
clock_A = clock_B = clock_C = 0x1000;
|
||||
noise_clock = 0x20;
|
||||
port_sel = 0;
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
Register[i] = 0x0000;
|
||||
}
|
||||
sync_psg_state();
|
||||
|
||||
_blip_L.SetRates(4194304, 44100);
|
||||
_blip_R.SetRates(4194304, 44100);
|
||||
}
|
||||
|
||||
#region audio
|
||||
|
||||
public bool CanProvideAsync => false;
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode != SyncSoundMode.Sync)
|
||||
{
|
||||
throw new InvalidOperationException("Only Sync mode is supported_");
|
||||
}
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode => SyncSoundMode.Sync;
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
_blip_L.EndFrame(master_audio_clock);
|
||||
_blip_R.EndFrame(master_audio_clock);
|
||||
|
||||
nsamp = _blip_L.SamplesAvailable();
|
||||
|
||||
// only for running without errors, remove this line once you get audio
|
||||
nsamp = 1;
|
||||
|
||||
samples = new short[nsamp * 2];
|
||||
|
||||
// uncomment these once you have audio to play
|
||||
//_blip_L.ReadSamplesLeft(samples, nsamp);
|
||||
//_blip_R.ReadSamplesRight(samples, nsamp);
|
||||
|
||||
master_audio_clock = 0;
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new NotSupportedException("Async is not available");
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
_blip_L.Clear();
|
||||
_blip_R.Clear();
|
||||
master_audio_clock = 0;
|
||||
}
|
||||
|
||||
private void GetSamples(short[] samples)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void DisposeSound()
|
||||
{
|
||||
_blip_L.Clear();
|
||||
_blip_R.Clear();
|
||||
_blip_L.Dispose();
|
||||
_blip_R.Dispose();
|
||||
_blip_L = null;
|
||||
_blip_R = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
using System;
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Common.NumberExtensions;
|
||||
using BizHawk.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Vectrex
|
||||
{
|
||||
public partial class VectrexHawk
|
||||
{
|
||||
// Interact with Hardware registers through these read and write methods
|
||||
// Typically you will only be able to access different parts of the hardware through their available registers
|
||||
// Sending the memory map of these regiesters through here helps keep things organized even though it results in an extra function call
|
||||
public byte Read_Registers(int addr)
|
||||
{
|
||||
byte ret = 0;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void Write_Registers(int addr, byte value)
|
||||
{
|
||||
switch (addr)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void Register_Reset()
|
||||
{
|
||||
// Registers will start with a default value at power on, use this funciton to set them
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
using BizHawk.Common;
|
||||
using System;
|
||||
|
||||
using BizHawk.Emulation.Common.Components.MC6809;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Vectrex
|
||||
{
|
||||
public class MapperBase
|
||||
{
|
||||
public VectrexHawk Core { get; set; }
|
||||
|
||||
public virtual byte ReadMemory(ushort addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public virtual byte PeekMemory(ushort addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public virtual void WriteMemory(ushort addr, byte value)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void PokeMemory(ushort addr, byte value)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void SyncState(Serializer ser)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void Mapper_Tick()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void RTC_Get(byte value, int index)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void MapCDL(ushort addr, MC6809.eCDLogMemFlags flags)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
using BizHawk.Common;
|
||||
using BizHawk.Common.NumberExtensions;
|
||||
using System;
|
||||
|
||||
using BizHawk.Emulation.Common.Components.MC6809;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Vectrex
|
||||
{
|
||||
// Default mapper with no bank switching
|
||||
// make sure peekmemory and poke memory don't effect the rest of the system!
|
||||
public class MapperDefault : MapperBase
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
// nothing to initialize
|
||||
}
|
||||
|
||||
public override byte ReadMemory(ushort addr)
|
||||
{
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
public override byte PeekMemory(ushort addr)
|
||||
{
|
||||
return ReadMemory(addr);
|
||||
}
|
||||
|
||||
public override void WriteMemory(ushort addr, byte value)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void PokeMemory(ushort addr, byte value)
|
||||
{
|
||||
WriteMemory(addr, value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
TODO:
|
||||
Official Mappers
|
||||
Unofficial Mappers
|
|
@ -0,0 +1,44 @@
|
|||
using System;
|
||||
|
||||
using BizHawk.Common.BufferExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
|
||||
/*
|
||||
Fill in the memory map in this space for easy reference
|
||||
ex:
|
||||
0x0000 - 0x0FFF RAM
|
||||
etc
|
||||
*/
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Vectrex
|
||||
{
|
||||
public partial class VectrexHawk
|
||||
{
|
||||
// typically here you have a big if / else if block to decide what to do with memory reads and writes
|
||||
// send hardware register accesses to the Read_register / Write_register methods
|
||||
// make sure you are returning the correct value (typically 0 or 0xFF) for unmapped memory
|
||||
|
||||
// PeekMemory is called by the hex eidtor and other tools to read what's on the bus
|
||||
// make sure it doesn't modify anything in the core or you will be in debugging hell.
|
||||
|
||||
public byte ReadMemory(ushort addr)
|
||||
{
|
||||
// memory callbacks are used for LUA and such
|
||||
MemoryCallbacks.CallReads(addr, "System Bus");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void WriteMemory(ushort addr, byte value)
|
||||
{
|
||||
MemoryCallbacks.CallWrites(addr, "System Bus");
|
||||
|
||||
}
|
||||
|
||||
public byte PeekMemory(ushort addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
using System;
|
||||
using BizHawk.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Vectrex
|
||||
{
|
||||
// Here is where you will write the renderer for the core.
|
||||
// You will probably spend just about all of your time writing this part.
|
||||
// Plan ahead on what types of memory structures you want, and understand how the physical display unit sees data
|
||||
// if you get stuck, probably GBHawk has the cleanest implementation to use for reference
|
||||
|
||||
public class PPU
|
||||
{
|
||||
public VectrexHawk Core { get; set; }
|
||||
|
||||
public byte ReadReg(int addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void WriteReg(int addr, byte value)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// you should be able to run the PPU one step at a time through this method.
|
||||
public void tick()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// if some values aren't latched immediately, you might need this function to delay their latching
|
||||
public virtual void latch_delay()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void render(int render_cycle)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Reset all values here, should be called along with other reset methods
|
||||
public void Reset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void SyncState(Serializer ser)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
TODO:
|
|
@ -0,0 +1,43 @@
|
|||
using System;
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Common.NumberExtensions;
|
||||
using BizHawk.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Vectrex
|
||||
{
|
||||
// your core may have several integral peripherals beyond the usual graphics / sound / controller
|
||||
// here is one such example
|
||||
// Treat it the same way as any other component. you should be able to run it one tick at a time in sync with the
|
||||
// other parts of the core
|
||||
|
||||
public class SerialPort
|
||||
{
|
||||
public VectrexHawk Core { get; set; }
|
||||
|
||||
public byte ReadReg(int addr)
|
||||
{
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
public void WriteReg(int addr, byte value)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void serial_transfer_tick()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void SyncState(Serializer ser)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
using BizHawk.Emulation.Cores.Components.M6502;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Vectrex
|
||||
{
|
||||
public partial class VectrexHawk
|
||||
{
|
||||
public struct CpuLink : IMOS6502XLink
|
||||
{
|
||||
private readonly VectrexHawk _Vectrex;
|
||||
|
||||
public CpuLink(VectrexHawk Vectrex)
|
||||
{
|
||||
_Vectrex = Vectrex;
|
||||
}
|
||||
|
||||
public byte DummyReadMemory(ushort address) => _Vectrex.ReadMemory(address);
|
||||
|
||||
public void OnExecFetch(ushort address) => _Vectrex.ExecFetch(address);
|
||||
|
||||
public byte PeekMemory(ushort address) => _Vectrex.CDL == null ? _Vectrex.PeekMemory(address) : _Vectrex.FetchMemory_CDL(address);
|
||||
|
||||
public byte ReadMemory(ushort address) => _Vectrex.CDL == null ? _Vectrex.ReadMemory(address) : _Vectrex.ReadMemory_CDL(address);
|
||||
|
||||
public void WriteMemory(ushort address, byte value) => _Vectrex.WriteMemory(address, value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Cores.Components.M6502;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Vectrex
|
||||
{
|
||||
public sealed partial class VectrexHawk : ICodeDataLogger
|
||||
{
|
||||
public void SetCDL(ICodeDataLog cdl)
|
||||
{
|
||||
CDL = cdl;
|
||||
}
|
||||
|
||||
public void NewCDL(ICodeDataLog cdl)
|
||||
{
|
||||
cdl["RAM"] = new byte[MemoryDomains["RAM"].Size];
|
||||
|
||||
if (MemoryDomains.Has("Save RAM"))
|
||||
{
|
||||
cdl["Save RAM"] = new byte[MemoryDomains["Save RAM"].Size];
|
||||
}
|
||||
|
||||
if (MemoryDomains.Has("Battery RAM"))
|
||||
{
|
||||
cdl["Battery RAM"] = new byte[MemoryDomains["Battery RAM"].Size];
|
||||
}
|
||||
|
||||
if (MemoryDomains.Has("Battery RAM"))
|
||||
{
|
||||
cdl["Battery RAM"] = new byte[MemoryDomains["Battery RAM"].Size];
|
||||
}
|
||||
|
||||
cdl.SubType = "VIC20";
|
||||
cdl.SubVer = 0;
|
||||
}
|
||||
|
||||
[FeatureNotImplemented]
|
||||
public void DisassembleCDL(Stream s, ICodeDataLog cdl)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private enum CDLog_AddrType
|
||||
{
|
||||
None,
|
||||
ROM,
|
||||
MainRAM,
|
||||
SaveRAM,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
private enum CDLog_Flags
|
||||
{
|
||||
ExecFirst = 0x01,
|
||||
ExecOperand = 0x02,
|
||||
Data = 0x04
|
||||
};
|
||||
|
||||
private struct CDLog_MapResults
|
||||
{
|
||||
public CDLog_AddrType Type;
|
||||
public int Address;
|
||||
}
|
||||
|
||||
private delegate CDLog_MapResults MapMemoryDelegate(ushort addr, bool write);
|
||||
private MapMemoryDelegate MapMemory;
|
||||
private ICodeDataLog CDL;
|
||||
|
||||
private void RunCDL(ushort address, CDLog_Flags flags)
|
||||
{
|
||||
if (MapMemory != null)
|
||||
{
|
||||
CDLog_MapResults results = MapMemory(address, false);
|
||||
switch (results.Type)
|
||||
{
|
||||
case CDLog_AddrType.None: break;
|
||||
case CDLog_AddrType.MainRAM: CDL["Main RAM"][results.Address] |= (byte)flags; break;
|
||||
case CDLog_AddrType.SaveRAM: CDL["Save RAM"][results.Address] |= (byte)flags; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A wrapper for FetchMemory which inserts CDL logic
|
||||
/// </summary>
|
||||
private byte FetchMemory_CDL(ushort address)
|
||||
{
|
||||
RunCDL(address, CDLog_Flags.ExecFirst);
|
||||
return PeekMemory(address);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A wrapper for ReadMemory which inserts CDL logic
|
||||
/// </summary>
|
||||
private byte ReadMemory_CDL(ushort address)
|
||||
{
|
||||
RunCDL(address, CDLog_Flags.Data);
|
||||
return ReadMemory(address);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Vectrex
|
||||
{
|
||||
public partial class VectrexHawk : IDebuggable
|
||||
{
|
||||
public IDictionary<string, RegisterValue> GetCpuFlagsAndRegisters()
|
||||
{
|
||||
return new Dictionary<string, RegisterValue>
|
||||
{
|
||||
/*
|
||||
["A"] = cpu.A,
|
||||
["X"] = cpu.X,
|
||||
["Y"] = cpu.Y,
|
||||
["S"] = cpu.S,
|
||||
["PC"] = cpu.PC,
|
||||
["Flag C"] = cpu.FlagC,
|
||||
["Flag Z"] = cpu.FlagZ,
|
||||
["Flag I"] = cpu.FlagI,
|
||||
["Flag D"] = cpu.FlagD,
|
||||
["Flag B"] = cpu.FlagB,
|
||||
["Flag V"] = cpu.FlagV,
|
||||
["Flag N"] = cpu.FlagN,
|
||||
["Flag T"] = cpu.FlagT
|
||||
*/
|
||||
};
|
||||
}
|
||||
|
||||
public void SetCpuRegister(string register, int value)
|
||||
{
|
||||
switch (register)
|
||||
{
|
||||
default:
|
||||
throw new InvalidOperationException();
|
||||
case "A":
|
||||
//cpu.A = (byte)value;
|
||||
break;
|
||||
case "X":
|
||||
//cpu.X = (byte)value;
|
||||
break;
|
||||
case "Y":
|
||||
//cpu.Y = (byte)value;
|
||||
break;
|
||||
case "S":
|
||||
//cpu.S = (byte)value;
|
||||
break;
|
||||
case "PC":
|
||||
//cpu.PC = (ushort)value;
|
||||
break;
|
||||
case "Flag I":
|
||||
//cpu.FlagI = value > 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public IMemoryCallbackSystem MemoryCallbacks { get; } = new MemoryCallbackSystem(new[] { "System Bus" });
|
||||
|
||||
public bool CanStep(StepType type)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
[FeatureNotImplemented]
|
||||
public void Step(StepType type)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public long TotalExecutedCycles
|
||||
{
|
||||
get { return (long)cpu.TotalExecutedCycles; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
using BizHawk.Common.NumberExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Vectrex
|
||||
{
|
||||
public partial class VectrexHawk : IEmulator, IVideoProvider
|
||||
{
|
||||
public IEmulatorServiceProvider ServiceProvider { get; }
|
||||
|
||||
public ControllerDefinition ControllerDefinition => _controllerDeck.Definition;
|
||||
|
||||
public bool FrameAdvance(IController controller, bool render, bool rendersound)
|
||||
{
|
||||
if (_tracer.Enabled)
|
||||
{
|
||||
cpu.TraceCallback = s => _tracer.Put(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
cpu.TraceCallback = null;
|
||||
}
|
||||
|
||||
_frame++;
|
||||
|
||||
if (controller.IsPressed("Power"))
|
||||
{
|
||||
HardReset();
|
||||
}
|
||||
|
||||
_islag = true;
|
||||
|
||||
do_frame();
|
||||
|
||||
if (_islag)
|
||||
{
|
||||
_lagcount++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void do_frame()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public int Frame => _frame;
|
||||
|
||||
public string SystemId => "VIC20";
|
||||
|
||||
public bool DeterministicEmulation { get; set; }
|
||||
|
||||
public void ResetCounters()
|
||||
{
|
||||
_frame = 0;
|
||||
_lagcount = 0;
|
||||
_islag = false;
|
||||
}
|
||||
|
||||
public CoreComm CoreComm { get; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
audio.DisposeSound();
|
||||
}
|
||||
|
||||
#region Video provider
|
||||
|
||||
public int _frameHz = 60;
|
||||
|
||||
public int[] _vidbuffer;
|
||||
|
||||
public int[] GetVideoBuffer()
|
||||
{
|
||||
return _vidbuffer;
|
||||
}
|
||||
|
||||
public int VirtualWidth => 160;
|
||||
public int VirtualHeight => 144;
|
||||
public int BufferWidth => 160;
|
||||
public int BufferHeight => 144;
|
||||
public int BackgroundColor => unchecked((int)0xFF000000);
|
||||
public int VsyncNumerator => _frameHz;
|
||||
public int VsyncDenominator => 1;
|
||||
|
||||
public static readonly uint[] color_palette_BW = { 0xFFFFFFFF , 0xFFAAAAAA, 0xFF555555, 0xFF000000 };
|
||||
public static readonly uint[] color_palette_Gr = { 0xFFA4C505, 0xFF88A905, 0xFF1D551D, 0xFF052505 };
|
||||
|
||||
public uint[] color_palette = new uint[4];
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Vectrex
|
||||
{
|
||||
public partial class VectrexHawk : IInputPollable
|
||||
{
|
||||
public int LagCount
|
||||
{
|
||||
get { return _lagcount; }
|
||||
set { _lagcount = value; }
|
||||
}
|
||||
|
||||
public bool IsLagFrame
|
||||
{
|
||||
get { return _islag; }
|
||||
set { _islag = value; }
|
||||
}
|
||||
|
||||
public IInputCallbackSystem InputCallbacks { get; } = new InputCallbackSystem();
|
||||
|
||||
public bool _islag = true;
|
||||
private int _lagcount;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Vectrex
|
||||
{
|
||||
public partial class VectrexHawk
|
||||
{
|
||||
private IMemoryDomains MemoryDomains;
|
||||
|
||||
public void SetupMemoryDomains()
|
||||
{
|
||||
var domains = new List<MemoryDomain>
|
||||
{
|
||||
new MemoryDomainDelegate(
|
||||
"Main RAM",
|
||||
RAM.Length,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => RAM[addr],
|
||||
(addr, value) => RAM[addr] = value,
|
||||
1),
|
||||
new MemoryDomainDelegate(
|
||||
"System Bus",
|
||||
0X10000,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => PeekSystemBus(addr),
|
||||
(addr, value) => PokeSystemBus(addr, value),
|
||||
1),
|
||||
new MemoryDomainDelegate(
|
||||
"ROM",
|
||||
_rom.Length,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => _rom[addr],
|
||||
(addr, value) => _rom[addr] = value,
|
||||
1),
|
||||
};
|
||||
|
||||
if (cart_RAM != null)
|
||||
{
|
||||
var CartRam = new MemoryDomainByteArray("Cart RAM", MemoryDomain.Endian.Little, cart_RAM, true, 1);
|
||||
domains.Add(CartRam);
|
||||
}
|
||||
|
||||
MemoryDomains = new MemoryDomainList(domains);
|
||||
(ServiceProvider as BasicServiceProvider).Register<IMemoryDomains>(MemoryDomains);
|
||||
}
|
||||
|
||||
private byte PeekSystemBus(long addr)
|
||||
{
|
||||
ushort addr2 = (ushort)(addr & 0xFFFF);
|
||||
return PeekMemory(addr2);
|
||||
}
|
||||
|
||||
private void PokeSystemBus(long addr, byte value)
|
||||
{
|
||||
ushort addr2 = (ushort)(addr & 0xFFFF);
|
||||
WriteMemory(addr2, value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
using System;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Vectrex
|
||||
{
|
||||
public partial class VectrexHawk : ISaveRam
|
||||
{
|
||||
public byte[] CloneSaveRam()
|
||||
{
|
||||
if (cart_RAM != null)
|
||||
{
|
||||
return (byte[])cart_RAM.Clone();
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void StoreSaveRam(byte[] data)
|
||||
{
|
||||
Buffer.BlockCopy(data, 0, cart_RAM, 0, data.Length);
|
||||
Console.WriteLine("loading SRAM here");
|
||||
}
|
||||
|
||||
public bool SaveRamModified
|
||||
{
|
||||
get
|
||||
{
|
||||
return has_bat & _syncSettings.Use_SRAM;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Vectrex
|
||||
{
|
||||
public partial class VectrexHawk : IEmulator, IStatable, ISettable<VectrexHawk.VectrexSettings, VectrexHawk.VectrexSyncSettings>
|
||||
{
|
||||
public VectrexSettings GetSettings()
|
||||
{
|
||||
return _settings.Clone();
|
||||
}
|
||||
|
||||
public VectrexSyncSettings GetSyncSettings()
|
||||
{
|
||||
return _syncSettings.Clone();
|
||||
}
|
||||
|
||||
public bool PutSettings(VectrexSettings o)
|
||||
{
|
||||
_settings = o;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool PutSyncSettings(VectrexSyncSettings o)
|
||||
{
|
||||
bool ret = VectrexSyncSettings.NeedsReboot(_syncSettings, o);
|
||||
_syncSettings = o;
|
||||
return ret;
|
||||
}
|
||||
|
||||
private VectrexSettings _settings = new VectrexSettings();
|
||||
public VectrexSyncSettings _syncSettings = new VectrexSyncSettings();
|
||||
|
||||
public class VectrexSettings
|
||||
{
|
||||
|
||||
public VectrexSettings Clone()
|
||||
{
|
||||
return (VectrexSettings)MemberwiseClone();
|
||||
}
|
||||
}
|
||||
|
||||
public class VectrexSyncSettings
|
||||
{
|
||||
[JsonIgnore]
|
||||
public string Port1 = VectrexHawkControllerDeck.DefaultControllerName;
|
||||
|
||||
public enum ControllerType
|
||||
{
|
||||
Default,
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
private ControllerType _VectrexController;
|
||||
|
||||
[DisplayName("Controller")]
|
||||
[Description("Select Controller Type")]
|
||||
[DefaultValue(ControllerType.Default)]
|
||||
public ControllerType VectrexController
|
||||
{
|
||||
get { return _VectrexController; }
|
||||
set
|
||||
{
|
||||
if (value == ControllerType.Default) { Port1 = VectrexHawkControllerDeck.DefaultControllerName; }
|
||||
else { Port1 = VectrexHawkControllerDeck.DefaultControllerName; }
|
||||
|
||||
_VectrexController = value;
|
||||
}
|
||||
}
|
||||
|
||||
[DisplayName("Use Existing SaveRAM")]
|
||||
[Description("When true, existing SaveRAM will be loaded at boot up")]
|
||||
[DefaultValue(false)]
|
||||
public bool Use_SRAM { get; set; }
|
||||
|
||||
public VectrexSyncSettings Clone()
|
||||
{
|
||||
return (VectrexSyncSettings)MemberwiseClone();
|
||||
}
|
||||
|
||||
public static bool NeedsReboot(VectrexSyncSettings x, VectrexSyncSettings y)
|
||||
{
|
||||
return !DeepEquality.DeepEquals(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
using System.IO;
|
||||
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Vectrex
|
||||
{
|
||||
public partial class VectrexHawk : IStatable
|
||||
{
|
||||
public bool BinarySaveStatesPreferred => true;
|
||||
|
||||
public void SaveStateText(TextWriter writer)
|
||||
{
|
||||
SyncState(new Serializer(writer));
|
||||
}
|
||||
|
||||
public void LoadStateText(TextReader reader)
|
||||
{
|
||||
SyncState(new Serializer(reader));
|
||||
}
|
||||
|
||||
public void SaveStateBinary(BinaryWriter bw)
|
||||
{
|
||||
SyncState(new Serializer(bw));
|
||||
}
|
||||
|
||||
public void LoadStateBinary(BinaryReader br)
|
||||
{
|
||||
SyncState(new Serializer(br));
|
||||
}
|
||||
|
||||
public byte[] SaveStateBinary()
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
BinaryWriter bw = new BinaryWriter(ms);
|
||||
SaveStateBinary(bw);
|
||||
bw.Flush();
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
// here is where all your savestated stuff will be called
|
||||
// make sure every variable you make is savestated
|
||||
// also all the components with their own savestate functions need to be called form here
|
||||
// for normal single variables the format is:
|
||||
// ser.Sync("var_name", ref var_name);
|
||||
|
||||
// for arrays, use:
|
||||
// ser.Sync("var_name", ref var_name, false);
|
||||
private void SyncState(Serializer ser)
|
||||
{
|
||||
byte[] core = null;
|
||||
if (ser.IsWriter)
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
ms.Close();
|
||||
core = ms.ToArray();
|
||||
}
|
||||
cpu.SyncState(ser);
|
||||
mapper.SyncState(ser);
|
||||
ppu.SyncState(ser);
|
||||
serialport.SyncState(ser);
|
||||
audio.SyncState(ser);
|
||||
|
||||
ser.BeginSection("VIC20");
|
||||
|
||||
ser.Sync("RAM", ref RAM, false);
|
||||
|
||||
// probably a better way to do this
|
||||
if (cart_RAM != null)
|
||||
{
|
||||
ser.Sync("cart_RAM", ref cart_RAM, false);
|
||||
}
|
||||
|
||||
ser.EndSection();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
using System;
|
||||
|
||||
using BizHawk.Common.BufferExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Common.Components.MC6809;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Vectrex
|
||||
{
|
||||
[Core(
|
||||
"VectrexHawk",
|
||||
"",
|
||||
isPorted: false,
|
||||
isReleased: true)]
|
||||
[ServiceNotApplicable(typeof(IDriveLight))]
|
||||
public partial class VectrexHawk : IEmulator, ISaveRam, IDebuggable, IStatable, IInputPollable, IRegionable,
|
||||
ISettable<VectrexHawk.VectrexSettings, VectrexHawk.VectrexSyncSettings>
|
||||
{
|
||||
// declaractions
|
||||
// put top level core variables here
|
||||
// including things like RAM and BIOS
|
||||
// they will be used in the hex editor and others
|
||||
|
||||
// the following declaraion is only an example
|
||||
// see memoryDomains.cs to see how it is used to define a Memory Domain that you can see in Hex editor
|
||||
// ex:
|
||||
public byte[] RAM = new byte[0x8000];
|
||||
|
||||
|
||||
public byte[] _bios;
|
||||
public readonly byte[] _rom;
|
||||
|
||||
// sometimes roms will have a header
|
||||
// the following is only an example in order to demonstrate how to extract the header
|
||||
public readonly byte[] header = new byte[0x50];
|
||||
|
||||
public byte[] cart_RAM;
|
||||
public bool has_bat;
|
||||
|
||||
private int _frame = 0;
|
||||
|
||||
public MapperBase mapper;
|
||||
|
||||
private readonly ITraceable _tracer;
|
||||
|
||||
public MC6809 cpu;
|
||||
public PPU ppu;
|
||||
public Audio audio;
|
||||
public SerialPort serialport;
|
||||
|
||||
private static byte[] GBA_override = { 0xFF, 0x00, 0xCD, 0x03, 0x35, 0xAA, 0x31, 0x90, 0x94, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
[CoreConstructor("Vectrex")]
|
||||
public VectrexHawk(CoreComm comm, GameInfo game, byte[] rom, /*string gameDbFn,*/ object settings, object syncSettings)
|
||||
{
|
||||
var ser = new BasicServiceProvider(this);
|
||||
|
||||
cpu = new MC6809
|
||||
{
|
||||
ReadMemory = ReadMemory,
|
||||
WriteMemory = WriteMemory,
|
||||
PeekMemory = PeekMemory,
|
||||
DummyReadMemory = ReadMemory,
|
||||
OnExecFetch = ExecFetch,
|
||||
};
|
||||
|
||||
audio = new Audio();
|
||||
ppu = new PPU();
|
||||
serialport = new SerialPort();
|
||||
|
||||
CoreComm = comm;
|
||||
|
||||
_settings = (VectrexSettings)settings ?? new VectrexSettings();
|
||||
_syncSettings = (VectrexSyncSettings)syncSettings ?? new VectrexSyncSettings();
|
||||
_controllerDeck = new VectrexHawkControllerDeck(_syncSettings.Port1);
|
||||
|
||||
// BIOS stuff can be tricky. Sometimes you'll have more then one vailable BIOS or different BIOSes for different regions
|
||||
// for now I suggest just picking one going
|
||||
byte[] Bios = null;
|
||||
//Bios = comm.CoreFileProvider.GetFirmware("Vectrex", "Bios", true, "BIOS Not Found, Cannot Load");
|
||||
_bios = Bios;
|
||||
|
||||
// the following few lines are jsut examples of working with a header and hashes
|
||||
Buffer.BlockCopy(rom, 0x100, header, 0, 0x50);
|
||||
string hash_md5 = null;
|
||||
hash_md5 = "md5:" + rom.HashMD5(0, rom.Length);
|
||||
Console.WriteLine(hash_md5);
|
||||
|
||||
// in this case our working ROm has the header removed (might not be the case for your system)
|
||||
_rom = rom;
|
||||
Setup_Mapper();
|
||||
|
||||
_frameHz = 60;
|
||||
|
||||
// usually you want to have a reflected core available to the various components since they share some information
|
||||
audio.Core = this;
|
||||
ppu.Core = this;
|
||||
serialport.Core = this;
|
||||
|
||||
// the following is just interface setup, dont worry to much about it
|
||||
ser.Register<IVideoProvider>(this);
|
||||
ser.Register<ISoundProvider>(audio);
|
||||
ServiceProvider = ser;
|
||||
|
||||
_settings = (VectrexSettings)settings ?? new VectrexSettings();
|
||||
_syncSettings = (VectrexSyncSettings)syncSettings ?? new VectrexSyncSettings();
|
||||
|
||||
_tracer = new TraceBuffer { Header = cpu.TraceHeader };
|
||||
ser.Register<ITraceable>(_tracer);
|
||||
|
||||
SetupMemoryDomains();
|
||||
HardReset();
|
||||
}
|
||||
|
||||
public DisplayType Region => DisplayType.NTSC;
|
||||
|
||||
private readonly VectrexHawkControllerDeck _controllerDeck;
|
||||
|
||||
public void HardReset()
|
||||
{
|
||||
Register_Reset();
|
||||
ppu.Reset();
|
||||
audio.Reset();
|
||||
serialport.Reset();
|
||||
|
||||
_vidbuffer = new int[VirtualWidth * VirtualHeight];
|
||||
}
|
||||
|
||||
private void ExecFetch(ushort addr)
|
||||
{
|
||||
MemoryCallbacks.CallExecutes(addr, "System Bus");
|
||||
}
|
||||
|
||||
// most systems have cartridges or other storage media that map memory in more then one way.
|
||||
// Use this ethod to set that stuff up when first starting the core
|
||||
private void Setup_Mapper()
|
||||
{
|
||||
mapper = new MapperDefault();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Common.ReflectionExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Vectrex
|
||||
{
|
||||
public class VectrexHawkControllerDeck
|
||||
{
|
||||
public VectrexHawkControllerDeck(string controller1Name)
|
||||
{
|
||||
if (!ValidControllerTypes.ContainsKey(controller1Name))
|
||||
{
|
||||
throw new InvalidOperationException("Invalid controller type: " + controller1Name);
|
||||
}
|
||||
|
||||
Port1 = (IPort)Activator.CreateInstance(ValidControllerTypes[controller1Name], 1);
|
||||
|
||||
Definition = new ControllerDefinition
|
||||
{
|
||||
Name = Port1.Definition.Name,
|
||||
BoolButtons = Port1.Definition.BoolButtons
|
||||
.ToList()
|
||||
};
|
||||
|
||||
Definition.FloatControls.AddRange(Port1.Definition.FloatControls);
|
||||
|
||||
Definition.FloatRanges.AddRange(Port1.Definition.FloatRanges);
|
||||
}
|
||||
|
||||
public byte ReadPort1(IController c)
|
||||
{
|
||||
return Port1.Read(c);
|
||||
}
|
||||
|
||||
public ControllerDefinition Definition { get; }
|
||||
|
||||
public void SyncState(Serializer ser)
|
||||
{
|
||||
ser.BeginSection("Port1");
|
||||
Port1.SyncState(ser);
|
||||
ser.EndSection();
|
||||
}
|
||||
|
||||
private readonly IPort Port1;
|
||||
|
||||
private static Dictionary<string, Type> _controllerTypes;
|
||||
|
||||
public static Dictionary<string, Type> ValidControllerTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_controllerTypes == null)
|
||||
{
|
||||
_controllerTypes = typeof(VectrexHawkControllerDeck).Assembly
|
||||
.GetTypes()
|
||||
.Where(t => typeof(IPort).IsAssignableFrom(t))
|
||||
.Where(t => !t.IsAbstract && !t.IsInterface)
|
||||
.ToDictionary(tkey => tkey.DisplayName());
|
||||
}
|
||||
|
||||
return _controllerTypes;
|
||||
}
|
||||
}
|
||||
|
||||
public static string DefaultControllerName => typeof(StandardControls).DisplayName();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Vectrex
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a Vectrex add on
|
||||
/// </summary>
|
||||
public interface IPort
|
||||
{
|
||||
byte Read(IController c);
|
||||
|
||||
ControllerDefinition Definition { get; }
|
||||
|
||||
void SyncState(Serializer ser);
|
||||
|
||||
int PortNum { get; }
|
||||
}
|
||||
|
||||
[DisplayName("Vectrex Controller")]
|
||||
public class StandardControls : IPort
|
||||
{
|
||||
public StandardControls(int portNum)
|
||||
{
|
||||
PortNum = portNum;
|
||||
Definition = new ControllerDefinition
|
||||
{
|
||||
Name = "Vectrex Controller",
|
||||
BoolButtons = BaseDefinition
|
||||
.Select(b => "P" + PortNum + " " + b)
|
||||
.ToList()
|
||||
};
|
||||
}
|
||||
|
||||
public int PortNum { get; }
|
||||
|
||||
public ControllerDefinition Definition { get; }
|
||||
|
||||
public byte Read(IController c)
|
||||
{
|
||||
byte result = 0xFF;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static readonly string[] BaseDefinition =
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
public void SyncState(Serializer ser)
|
||||
{
|
||||
//nothing
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue