// 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; struct AddData{ int cycles; int length; address add; byte value; }; typedef struct AddData AddData; #include"instructions-init.h" //Holds address of current instruction. void* current_instruction; int fAddressGetLength(Addressing addr){ switch(addr){ case eAbsolute: case eAbsoluteIndexedX: case eAbsoluteIndexedY: return 3; case eAccumulator: return 1; default: return 2; } } int fAddressGetLengthPrempt(int i){ //Check the functions to make sure that there isnt some incorrect values being given for length. switch(i){ case 0x6D: case 0x7D: case 0x79: case 0x2D: case 0x3D: case 0x39: case 0x0E: case 0x1E: case 0x2C: case 0xCD: case 0xD0: case 0xD9: case 0xEC: case 0xCC: case 0xCE: case 0xDE: case 0x4D: case 0x5D: case 0x59: case 0xEE: case 0xFE: case 0x4C: case 0x20: case 0xAD: case 0xBD: case 0xB9: case 0xAE: case 0xBE: case 0xAC: case 0xBC: case 0x4E: case 0x5E: case 0x0D: case 0x1D: case 0x19: case 0x2E: case 0x3E: case 0x6E: case 0x7E: case 0xED: case 0xFD: case 0xF9: case 0x8D: case 0x9D: case 0x99: case 0x8E: case 0x8C: return 3; case 0x0A: case 0x2A: case 0x4A: case 0x6A: return 1; default: return 2; } } AddData fAddress(Addressing addr, short x) { AddData ret; // ADDRESS switch(addr){ case eImplied: case eIndirectAbsolute: case eRelative: case eImmediate: case eAccumulator: ret.add = 0x0000; 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 ret.length = fAddressGetLength(addr); // CYCLES //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: if ( current_instruction == &fADC || current_instruction == &fAND || current_instruction == &fBIT || current_instruction == &fCMP || current_instruction == &fCPX || current_instruction == &fCPY || current_instruction == &fEOR || current_instruction == &fLDA || current_instruction == &fLDX || current_instruction == &fLDY || current_instruction == &fORA || current_instruction == &fSBC || current_instruction == &fSTX || current_instruction == &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; } } //case &fASL: case &fDEC: case &fINC: case &fLSR: case &fROL: case &fROR: else if( current_instruction == &fASL || current_instruction == &fDEC || current_instruction == &fINC || current_instruction == &fLSR || current_instruction == &fROL || current_instruction == &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; } } //case &fSTA: else if (current_instruction == &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; } } //case &fBRK: else if (current_instruction == &fBRK){ ret.cycles = 7; } //case &fRTI: case &fRTS: case &fJSR: else if (current_instruction == &fRTI || current_instruction == &fRTS || current_instruction == &fJSR){ ret.cycles = 6; } //case &fJMP: else if (current_instruction == &fJMP){ ret.cycles = 5; } //case &fPLA: case &fPLP: else if (current_instruction == &fPLA || current_instruction == &fPLP){ ret.cycles = 4; } //case &fPHA: case &fPHP: else if (current_instruction == &fPHA || current_instruction == &fPHP){ ret.cycles = 3; } else { ret.cycles = 2; } // Page Boundary //case &fADC: case &fSBC: case &fLDA: case &fLDX: case &fLDY: case &fEOR: case &fAND: case &fORA: case &fCMP: if ( current_instruction == &fADC || current_instruction == &fSBC || current_instruction == &fLDA || current_instruction == &fLDX || current_instruction == &fLDY || current_instruction == &fEOR || current_instruction == &fAND || current_instruction == &fORA || current_instruction == &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; } } return ret; }