package com.bytezone.diskbrowser.utilities; public abstract class CPU { // registers private byte xReg; private byte yReg; private byte aReg; // status register protected boolean carry; protected boolean zero; protected boolean interrupt; protected boolean decimal; protected boolean breakFlag; protected boolean overflow; // Clancy protected boolean negative; // stack private final byte[] stack = new byte[0x100]; private int sp = stack.length; private boolean debug = false; protected void setDebug (boolean value) { debug = value; } protected void and (byte mask) // AND { aReg &= mask; zero = aReg == 0; negative = (aReg & 0x80) != 0; debug ("AND"); } protected void asl () // ASL { carry = (aReg & 0x80) != 0; // move bit 7 into the carry flag aReg = (byte) (aReg << 1); // shift left zero = aReg == 0; negative = (aReg & 0x80) != 0; debug ("ASL"); } // unfinished protected void bit (byte value) // BIT { byte b = (byte) (aReg & value); zero = b == 0; overflow = (value & 0x40) != 0; negative = (value & 0x80) != 0; debug ("BIT"); } protected void clc () // CLC { carry = false; debug ("CLC"); } protected void cli () // CLI { interrupt = false; debug ("CLI"); } protected void clv () // CLV { overflow = false; debug ("CLV"); } protected void cmp (byte value) // CMP { int tmp = (aReg & 0xFF) - (value & 0xFF); zero = tmp == 0; negative = (tmp & 0x80) != 0; carry = (aReg & 0xFF) >= (value & 0xFF); debug ("CMP"); } protected void cpx (byte value) // CPX { int tmp = (xReg & 0xFF) - (value & 0xFF); zero = tmp == 0; negative = (tmp & 0x80) != 0; carry = (xReg & 0xFF) >= (value & 0xFF); debug ("CPX"); } protected void cpy (byte value) // CPY { int tmp = (yReg & 0xFF) - (value & 0xFF); zero = tmp == 0; negative = (tmp & 0x80) != 0; carry = (yReg & 0xFF) >= (value & 0xFF); debug ("CPY"); } protected byte dec (byte value) // DEC { value = (byte) ((value & 0xFF) - 1); zero = value == 0; negative = (value & 0x80) != 0; debug ("DEC"); return value; } protected byte inc (byte value) // INC { value = (byte) ((value & 0xFF) + 1); zero = value == 0; negative = (value & 0x80) != 0; debug ("INC"); return value; } protected void inx () // INX { xReg = (byte) ((xReg & 0xFF) + 1); xReg &= 0xFF; zero = xReg == 0; negative = (xReg & 0x80) != 0; debug ("INX"); } protected void lda (byte value) // LDA { aReg = value; zero = aReg == 0; negative = (aReg & 0x80) != 0; debug ("LDA"); } protected void lda (byte[] buffer, int offset) // LDA { aReg = buffer[offset]; zero = aReg == 0; negative = (aReg & 0x80) != 0; debug ("LDA"); } protected void ldx (byte value) // LDX { xReg = value; zero = xReg == 0; negative = (xReg & 0x80) != 0; debug ("LDX"); } protected void ldy (byte value) // LDY { yReg = value; zero = yReg == 0; negative = (yReg & 0x80) != 0; debug ("LDY"); } protected void lsr () // LSR { negative = false; carry = (aReg & 0x01) != 0; aReg = (byte) ((aReg & 0xFF) >>> 1); zero = aReg == 0; debug ("LSR"); } protected void ora (byte mask) // ORA { aReg |= mask; zero = aReg == 0; negative = (aReg & 0x80) != 0; debug ("ORA"); } protected void php () // PHP { byte flags = 0; if (negative) flags |= 0x80; if (overflow) flags |= 0x40; if (breakFlag) flags |= 0x10; if (decimal) flags |= 0x08; if (interrupt) flags |= 0x04; if (zero) flags |= 0x02; if (carry) flags |= 0x01; stack[--sp] = flags; debug ("PHP"); } protected void plp () // PLP { byte flags = stack[sp++]; negative = (flags & 0x80) != 0; overflow = (flags & 0x40) != 0; breakFlag = (flags & 0x10) != 0; decimal = (flags & 0x08) != 0; interrupt = (flags & 0x04) != 0; zero = (flags & 0x02) != 0; carry = (flags & 0x01) != 0; debug ("PLP"); } protected void pha () // PHA { stack[--sp] = aReg; debug ("PHA"); } protected void pla () // PLA { aReg = stack[sp++]; zero = aReg == 0; negative = (aReg & 0x80) != 0; debug ("PLA"); } protected void rol () // ROL { boolean tempCarry = carry; carry = (aReg & 0x80) != 0; // move bit 7 into the carry flag aReg = (byte) (aReg << 1); // shift left if (tempCarry) aReg |= 0x01; // move old carry into bit 0 zero = aReg == 0; negative = (aReg & 0x80) != 0; debug ("ROL"); } protected byte rol (byte value) // ROL { boolean tempCarry = carry; carry = (value & 0x80) != 0; // move bit 7 into the carry flag value = (byte) (value << 1); if (tempCarry) value |= 0x01; // move old carry into bit 0 zero = value == 0; negative = (value & 0x80) != 0; debug ("ROL"); return value; } protected byte ror (byte value) // ROR { boolean tempCarry = carry; carry = (value & 0x01) != 0; // move bit 0 into the carry flag value = (byte) ((value & 0xFF) >>> 1); if (tempCarry) value |= 0x80; // move old carry into bit 7 zero = value == 0; negative = (value & 0x80) != 0; debug ("ROR"); return value; } protected byte sta () // STA { debug ("STA"); return aReg; } protected void sta (byte[] buffer, int offset) // STA { buffer[offset] = aReg; zero = aReg == 0; negative = (aReg & 0x80) != 0; debug ("STA"); } protected byte stx () // STX { debug ("STX"); return xReg; } protected byte sty () // STY { debug ("STY"); return yReg; } protected void txa () // TXA { aReg = xReg; zero = aReg == 0; negative = (aReg & 0x80) != 0; debug ("TXA"); } protected void tya () // TYA { aReg = yReg; zero = aReg == 0; negative = (aReg & 0x80) != 0; debug ("TYA"); } protected void tax () // TAX { xReg = aReg; zero = xReg == 0; negative = (xReg & 0x80) != 0; debug ("TAX"); } protected void tay () // TAY { yReg = aReg; zero = yReg == 0; negative = (yReg & 0x80) != 0; debug ("TAY"); } protected void sei () // SEI { interrupt = true; debug ("SEI"); } protected String debugString () { return ""; } protected void debug (String cmd) { if (debug) { String flags = String.format ("%s %s - %s %s %s %s %s", negative ? "1" : ".", overflow ? "1" : ".", breakFlag ? "1" : ".", decimal ? "1" : ".", interrupt ? "1" : ".", zero ? "1" : ".", carry ? "1" : "."); System.out.printf ("%3s A: %02X X: %02X Y: %02X %s %s%n", cmd, aReg, xReg, yReg, flags, debugString ()); } } protected int indirectY (int base, byte offset, byte page) { if (debug) System.out.printf ("base: %,6d, page: %02X, offset: %02X, yReg: %02X%n", base, page, offset, yReg); return ((page & 0xFF) * 256 + (offset & 0xFF)) - base + (yReg & 0xFF); } }