pom1/src/m6502.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];
}