void full_step(uint16_t *a, uint8_t *d, BOOL *r_w) { step(); step(); *a = readAddressBus(); *d = readDataBus(); *r_w = isNodeHigh(rw); } #define RESET 0xF000 #define A_OUT 0xF100 #define X_OUT 0xF101 #define Y_OUT 0xF102 #define S_OUT 0xF103 #define P_OUT 0xF104 #define TRIGGER1 0x5555 uint16_t trigger2; #define TRIGGER3 0xAAAA void setup_memory(int length, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t A, uint8_t X, uint8_t Y, uint8_t S, uint8_t P) { bzero(memory, 65536); memory[0xFFFC] = RESET & 0xFF; memory[0xFFFD] = RESET >> 8; memory[RESET + 0x00] = 0xA2; /* LDA #S */ memory[RESET + 0x01] = S; memory[RESET + 0x02] = 0x9A; /* TXS */ memory[RESET + 0x03] = 0xA9; /* LDA #P */ memory[RESET + 0x04] = P; memory[RESET + 0x05] = 0x48; /* PHA */ memory[RESET + 0x06] = 0xA9; /* LHA #A */ memory[RESET + 0x07] = A; memory[RESET + 0x08] = 0xA2; /* LDX #X */ memory[RESET + 0x09] = X; memory[RESET + 0x0A] = 0xA0; /* LDY #Y */ memory[RESET + 0x0B] = Y; memory[RESET + 0x0C] = 0x28; /* PLP */ memory[RESET + 0x0D] = 0x8D; /* STA TRIGGER1 */ memory[RESET + 0x0E] = TRIGGER1 & 0xFF; memory[RESET + 0x0F] = TRIGGER1 >> 8; memory[RESET + 0x10] = b1; uint16_t addr = RESET + 0x11; if (length >= 2) memory[addr++] = b2; if (length >= 3) memory[addr++] = b3; trigger2 = addr; memory[addr++] = 0x08; /* PHP */ memory[addr++] = 0x8D; /* STA A_OUT */ memory[addr++] = A_OUT & 0xFF; memory[addr++] = A_OUT >> 8; memory[addr++] = 0x8E; /* STX X_OUT */ memory[addr++] = X_OUT & 0xFF; memory[addr++] = X_OUT >> 8; memory[addr++] = 0x8C; /* STY Y_OUT */ memory[addr++] = Y_OUT & 0xFF; memory[addr++] = Y_OUT >> 8; memory[addr++] = 0x68; /* PLA */ memory[addr++] = 0x8D; /* STA P_OUT */ memory[addr++] = P_OUT & 0xFF; memory[addr++] = P_OUT >> 8; memory[addr++] = 0xBA; /* TSX */ memory[addr++] = 0x8E; /* STX S_OUT */ memory[addr++] = S_OUT & 0xFF; memory[addr++] = S_OUT >> 8; memory[addr++] = 0x8D; /* STA TRIGGER3 */ memory[addr++] = TRIGGER3 & 0xFF; memory[addr++] = TRIGGER3 >> 8; memory[addr++] = 0xA9; /* LDA #$00 */ memory[addr++] = 0x00; memory[addr++] = 0xF0; /* BEQ . */ memory[addr++] = 0xFE; } #define IS_READ_CYCLE (isNodeHigh(clk0) && isNodeHigh(rw)) #define IS_WRITE_CYCLE (isNodeHigh(clk0) && !isNodeHigh(rw)) #define IS_READING(a) (IS_READ_CYCLE && readAddressBus() == (a)) #define MAX_CYCLES 100 enum { STATE_BEFORE_INSTRUCTION, STATE_DURING_INSTRUCTION, STATE_FIRST_FETCH }; void setup_perfect() { setupNodesAndTransistors(); verbose = 0; } uint16_t instr_ab[10]; uint8_t instr_db[10]; BOOL instr_rw[10]; int perfect_measure_instruction() { int state = STATE_BEFORE_INSTRUCTION; int c = 0; for (int i = 0; i < MAX_CYCLES; i++) { uint16_t ab; uint8_t db; BOOL r_w; full_step(&ab, &db, &r_w); if (state == STATE_DURING_INSTRUCTION && ab > trigger2) { /* * we see the FIRST fetch of the next instruction, * the test instruction MIGHT be done */ state = STATE_FIRST_FETCH; } if (state == STATE_DURING_INSTRUCTION) { instr_rw[c] = r_w; instr_ab[c] = ab; instr_db[c] = db; c++; } if (ab == TRIGGER1) { state = STATE_DURING_INSTRUCTION; /* we're done writing the trigger value; now comes the instruction! */ } if (ab == TRIGGER3) { break; /* we're done dumping the CPU state */ } }; return c; } extern void setup_emu(void); void reset_emu(void); extern int emu_measure_instruction(void); int main() { setup_perfect(); // setup_memory(1, 0xEA, 0x00, 0x00, 0, 0, 0, 0, 0); // setup_memory(2, 0xA9, 0x00, 0x00, 0, 0, 0, 0, 0); // setup_memory(2, 0xAD, 0x00, 0x10, 0, 0, 0, 0, 0); // setup_memory(3, 0xFE, 0x00, 0x10, 0, 0, 0, 0, 0); // setup_memory(3, 0x9D, 0xFF, 0x10, 0, 2, 0, 0, 0); setup_memory(1, 0x28, 0x00, 0x00, 0x55, 0, 0, 0x80, 0); resetChip(); int instr_cycles = perfect_measure_instruction(); for (int c = 0; c < instr_cycles; c++ ) { printf("T%d ", c+1); if (instr_rw[c]) printf("R $%04X\n", instr_ab[c]); else printf("W $%04X = $%02X\n", instr_ab[c], instr_db[c]); } setup_emu(); setup_memory(1, 0x48, 0x00, 0x00, 0x55, 0, 0, 0x80, 0); reset_emu(); int instr_cycles2 = emu_measure_instruction(); }