#include "6502.h" #include "mem.h" #include "debug.h" namespace cpu6502 { static uint32_t clock = 0; static uint32_t t = 0; // P register Flags #define fC 0b00000001 // Carry #define fZ 0b00000010 // Zero #define fI 0b00000100 // Interrupt disable #define fD 0b00001000 // Decimal #define fB 0b00010000 // Interrupt type? #define f1 0b00100000 // -Unused- #define fV 0b01000000 // Overflow #define fN 0b10000000 // Negative // Jump types #define cUnconditional 255 #define cNZ 0 #define cZ 1 #define cNC 2 #define cC 3 #define cNN 4 #define cN 5 #define cNV 6 #define cV 7 // Addressing modes #define aAccumulator 0 #define aImmediate 1 #define aZeroPage 2 #define aZeroPageX 3 #define aZeroPageY 4 #define aRelative 5 #define aIndirect 6 #define aIndirectX 7 #define aIndirectY 8 #define aAbsolute 9 #define aAbsoluteX 10 #define aAbsoluteY 11 uint8_t regs[7]; uint8_t *_rA = ®s[0]; uint8_t *_rX = ®s[1]; uint8_t *_rY = ®s[2]; uint8_t *_rS = ®s[3]; uint8_t *_rP = ®s[4]; uint16_t *_rPC = (uint16_t*)®s[5]; #define rA (*_rA) #define rX (*_rX) #define rY (*_rY) #define rS (*_rS) #define rP (*_rP) #define rPC (*_rPC) bool reading_m1 = false; uint8_t READ_MEM_8(const uint16_t addr, const bool code=false) { if (debug::isbreak(addr, 2)) debug::stop(); t+=1; //[TODO] const uint8_t tag = mem::getTag(addr); if ( !(tag&MEMTAG_IGNORE) ) { if (!code) { if ( tag & MEMTAG_INST ) { } else { mem::setTag(addr, tag | MEMTAG_DATA); } } else { if ( (reading_m1) && ( tag & MEMTAG_DATA ) ) { } } } reading_m1 = false; return mem::readMem(addr); } uint8_t READ_MEM_8() { const uint8_t data = READ_MEM_8(rPC, true); const uint8_t tag = mem::getTag(rPC); if ( !(tag & MEMTAG_IGNORE) ) mem::setTag(rPC, tag | MEMTAG_CODE); rPC++; return data; } uint8_t READ_M1() { reading_m1 = true; return READ_MEM_8(); } uint16_t READ_MEM_16() { const uint8_t L = READ_MEM_8(); const uint8_t H = READ_MEM_8(); return (H << 8) + L; } uint16_t READ_MEM_16(const uint16_t addr) { return READ_MEM_8(addr) + (READ_MEM_8(addr+1) << 8); } const uint8_t WRITE_MEM_8(const uint16_t addr, const uint8_t value) { t+=1; // [TODO] mem::writeMem(addr, value); if (debug::isbreak(addr, 4)) debug::stop(); debug::setmemmodified(addr); const uint8_t tag = mem::getTag(addr); if ( !(tag & MEMTAG_IGNORE) ) { if ( tag & MEMTAG_INST ) { //printf("WARNING! WRITING DATA OVER CODE!!! $%4X\n", addr); //z80debug::stop(); } else { mem::setTag(addr, tag | MEMTAG_DATA | MEMTAG_TDATA); } } return value; } void WRITE_MEM_16(const uint16_t addr, const uint16_t value) { WRITE_MEM_8(addr, value & 0xff); WRITE_MEM_8(addr+1, (value>>8) & 0xff); } void reset() { mem::reset(); rPC = 0x00; rA = rX = rY = rS = rP = 0xff; t = 0; } void interrupt(uint8_t type) { } void BRK() { rPC++; WRITE_MEM_16(0x0100+rS, rPC); rS-=2; WRITE_MEM_8(0x0100+rS, rP|f1|fB); rS--; rP |= fI; rPC = READ_MEM_16(0xfffe); t++; } void ORA(uint8_t addr_mode) { } uint32_t step() { t = 0; uint16_t current_opcode_address = rPC; const uint8_t opcode = READ_M1(); uint8_t tag = mem::getTag(current_opcode_address); if ( !(tag & MEMTAG_IGNORE) ) tag = tag | MEMTAG_INST; mem::setTag(current_opcode_address, tag | (!(tag&MEMTAG_TOUCHED) ? MEMTAG_TREPEAT : MEMTAG_TINST) ); uint16_t tmp; switch (opcode) { case 0x00: BRK(); break; case 0x01: ORA(aIndirectX); break; }; // [TODO] Gestionar interrupcions //debug::setcursor(rPC); //debug::history::store(); mem::update_mapped(t); return t; } }