// addressing.h // Contains definitions relevant to addressing, as well as fAddress() which returns time, length, value, and address for an instruction function call. enum Addressing { eImmediate, eAccumulator, eZeroPage, eZeroPageIndexedX, eZeroPageIndexedY, eAbsolute, eAbsoluteIndexedX, eAbsoluteIndexedY, eIndexedIndirect, eIndirectIndexed, eImplied, eIndirectAbsolute, eRelative }; typedef int Addressing; //Holds address of current instruction. void (*current_instruction)(Addressing, address); struct AddData{ int cycles; int length; address add; byte value; }; AddData fAddress(Addressing addr, short x) { AddData ret; // ADDRESS switch(addr){ case eImplied: case eIndirectAbsolute: case eRelative: break; case eAbsolute: ret.add = x; break; case eAbsoluteIndexedX: ret.add = (x + X); break; case eAbsoluteIndexedY: ret.add = (x + Y); break; case eZeroPage: ret.add = (x & 0x00FF); break; case eZeroPageIndexedX: ret.add = ((x + X) & 0x00FF); break; case eZeroPageIndexedY: ret.add = ((x + Y) & 0x00FF); break; case eIndexedIndirect: ret.add = (((address)Memory[x+X+1])<<8) + (Memory[x+X]); break; case eIndirectIndexed: ret.add = (((address)Memory[x+1])<<8) + (Memory[x]) + Y; break; } // VALUE switch(addr){ case eImplied: case eIndirectAbsolute: case eRelative: break; case eImmediate: ret.value = x; break; case eAccumulator: ret.value = acc; break; default: ret.value = Memory[ret.add] } // LENGTH switch(addr){ case eAbsolute: case eAbsoluteIndexedX: case eAbsoluteIndexedY: ret.length = 3; break; case eAccumulator: ret.length = 1; break; default: ret.length = 2; break; } // CYCLES switch(current_function){ // Initial value case &fADC: case &fAND: case &fBIT: case &fCMP: case &fCPX: case &fCPY: case &fEOR: case &fLDA: case &fLDX: case &fLDY: case &fORA: case &fSBC: case &fSTX: case &fSTY: switch(addr){ case eImmediate: ret.cycles = 2; break; case eZeroPage: ret.cycles = 3; break; case eZeroPageIndexedX: case eAbsolute: case eAbsoluteIndexedX: case eAbsoluteIndexedY: ret.cycles = 4; break; case eIndexedIndirect: ret.cycles = 6; break; case eIndirectIndexed: ret.cycles = 5; break; } break; case &fASL: case &fDEC: case &fINC: case &fLSR: case &fROL: case &fROR: switch(addr){ case eAccumulator: ret.cycles = 2; break; case eZeroPage: ret.cycles = 5; break; case eZeroPageIndexedX: case eAbsolute: ret.cycles = 6; break; case eAbsoluteIndexedX: ret.cycles = 7; break; } break; case &fSTA: switch(addr){ case eZeroPage: ret.cycles = 3; break; case eZeroPageIndexedX: case eAbsolute: ret.cycles = 4; break; case eAbsoluteIndexedX: case eAbsoluteIndexedY: ret.cycles = 5; break; case eIndexedIndirect: case eIndirectIndexed: ret.cycles = 6; break; } break; case &fBRK: ret.cycles = 7; break; case &RTI: case &RTS: case &JSR: ret.cycles = 6; break; case &fJMP: ret.cycles = 5; break; case &fPLA: case &fPLP: ret.cycles = 4; break; case &fPHA: case &fPHP: ret.cycles = 3; break; default: ret.cycles = 2; } switch(current_function){ // Page Boundary case &fADC: case &fSBC: case &fLDA: case &fLDX: case &fLDY: case &fEOR: case &fAND: case &fORA: case &fCMP: switch(addr){ case eAbsoluteIndexedX: if ((x & 0xFFFC) != ((x + X) & 0xFFFC)) ret.cycles++; break; case eAbsoluteIndexedY: if ((x & 0xFFFC) != ((x + Y) & 0xFFFC)) ret.cycles++; break; case eIndirectIndexed: if ((ret.add & 0xFFFC) != (ret.add - Y & 0xFFFC)) ret.cycles++; break; } } }