mirror of
https://github.com/anarkavre/pom1.git
synced 2024-06-10 02:29:32 +00:00
1817 lines
25 KiB
C
1817 lines
25 KiB
C
|
// Pom1 Apple 1 Emulator
|
||
|
// Copyright (C) 2000 Verhille Arnaud
|
||
|
// Copyright (C) 2012 John D. Corrado
|
||
|
//
|
||
|
// This program is free software; you can redistribute it and/or
|
||
|
// modify it under the terms of the GNU General Public License
|
||
|
// as published by the Free Software Foundation; either version 2
|
||
|
// of the License, or (at your option) any later version.
|
||
|
//
|
||
|
// This program is distributed in the hope that it will be useful,
|
||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
// GNU General Public License for more details.
|
||
|
//
|
||
|
// You should have received a copy of the GNU General Public License
|
||
|
// along with this program; if not, write to the Free Software
|
||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
|
|
||
|
#include "SDL.h"
|
||
|
#include "memory.h"
|
||
|
|
||
|
#define N 0x80
|
||
|
#define V 0x40
|
||
|
#define B 0x10
|
||
|
#define D 0x08
|
||
|
#define I 0x04
|
||
|
#define Z 0x02
|
||
|
#define C 0x01
|
||
|
|
||
|
static unsigned char accumulator, xRegister, yRegister, statusRegister = 0x24, stackPointer;
|
||
|
static int IRQ = 0, NMI = 0;
|
||
|
static unsigned short programCounter;
|
||
|
static unsigned char btmp;
|
||
|
static unsigned short op, opH, opL, ptr, ptrH, ptrL, tmp;
|
||
|
static long lastTime;
|
||
|
static int cycles, cyclesBeforeSynchro, _synchroMillis;
|
||
|
static SDL_Thread *thread;
|
||
|
static int running;
|
||
|
|
||
|
static unsigned short memReadAbsolute(unsigned short adr)
|
||
|
{
|
||
|
return (memRead(adr) | memRead((unsigned short)(adr + 1)) << 8);
|
||
|
}
|
||
|
|
||
|
static void synchronize(void)
|
||
|
{
|
||
|
int realTimeMillis = SDL_GetTicks() - lastTime;
|
||
|
int sleepMillis = _synchroMillis - realTimeMillis;
|
||
|
|
||
|
if (sleepMillis < 0)
|
||
|
sleepMillis = 5;
|
||
|
|
||
|
SDL_Delay(sleepMillis);
|
||
|
|
||
|
lastTime = SDL_GetTicks();
|
||
|
}
|
||
|
|
||
|
static void pushProgramCounter(void)
|
||
|
{
|
||
|
memWrite((unsigned short)(stackPointer + 0x100), (unsigned char)(programCounter >> 8));
|
||
|
stackPointer--;
|
||
|
memWrite((unsigned short)(stackPointer + 0x100), (unsigned char)programCounter);
|
||
|
stackPointer--;
|
||
|
cycles += 2;
|
||
|
}
|
||
|
|
||
|
static void popProgramCounter(void)
|
||
|
{
|
||
|
stackPointer++;
|
||
|
programCounter = memRead((unsigned short)(stackPointer + 0x100));
|
||
|
stackPointer++;
|
||
|
programCounter += memRead((unsigned short)(stackPointer + 0x100)) << 8;
|
||
|
cycles += 2;
|
||
|
}
|
||
|
|
||
|
static void handleIRQ(void)
|
||
|
{
|
||
|
pushProgramCounter();
|
||
|
memWrite((unsigned short)(0x100 + stackPointer), (unsigned char)(statusRegister & ~0x10));
|
||
|
stackPointer--;
|
||
|
statusRegister |= I;
|
||
|
programCounter = memReadAbsolute(0xFFFE);
|
||
|
cycles += 8;
|
||
|
}
|
||
|
|
||
|
static void handleNMI(void)
|
||
|
{
|
||
|
pushProgramCounter();
|
||
|
memWrite((unsigned short)(0x100 + stackPointer), (unsigned char)(statusRegister & ~0x10));
|
||
|
stackPointer--;
|
||
|
statusRegister |= I;
|
||
|
NMI = 0;
|
||
|
programCounter = memReadAbsolute(0xFFFA);
|
||
|
cycles += 8;
|
||
|
}
|
||
|
|
||
|
static void Imp(void)
|
||
|
{
|
||
|
cycles++;
|
||
|
}
|
||
|
|
||
|
static void Imm(void)
|
||
|
{
|
||
|
op = programCounter++;
|
||
|
}
|
||
|
|
||
|
static void Zero(void)
|
||
|
{
|
||
|
op = memRead(programCounter++);
|
||
|
cycles++;
|
||
|
}
|
||
|
|
||
|
static void ZeroX(void)
|
||
|
{
|
||
|
op = memRead(programCounter++) + xRegister & 0xFF;
|
||
|
cycles++;
|
||
|
}
|
||
|
|
||
|
static void ZeroY(void)
|
||
|
{
|
||
|
op = memRead(programCounter++) + yRegister & 0xFF;
|
||
|
cycles++;
|
||
|
}
|
||
|
|
||
|
static void Abs(void)
|
||
|
{
|
||
|
op = memReadAbsolute(programCounter);
|
||
|
programCounter += 2;
|
||
|
cycles += 2;
|
||
|
}
|
||
|
|
||
|
static void AbsX(void)
|
||
|
{
|
||
|
opL = memRead(programCounter++) + xRegister;
|
||
|
opH = memRead(programCounter++) << 8;
|
||
|
cycles += 2;
|
||
|
|
||
|
if (opL & 0x100)
|
||
|
cycles++;
|
||
|
|
||
|
op = opH + opL;
|
||
|
}
|
||
|
|
||
|
static void AbsY(void)
|
||
|
{
|
||
|
opL = memRead(programCounter++) + yRegister;
|
||
|
opH = memRead(programCounter++) << 8;
|
||
|
cycles += 2;
|
||
|
|
||
|
if (opL & 0x100)
|
||
|
cycles++;
|
||
|
|
||
|
op = opH + opL;
|
||
|
}
|
||
|
|
||
|
static void Ind(void)
|
||
|
{
|
||
|
ptrL = memRead(programCounter++);
|
||
|
ptrH = memRead(programCounter++) << 8;
|
||
|
op = memRead((unsigned short)(ptrH + ptrL));
|
||
|
ptrL = ptrL + 1 & 0xFF;
|
||
|
op += memRead((unsigned short)(ptrH + ptrL)) << 8;
|
||
|
cycles += 4;
|
||
|
}
|
||
|
|
||
|
static void IndZeroX(void)
|
||
|
{
|
||
|
ptr = memRead(programCounter++) + xRegister & 0xFF;
|
||
|
op = memRead(ptr);
|
||
|
op += memRead((unsigned short)(ptr + 1 & 0xFF)) << 8;
|
||
|
cycles += 3;
|
||
|
}
|
||
|
|
||
|
static void IndZeroY(void)
|
||
|
{
|
||
|
ptr = memRead(programCounter++);
|
||
|
opL = memRead(ptr) + yRegister;
|
||
|
opH = memRead((unsigned short)(ptr + 1 & 0xFF)) << 8;
|
||
|
cycles += 3;
|
||
|
|
||
|
if (opL & 0x100)
|
||
|
cycles++;
|
||
|
|
||
|
op = opH + opL;
|
||
|
}
|
||
|
|
||
|
static void Rel(void)
|
||
|
{
|
||
|
op = memRead(programCounter++);
|
||
|
|
||
|
if (op & 0x80)
|
||
|
op |= 0xFF00;
|
||
|
|
||
|
op += programCounter;
|
||
|
cycles++;
|
||
|
}
|
||
|
|
||
|
static void WAbsX(void)
|
||
|
{
|
||
|
opL = memRead(programCounter++) + xRegister;
|
||
|
opH = memRead(programCounter++) << 8;
|
||
|
cycles += 3;
|
||
|
op = opH + opL;
|
||
|
}
|
||
|
|
||
|
static void WAbsY(void)
|
||
|
{
|
||
|
opL = memRead(programCounter++) + yRegister;
|
||
|
opH = memRead(programCounter++) << 8;
|
||
|
cycles += 3;
|
||
|
op = opH + opL;
|
||
|
}
|
||
|
|
||
|
static void WIndZeroY(void)
|
||
|
{
|
||
|
ptr = memRead(programCounter++);
|
||
|
opL = memRead(ptr) + yRegister;
|
||
|
opH = memRead((unsigned short)(ptr + 1 & 0xFF)) << 8;
|
||
|
cycles += 4;
|
||
|
op = opH + opL;
|
||
|
}
|
||
|
|
||
|
static void setStatusRegisterNZ(unsigned char val)
|
||
|
{
|
||
|
if (val & 0x80)
|
||
|
statusRegister |= N;
|
||
|
else
|
||
|
statusRegister &= ~N;
|
||
|
|
||
|
if (!val)
|
||
|
statusRegister |= Z;
|
||
|
else
|
||
|
statusRegister &= ~Z;
|
||
|
}
|
||
|
|
||
|
static void LDA(void)
|
||
|
{
|
||
|
accumulator = memRead(op);
|
||
|
setStatusRegisterNZ(accumulator);
|
||
|
cycles++;
|
||
|
}
|
||
|
|
||
|
static void LDX(void)
|
||
|
{
|
||
|
xRegister = memRead(op);
|
||
|
setStatusRegisterNZ(xRegister);
|
||
|
cycles++;
|
||
|
}
|
||
|
|
||
|
static void LDY(void)
|
||
|
{
|
||
|
yRegister = memRead(op);
|
||
|
setStatusRegisterNZ(yRegister);
|
||
|
cycles++;
|
||
|
}
|
||
|
|
||
|
static void STA(void)
|
||
|
{
|
||
|
memWrite(op, accumulator);
|
||
|
cycles++;
|
||
|
}
|
||
|
|
||
|
static void STX(void)
|
||
|
{
|
||
|
memWrite(op, xRegister);
|
||
|
cycles++;
|
||
|
}
|
||
|
|
||
|
static void STY(void)
|
||
|
{
|
||
|
memWrite(op, yRegister);
|
||
|
cycles++;
|
||
|
}
|
||
|
|
||
|
static void setFlagCarry(unsigned short val)
|
||
|
{
|
||
|
if (val & 0x100)
|
||
|
statusRegister |= C;
|
||
|
else
|
||
|
statusRegister &= ~C;
|
||
|
}
|
||
|
|
||
|
static void ADC(void)
|
||
|
{
|
||
|
unsigned short Op1 = accumulator, Op2 = memRead(op);
|
||
|
cycles++;
|
||
|
|
||
|
if (statusRegister & D)
|
||
|
{
|
||
|
if (!(Op1 + Op2 + (statusRegister & C ? 1 : 0) & 0xFF))
|
||
|
statusRegister |= Z;
|
||
|
else
|
||
|
statusRegister &= ~Z;
|
||
|
|
||
|
tmp = (Op1 & 0x0F) + (Op2 & 0x0F) + (statusRegister & C ? 1 : 0);
|
||
|
accumulator = tmp < 0x0A ? tmp : tmp + 6;
|
||
|
tmp = (Op1 & 0xF0) + (Op2 & 0xF0) + (tmp & 0xF0);
|
||
|
|
||
|
if (tmp & 0x80)
|
||
|
statusRegister |= N;
|
||
|
else
|
||
|
statusRegister &= ~N;
|
||
|
|
||
|
if ((Op1 ^ tmp) & ~(Op1 ^ Op2) & 0x80)
|
||
|
statusRegister |= V;
|
||
|
else
|
||
|
statusRegister &= ~V;
|
||
|
|
||
|
tmp = (accumulator & 0x0F) | (tmp < 0xA0 ? tmp : tmp + 0x60);
|
||
|
|
||
|
if (tmp & 0x100)
|
||
|
statusRegister |= C;
|
||
|
else
|
||
|
statusRegister &= ~C;
|
||
|
|
||
|
accumulator = tmp & 0xFF;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tmp = Op1 + Op2 + (statusRegister & C ? 1 : 0);
|
||
|
accumulator = tmp & 0xFF;
|
||
|
|
||
|
if ((Op1 ^ accumulator) & ~(Op1 ^ Op2) & 0x80)
|
||
|
statusRegister |= V;
|
||
|
else
|
||
|
statusRegister &= ~V;
|
||
|
|
||
|
setFlagCarry(tmp);
|
||
|
setStatusRegisterNZ(accumulator);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void setFlagBorrow(unsigned short val)
|
||
|
{
|
||
|
if (!(val & 0x100))
|
||
|
statusRegister |= C;
|
||
|
else
|
||
|
statusRegister &= ~C;
|
||
|
}
|
||
|
|
||
|
static void SBC(void)
|
||
|
{
|
||
|
unsigned short Op1 = accumulator, Op2 = memRead(op);
|
||
|
cycles++;
|
||
|
|
||
|
if (statusRegister & D)
|
||
|
{
|
||
|
tmp = (Op1 & 0x0F) - (Op2 & 0x0F) - (statusRegister & C ? 0 : 1);
|
||
|
accumulator = !(tmp & 0x10) ? tmp : tmp - 6;
|
||
|
tmp = (Op1 & 0xF0) - (Op2 & 0xF0) - (accumulator & 0x10);
|
||
|
accumulator = (accumulator & 0x0F) | (!(tmp & 0x100) ? tmp : tmp - 0x60);
|
||
|
tmp = Op1 - Op2 - (statusRegister & C ? 0 : 1);
|
||
|
setFlagBorrow(tmp);
|
||
|
setStatusRegisterNZ((unsigned char)tmp);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tmp = Op1 - Op2 - (statusRegister & C ? 0 : 1);
|
||
|
accumulator = tmp & 0xFF;
|
||
|
|
||
|
if ((Op1 ^ Op2) & (Op1 ^ accumulator) & 0x80)
|
||
|
statusRegister |= V;
|
||
|
else
|
||
|
statusRegister &= ~V;
|
||
|
|
||
|
setFlagBorrow(tmp);
|
||
|
setStatusRegisterNZ(accumulator);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void CMP(void)
|
||
|
{
|
||
|
tmp = accumulator - memRead(op);
|
||
|
cycles++;
|
||
|
setFlagBorrow(tmp);
|
||
|
setStatusRegisterNZ((unsigned char)tmp);
|
||
|
}
|
||
|
|
||
|
static void CPX(void)
|
||
|
{
|
||
|
tmp = xRegister - memRead(op);
|
||
|
cycles++;
|
||
|
setFlagBorrow(tmp);
|
||
|
setStatusRegisterNZ((unsigned char)tmp);
|
||
|
}
|
||
|
|
||
|
static void CPY(void)
|
||
|
{
|
||
|
tmp = yRegister - memRead(op);
|
||
|
cycles++;
|
||
|
setFlagBorrow(tmp);
|
||
|
setStatusRegisterNZ((unsigned char)tmp);
|
||
|
}
|
||
|
|
||
|
static void AND(void)
|
||
|
{
|
||
|
accumulator &= memRead(op);
|
||
|
cycles++;
|
||
|
setStatusRegisterNZ(accumulator);
|
||
|
}
|
||
|
|
||
|
static void ORA(void)
|
||
|
{
|
||
|
accumulator |= memRead(op);
|
||
|
cycles++;
|
||
|
setStatusRegisterNZ(accumulator);
|
||
|
}
|
||
|
|
||
|
static void EOR(void)
|
||
|
{
|
||
|
accumulator ^= memRead(op);
|
||
|
cycles++;
|
||
|
setStatusRegisterNZ(accumulator);
|
||
|
}
|
||
|
|
||
|
static void ASL(void)
|
||
|
{
|
||
|
btmp = memRead(op);
|
||
|
|
||
|
if (btmp & 0x80)
|
||
|
statusRegister |= C;
|
||
|
else
|
||
|
statusRegister &= ~C;
|
||
|
|
||
|
btmp <<= 1;
|
||
|
setStatusRegisterNZ(btmp);
|
||
|
memWrite(op, btmp);
|
||
|
cycles += 3;
|
||
|
}
|
||
|
|
||
|
static void ASL_A(void)
|
||
|
{
|
||
|
tmp = accumulator << 1;
|
||
|
accumulator = tmp & 0xFF;
|
||
|
setFlagCarry(tmp);
|
||
|
setStatusRegisterNZ(accumulator);
|
||
|
}
|
||
|
|
||
|
static void LSR(void)
|
||
|
{
|
||
|
btmp = memRead(op);
|
||
|
|
||
|
if (btmp & 1)
|
||
|
statusRegister |= C;
|
||
|
else
|
||
|
statusRegister &= ~C;
|
||
|
|
||
|
btmp >>= 1;
|
||
|
setStatusRegisterNZ(btmp);
|
||
|
memWrite(op, btmp);
|
||
|
cycles += 3;
|
||
|
}
|
||
|
|
||
|
static void LSR_A(void)
|
||
|
{
|
||
|
if (accumulator & 1)
|
||
|
statusRegister |= C;
|
||
|
else
|
||
|
statusRegister &= ~C;
|
||
|
|
||
|
accumulator >>= 1;
|
||
|
setStatusRegisterNZ(accumulator);
|
||
|
}
|
||
|
|
||
|
static void ROL(void)
|
||
|
{
|
||
|
int newCarry;
|
||
|
|
||
|
btmp = memRead(op);
|
||
|
newCarry = btmp & 0x80;
|
||
|
btmp = (btmp << 1) | (statusRegister & C ? 1 : 0);
|
||
|
|
||
|
if (newCarry)
|
||
|
statusRegister |= C;
|
||
|
else
|
||
|
statusRegister &= ~C;
|
||
|
|
||
|
setStatusRegisterNZ(btmp);
|
||
|
memWrite(op, btmp);
|
||
|
cycles += 3;
|
||
|
}
|
||
|
|
||
|
static void ROL_A(void)
|
||
|
{
|
||
|
tmp = (accumulator << 1) | (statusRegister & C ? 1 : 0);
|
||
|
accumulator = tmp & 0xFF;
|
||
|
setFlagCarry(tmp);
|
||
|
setStatusRegisterNZ(accumulator);
|
||
|
}
|
||
|
|
||
|
static void ROR(void)
|
||
|
{
|
||
|
int newCarry;
|
||
|
|
||
|
btmp = memRead(op);
|
||
|
newCarry = btmp & 1;
|
||
|
btmp = (btmp >> 1) | (statusRegister & C ? 0x80 : 0);
|
||
|
|
||
|
if (newCarry)
|
||
|
statusRegister |= C;
|
||
|
else
|
||
|
statusRegister &= ~C;
|
||
|
|
||
|
setStatusRegisterNZ(btmp);
|
||
|
memWrite(op, btmp);
|
||
|
cycles += 3;
|
||
|
}
|
||
|
|
||
|
static void ROR_A(void)
|
||
|
{
|
||
|
tmp = accumulator | (statusRegister & C ? 0x100 : 0);
|
||
|
|
||
|
if (accumulator & 1)
|
||
|
statusRegister |= C;
|
||
|
else
|
||
|
statusRegister &= ~C;
|
||
|
|
||
|
accumulator = tmp >> 1;
|
||
|
setStatusRegisterNZ(accumulator);
|
||
|
}
|
||
|
|
||
|
static void INC(void)
|
||
|
{
|
||
|
btmp = memRead(op);
|
||
|
btmp++;
|
||
|
setStatusRegisterNZ(btmp);
|
||
|
memWrite(op, btmp);
|
||
|
cycles += 2;
|
||
|
}
|
||
|
|
||
|
static void DEC(void)
|
||
|
{
|
||
|
btmp = memRead(op);
|
||
|
btmp--;
|
||
|
setStatusRegisterNZ(btmp);
|
||
|
memWrite(op, btmp);
|
||
|
cycles += 2;
|
||
|
}
|
||
|
|
||
|
static void INX(void)
|
||
|
{
|
||
|
xRegister++;
|
||
|
setStatusRegisterNZ(xRegister);
|
||
|
}
|
||
|
|
||
|
static void INY(void)
|
||
|
{
|
||
|
yRegister++;
|
||
|
setStatusRegisterNZ(yRegister);
|
||
|
}
|
||
|
|
||
|
static void DEX(void)
|
||
|
{
|
||
|
xRegister--;
|
||
|
setStatusRegisterNZ(xRegister);
|
||
|
}
|
||
|
|
||
|
static void DEY(void)
|
||
|
{
|
||
|
yRegister--;
|
||
|
setStatusRegisterNZ(yRegister);
|
||
|
}
|
||
|
|
||
|
static void BIT(void)
|
||
|
{
|
||
|
btmp = memRead(op);
|
||
|
|
||
|
if (btmp & 0x40)
|
||
|
statusRegister |= V;
|
||
|
else
|
||
|
statusRegister &= ~V;
|
||
|
|
||
|
if (btmp & 0x80)
|
||
|
statusRegister |= N;
|
||
|
else
|
||
|
statusRegister &= ~N;
|
||
|
|
||
|
if (!(btmp & accumulator))
|
||
|
statusRegister |= Z;
|
||
|
else
|
||
|
statusRegister &= ~Z;
|
||
|
|
||
|
cycles++;
|
||
|
}
|
||
|
|
||
|
static void PHA(void)
|
||
|
{
|
||
|
memWrite((unsigned short)(0x100 + stackPointer), accumulator);
|
||
|
stackPointer--;
|
||
|
cycles++;
|
||
|
}
|
||
|
|
||
|
static void PHP(void)
|
||
|
{
|
||
|
memWrite((unsigned short)(0x100 + stackPointer), statusRegister);
|
||
|
stackPointer--;
|
||
|
cycles++;
|
||
|
}
|
||
|
|
||
|
static void PLA(void)
|
||
|
{
|
||
|
stackPointer++;
|
||
|
accumulator = memRead((unsigned short)(stackPointer + 0x100));
|
||
|
setStatusRegisterNZ(accumulator);
|
||
|
cycles += 2;
|
||
|
}
|
||
|
|
||
|
static void PLP(void)
|
||
|
{
|
||
|
stackPointer++;
|
||
|
statusRegister = memRead((unsigned short)(stackPointer + 0x100));
|
||
|
cycles += 2;
|
||
|
}
|
||
|
|
||
|
static void BRK(void)
|
||
|
{
|
||
|
pushProgramCounter();
|
||
|
PHP();
|
||
|
statusRegister |= B;
|
||
|
programCounter = memReadAbsolute(0xFFFE);
|
||
|
cycles += 3;
|
||
|
}
|
||
|
|
||
|
static void RTI(void)
|
||
|
{
|
||
|
PLP();
|
||
|
popProgramCounter();
|
||
|
cycles++;
|
||
|
}
|
||
|
|
||
|
static void JMP(void)
|
||
|
{
|
||
|
programCounter = op;
|
||
|
}
|
||
|
|
||
|
static void RTS(void)
|
||
|
{
|
||
|
popProgramCounter();
|
||
|
programCounter++;
|
||
|
cycles += 2;
|
||
|
}
|
||
|
|
||
|
static void JSR(void)
|
||
|
{
|
||
|
opL = memRead(programCounter++);
|
||
|
pushProgramCounter();
|
||
|
programCounter = opL + (memRead(programCounter) << 8);
|
||
|
cycles += 3;
|
||
|
}
|
||
|
|
||
|
static void branch(void)
|
||
|
{
|
||
|
cycles++;
|
||
|
|
||
|
if ((programCounter & 0xFF00) != (op & 0xFF00))
|
||
|
cycles++;
|
||
|
|
||
|
programCounter = op;
|
||
|
}
|
||
|
|
||
|
static void BNE(void)
|
||
|
{
|
||
|
if (!(statusRegister & Z))
|
||
|
branch();
|
||
|
}
|
||
|
|
||
|
static void BEQ(void)
|
||
|
{
|
||
|
if (statusRegister & Z)
|
||
|
branch();
|
||
|
}
|
||
|
|
||
|
static void BVC(void)
|
||
|
{
|
||
|
if (!(statusRegister & V))
|
||
|
branch();
|
||
|
}
|
||
|
|
||
|
static void BVS(void)
|
||
|
{
|
||
|
if (statusRegister & V)
|
||
|
branch();
|
||
|
}
|
||
|
|
||
|
static void BCC(void)
|
||
|
{
|
||
|
if (!(statusRegister & C))
|
||
|
branch();
|
||
|
}
|
||
|
|
||
|
static void BCS(void)
|
||
|
{
|
||
|
if (statusRegister & C)
|
||
|
branch();
|
||
|
}
|
||
|
|
||
|
static void BPL(void)
|
||
|
{
|
||
|
if (!(statusRegister & N))
|
||
|
branch();
|
||
|
}
|
||
|
|
||
|
static void BMI(void)
|
||
|
{
|
||
|
if (statusRegister & N)
|
||
|
branch();
|
||
|
}
|
||
|
|
||
|
static void TAX(void)
|
||
|
{
|
||
|
xRegister = accumulator;
|
||
|
setStatusRegisterNZ(accumulator);
|
||
|
}
|
||
|
|
||
|
static void TXA(void)
|
||
|
{
|
||
|
accumulator = xRegister;
|
||
|
setStatusRegisterNZ(accumulator);
|
||
|
}
|
||
|
|
||
|
static void TAY(void)
|
||
|
{
|
||
|
yRegister = accumulator;
|
||
|
setStatusRegisterNZ(accumulator);
|
||
|
}
|
||
|
|
||
|
static void TYA(void)
|
||
|
{
|
||
|
accumulator = yRegister;
|
||
|
setStatusRegisterNZ(accumulator);
|
||
|
}
|
||
|
|
||
|
static void TXS(void)
|
||
|
{
|
||
|
stackPointer = xRegister;
|
||
|
}
|
||
|
|
||
|
static void TSX(void)
|
||
|
{
|
||
|
xRegister = stackPointer;
|
||
|
setStatusRegisterNZ(xRegister);
|
||
|
}
|
||
|
|
||
|
static void CLC(void)
|
||
|
{
|
||
|
statusRegister &= ~C;
|
||
|
}
|
||
|
|
||
|
static void SEC(void)
|
||
|
{
|
||
|
statusRegister |= C;
|
||
|
}
|
||
|
|
||
|
static void CLI(void)
|
||
|
{
|
||
|
statusRegister &= ~I;
|
||
|
}
|
||
|
|
||
|
static void SEI(void)
|
||
|
{
|
||
|
statusRegister |= I;
|
||
|
}
|
||
|
|
||
|
static void CLV(void)
|
||
|
{
|
||
|
statusRegister &= ~V;
|
||
|
}
|
||
|
|
||
|
static void CLD(void)
|
||
|
{
|
||
|
statusRegister &= ~D;
|
||
|
}
|
||
|
|
||
|
static void SED(void)
|
||
|
{
|
||
|
statusRegister |= D;
|
||
|
}
|
||
|
|
||
|
static void NOP(void)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
static void Unoff(void)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
static void Unoff1(void)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
static void Unoff2(void)
|
||
|
{
|
||
|
programCounter++;
|
||
|
}
|
||
|
|
||
|
static void Unoff3(void)
|
||
|
{
|
||
|
programCounter += 2;
|
||
|
}
|
||
|
|
||
|
static void Hang(void)
|
||
|
{
|
||
|
programCounter--;
|
||
|
}
|
||
|
|
||
|
static void executeOpcode(void)
|
||
|
{
|
||
|
unsigned char opcode = memRead(programCounter++);
|
||
|
|
||
|
switch (opcode)
|
||
|
{
|
||
|
case 0x00:
|
||
|
Imm();
|
||
|
BRK();
|
||
|
break;
|
||
|
case 0x01:
|
||
|
IndZeroX();
|
||
|
ORA();
|
||
|
break;
|
||
|
case 0x02:
|
||
|
Hang();
|
||
|
break;
|
||
|
case 0x03:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x04:
|
||
|
Unoff2();
|
||
|
break;
|
||
|
case 0x05:
|
||
|
Zero();
|
||
|
ORA();
|
||
|
break;
|
||
|
case 0x06:
|
||
|
Zero();
|
||
|
ASL();
|
||
|
break;
|
||
|
case 0x07:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x08:
|
||
|
Imp();
|
||
|
PHP();
|
||
|
break;
|
||
|
case 0x09:
|
||
|
Imm();
|
||
|
ORA();
|
||
|
break;
|
||
|
case 0x0A:
|
||
|
Imp();
|
||
|
ASL_A();
|
||
|
break;
|
||
|
case 0x0B:
|
||
|
Imm();
|
||
|
AND();
|
||
|
break;
|
||
|
case 0x0C:
|
||
|
Unoff3();
|
||
|
break;
|
||
|
case 0x0D:
|
||
|
Abs();
|
||
|
ORA();
|
||
|
break;
|
||
|
case 0x0E:
|
||
|
Abs();
|
||
|
ASL();
|
||
|
break;
|
||
|
case 0x0F:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x10:
|
||
|
Rel();
|
||
|
BPL();
|
||
|
break;
|
||
|
case 0x11:
|
||
|
IndZeroY();
|
||
|
ORA();
|
||
|
break;
|
||
|
case 0x12:
|
||
|
Hang();
|
||
|
break;
|
||
|
case 0x13:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x14:
|
||
|
Unoff2();
|
||
|
break;
|
||
|
case 0x15:
|
||
|
ZeroX();
|
||
|
ORA();
|
||
|
break;
|
||
|
case 0x16:
|
||
|
ZeroX();
|
||
|
ASL();
|
||
|
break;
|
||
|
case 0x17:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x18:
|
||
|
Imp();
|
||
|
CLC();
|
||
|
break;
|
||
|
case 0x19:
|
||
|
AbsY();
|
||
|
ORA();
|
||
|
break;
|
||
|
case 0x1A:
|
||
|
Unoff1();
|
||
|
break;
|
||
|
case 0x1B:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x1C:
|
||
|
Unoff3();
|
||
|
break;
|
||
|
case 0x1D:
|
||
|
AbsX();
|
||
|
ORA();
|
||
|
break;
|
||
|
case 0x1E:
|
||
|
WAbsX();
|
||
|
ASL();
|
||
|
break;
|
||
|
case 0x1F:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x20:
|
||
|
JSR();
|
||
|
break;
|
||
|
case 0x21:
|
||
|
IndZeroX();
|
||
|
AND();
|
||
|
break;
|
||
|
case 0x22:
|
||
|
Hang();
|
||
|
break;
|
||
|
case 0x23:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x24:
|
||
|
Zero();
|
||
|
BIT();
|
||
|
break;
|
||
|
case 0x25:
|
||
|
Zero();
|
||
|
AND();
|
||
|
break;
|
||
|
case 0x26:
|
||
|
Zero();
|
||
|
ROL();
|
||
|
break;
|
||
|
case 0x27:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x28:
|
||
|
Imp();
|
||
|
PLP();
|
||
|
break;
|
||
|
case 0x29:
|
||
|
Imm();
|
||
|
AND();
|
||
|
break;
|
||
|
case 0x2A:
|
||
|
Imp();
|
||
|
ROL_A();
|
||
|
break;
|
||
|
case 0x2B:
|
||
|
Imm();
|
||
|
AND();
|
||
|
break;
|
||
|
case 0x2C:
|
||
|
Abs();
|
||
|
BIT();
|
||
|
break;
|
||
|
case 0x2D:
|
||
|
Abs();
|
||
|
AND();
|
||
|
break;
|
||
|
case 0x2E:
|
||
|
Abs();
|
||
|
ROL();
|
||
|
break;
|
||
|
case 0x2F:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x30:
|
||
|
Rel();
|
||
|
BMI();
|
||
|
break;
|
||
|
case 0x31:
|
||
|
IndZeroY();
|
||
|
AND();
|
||
|
break;
|
||
|
case 0x32:
|
||
|
Hang();
|
||
|
break;
|
||
|
case 0x33:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x34:
|
||
|
Unoff2();
|
||
|
break;
|
||
|
case 0x35:
|
||
|
ZeroX();
|
||
|
AND();
|
||
|
break;
|
||
|
case 0x36:
|
||
|
ZeroX();
|
||
|
ROL();
|
||
|
break;
|
||
|
case 0x37:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x38:
|
||
|
Imp();
|
||
|
SEC();
|
||
|
break;
|
||
|
case 0x39:
|
||
|
AbsY();
|
||
|
AND();
|
||
|
break;
|
||
|
case 0x3A:
|
||
|
Unoff1();
|
||
|
break;
|
||
|
case 0x3B:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x3C:
|
||
|
Unoff3();
|
||
|
break;
|
||
|
case 0x3D:
|
||
|
AbsX();
|
||
|
AND();
|
||
|
break;
|
||
|
case 0x3E:
|
||
|
WAbsX();
|
||
|
ROL();
|
||
|
break;
|
||
|
case 0x3F:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x40:
|
||
|
Imp();
|
||
|
RTI();
|
||
|
break;
|
||
|
case 0x41:
|
||
|
IndZeroX();
|
||
|
EOR();
|
||
|
break;
|
||
|
case 0x42:
|
||
|
Hang();
|
||
|
break;
|
||
|
case 0x43:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x44:
|
||
|
Unoff2();
|
||
|
break;
|
||
|
case 0x45:
|
||
|
Zero();
|
||
|
EOR();
|
||
|
break;
|
||
|
case 0x46:
|
||
|
Zero();
|
||
|
LSR();
|
||
|
break;
|
||
|
case 0x47:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x48:
|
||
|
Imp();
|
||
|
PHA();
|
||
|
break;
|
||
|
case 0x49:
|
||
|
Imm();
|
||
|
EOR();
|
||
|
break;
|
||
|
case 0x4A:
|
||
|
Imp();
|
||
|
LSR_A();
|
||
|
break;
|
||
|
case 0x4B:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x4C:
|
||
|
Abs();
|
||
|
JMP();
|
||
|
break;
|
||
|
case 0x4D:
|
||
|
Abs();
|
||
|
EOR();
|
||
|
break;
|
||
|
case 0x4E:
|
||
|
Abs();
|
||
|
LSR();
|
||
|
break;
|
||
|
case 0x4F:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x50:
|
||
|
Rel();
|
||
|
BVC();
|
||
|
break;
|
||
|
case 0x51:
|
||
|
IndZeroY();
|
||
|
EOR();
|
||
|
break;
|
||
|
case 0x52:
|
||
|
Hang();
|
||
|
break;
|
||
|
case 0x53:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x54:
|
||
|
Unoff2();
|
||
|
break;
|
||
|
case 0x55:
|
||
|
ZeroX();
|
||
|
EOR();
|
||
|
break;
|
||
|
case 0x56:
|
||
|
ZeroX();
|
||
|
LSR();
|
||
|
break;
|
||
|
case 0x57:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x58:
|
||
|
Imp();
|
||
|
CLI();
|
||
|
break;
|
||
|
case 0x59:
|
||
|
AbsY();
|
||
|
EOR();
|
||
|
break;
|
||
|
case 0x5A:
|
||
|
Unoff1();
|
||
|
break;
|
||
|
case 0x5B:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x5C:
|
||
|
Unoff3();
|
||
|
break;
|
||
|
case 0x5D:
|
||
|
AbsX();
|
||
|
EOR();
|
||
|
break;
|
||
|
case 0x5E:
|
||
|
WAbsX();
|
||
|
LSR();
|
||
|
break;
|
||
|
case 0x5F:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x60:
|
||
|
Imp();
|
||
|
RTS();
|
||
|
break;
|
||
|
case 0x61:
|
||
|
IndZeroX();
|
||
|
ADC();
|
||
|
break;
|
||
|
case 0x62:
|
||
|
Hang();
|
||
|
break;
|
||
|
case 0x63:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x64:
|
||
|
Unoff2();
|
||
|
break;
|
||
|
case 0x65:
|
||
|
Zero();
|
||
|
ADC();
|
||
|
break;
|
||
|
case 0x66:
|
||
|
Zero();
|
||
|
ROR();
|
||
|
break;
|
||
|
case 0x67:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x68:
|
||
|
Imp();
|
||
|
PLA();
|
||
|
break;
|
||
|
case 0x69:
|
||
|
Imm();
|
||
|
ADC();
|
||
|
break;
|
||
|
case 0x6A:
|
||
|
Imp();
|
||
|
ROR_A();
|
||
|
break;
|
||
|
case 0x6B:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x6C:
|
||
|
Ind();
|
||
|
JMP();
|
||
|
break;
|
||
|
case 0x6D:
|
||
|
Abs();
|
||
|
ADC();
|
||
|
break;
|
||
|
case 0x6E:
|
||
|
Abs();
|
||
|
ROR();
|
||
|
break;
|
||
|
case 0x6F:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x70:
|
||
|
Rel();
|
||
|
BVS();
|
||
|
break;
|
||
|
case 0x71:
|
||
|
IndZeroY();
|
||
|
ADC();
|
||
|
break;
|
||
|
case 0x72:
|
||
|
Hang();
|
||
|
break;
|
||
|
case 0x73:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x74:
|
||
|
Unoff2();
|
||
|
break;
|
||
|
case 0x75:
|
||
|
ZeroX();
|
||
|
ADC();
|
||
|
break;
|
||
|
case 0x76:
|
||
|
ZeroX();
|
||
|
ROR();
|
||
|
break;
|
||
|
case 0x77:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x78:
|
||
|
Imp();
|
||
|
SEI();
|
||
|
break;
|
||
|
case 0x79:
|
||
|
AbsY();
|
||
|
ADC();
|
||
|
break;
|
||
|
case 0x7A:
|
||
|
Unoff1();
|
||
|
break;
|
||
|
case 0x7B:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x7C:
|
||
|
Unoff3();
|
||
|
break;
|
||
|
case 0x7D:
|
||
|
AbsX();
|
||
|
ADC();
|
||
|
break;
|
||
|
case 0x7E:
|
||
|
WAbsX();
|
||
|
ROR();
|
||
|
break;
|
||
|
case 0x7F:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x80:
|
||
|
Unoff2();
|
||
|
break;
|
||
|
case 0x81:
|
||
|
IndZeroX();
|
||
|
STA();
|
||
|
break;
|
||
|
case 0x82:
|
||
|
Unoff2();
|
||
|
break;
|
||
|
case 0x83:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x84:
|
||
|
Zero();
|
||
|
STY();
|
||
|
break;
|
||
|
case 0x85:
|
||
|
Zero();
|
||
|
STA();
|
||
|
break;
|
||
|
case 0x86:
|
||
|
Zero();
|
||
|
STX();
|
||
|
break;
|
||
|
case 0x87:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x88:
|
||
|
Imp();
|
||
|
DEY();
|
||
|
break;
|
||
|
case 0x89:
|
||
|
Unoff2();
|
||
|
break;
|
||
|
case 0x8A:
|
||
|
Imp();
|
||
|
TXA();
|
||
|
break;
|
||
|
case 0x8B:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x8C:
|
||
|
Abs();
|
||
|
STY();
|
||
|
break;
|
||
|
case 0x8D:
|
||
|
Abs();
|
||
|
STA();
|
||
|
break;
|
||
|
case 0x8E:
|
||
|
Abs();
|
||
|
STX();
|
||
|
break;
|
||
|
case 0x8F:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x90:
|
||
|
Rel();
|
||
|
BCC();
|
||
|
break;
|
||
|
case 0x91:
|
||
|
WIndZeroY();
|
||
|
STA();
|
||
|
break;
|
||
|
case 0x92:
|
||
|
Hang();
|
||
|
break;
|
||
|
case 0x93:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x94:
|
||
|
ZeroX();
|
||
|
STY();
|
||
|
break;
|
||
|
case 0x95:
|
||
|
ZeroX();
|
||
|
STA();
|
||
|
break;
|
||
|
case 0x96:
|
||
|
ZeroY();
|
||
|
STX();
|
||
|
break;
|
||
|
case 0x97:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x98:
|
||
|
Imp();
|
||
|
TYA();
|
||
|
break;
|
||
|
case 0x99:
|
||
|
WAbsY();
|
||
|
STA();
|
||
|
break;
|
||
|
case 0x9A:
|
||
|
Imp();
|
||
|
TXS();
|
||
|
break;
|
||
|
case 0x9B:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x9C:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x9D:
|
||
|
WAbsX();
|
||
|
STA();
|
||
|
break;
|
||
|
case 0x9E:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0x9F:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0xA0:
|
||
|
Imm();
|
||
|
LDY();
|
||
|
break;
|
||
|
case 0xA1:
|
||
|
IndZeroX();
|
||
|
LDA();
|
||
|
break;
|
||
|
case 0xA2:
|
||
|
Imm();
|
||
|
LDX();
|
||
|
break;
|
||
|
case 0xA3:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0xA4:
|
||
|
Zero();
|
||
|
LDY();
|
||
|
break;
|
||
|
case 0xA5:
|
||
|
Zero();
|
||
|
LDA();
|
||
|
break;
|
||
|
case 0xA6:
|
||
|
Zero();
|
||
|
LDX();
|
||
|
break;
|
||
|
case 0xA7:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0xA8:
|
||
|
Imp();
|
||
|
TAY();
|
||
|
break;
|
||
|
case 0xA9:
|
||
|
Imm();
|
||
|
LDA();
|
||
|
break;
|
||
|
case 0xAA:
|
||
|
Imp();
|
||
|
TAX();
|
||
|
break;
|
||
|
case 0xAB:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0xAC:
|
||
|
Abs();
|
||
|
LDY();
|
||
|
break;
|
||
|
case 0xAD:
|
||
|
Abs();
|
||
|
LDA();
|
||
|
break;
|
||
|
case 0xAE:
|
||
|
Abs();
|
||
|
LDX();
|
||
|
break;
|
||
|
case 0xAF:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0xB0:
|
||
|
Rel();
|
||
|
BCS();
|
||
|
break;
|
||
|
case 0xB1:
|
||
|
IndZeroY();
|
||
|
LDA();
|
||
|
break;
|
||
|
case 0xB2:
|
||
|
Hang();
|
||
|
break;
|
||
|
case 0xB3:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0xB4:
|
||
|
ZeroX();
|
||
|
LDY();
|
||
|
break;
|
||
|
case 0xB5:
|
||
|
ZeroX();
|
||
|
LDA();
|
||
|
break;
|
||
|
case 0xB6:
|
||
|
ZeroY();
|
||
|
LDX();
|
||
|
break;
|
||
|
case 0xB7:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0xB8:
|
||
|
Imp();
|
||
|
CLV();
|
||
|
break;
|
||
|
case 0xB9:
|
||
|
AbsY();
|
||
|
LDA();
|
||
|
break;
|
||
|
case 0xBA:
|
||
|
Imp();
|
||
|
TSX();
|
||
|
break;
|
||
|
case 0xBB:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0xBC:
|
||
|
AbsX();
|
||
|
LDY();
|
||
|
break;
|
||
|
case 0xBD:
|
||
|
AbsX();
|
||
|
LDA();
|
||
|
break;
|
||
|
case 0xBE:
|
||
|
AbsY();
|
||
|
LDX();
|
||
|
break;
|
||
|
case 0xBF:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0xC0:
|
||
|
Imm();
|
||
|
CPY();
|
||
|
break;
|
||
|
case 0xC1:
|
||
|
IndZeroX();
|
||
|
CMP();
|
||
|
break;
|
||
|
case 0xC2:
|
||
|
Unoff2();
|
||
|
break;
|
||
|
case 0xC3:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0xC4:
|
||
|
Zero();
|
||
|
CPY();
|
||
|
break;
|
||
|
case 0xC5:
|
||
|
Zero();
|
||
|
CMP();
|
||
|
break;
|
||
|
case 0xC6:
|
||
|
Zero();
|
||
|
DEC();
|
||
|
break;
|
||
|
case 0xC7:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0xC8:
|
||
|
Imp();
|
||
|
INY();
|
||
|
break;
|
||
|
case 0xC9:
|
||
|
Imm();
|
||
|
CMP();
|
||
|
break;
|
||
|
case 0xCA:
|
||
|
Imp();
|
||
|
DEX();
|
||
|
break;
|
||
|
case 0xCB:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0xCC:
|
||
|
Abs();
|
||
|
CPY();
|
||
|
break;
|
||
|
case 0xCD:
|
||
|
Abs();
|
||
|
CMP();
|
||
|
break;
|
||
|
case 0xCE:
|
||
|
Abs();
|
||
|
DEC();
|
||
|
break;
|
||
|
case 0xCF:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0xD0:
|
||
|
Rel();
|
||
|
BNE();
|
||
|
break;
|
||
|
case 0xD1:
|
||
|
IndZeroY();
|
||
|
CMP();
|
||
|
break;
|
||
|
case 0xD2:
|
||
|
Hang();
|
||
|
break;
|
||
|
case 0xD3:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0xD4:
|
||
|
Unoff2();
|
||
|
break;
|
||
|
case 0xD5:
|
||
|
ZeroX();
|
||
|
CMP();
|
||
|
break;
|
||
|
case 0xD6:
|
||
|
ZeroX();
|
||
|
DEC();
|
||
|
break;
|
||
|
case 0xD7:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0xD8:
|
||
|
Imp();
|
||
|
CLD();
|
||
|
break;
|
||
|
case 0xD9:
|
||
|
AbsY();
|
||
|
CMP();
|
||
|
break;
|
||
|
case 0xDA:
|
||
|
Unoff1();
|
||
|
break;
|
||
|
case 0xDB:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0xDC:
|
||
|
Unoff3();
|
||
|
break;
|
||
|
case 0xDD:
|
||
|
AbsX();
|
||
|
CMP();
|
||
|
break;
|
||
|
case 0xDE:
|
||
|
WAbsX();
|
||
|
DEC();
|
||
|
break;
|
||
|
case 0xDF:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0xE0:
|
||
|
Imm();
|
||
|
CPX();
|
||
|
break;
|
||
|
case 0xE1:
|
||
|
IndZeroX();
|
||
|
SBC();
|
||
|
break;
|
||
|
case 0xE2:
|
||
|
Unoff2();
|
||
|
break;
|
||
|
case 0xE3:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0xE4:
|
||
|
Zero();
|
||
|
CPX();
|
||
|
break;
|
||
|
case 0xE5:
|
||
|
Zero();
|
||
|
SBC();
|
||
|
break;
|
||
|
case 0xE6:
|
||
|
Zero();
|
||
|
INC();
|
||
|
break;
|
||
|
case 0xE7:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0xE8:
|
||
|
Imp();
|
||
|
INX();
|
||
|
break;
|
||
|
case 0xE9:
|
||
|
Imm();
|
||
|
SBC();
|
||
|
break;
|
||
|
case 0xEA:
|
||
|
Imp();
|
||
|
NOP();
|
||
|
break;
|
||
|
case 0xEB:
|
||
|
Imm();
|
||
|
SBC();
|
||
|
break;
|
||
|
case 0xEC:
|
||
|
Abs();
|
||
|
CPX();
|
||
|
break;
|
||
|
case 0xED:
|
||
|
Abs();
|
||
|
SBC();
|
||
|
break;
|
||
|
case 0xEE:
|
||
|
Abs();
|
||
|
INC();
|
||
|
break;
|
||
|
case 0xEF:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0xF0:
|
||
|
Rel();
|
||
|
BEQ();
|
||
|
break;
|
||
|
case 0xF1:
|
||
|
IndZeroY();
|
||
|
SBC();
|
||
|
break;
|
||
|
case 0xF2:
|
||
|
Hang();
|
||
|
break;
|
||
|
case 0xF3:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0xF4:
|
||
|
Unoff2();
|
||
|
break;
|
||
|
case 0xF5:
|
||
|
ZeroX();
|
||
|
SBC();
|
||
|
break;
|
||
|
case 0xF6:
|
||
|
ZeroX();
|
||
|
INC();
|
||
|
break;
|
||
|
case 0xF7:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0xF8:
|
||
|
Imp();
|
||
|
SED();
|
||
|
break;
|
||
|
case 0xF9:
|
||
|
AbsY();
|
||
|
SBC();
|
||
|
break;
|
||
|
case 0xFA:
|
||
|
Unoff1();
|
||
|
break;
|
||
|
case 0xFB:
|
||
|
Unoff();
|
||
|
break;
|
||
|
case 0xFC:
|
||
|
Unoff3();
|
||
|
break;
|
||
|
case 0xFD:
|
||
|
AbsX();
|
||
|
SBC();
|
||
|
break;
|
||
|
case 0xFE:
|
||
|
WAbsX();
|
||
|
INC();
|
||
|
break;
|
||
|
case 0xFF:
|
||
|
Unoff();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int runM6502(void *data)
|
||
|
{
|
||
|
while (running)
|
||
|
{
|
||
|
synchronize();
|
||
|
|
||
|
cycles = 0;
|
||
|
|
||
|
while (running && cycles < cyclesBeforeSynchro)
|
||
|
{
|
||
|
if (!(statusRegister & I) && IRQ)
|
||
|
handleIRQ();
|
||
|
if (NMI)
|
||
|
handleNMI();
|
||
|
|
||
|
executeOpcode();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void startM6502(void)
|
||
|
{
|
||
|
running = 1;
|
||
|
lastTime = SDL_GetTicks();
|
||
|
thread = SDL_CreateThread(runM6502, NULL);
|
||
|
}
|
||
|
|
||
|
void stopM6502(void)
|
||
|
{
|
||
|
running = 0;
|
||
|
SDL_WaitThread(thread, NULL);
|
||
|
}
|
||
|
|
||
|
void resetM6502(void)
|
||
|
{
|
||
|
statusRegister |= I;
|
||
|
stackPointer = 0xFF;
|
||
|
programCounter = memReadAbsolute(0xFFFC);
|
||
|
}
|
||
|
|
||
|
void setSpeed(int freq, int synchroMillis)
|
||
|
{
|
||
|
cyclesBeforeSynchro = synchroMillis * freq;
|
||
|
_synchroMillis = synchroMillis;
|
||
|
}
|
||
|
|
||
|
void setIRQ(int state)
|
||
|
{
|
||
|
IRQ = state;
|
||
|
}
|
||
|
|
||
|
void setNMI(void)
|
||
|
{
|
||
|
NMI = 1;
|
||
|
}
|
||
|
|
||
|
int *dumpState(void)
|
||
|
{
|
||
|
int *state = (int *)malloc(sizeof(int) * 6);
|
||
|
|
||
|
state[0] = programCounter;
|
||
|
state[1] = statusRegister;
|
||
|
state[2] = accumulator;
|
||
|
state[3] = xRegister;
|
||
|
state[4] = yRegister;
|
||
|
state[5] = stackPointer;
|
||
|
|
||
|
return state;
|
||
|
}
|
||
|
|
||
|
void loadState(int *state)
|
||
|
{
|
||
|
programCounter = state[0];
|
||
|
statusRegister = state[1];
|
||
|
accumulator = state[2];
|
||
|
xRegister = state[3];
|
||
|
yRegister = state[4];
|
||
|
stackPointer = state[5];
|
||
|
}
|