HDNes/Rewrite/core/cpu.cpp
mkwong98 10e66a742e
2017-07-08 02:07:51 +08:00

658 lines
21 KiB
C++

#include "cpu.h"
#include "memBus.h"
#include "../gameManager.h"
cpu::cpu()
{
instructionLen[0] = 6;
instructionLen[1] = 3;
instructionLen[2] = 2;
instructionLen[3] = 4;
instructionLen[4] = 5;
instructionLen[5] = 4;
instructionLen[6] = 4;
instructionLen[7] = 4;
flagMask[0] = 0x01;
flagMask[1] = 0x02;
flagMask[2] = 0x04;
flagMask[3] = 0x08;
flagMask[4] = 0x10;
flagMask[5] = 0x20;
flagMask[6] = 0x40;
flagMask[7] = 0x80;
branchFlag[0] = FLAG_N;
branchFlag[1] = FLAG_V;
branchFlag[2] = FLAG_C;
branchFlag[3] = FLAG_Z;
for(Uint8 i = 0; i < 256; ++i){
addressMode = (i >> 2) & 0x07;
operation = (i >> 5) & 0x07;
opGroup = i & 0x03;
if(addressMode == 4 && opGroup == 0){ //branch xxx10000
opHdl[i] = &cpu::opcodeBranch;
}
else if(addressMode == 6 && opGroup == 0){ //flag xxx11000
opHdl[i] = &cpu::opcodeFlag;
}
else if(addressMode > 4 && operation > 4 && opGroup == 0){ //0xx0xx00
opHdl[i] = &cpu::opcodeCtrl;
}
else if((nextInstruction[0] & 0x8F) == 0x8A){ //1xxx1010
opHdl[i] = &cpu::opcodeMisB;
}
else if((nextInstruction[0] & 0x9F) == 0x88){ //1xx01000
opHdl[i] = &cpu::opcodeMisA;
}
else if(operation == 4){
opHdl[i] = &cpu::opcodeST;
}
else if(operation == 5){
opHdl[i] = &cpu::opcodeLD;
}
else if(opGroup == 0){
opHdl[i] = &cpu::opcodeHandler0;
}
else if(opGroup == 1){
opHdl[i] = &cpu::opcodeHandler1;
}
else if(opGroup == 2){
opHdl[i] = &cpu::opcodeHandler2;
}
else if(opGroup == 3){
opHdl[i] = &cpu::opcodeHandler3;
}
}
adHdl[0] = &cpu::resolveAddress0;
adHdl[1] = &cpu::resolveAddress1;
adHdl[2] = &cpu::resolveAddress2;
adHdl[3] = &cpu::resolveAddress3;
adHdl[4] = &cpu::resolveAddress4;
adHdl[5] = &cpu::resolveAddress5;
adHdl[6] = &cpu::resolveAddress6;
adHdl[7] = &cpu::resolveAddress7;
adHdl[8] = &cpu::resolveAddress8;
}
cpu::~cpu()
{
//dtor
}
Uint8 cpu::getNextInstructionLength(){
return instructionTicks;
}
void cpu::processInstruction(){
newState = state;
nextInstruction[0] = mb->memRead(newState.programCounter);
++(newState.programCounter);
addressMode = (nextInstruction[0] >> 2) & 0x07;
operation = (nextInstruction[0] >> 5) & 0x07;
opGroup = nextInstruction[0] & 0x03;
(this->*opHdl[nextInstruction[0]])();
}
void cpu::opcodeBranch(){
instructionType = OP_TYPE_CPU;
instructionTicks = 2;
nextInstruction[1] = mb->memRead(newState.programCounter);
++(newState.programCounter);
bool branchResult;
if(operation & 0x01){
branchResult = checkFlag(branchFlag[(operation >> 1) & 0x03]);
}
else{
branchResult = !checkFlag(branchFlag[(operation >> 1) & 0x03]);
}
if(branchResult){
++instructionTicks;
Uint16 pcPage;
pcPage = newState.programCounter & 0xFF00;
newState.programCounter += (nextInstruction[1] & 0x80 ? -(nextInstruction[1] & 0x7F) - 1 : nextInstruction[1]);
if(pcPage != (newState.programCounter & 0xFF00)) ++instructionTicks;
}
}
void cpu::opcodeFlag(){
instructionTicks = 2;
instructionType = OP_TYPE_CPU;
if(nextInstruction[0] == 0x98){ //TYA
newState.reg[REG_INDEX_Y] = newState.reg[REG_ACCUMULATOR];
updateFlag(FLAG_Z, !newState.reg[REG_INDEX_Y]);
updateFlag(FLAG_N, newState.reg[REG_INDEX_Y] & 0x80);
}
else{
Uint8 flagID;
switch(operation & 0x06){
case 0:
flagID = FLAG_C;
break;
case 2:
flagID = FLAG_I;
break;
case 4:
flagID = FLAG_V;
break;
case 6:
flagID = FLAG_D;
break;
}
if((operation & 0x01) && (operation != 0x05)){
setFlag(flagID);
}
else{
clearFlag(flagID);
}
}
}
void cpu::opcodeCtrl(){
if(addressMode == 0){
switch(operation){
case 0x00: //BRK
instructionTicks = 7;
instructionType = OP_TYPE_BRK;
setFlag(FLAG_I);
break;
case 0x01: //JSR
instructionTicks = 6;
instructionType = OP_TYPE_JSR;
nextInstruction[1] = mb->memRead(newState.programCounter);
++(newState.programCounter);
nextInstruction[2] = mb->memRead(newState.programCounter);
break;
case 0x02: //RTI
instructionTicks = 6;
instructionType = OP_TYPE_CPU;
++(newState.reg[REG_STACK_PTR]);
newState.reg[REG_STATUS] = (mb->memRead(0x0100 + newState.reg[REG_STACK_PTR]) & 0xCF) | (newState.reg[REG_STATUS] & 0x30); //ignore bit 4 and 5
//immediately effective
state.reg[REG_STATUS] = newState.reg[REG_STATUS];
++(newState.reg[REG_STACK_PTR]);
newState.programCounter = (mb->memRead(0x0100 + newState.reg[REG_STACK_PTR]) & 0x00FF);
++(newState.reg[REG_STACK_PTR]);
newState.programCounter += (mb->memRead(0x0100 + newState.reg[REG_STACK_PTR]) << 8) ;
break;
case 0x03: //RTS
instructionTicks = 6;
instructionType = OP_TYPE_CPU;
++(newState.reg[REG_STACK_PTR]);
newState.programCounter = (mb->memRead(0x0100 + newState.reg[REG_STACK_PTR]) & 0x00FF);
++(newState.reg[REG_STACK_PTR]);
newState.programCounter += (mb->memRead(0x0100 + newState.reg[REG_STACK_PTR]) << 8) ;
++(newState.programCounter);
break;
}
}
else if(addressMode == 2){
switch(operation){
case 0x00:
//PHP, bit 4 and 5 are always 1 in stack
pushStack(newState.reg[REG_STATUS] | 0x30);
break;
case 0x01:
//PLP , ignore bit 4 and 5
newState.reg[REG_STATUS] = (pullStack() & 0xCF) | (newState.reg[REG_STATUS] & 0x30);
break;
case 0x028:
//PHA
pushStack(newState.reg[REG_ACCUMULATOR]);
break;
case 0x03:
//PLA
newState.reg[REG_ACCUMULATOR] = pullStack();
break;
}
}
else{
if(operation == 0x01){ //BIT
instructionType = OP_TYPE_CPU;
instructionTicks = (addressMode == 0x01 ? 3 : 4);
opValue = getValue((addressMode == 0x01 ? 1 : 3), pageCrossed);
outValue = opValue & newState.reg[REG_ACCUMULATOR];
updateFlag(FLAG_Z, !outValue);
updateFlag(FLAG_V, opValue & 0x40);
updateFlag(FLAG_N, opValue & 0x80);
}
else{ //JMP
instructionType = OP_TYPE_CPU;
outAddress = resolveAddress(3, pageCrossed);
if(operation == 0x02){
instructionTicks = 3;
newState.programCounter = outAddress;
}
else{
instructionTicks = 5;
newState.programCounter = (mb->memRead(outAddress + 1) << 8) + mb->memRead(outAddress);
}
}
}
}
void cpu::opcodeMisA(){
instructionTicks = 2;
instructionType = OP_TYPE_CPU;
switch(operation){
case 0x04:
//DEY
newState.reg[REG_INDEX_Y] = (newState.reg[REG_INDEX_Y] ? newState.reg[REG_INDEX_Y] - 1 : 0xFF);
updateFlag(FLAG_Z, !newState.reg[REG_INDEX_Y]);
updateFlag(FLAG_N, newState.reg[REG_INDEX_Y] & 0x80);
break;
case 0x05:
//TAY
newState.reg[REG_INDEX_Y] = newState.reg[REG_ACCUMULATOR];
updateFlag(FLAG_Z, !newState.reg[REG_INDEX_Y]);
updateFlag(FLAG_N, newState.reg[REG_INDEX_Y] & 0x80);
case 0x06:
//INY
newState.reg[REG_INDEX_Y] = (newState.reg[REG_INDEX_Y] < 0xFF ? newState.reg[REG_INDEX_Y] + 1 : 0);
updateFlag(FLAG_Z, !newState.reg[REG_INDEX_Y]);
updateFlag(FLAG_N, newState.reg[REG_INDEX_Y] & 0x80);
break;
case 0x07:
//INX
newState.reg[REG_INDEX_X] = (newState.reg[REG_INDEX_X] < 0xFF ? newState.reg[REG_INDEX_X] + 1 : 0);
updateFlag(FLAG_Z, !newState.reg[REG_INDEX_X]);
updateFlag(FLAG_N, newState.reg[REG_INDEX_X] & 0x80);
break;
}
}
void cpu::opcodeMisB(){
instructionTicks = 2;
instructionType = OP_TYPE_CPU;
switch(operation){
case 0x8A: //TXA
newState.reg[REG_ACCUMULATOR] = newState.reg[REG_INDEX_X];
updateFlag(FLAG_Z, !newState.reg[REG_ACCUMULATOR]);
updateFlag(FLAG_N, newState.reg[REG_ACCUMULATOR] & 0x80);
break;
case 0x9A: //TXS
newState.reg[REG_STACK_PTR] = newState.reg[REG_INDEX_X];
break;
case 0xAA: //TAX
newState.reg[REG_INDEX_X] = newState.reg[REG_ACCUMULATOR];
updateFlag(FLAG_Z, !newState.reg[REG_INDEX_X]);
updateFlag(FLAG_N, newState.reg[REG_INDEX_X] & 0x80);
break;
case 0xBA: //TSX
newState.reg[REG_INDEX_X] = newState.reg[REG_STACK_PTR];
updateFlag(FLAG_Z, !newState.reg[REG_INDEX_X]);
updateFlag(FLAG_N, newState.reg[REG_INDEX_X] & 0x80);
break;
case 0xCA: //DEX
newState.reg[REG_INDEX_X] = (newState.reg[REG_INDEX_X] ? newState.reg[REG_INDEX_X] - 1 : 0xFF);
updateFlag(FLAG_Z, !newState.reg[REG_INDEX_X]);
updateFlag(FLAG_N, newState.reg[REG_INDEX_X] & 0x80);
break;
case 0xEA: //NOP
break;
}
}
void cpu::opcodeST(){
instructionTicks = instructionLen[addressMode];
instructionType = OP_TYPE_OUT;
switch(opGroup){
case 1:
if(addressMode == 4 || addressMode == 6 || addressMode == 7) ++instructionTicks;
break;
case 2:
if(addressMode == 5) addressMode = 8;
break;
}
outValue = newState.reg[opGroup];
outAddress = resolveAddress(addressMode, pageCrossed);
}
void cpu::opcodeLD(){
if(opGroup != 1 && addressMode == 0) addressMode = 2;
instructionTicks = instructionLen[addressMode];
instructionType = OP_TYPE_CPU;
if(opGroup == 2 && addressMode == 5) addressMode = 8;
if(opGroup == 2 && addressMode == 7) addressMode = 6;
newState.reg[opGroup] = getValue(addressMode, pageCrossed);
updateFlag(FLAG_Z, !newState.reg[opGroup]);
updateFlag(FLAG_N, newState.reg[opGroup] & 0x80);
if(pageCrossed) ++instructionTicks;
}
void cpu::opcodeHandler0(){ //xxxxxx00
if((nextInstruction[0] & 0x80) == 0x80){ //1xxxxx00
if(operation == 6){ //CPY
if(addressMode == 0) addressMode = 2;
instructionTicks = instructionLen[addressMode];
instructionType = OP_TYPE_CPU;
opValue = getValue(addressMode, pageCrossed);
compare(newState.reg[REG_INDEX_Y], opValue);
}
else if(operation == 7){ //CPX
if(addressMode == 0) addressMode = 2;
instructionTicks = instructionLen[addressMode];
instructionType = OP_TYPE_CPU;
opValue = getValue(addressMode, pageCrossed);
compare(newState.reg[REG_INDEX_X], opValue);
}
}
}
void cpu::opcodeHandler1(){ //PPPAAA01
instructionTicks = instructionLen[addressMode];
instructionType = OP_TYPE_CPU;
opValue = getValue(addressMode, pageCrossed);
if(pageCrossed) ++instructionTicks;
if(operation == 6){//CMP
compare(newState.reg[REG_ACCUMULATOR], opValue);
}
else{
Uint16 tmpValue;
switch(operation){
case 0:
//ORA
newState.reg[REG_ACCUMULATOR] = newState.reg[REG_ACCUMULATOR] | opValue;
break;
case 1:
//AND
newState.reg[REG_ACCUMULATOR] = newState.reg[REG_ACCUMULATOR] & opValue;
break;
case 2:
//EOR
newState.reg[REG_ACCUMULATOR] = newState.reg[REG_ACCUMULATOR] ^ opValue;
break;
case 3:
//ADC
tmpValue = newState.reg[REG_ACCUMULATOR] + opValue + (checkFlag(FLAG_C) ? 1 : 0);
newState.reg[REG_ACCUMULATOR] = tmpValue & 0x00FF;
updateFlag(FLAG_C, tmpValue > 0x00FF);
updateFlag(FLAG_V, (((newState.reg[REG_ACCUMULATOR] ^ opValue) & (newState.reg[REG_ACCUMULATOR] ^ state.reg[REG_ACCUMULATOR]) & 0x80) != 0));
break;
case 7:
//SBC
tmpValue = newState.reg[REG_ACCUMULATOR];
tmpValue = tmpValue - opValue;
if(checkFlag(FLAG_C)) --tmpValue;
newState.reg[REG_ACCUMULATOR] = tmpValue & 0x00FF;
updateFlag(FLAG_C, tmpValue < 0x100);
updateFlag(FLAG_V, ((newState.reg[REG_ACCUMULATOR] ^ (opValue ^ 0xFF)) & (newState.reg[REG_ACCUMULATOR] ^ state.reg[REG_ACCUMULATOR]) & 0x80) != 0);
}
updateFlag(FLAG_Z, !newState.reg[REG_ACCUMULATOR]);
updateFlag(FLAG_N, newState.reg[REG_ACCUMULATOR] & 0x80);
}
}
void cpu::opcodeHandler2(){ //xxxxxx10
instructionTicks = 2;
if(addressMode == 2){
instructionType = OP_TYPE_CPU;
opValue = newState.reg[REG_ACCUMULATOR];
}
else{
instructionType = OP_TYPE_OUT;
instructionTicks += 2;
if(addressMode == 7) ++instructionTicks;
outAddress = resolveAddress(addressMode, pageCrossed);
opValue = mb->memRead(outAddress);
}
switch(operation){
case 0:
//ASL
outValue = (opValue << 1) & 0xFE;
updateFlag(FLAG_C, opValue & 0x80);
break;
case 1:
//ROL
outValue = ((opValue << 1) & 0xFE) | (checkFlag(FLAG_C) ? 0x01 : 0x00);
updateFlag(FLAG_C, opValue & 0x80);
break;
case 2:
//LSR
outValue = (opValue >> 1) & 0x7F;
updateFlag(FLAG_C, opValue & 0x01);
break;
case 3:
//ROR
outValue = ((opValue >> 1) & 0x7F) | (checkFlag(FLAG_C) ? 0x80 : 0x00);
updateFlag(FLAG_C, opValue & 0x01);
break;
case 6:
//DEC
outValue = (opValue ? opValue - 1 : 0xFF);
break;
case 7:
//INC
outValue = (opValue < 0xFF ? opValue + 1 : 0);
break;
}
updateFlag(FLAG_Z, !outValue);
updateFlag(FLAG_N, outValue & 0x80);
if(addressMode == 2){
newState.reg[REG_ACCUMULATOR] = outValue;
}
}
void cpu::opcodeHandler3(){ //xxxxxx11
//unsupported op
instructionType = OP_TYPE_CPU;
instructionTicks = 2;
}
void cpu::pushStack(Uint8 value){
instructionTicks = 3;
instructionType = OP_TYPE_OUT;
outValue = value;
outAddress = 0x0100 + newState.reg[REG_STACK_PTR];
--(newState.reg[REG_STACK_PTR]);
}
Uint8 cpu::pullStack(){
instructionTicks = 4;
instructionType = OP_TYPE_CPU;
++(newState.reg[REG_STACK_PTR]);
return mb->memRead(0x0100 + newState.reg[REG_STACK_PTR]);
}
void cpu::compare(Uint8 regValue, Uint8 opValue){
updateFlag(FLAG_C, regValue >= opValue);
updateFlag(FLAG_Z, regValue == opValue);
updateFlag(FLAG_N, ((regValue - opValue) & 0x80) != 0);
}
Uint8 cpu::getValue(Uint8 addressMode, bool& hasCrossPage){
if(addressMode == 2){
//#v
nextInstruction[1] = mb->memRead(newState.programCounter);
++(newState.programCounter);
hasCrossPage = false;
return nextInstruction[1];
}
else{
return mb->memRead(resolveAddress(addressMode, hasCrossPage));
}
}
Uint16 cpu::resolveAddress(Uint8 addressMode, bool& hasCrossPage){
Uint16 tmpAddress;
nextInstruction[1] = mb->memRead(newState.programCounter);
++(newState.programCounter);
hasCrossPage = false;
return (this->*adHdl[addressMode])(hasCrossPage);
}
Uint16 cpu::resolveAddress0(bool& hasCrossPage){ //(d,x)
return mb->memRead((nextInstruction[1] + state.reg[REG_INDEX_X]) & 0x00FF) + (mb->memRead((nextInstruction[1] + state.reg[REG_INDEX_X] + 1) & 0x00FF) << 8);
}
Uint16 cpu::resolveAddress1(bool& hasCrossPage){ //d
return nextInstruction[1];
}
Uint16 cpu::resolveAddress2(bool& hasCrossPage){ //#v
return 0;
}
Uint16 cpu::resolveAddress3(bool& hasCrossPage){ //a
nextInstruction[2] = mb->memRead(newState.programCounter);
++(newState.programCounter);
return (nextInstruction[2] >> 8) + nextInstruction[1];
}
Uint16 cpu::resolveAddress4(bool& hasCrossPage){ //(d),y
Uint16 tmpAddress;
tmpAddress = mb->memRead((nextInstruction[1]) + newState.reg[REG_INDEX_Y]);
if(tmpAddress > 0x00FF){
hasCrossPage = true;
}
return tmpAddress + (mb->memRead((nextInstruction[1] + state.reg[REG_INDEX_X] + 1) & 0x00FF) << 8);
}
Uint16 cpu::resolveAddress5(bool& hasCrossPage){ //d,x
return (nextInstruction[1] + state.reg[REG_INDEX_X]) & 0x00FF;
}
Uint16 cpu::resolveAddress6(bool& hasCrossPage){ //a,y
Uint16 tmpAddress;
nextInstruction[2] = mb->memRead(newState.programCounter);
++(newState.programCounter);
tmpAddress = nextInstruction[1] + newState.reg[REG_INDEX_Y];
if(tmpAddress > 0x00FF){
hasCrossPage = true;
}
return tmpAddress + mb->memRead(nextInstruction[2] << 8);
}
Uint16 cpu::resolveAddress7(bool& hasCrossPage){ //a,x
Uint16 tmpAddress;
nextInstruction[2] = mb->memRead(newState.programCounter);
++(newState.programCounter);
tmpAddress = nextInstruction[1] + newState.reg[REG_INDEX_X];
if(tmpAddress > 0x00FF){
hasCrossPage = true;
}
return tmpAddress + mb->memRead(nextInstruction[2] << 8);
}
Uint16 cpu::resolveAddress8(bool& hasCrossPage){ //d,y
return (nextInstruction[1] + state.reg[REG_INDEX_Y]) & 0x00FF;
}
void cpu::updateFlag(Uint8 flag, bool value){
if(value){
setFlag(flag);
}
else{
clearFlag(flag);
}
}
void cpu::setFlag(Uint8 flag){
newState.reg[REG_STATUS] = newState.reg[REG_STATUS] | flagMask[flag];
}
void cpu::clearFlag(Uint8 flag){
newState.reg[REG_STATUS] = newState.reg[REG_STATUS] & ~flagMask[flag];
}
bool cpu::checkFlag(Uint8 flag){
return state.reg[REG_STATUS] & flagMask[flag];
}
void cpu::runInstruction(){
if(instructionType == OP_TYPE_OUT){
mb->memWrite(outAddress, outValue);
}
else if(instructionType == OP_TYPE_BRK){
interruptJump(0xFFFE, 0xFFFF);
}
else if(instructionType == OP_TYPE_JSR){
mb->memWrite(0x0100 + newState.reg[REG_STACK_PTR], newState.programCounter >> 8);
--(newState.reg[REG_STACK_PTR]);
mb->memWrite(0x0100 + newState.reg[REG_STACK_PTR], newState.programCounter);
--(newState.reg[REG_STACK_PTR]);
newState.programCounter = ((nextInstruction[2] << 8) | nextInstruction[1]);
}
state = newState;
serviceInterrupt();
}
void cpu::reset(){
state.reg[REG_STACK_PTR] -= 3;
state.reg[REG_STATUS] = state.reg[REG_STATUS] | flagMask[FLAG_I];
state.programCounter = ((mb->memRead(0xFFFD) << 8) | mb->memRead(0xFFFC));
}
void cpu::saveState(fstream* statefile){
}
void cpu::loadState(fstream* statefile){
}
void cpu::init(){
mb = gameManager::gm->mb;
}
void cpu::init2(){
state.reg[REG_STATUS] = 0x34;
state.reg[REG_ACCUMULATOR] = 0;
state.reg[REG_INDEX_X] = 0;
state.reg[REG_INDEX_Y] = 0;
state.reg[REG_STACK_PTR] = 0xFD;
state.programCounter = ((mb->memRead(0xFFFD) << 8) | mb->memRead(0xFFFC));
for(Uint8 i = 0; i < 3; ++i){
flagNMI[i] = false;
flagIRQ[i] = false;
}
}
void cpu::pullNMILow(){
flagNMI[INTERRUPT_FLAG_IS_LOW_NEW] = true;
}
void cpu::pullIRQLow(){
flagIRQ[INTERRUPT_FLAG_IS_LOW_NEW] = true;
}
void cpu::runInterruptDetector(){
//NMI raises when becomes low or is raised already
flagNMI[INTERRUPT_FLAG_DETECTOR_OUTPUT] = ((flagNMI[INTERRUPT_FLAG_IS_LOW_NEW] && !flagNMI[INTERRUPT_FLAG_IS_LOW_OLD]) || flagNMI[INTERRUPT_FLAG_DETECTOR_OUTPUT]);
//IRQ raises when low
flagIRQ[INTERRUPT_FLAG_DETECTOR_OUTPUT] = flagIRQ[INTERRUPT_FLAG_IS_LOW_NEW];
}
void cpu::updateOldInterruptFlag(){
flagNMI[INTERRUPT_FLAG_IS_LOW_OLD] = flagNMI[INTERRUPT_FLAG_IS_LOW_NEW];
flagIRQ[INTERRUPT_FLAG_IS_LOW_OLD] = flagIRQ[INTERRUPT_FLAG_IS_LOW_NEW];
}
void cpu::serviceInterrupt(){
if(flagNMI[INTERRUPT_FLAG_DETECTOR_OUTPUT]){
flagNMI[INTERRUPT_FLAG_DETECTOR_OUTPUT] = false;
interruptJump(0xFFFA, 0xFFFB);
state = newState;
}
else if(flagIRQ[INTERRUPT_FLAG_DETECTOR_OUTPUT] && !checkFlag(FLAG_I)){
interruptJump(0xFFFE, 0xFFFF);
state = newState;
}
}
void cpu::interruptJump(Uint16 vectorL, Uint16 vectorH){
mb->memWrite(0x0100 + newState.reg[REG_STACK_PTR], newState.programCounter >> 8);
--(newState.reg[REG_STACK_PTR]);
mb->memWrite(0x0100 + newState.reg[REG_STACK_PTR], newState.programCounter);
--(newState.reg[REG_STACK_PTR]);
mb->memWrite(0x0100 + newState.reg[REG_STACK_PTR], newState.reg[REG_STATUS] | 0x30);
--(newState.reg[REG_STACK_PTR]);
newState.programCounter = ((mb->memRead(vectorH) << 8) | mb->memRead(vectorL));
setFlag(FLAG_I);
}