#include "6502.h" byte getAccumulator() { return OurComputer->cpu_inst->accumulator; }; byte getRegisterX() { return OurComputer->cpu_inst->register_x; }; byte getRegisterY() { return OurComputer->cpu_inst->register_y; }; byte getStatusRegister() { return OurComputer->cpu_inst->status_register; }; byte getStackPointer() { return OurComputer->cpu_inst->stack_pointer; }; address getProgramCounter() { return OurComputer->cpu_inst->pc; }; void setNegativeFlag() { OurComputer->cpu_inst->status_register |= 0b1 << 7; } void clearNegativeFlag() { OurComputer->cpu_inst->status_register &= ~(0b1 << 7); } byte getNegativeFlag(){ return ((OurComputer->cpu_inst->status_register) & 0b1 << 7) >> 7; } void setOverflowFlag() { OurComputer->cpu_inst->status_register |= 0b1 << 6; } void clearOverflowFlag() { OurComputer->cpu_inst->status_register &= ~(0b1 << 6); } byte getOverflowFlag(){ return ((OurComputer->cpu_inst->status_register) & 0b1 << 6) >> 6; } void setBreakFlag() { OurComputer->cpu_inst->status_register |= 0b1 << 4; } void clearBreakFlag() { OurComputer->cpu_inst->status_register &= ~(0b1 << 4); } byte getBreakFlag(){ return ((OurComputer->cpu_inst->status_register) & 0b1 << 4) >> 4; } void setIgnoreFlag() { OurComputer->cpu_inst->status_register |= 0b1 << 5; } void clearIgnoreFlag() { OurComputer->cpu_inst->status_register &= ~(0b1 << 5); } byte getIgnoreFlag(){ return ((OurComputer->cpu_inst->status_register) & 0b1 << 5) >> 5; } void setDecimalFlag() { OurComputer->cpu_inst->status_register |= 0b1 << 3; } void clearDecimalFlag() { OurComputer->cpu_inst->status_register &= ~(0b1 << 3); } byte getDecimalFlag(){ return ((OurComputer->cpu_inst->status_register) & 0b1 << 3) >> 3; } void setInterruptFlag() { OurComputer->cpu_inst->status_register |= 0b1 << 2; } void clearInterruptFlag() { OurComputer->cpu_inst->status_register &= ~(0b1 << 2); } byte getInterruptFlag(){ return ((OurComputer->cpu_inst->status_register) & 0b1 << 2) >> 2; } void setZeroFlag() { OurComputer->cpu_inst->status_register |= 0b1 << 1; } void clearZeroFlag() { OurComputer->cpu_inst->status_register &= ~(0b1 << 1); } byte getZeroFlag(){ return ((OurComputer->cpu_inst->status_register) & 0b1 << 1) >> 1; } void setCarryFlag() { OurComputer->cpu_inst->status_register |= 0b1; } void clearCarryFlag() { OurComputer->cpu_inst->status_register &= ~(0b1); } byte getCarryFlag(){ return ((OurComputer->cpu_inst->status_register) & 0b1); } address read_16(address pc) { return OurComputer->RAM[pc] | OurComputer->RAM[pc + 1] << 8; } int write_opcodes(byte a_mask) { return (a_mask == 0b110 || a_mask == 0b111 || a_mask == 0b100 || a_mask == 0b000 || a_mask == 0b001 || a_mask == 0b010 || a_mask == 0b011); } void update_PC(){ OurComputer->cpu_inst->pc = ret.pc; } void decode(byte opcode) { int a_mask, b_mask, c_mask; a_mask = (opcode & 0b11100000) >> 5; b_mask = (opcode & 0b00011100) >> 2; c_mask = opcode & 0b00000011; if (c_mask == 0b00) { switch(b_mask) { // immedate case 0: ret.arg = OurComputer->RAM[getProgramCounter() + 1]; ret.pc = getProgramCounter() + 2; break; // zeropage case 1: ret.pc = OurComputer->RAM[getProgramCounter() + 1]; if (a_mask == 0b100) { // STY ret.arg = 2; break; } ret.arg = OurComputer->RAM[ret.pc]; ret.pc = getProgramCounter() + 2; break; // absolute case 3: ret.pc = read_16(getProgramCounter() + 1); if (a_mask == 0b010) { // JMP break; } if (a_mask == 0b011) { // JMP (abs) ret.pc = read_16(ret.pc); break; } if (a_mask == 0b100) { // STY ret.arg = 3; break; } ret.arg = OurComputer->RAM[ret.pc]; ret.pc = getProgramCounter() + 3; break; // zeropage, x case 5: ret.pc = OurComputer->RAM[getProgramCounter() + 1]; ret.pc += getRegisterX(); if (a_mask == 0b100) { // STY ret.arg = 2; break; } ret.arg = OurComputer->RAM[ret.pc]; ret.pc = getProgramCounter() + 2; break; // absolute, x case 7: ret.pc = read_16(getProgramCounter() + 1); ret.pc += getRegisterX(); ret.arg = OurComputer->RAM[ret.pc]; ret.pc = getProgramCounter() + 3; break; default: break; } } else if (c_mask == 0b01) { switch(b_mask) { // (zeropage, x) case 0: ret.pc = OurComputer->RAM[getProgramCounter() + 1]; ret.pc += getRegisterX(); ret.pc = read_16(ret.pc); if (a_mask == 0b100) { // STA ret.arg = 2; break; } ret.arg = OurComputer->RAM[ret.pc]; ret.pc = getProgramCounter() + 2; break; // zeropage case 1: ret.pc = OurComputer->RAM[getProgramCounter() + 1]; if (a_mask == 0b100) { // STA ret.arg = 2; break; } ret.arg = OurComputer->RAM[ret.pc]; ret.pc = getProgramCounter() + 2; break; // immediate case 2: ret.arg = OurComputer->RAM[getProgramCounter() + 1]; ret.pc = getProgramCounter() + 2; break; // absolute case 3: ret.pc = read_16(getProgramCounter() + 1); if (a_mask == 0b100) { // STA ret.arg = 3; break; } ret.arg = OurComputer->RAM[ret.pc]; ret.pc = getProgramCounter() + 3; break; // (zeropage), y case 4: ret.pc = OurComputer->RAM[getProgramCounter() + 1]; ret.pc = read_16(ret.pc); ret.pc += getRegisterY(); ret.pc = read_16(ret.pc); if (a_mask == 0b100) { // STA ret.arg = 2; break; } ret.arg = OurComputer->RAM[ret.pc]; ret.pc = getProgramCounter() + 2; break; // zeropage, x case 5: ret.pc = OurComputer->RAM[getProgramCounter() + 1]; ret.pc += getRegisterX(); if (a_mask == 0b100) { // STA ret.arg = 2; break; } ret.arg = OurComputer->RAM[ret.pc]; ret.pc = getProgramCounter() + 2; break; // absolute, y case 6: ret.pc = read_16(getProgramCounter() + 1); ret.pc += getRegisterY(); if (a_mask == 0b100) { // STA ret.arg = 3; break; } ret.arg = OurComputer->RAM[ret.pc]; ret.pc = getProgramCounter() + 3; break; // absolute, x case 7: ret.pc = read_16(getProgramCounter() + 1); ret.pc += getRegisterX(); if (a_mask == 0b100) { // STA ret.arg = 3; break; } ret.arg = OurComputer->RAM[ret.pc]; ret.pc = getProgramCounter() + 3; break; default: break; } } else if (c_mask == 0b10) { switch(b_mask) { // immedate case 0: ret.arg = OurComputer->RAM[getProgramCounter() + 1]; ret.pc = getProgramCounter() + 2; break; // zeropage case 1: ret.pc = OurComputer->RAM[getProgramCounter() + 1]; if (write_opcodes(a_mask)) { // DEC or INC or STX or ASL or ROL or LSR or ROR ret.arg = 2; break; } ret.arg = OurComputer->RAM[ret.pc]; ret.pc = getProgramCounter() + 2; break; // accumulator case 2: ret.arg = getAccumulator(); ret.pc = getProgramCounter() + 1; break; // absolute case 3: ret.pc = read_16(getProgramCounter() + 1); if (write_opcodes(a_mask)) { // DEC or INC or STX or ASL or ROL or LSR or ROR ret.arg = 3; break; } ret.arg = OurComputer->RAM[ret.pc]; ret.pc = getProgramCounter() + 3; break; // zeropage, x case 5: ret.pc = OurComputer->RAM[getProgramCounter() + 1]; if (a_mask == 0b100 || a_mask == 0b101){ // STX or LDX ret.pc += getRegisterY(); } else{ ret.pc += getRegisterX(); } if (write_opcodes(a_mask)) { // DEC or INC or STX or ASL or ROL or LSR or ROR ret.arg = 2; break; } ret.arg = OurComputer->RAM[ret.pc]; ret.pc = getProgramCounter() + 2; break; // absolute, x case 7: ret.pc = read_16(getProgramCounter() + 1); if (a_mask == 0b100 || a_mask == 0b101){ // STX or LDX ret.pc += getRegisterY(); } else{ ret.pc += getRegisterX(); } if (write_opcodes(a_mask)) { // DEC or INC or STX or ASL or ROL or LSR or ROR ret.arg = 3; break; } ret.arg = OurComputer->RAM[ret.pc]; ret.pc = getProgramCounter() + 3; break; default: break; } } return; } void stack_push(byte val){ if(OurComputer->cpu_inst->stack_pointer == 0){ printf("Stack full"); exit(-1); } address stack_ptr = 1U << 8 | OurComputer->cpu_inst->stack_pointer; OurComputer->RAM[stack_ptr] = val; OurComputer->cpu_inst->stack_pointer--; } byte stack_pull(){ if(OurComputer->cpu_inst->stack_pointer == 0xFF){ printf("Stack empty"); exit(-1); } OurComputer->cpu_inst->stack_pointer++; address stack_ptr = 1U << 8 | OurComputer->cpu_inst->stack_pointer; return OurComputer->RAM[stack_ptr]; } // May need to figure out how to adjust bases for decimal, binary addition /* // set carry flag if result bigger than max value // in decimal mode if(getDecimalFlag()){ if(res > 99){ setCarryFlag(); }else{ clearCarryFlag(); } } // in binary (normal) mode else{ if(res > 255){ setCarryFlag(); }else{ clearCarryFlag(); } }*/ void ADC(byte opcode, address pc) { decode(opcode); // pull high bits to test for overflow later byte acc_hi = ((getAccumulator() & 0x80) >> 7); byte arg_hi = ((ret.arg & 0x80) >> 7); // perform addition, cull result to 2 bytes int16_t res = (int16_t) (getAccumulator() + ret.arg); printf("res = %d \n", res); printf("ret.arg = %d \n", ret.arg); printf("Accumulator = %u \n", getAccumulator()); OurComputer->cpu_inst->accumulator = (byte) (res & 0x00ff); // add 1 if carry flag set if(getCarryFlag()){ OurComputer->cpu_inst->accumulator += 1; res += 1; } if(res > 255){ setCarryFlag(); }else{ clearCarryFlag(); } // pull high bits of result to test for overflow byte res_hi = ((getAccumulator() & 0x80) >> 7); if(acc_hi == arg_hi && acc_hi != res_hi){ setOverflowFlag(); }else{ clearOverflowFlag(); } // test high bit of result to see if negative if(res_hi){ setNegativeFlag(); }else{ clearNegativeFlag(); } // if result is 0, set zero flag if(getAccumulator() == 0x00){ setZeroFlag(); }else{ clearZeroFlag(); } update_PC(); } void AND(byte opcode, address pc) { decode(opcode); OurComputer->cpu_inst->accumulator &= ret.arg; if(OurComputer->cpu_inst->accumulator == 0){ setZeroFlag(); } else{ clearZeroFlag(); } if((OurComputer->cpu_inst->accumulator >> 7) & 1){ setNegativeFlag(); } else{ clearNegativeFlag(); } update_PC(); } void ASL(byte opcode, address pc) { byte inp; decode(opcode); if (opcode == 0xa) { inp = ret.arg; } else { inp = OurComputer->RAM[ret.pc]; } // set carry (with 0th bit) printf("inp = %u \n", inp); clearCarryFlag(); OurComputer->cpu_inst->status_register |= (inp >> 7); // perform shift inp = inp << 1; printf("inp = %u \n", inp); // set zero if(inp == 0){ setZeroFlag(); } else{ clearZeroFlag(); } // get high bit of result to set negative byte res_hi = inp >> 7; // set negative if(res_hi){ setNegativeFlag(); } else{ clearNegativeFlag(); } // check opcode to see if using accumulator if(opcode == 0xa){ printf("inp = %u \n", inp); printf("Accumulator = %u \n", OurComputer->cpu_inst->accumulator); OurComputer->cpu_inst->accumulator = inp; OurComputer->cpu_inst->pc++; } else{ OurComputer->RAM[ret.pc] = inp; OurComputer->cpu_inst->pc += ret.arg; } } // BCC - branch on Carry Flag = 0 void BCC(byte opcode, address pc){ if (!getCarryFlag()) { OurComputer->cpu_inst->pc += OurComputer->RAM[pc + 1]; } OurComputer->cpu_inst->pc += 2; return; } // BCS - branch on Carry Flag = 1 void BCS(byte opcode, address pc){ if (getCarryFlag()) { OurComputer->cpu_inst->pc += OurComputer->RAM[pc + 1]; } OurComputer->cpu_inst->pc += 2; return; } // BEQ - branch on Zero Flag = 1 void BEQ(byte opcode, address pc) { if (getZeroFlag()) { OurComputer->cpu_inst->pc += OurComputer->RAM[pc + 1]; } OurComputer->cpu_inst->pc += 2; return; } void BIT(byte opcode, address pc) { decode(opcode); int BIT6_mask = 0b1 << 6; int BIT7_mask = 0b1 << 7; clearOverflowFlag(); clearNegativeFlag(); clearZeroFlag(); OurComputer->cpu_inst->status_register |= (((BIT6_mask & ret.arg) >> 6) << 6) ; OurComputer->cpu_inst->status_register |= (((BIT7_mask & ret.arg) >> 7) << 7) ; OurComputer->cpu_inst->status_register |= (((OurComputer->cpu_inst->accumulator & ret.arg) & 0b10)); update_PC(); return; } void CLC(byte opcode, address pc) { clearCarryFlag(); OurComputer->cpu_inst->pc++; // update PC return; } // BMI - branch on Negative Flag = 1 void BMI (byte opcode, address pc) { if (getNegativeFlag()) { OurComputer->cpu_inst->pc += OurComputer->RAM[pc + 1]; } OurComputer->cpu_inst->pc += 2; return; } // BNE - branch on Zero Flag = 0 void BNE (byte opcode, address pc) { if (!getZeroFlag()) { OurComputer->cpu_inst->pc += OurComputer->RAM[pc + 1]; } OurComputer->cpu_inst->pc += 2; return; } // BPL - branch on Negative Flag = 0 void BPL (byte opcode, address pc) { if (!getNegativeFlag()) { OurComputer->cpu_inst->pc += OurComputer->RAM[pc + 1]; } OurComputer->cpu_inst->pc += 2; return; } //BVC - branch on Overflow = 0 void BVC (byte opcode, address pc) { if (getOverflowFlag() == 0) { OurComputer->cpu_inst->pc += OurComputer->RAM[pc + 1]; } OurComputer->cpu_inst->pc+=2; } // BVS - branch on Overflow = 1 void BVS (byte opcode, address pc) { if(getOverflowFlag() == 1) { OurComputer->cpu_inst->pc += OurComputer->RAM[pc + 1]; } OurComputer->cpu_inst->pc+=2; } void CLD(byte opcode, address pc) { clearDecimalFlag(); OurComputer->cpu_inst->pc++; // update PC } void CLI(byte opcode, address pc) { clearInterruptFlag(); OurComputer->cpu_inst->pc++; // update PC } void CLV(byte opcode, address pc) { clearOverflowFlag(); OurComputer->cpu_inst->pc++; // update PC } /* The use of the CMP affects the following flags: Z flag is set on an equal comparison, reset otherwise; the N flag is Set or reset by the result bit 7, the carry flag is Set when the value in memory is less than or equal to the accumulator, reset when it is greater than the accumulator. */ void CMP(byte opcode, address pc) { decode(opcode); byte res = getAccumulator() - ret.arg; if (res == 0) { setZeroFlag(); } else { clearZeroFlag(); } if ((res >> 7) & 0b1 ){ setNegativeFlag(); } else{ clearNegativeFlag(); } if (ret.arg <= getAccumulator()){ setCarryFlag(); } else{ clearCarryFlag(); } update_PC(); } /* The CPX instruction does not affect any register in the machine; it also does not affect the overflow flag. It causes the carry to be set on if the absolute value of the index register X is equal to or greater than the data from memory. If the value of the memory is greater than the content of the index register X, carry is reset. If the results of the subtraction contain a bit 7, then the N flag is set, if not, it is reset. If the value in memory is equal to the value in index register X, the Z flag is set, otherwise it is reset. */ void CPX(byte opcode, address pc) { decode(opcode); byte res = getRegisterX() - ret.arg; printf("res = %d \n", res); printf("ret.arg = %d \n", ret.arg); printf("Register x = %u \n", getRegisterX()); printf("7th bit = %u \n", (res >> 7U) & 0b1); if(abs( (int8_t) getRegisterX()) >= ret.arg){ setCarryFlag(); } else{ clearCarryFlag(); } if ((res >> 7) & 0b1) { setNegativeFlag(); } else { clearNegativeFlag(); } if (res == 0) { setZeroFlag(); } else { clearZeroFlag(); } update_PC(); } /* If the value in the index register Y is equal to or greater than the value in the memory, the carry flag will be set, otherwise it will be cleared. If the results of the subtract- tion contain bit 7 on the N bit will be set, otherwise it will be cleared. If the value in the index register Y and the value in the memory are equal, the zero flag will be set, otherwise it will be cleared.*/ void CPY(byte opcode, address pc) { decode(opcode); byte res = getRegisterY() - ret.arg; if(abs( (int8_t) getRegisterY()) >= ret.arg){ setCarryFlag(); } else{ clearCarryFlag(); } if((res >> 7) & 0b1){ setNegativeFlag(); } else { clearNegativeFlag(); } if (res == 0) { setZeroFlag(); } else { clearZeroFlag(); } update_PC(); } //Flags: N+ Z+ void DEC(byte opcode, address pc) { decode(opcode); OurComputer->RAM[ret.pc] -= 1; //set flags if ((OurComputer->RAM[ret.pc] & (0b1 << 7)) >> 7 ) { setNegativeFlag(); } else { clearNegativeFlag(); } if (OurComputer->RAM[ret.pc] == 0) { setZeroFlag(); } else { clearZeroFlag(); } OurComputer->cpu_inst->pc += ret.arg; // update PC } void DEX(byte opcode, address pc) { OurComputer->cpu_inst->register_x -= 1; if((OurComputer->cpu_inst->register_x >> 7) & 0b1){ setNegativeFlag(); } else { clearNegativeFlag(); } if (OurComputer->cpu_inst->register_x == 0) { setZeroFlag(); } else { clearZeroFlag(); } OurComputer->cpu_inst->pc++; } void DEY(byte opcode, address pc) { OurComputer->cpu_inst->register_y -= 1; if((OurComputer->cpu_inst->register_y >> 7) & 0b1){ setNegativeFlag(); } else { clearNegativeFlag(); } if (OurComputer->cpu_inst->register_y == 0) { setZeroFlag(); } else { clearZeroFlag(); } OurComputer->cpu_inst->pc++; } //Flags: N+ Z+ void INC(byte opcode, address pc) { decode(opcode); OurComputer->RAM[ret.pc] += 1; //set flags if ((OurComputer->RAM[ret.pc] & (0b1 << 7)) >> 7 ) { setNegativeFlag(); } else { clearNegativeFlag(); } if (OurComputer->RAM[ret.pc] == 0) { setZeroFlag(); } else { clearZeroFlag(); } OurComputer->cpu_inst->pc += ret.arg; // update PC } void INX(byte opcode, address pc) { OurComputer->cpu_inst->register_x += 1; if((OurComputer->cpu_inst->register_x >> 7) & 0b1){ setNegativeFlag(); } else { clearNegativeFlag(); } if (OurComputer->cpu_inst->register_x == 0) { setZeroFlag(); } else { clearZeroFlag(); } OurComputer->cpu_inst->pc++; } void INY(byte opcode, address pc) { OurComputer->cpu_inst->register_y += 1; if((OurComputer->cpu_inst->register_y >> 7) & 0b1){ setNegativeFlag(); } else { clearNegativeFlag(); } if (OurComputer->cpu_inst->register_y == 0) { setZeroFlag(); } else { clearZeroFlag(); } OurComputer->cpu_inst->pc++; } void EOR(byte opcode, address pc) { decode(opcode); OurComputer->cpu_inst->accumulator ^= ret.arg; if((OurComputer->cpu_inst->accumulator >> 7) & 0b1){ setNegativeFlag(); } else { clearNegativeFlag(); } if (OurComputer->cpu_inst->accumulator == 0) { setZeroFlag(); } else { clearZeroFlag(); } update_PC(); } void LDA(byte opcode, address pc) { decode(opcode); OurComputer->cpu_inst->accumulator = ret.arg; if(OurComputer->cpu_inst->accumulator == 0){ setZeroFlag(); } else{ clearZeroFlag(); } if(OurComputer->cpu_inst->accumulator >> 7){ setNegativeFlag(); } else{ clearNegativeFlag(); } update_PC(); } void LDX(byte opcode, address pc) { decode(opcode); OurComputer->cpu_inst->register_x = ret.arg; if(OurComputer->cpu_inst->register_x == 0){ setZeroFlag(); } else{ clearZeroFlag(); } if((OurComputer->cpu_inst->register_x >> 7) & 1){ setNegativeFlag(); } else{ clearNegativeFlag(); } update_PC(); } void LDY(byte opcode, address pc) { decode(opcode); OurComputer->cpu_inst->register_y = ret.arg; if(OurComputer->cpu_inst->register_y == 0){ setZeroFlag(); } else{ clearZeroFlag(); } if((OurComputer->cpu_inst->register_y >> 7) & 1){ setNegativeFlag(); } else{ clearNegativeFlag(); } update_PC(); } void NOP(byte opcode, address pc) { OurComputer->cpu_inst->pc += 1; // update PC } void ORA(byte opcode, address pc) { decode(opcode); OurComputer->cpu_inst->accumulator |= ret.arg; if(OurComputer->cpu_inst->accumulator == 0){ setZeroFlag(); } else{ clearZeroFlag(); } if((OurComputer->cpu_inst->accumulator >> 7) & 1){ setNegativeFlag(); } else{ clearNegativeFlag(); } update_PC(); } // N+ Z+ C+ void ROL(byte opcode, address pc) { decode(opcode); byte rotated; byte carry = getCarryFlag(); clearCarryFlag(); if(opcode == 0x2a){ OurComputer->cpu_inst->status_register |= OurComputer->cpu_inst->accumulator >> 7; OurComputer->cpu_inst->accumulator = OurComputer->cpu_inst->accumulator << 1U; rotated = OurComputer->cpu_inst->accumulator | carry ; OurComputer->cpu_inst->accumulator = rotated; } else{ // memory OurComputer->cpu_inst->status_register |= OurComputer->RAM[ret.pc] >> 7; OurComputer->RAM[ret.pc] = OurComputer->RAM[ret.pc] << 1U; //shift OurComputer->RAM[ret.pc] over one bit rotated = OurComputer->RAM[ret.pc] | carry; OurComputer->RAM[ret.pc] = rotated; //move carry into the 7th bit } if( rotated >> 7 ) { setNegativeFlag(); } else { clearNegativeFlag(); } if (rotated == 0) { setZeroFlag(); } else { clearZeroFlag(); } if (opcode == 0x2a) { OurComputer->cpu_inst->pc++; } else { OurComputer->RAM[ret.pc] += ret.arg; } } //void ROR(byte opcode, byte* pc) {decode(opcode); rotate *ret.arg by 1 bit right}; void ROR(byte opcode, address pc) { decode(opcode); byte rotated; byte carry = getCarryFlag(); clearCarryFlag(); if(opcode == 0x6a){ OurComputer->cpu_inst->status_register |= OurComputer->cpu_inst->accumulator & 1; OurComputer->cpu_inst->accumulator = OurComputer->cpu_inst->accumulator >> 1U; rotated = (carry << 7) | OurComputer->cpu_inst->accumulator; OurComputer->cpu_inst->accumulator = rotated; } else{ // memory OurComputer->cpu_inst->status_register |= OurComputer->RAM[ret.pc] & 1; OurComputer->RAM[ret.pc] = OurComputer->RAM[ret.pc] >> 1; //shift OurComputer->RAM[ret.pc] over one bit rotated = (carry << 7) | OurComputer->RAM[ret.pc]; OurComputer->RAM[ret.pc] = rotated; //move carry into the 7th bit } if(rotated >> 7) { setNegativeFlag(); } else { clearNegativeFlag(); } if (rotated == 0) { setZeroFlag(); } else { clearZeroFlag(); } if (opcode == 0x6a) { OurComputer->cpu_inst->pc++; } else { OurComputer->RAM[ret.pc] += ret.arg; } } void SBC(byte opcode, address pc) { decode(opcode); // pull high bits to test for overflow later ret.arg = ~(ret.arg); byte acc_hi = ((getAccumulator() & 0x80) >> 7); byte arg_hi = ((ret.arg & 0x80) >> 7); // perform addition, cull result to 2 bytes int16_t res = (int16_t) (getAccumulator() + ret.arg); printf("res = %d \n", res); printf("ret.arg = %d \n", ret.arg); printf("Accumulator = %u \n", getAccumulator()); OurComputer->cpu_inst->accumulator = (byte) (res & 0x00ff); // add 1 if carry flag set if(getCarryFlag()){ OurComputer->cpu_inst->accumulator += 1; res += 1; } if(res > 255){ setCarryFlag(); }else{ clearCarryFlag(); } // pull high bits of result to test for overflow byte res_hi = ((getAccumulator() & 0x80) >> 7); if(acc_hi == arg_hi && acc_hi != res_hi){ setOverflowFlag(); }else{ clearOverflowFlag(); } // test high bit of result to see if negative if(res_hi){ setNegativeFlag(); }else{ clearNegativeFlag(); } // if result is 0, set zero flag if(getAccumulator() == 0x00){ setZeroFlag(); }else{ clearZeroFlag(); } update_PC(); } void SEC(byte opcode, address pc) { setCarryFlag(); OurComputer->cpu_inst->pc++; // update PC } void SED(byte opcode, address pc) { setDecimalFlag(); OurComputer->cpu_inst->pc++; // update PC } void SEI(byte opcode, address pc) { setInterruptFlag(); OurComputer->cpu_inst->pc++; } void STA(byte opcode, address pc) { decode(opcode); OurComputer->RAM[ret.pc] = getAccumulator(); OurComputer->cpu_inst->pc += ret.arg; } void STX(byte opcode, address pc) { decode(opcode); OurComputer->RAM[ret.pc] = getRegisterX(); OurComputer->cpu_inst->pc += ret.arg; } void STY(byte opcode, address pc) { decode(opcode); OurComputer->RAM[ret.pc] = getRegisterY(); OurComputer->cpu_inst->pc += ret.arg; } void TAX(byte opcode, address pc) { OurComputer->cpu_inst->register_x = getAccumulator(); if(OurComputer->cpu_inst->register_x == 0){ setZeroFlag(); } else{ clearZeroFlag(); } if((OurComputer->cpu_inst->register_x >> 7) & 1){ setNegativeFlag(); } else{ clearNegativeFlag(); } OurComputer->cpu_inst->pc++; // update PC } void TAY(byte opcode, address pc) { OurComputer->cpu_inst->register_y = getAccumulator(); if(OurComputer->cpu_inst->register_y == 0){ setZeroFlag(); } else{ clearZeroFlag(); } if((OurComputer->cpu_inst->register_y >> 7) & 1){ setNegativeFlag(); } else{ clearNegativeFlag(); } OurComputer->cpu_inst->pc++; // update PC } void TSX(byte opcode, address pc) { OurComputer->cpu_inst->register_x = getStackPointer(); if(OurComputer->cpu_inst->register_x == 0){ setZeroFlag(); } else{ clearZeroFlag(); } if((OurComputer->cpu_inst->register_x >> 7) & 1){ setNegativeFlag(); } else{ clearNegativeFlag(); } OurComputer->cpu_inst->pc++; // update PC } void TXA(byte opcode, address pc) { OurComputer->cpu_inst->accumulator = getRegisterX(); if(OurComputer->cpu_inst->accumulator == 0){ setZeroFlag(); } else{ clearZeroFlag(); } if((OurComputer->cpu_inst->accumulator >> 7) & 1){ setNegativeFlag(); } else{ clearNegativeFlag(); } OurComputer->cpu_inst->pc++; // update PC } void TXS(byte opcode, address pc) { OurComputer->cpu_inst->stack_pointer = getRegisterX(); OurComputer->cpu_inst->pc++; // update PC } void TYA(byte opcode, address pc) { OurComputer->cpu_inst->accumulator = getRegisterY(); if(OurComputer->cpu_inst->accumulator == 0){ setZeroFlag(); } else{ clearZeroFlag(); } if((OurComputer->cpu_inst->accumulator >> 7) & 1){ setNegativeFlag(); } else{ clearNegativeFlag(); } OurComputer->cpu_inst->pc++; // update PC } void JMP(byte opcode, address pc) { decode(opcode); OurComputer->cpu_inst->pc = ret.pc; return; } void LSR(byte opcode, address pc) { byte inp; decode(opcode); if (opcode == 0x4a) { inp = ret.arg; } else { inp = OurComputer->RAM[ret.pc]; } // get low bit of input to set carry byte inp_low = inp & 0x01; // set carry (with 0th bit) printf("inp = %u \n", inp); clearCarryFlag(); OurComputer->cpu_inst->status_register |= inp_low; // perform shift inp = inp >> 1; printf("inp = %u \n", inp); // set zero if(inp == 0){ setZeroFlag(); } else{ clearZeroFlag(); } // get high bit of result to set negative byte res_hi = inp >> 7; // set negative if(res_hi){ setNegativeFlag(); } else{ clearNegativeFlag(); } // check opcode to see if using accumulator if(opcode == 0x4a){ printf("inp = %u \n", inp); printf("Accumulator = %u \n", OurComputer->cpu_inst->accumulator); OurComputer->cpu_inst->accumulator = inp; OurComputer->cpu_inst->pc++; } else{ OurComputer->RAM[ret.pc] = inp; OurComputer->cpu_inst->pc += ret.arg; } } void PHP(byte opcode, address pc) { setBreakFlag(); setIgnoreFlag(); stack_push(getStatusRegister()); OurComputer->cpu_inst->pc++; return; } void PLP(byte opcode, address pc) { OurComputer->cpu_inst->status_register = stack_pull(); clearBreakFlag(); //clearIgnoreFlag(); OurComputer->cpu_inst->pc++; return; } void PHA(byte opcode, address pc) { stack_push(getAccumulator()); OurComputer->cpu_inst->pc++; return; } void PLA(byte opcode, address pc) { OurComputer->cpu_inst->accumulator = stack_pull(); if((OurComputer->cpu_inst->accumulator & 1 << 7)){ // if 7th bit is set in accumulator setNegativeFlag(); } else{ clearNegativeFlag(); } if(OurComputer->cpu_inst->accumulator == 0){ setZeroFlag(); } else{ clearZeroFlag(); } OurComputer->cpu_inst->pc++; return; } void RTI(byte opcode, address pc) { byte PCLOW, PCHIGH; OurComputer->cpu_inst->status_register = stack_pull(); //PCHIGH = stack_pull(); PCLOW = stack_pull() - 1; PCHIGH = stack_pull(); OurComputer->cpu_inst->pc = PCHIGH << 8 | PCLOW; OurComputer->cpu_inst->pc++; return; } void RTS(byte opcode, address pc) { byte PCLOW, PCHIGH; //PCHIGH = stack_pull(); PCLOW = stack_pull() - 1; PCHIGH = stack_pull(); OurComputer->cpu_inst->pc = PCHIGH << 8 | PCLOW; OurComputer->cpu_inst->pc += 2; return; } void BRK(byte opcode, address pc) { setBreakFlag(); setInterruptFlag(); // software interrupt byte PCLOW, PCHIGH; PCHIGH = (getProgramCounter()) >> 8; PCLOW = 0x00FF & (getProgramCounter() + 2); stack_push(PCHIGH); stack_push(PCLOW); stack_push(getStatusRegister()); return; } void JSR(byte opcode, address pc) { byte PCLOW, PCHIGH; PCHIGH = (getProgramCounter()) >> 8; PCLOW = 0x00FF & (getProgramCounter() + 2); stack_push(PCHIGH); stack_push(PCLOW); OurComputer->cpu_inst->pc = read_16(getProgramCounter() + 1); return; }