From 8bcd8a4a75bbc2c6102fa2cacfef0beb09130597 Mon Sep 17 00:00:00 2001 From: "Seth J. Morabito" Date: Sat, 27 Dec 2008 21:09:47 -0800 Subject: [PATCH] Whitespace and indentation canonicalization. That's what I get for using two editors. --- src/main/java/com/loomcom/symon/Bus.java | 252 +- .../java/com/loomcom/symon/CommandParser.java | 110 +- src/main/java/com/loomcom/symon/Cpu.java | 2670 ++++++++--------- .../com/loomcom/symon/InstructionTable.java | 452 +-- .../java/com/loomcom/symon/MemoryRange.java | 132 +- src/main/java/com/loomcom/symon/Profiler.java | 239 +- .../java/com/loomcom/symon/Simulator.java | 172 +- .../com/loomcom/symon/devices/Device.java | 98 +- .../com/loomcom/symon/devices/Memory.java | 46 +- .../exceptions/MemoryAccessException.java | 6 +- .../exceptions/MemoryRangeException.java | 6 +- src/test/java/com/loomcom/symon/BusTest.java | 172 +- .../loomcom/symon/CpuImmediateModeTest.java | 1690 +++++------ .../com/loomcom/symon/CpuImpliedModeTest.java | 1172 ++++---- src/test/java/com/loomcom/symon/CpuTest.java | 688 ++--- .../loomcom/symon/CpuZeroPageModeTest.java | 2350 +++++++-------- .../com/loomcom/symon/MemoryRangeTest.java | 204 +- .../java/com/loomcom/symon/SimulatorTest.java | 40 +- 18 files changed, 5249 insertions(+), 5250 deletions(-) diff --git a/src/main/java/com/loomcom/symon/Bus.java b/src/main/java/com/loomcom/symon/Bus.java index 18bae13..1f48e35 100644 --- a/src/main/java/com/loomcom/symon/Bus.java +++ b/src/main/java/com/loomcom/symon/Bus.java @@ -9,136 +9,136 @@ import com.loomcom.symon.exceptions.*; */ public class Bus { - // By default, our bus starts at 0, and goes up to 64K - private int startAddress = 0x0000; - private int endAddress = 0xffff; - // The CPU - private Cpu cpu; - // Ordered list of IO devices. - private SortedSet devices; + // By default, our bus starts at 0, and goes up to 64K + private int startAddress = 0x0000; + private int endAddress = 0xffff; + // The CPU + private Cpu cpu; + // Ordered list of IO devices. + private SortedSet devices; - public Bus(int size) { - this(0, size - 1); - } + public Bus(int size) { + this(0, size - 1); + } - public Bus(int startAddress, int endAddress) { - this.devices = new TreeSet(); - this.startAddress = startAddress; - this.endAddress = endAddress; - } + public Bus(int startAddress, int endAddress) { + this.devices = new TreeSet(); + this.startAddress = startAddress; + this.endAddress = endAddress; + } - public int startAddress() { - return startAddress; - } + public int startAddress() { + return startAddress; + } - public int endAddress() { - return endAddress; - } + public int endAddress() { + return endAddress; + } - public void addDevice(Device device) - throws MemoryRangeException { - // Make sure there's no memory overlap. - MemoryRange memRange = device.getMemoryRange(); - for (Device d : devices) { - if (d.getMemoryRange().overlaps(memRange)) { - throw new MemoryRangeException("The device being added " + - "overlaps with an existing " + - "device."); - } - } - - // Add the device - device.setBus(this); - devices.add(device); - } - - public void addCpu(Cpu cpu) { - cpu.setBus(this); - this.cpu = cpu; - } - - /** - * Returns true if the memory map is full, i.e., there are no - * gaps between any IO devices. All memory locations map to some - * device. - */ - public boolean isComplete() { - // Empty maps cannot be complete. - if (devices.isEmpty()) { return false; } - - // Loop over devices and ensure they are contiguous. - MemoryRange prev = null; - int i = 0; - int length = devices.size(); - for (Device d : devices) { - MemoryRange cur = d.getMemoryRange(); - if (i == 0) { - // If the first entry doesn't start at 'startAddress', return false. - if (cur.startAddress() != startAddress) { return false; } - } - - if (prev != null && i < length - 1) { - // Otherwise, compare previous map's end against this map's - // endAddress. They must be adjacent! - if (cur.startAddress() - 1 != prev.endAddress()) { - return false; - } - } - - if (i == length - 1) { - // If the last entry doesn't end at endAddress, return false; - if (cur.endAddress() != endAddress) { return false; } - } - - i++; - prev = cur; - } - - // Must be complete. - return true; - } - - public int read(int address) { - for (Device d : devices) { - MemoryRange range = d.getMemoryRange(); - if (range.includes(address)) { - // Compute offset into this device's address space. - int devAddr = address - range.startAddress(); - return d.read(devAddr); - } - } - // TODO: Raise access error. - throw new RuntimeException("Read failed! Device not found."); - } - - public void write(int address, int value) { - for (Device d : devices) { - MemoryRange range = d.getMemoryRange(); - if (range.includes(address)) { - // Compute offset into this device's address space. - int devAddr = address - range.startAddress(); - d.write(devAddr, value); - return; - } - } - // TODO: Raise access error. - throw new RuntimeException("Write failed! Device not found."); - } - - public SortedSet getDevices() { - // Expose a copy of the device list, not the original - return new TreeSet(devices); - } - - public Cpu getCpu() { - return cpu; - } - - public void loadProgram(int... program) { - int address = getCpu().getProgramCounter(); - int i = 0; - for (int d : program) { - write(address + i++, d); - } + public void addDevice(Device device) + throws MemoryRangeException { + // Make sure there's no memory overlap. + MemoryRange memRange = device.getMemoryRange(); + for (Device d : devices) { + if (d.getMemoryRange().overlaps(memRange)) { + throw new MemoryRangeException("The device being added " + + "overlaps with an existing " + + "device."); + } } + + // Add the device + device.setBus(this); + devices.add(device); + } + + public void addCpu(Cpu cpu) { + cpu.setBus(this); + this.cpu = cpu; + } + + /** + * Returns true if the memory map is full, i.e., there are no + * gaps between any IO devices. All memory locations map to some + * device. + */ + public boolean isComplete() { + // Empty maps cannot be complete. + if (devices.isEmpty()) { return false; } + + // Loop over devices and ensure they are contiguous. + MemoryRange prev = null; + int i = 0; + int length = devices.size(); + for (Device d : devices) { + MemoryRange cur = d.getMemoryRange(); + if (i == 0) { + // If the first entry doesn't start at 'startAddress', return false. + if (cur.startAddress() != startAddress) { return false; } + } + + if (prev != null && i < length - 1) { + // Otherwise, compare previous map's end against this map's + // endAddress. They must be adjacent! + if (cur.startAddress() - 1 != prev.endAddress()) { + return false; + } + } + + if (i == length - 1) { + // If the last entry doesn't end at endAddress, return false; + if (cur.endAddress() != endAddress) { return false; } + } + + i++; + prev = cur; + } + + // Must be complete. + return true; + } + + public int read(int address) { + for (Device d : devices) { + MemoryRange range = d.getMemoryRange(); + if (range.includes(address)) { + // Compute offset into this device's address space. + int devAddr = address - range.startAddress(); + return d.read(devAddr); + } + } + // TODO: Raise access error. + throw new RuntimeException("Read failed! Device not found."); + } + + public void write(int address, int value) { + for (Device d : devices) { + MemoryRange range = d.getMemoryRange(); + if (range.includes(address)) { + // Compute offset into this device's address space. + int devAddr = address - range.startAddress(); + d.write(devAddr, value); + return; + } + } + // TODO: Raise access error. + throw new RuntimeException("Write failed! Device not found."); + } + + public SortedSet getDevices() { + // Expose a copy of the device list, not the original + return new TreeSet(devices); + } + + public Cpu getCpu() { + return cpu; + } + + public void loadProgram(int... program) { + int address = getCpu().getProgramCounter(); + int i = 0; + for (int d : program) { + write(address + i++, d); + } + } } diff --git a/src/main/java/com/loomcom/symon/CommandParser.java b/src/main/java/com/loomcom/symon/CommandParser.java index 602c855..5f39d5e 100644 --- a/src/main/java/com/loomcom/symon/CommandParser.java +++ b/src/main/java/com/loomcom/symon/CommandParser.java @@ -4,69 +4,69 @@ import java.io.*; public class CommandParser { - private BufferedReader in; - private BufferedWriter out; - private Simulator simulator; + private BufferedReader in; + private BufferedWriter out; + private Simulator simulator; - public CommandParser(InputStream i, OutputStream o, Simulator s) { - this.in = new BufferedReader(new InputStreamReader(i)); - this.out = new BufferedWriter(new OutputStreamWriter(o)); - this.simulator = s; - } + public CommandParser(InputStream i, OutputStream o, Simulator s) { + this.in = new BufferedReader(new InputStreamReader(i)); + this.out = new BufferedWriter(new OutputStreamWriter(o)); + this.simulator = s; + } - public void run() { - try { - String command = null; - greeting(); - prompt(); - while (!shouldQuit(command = readLine())) { - dispatch(command); - prompt(); - } - writeLine("\n\nGoodbye!"); - } catch (IOException ex) { - System.err.println("Error: " + ex.toString()); - System.exit(1); - } - } + public void run() { + try { + String command = null; + greeting(); + prompt(); + while (!shouldQuit(command = readLine())) { + dispatch(command); + prompt(); + } + writeLine("\n\nGoodbye!"); + } catch (IOException ex) { + System.err.println("Error: " + ex.toString()); + System.exit(1); + } + } - /** - * Dispatch the command. - */ - public void dispatch(String command) throws IOException { - writeLine("You entered: " + command); - } + /** + * Dispatch the command. + */ + public void dispatch(String command) throws IOException { + writeLine("You entered: " + command); + } - /******************************************************************* - * Private - *******************************************************************/ + /******************************************************************* + * Private + *******************************************************************/ - private void greeting() throws IOException { - writeLine("Welcome to the j6502 Simulator!"); - } + private void greeting() throws IOException { + writeLine("Welcome to the j6502 Simulator!"); + } - private void prompt() throws IOException { - out.write("j6502> "); - out.flush(); - } + private void prompt() throws IOException { + out.write("j6502> "); + out.flush(); + } - private String readLine() throws IOException { - String line = in.readLine(); - if (line == null) { return null; } - return line.trim(); - } + private String readLine() throws IOException { + String line = in.readLine(); + if (line == null) { return null; } + return line.trim(); + } - private void writeLine(String line) throws IOException { - out.write(line); - out.newLine(); - out.flush(); - } + private void writeLine(String line) throws IOException { + out.write(line); + out.newLine(); + out.flush(); + } - /** - * Returns true if the line is a quit. - */ - private boolean shouldQuit(String line) { - return (line == null || "q".equals(line.toLowerCase())); - } + /** + * Returns true if the line is a quit. + */ + private boolean shouldQuit(String line) { + return (line == null || "q".equals(line.toLowerCase())); + } } \ No newline at end of file diff --git a/src/main/java/com/loomcom/symon/Cpu.java b/src/main/java/com/loomcom/symon/Cpu.java index 6f5828a..2ff5cfc 100644 --- a/src/main/java/com/loomcom/symon/Cpu.java +++ b/src/main/java/com/loomcom/symon/Cpu.java @@ -7,1386 +7,1386 @@ import java.util.Arrays; */ public class Cpu implements InstructionTable { - public static final int DEFAULT_BASE_ADDRESS = 0x200; + public static final int DEFAULT_BASE_ADDRESS = 0x200; - /* Process status register mnemonics */ - public static final int P_CARRY = 0x01; - public static final int P_ZERO = 0x02; - public static final int P_IRQ_DISABLE = 0x04; - public static final int P_DECIMAL = 0x08; - public static final int P_BREAK = 0x10; - // Bit 5 is always '1' - public static final int P_OVERFLOW = 0x40; - public static final int P_NEGATIVE = 0x80; + /* Process status register mnemonics */ + public static final int P_CARRY = 0x01; + public static final int P_ZERO = 0x02; + public static final int P_IRQ_DISABLE = 0x04; + public static final int P_DECIMAL = 0x08; + public static final int P_BREAK = 0x10; + // Bit 5 is always '1' + public static final int P_OVERFLOW = 0x40; + public static final int P_NEGATIVE = 0x80; - // NMI vector - public static final int IRQ_VECTOR_L = 0xfffa; - public static final int IRQ_VECTOR_H = 0xfffb; - // Reset vector - public static final int RST_VECTOR_L = 0xfffc; - public static final int RST_VECTOR_H = 0xfffd; - // IRQ vector - public static final int NMI_VECTOR_L = 0xfffe; - public static final int NMI_VECTOR_H = 0xffff; + // NMI vector + public static final int IRQ_VECTOR_L = 0xfffa; + public static final int IRQ_VECTOR_H = 0xfffb; + // Reset vector + public static final int RST_VECTOR_L = 0xfffc; + public static final int RST_VECTOR_H = 0xfffd; + // IRQ vector + public static final int NMI_VECTOR_L = 0xfffe; + public static final int NMI_VECTOR_H = 0xffff; - /* The Bus */ - private Bus bus; + /* The Bus */ + private Bus bus; - /* User Registers */ - private int a; // Accumulator - private int x; // X index register - private int y; // Y index register + /* User Registers */ + private int a; // Accumulator + private int x; // X index register + private int y; // Y index register - /* Internal Registers */ - private int pc; // Program Counter register - private int sp; // Stack Pointer register, offset into page 1 - private int ir; // Instruction register + /* Internal Registers */ + private int pc; // Program Counter register + private int sp; // Stack Pointer register, offset into page 1 + private int ir; // Instruction register - /* Internal scratch space */ - private int lo = 0, hi = 0; // Used in address calculation - private int j = 0, k = 0; // Used for temporary storage + /* Internal scratch space */ + private int lo = 0, hi = 0; // Used in address calculation + private int j = 0, k = 0; // Used for temporary storage - /* Operands for the current instruction */ - private int[] operands = new int[2]; - private int addr; // The address the most recent instruction - // was fetched from + /* Operands for the current instruction */ + private int[] operands = new int[2]; + private int addr; // The address the most recent instruction + // was fetched from - /* Status Flag Register bits */ - private boolean carryFlag; - private boolean negativeFlag; - private boolean zeroFlag; - private boolean irqDisableFlag; - private boolean decimalModeFlag; - private boolean breakFlag; - private boolean overflowFlag; + /* Status Flag Register bits */ + private boolean carryFlag; + private boolean negativeFlag; + private boolean zeroFlag; + private boolean irqDisableFlag; + private boolean decimalModeFlag; + private boolean breakFlag; + private boolean overflowFlag; - /** - * Construct a new CPU. - */ - public Cpu() {} + /** + * Construct a new CPU. + */ + public Cpu() {} - /** - * Set the bus reference for this CPU. - */ - public void setBus(Bus bus) { - this.bus = bus; - } + /** + * Set the bus reference for this CPU. + */ + public void setBus(Bus bus) { + this.bus = bus; + } - /** - * Return the Bus that this CPU is associated with. - */ - public Bus getBus() { - return bus; - } + /** + * Return the Bus that this CPU is associated with. + */ + public Bus getBus() { + return bus; + } - /** - * Reset the CPU to known initial values. - */ - public void reset() { - // Registers - sp = 0xff; + /** + * Reset the CPU to known initial values. + */ + public void reset() { + // Registers + sp = 0xff; - // Set the PC to the address stored in the reset vector - pc = address(bus.read(RST_VECTOR_L), bus.read(RST_VECTOR_H)); + // Set the PC to the address stored in the reset vector + pc = address(bus.read(RST_VECTOR_L), bus.read(RST_VECTOR_H)); - // Clear instruction register. - ir = 0; + // Clear instruction register. + ir = 0; - // Clear status register bits. - carryFlag = false; - irqDisableFlag = false; - decimalModeFlag = false; - breakFlag = false; - overflowFlag = false; - } + // Clear status register bits. + carryFlag = false; + irqDisableFlag = false; + decimalModeFlag = false; + breakFlag = false; + overflowFlag = false; + } - public void step(int num) { - for (int i = 0; i < num; i++) { - step(); - } - } + public void step(int num) { + for (int i = 0; i < num; i++) { + step(); + } + } - /** - * Performs an individual machine cycle. - */ - public void step() { - // Store the address from which the IR was read, for debugging - addr = pc; + /** + * Performs an individual machine cycle. + */ + public void step() { + // Store the address from which the IR was read, for debugging + addr = pc; - // Fetch memory location for this instruction. - ir = bus.read(pc); + // Fetch memory location for this instruction. + ir = bus.read(pc); - // Increment PC - incrementPC(); + // Increment PC + incrementPC(); - // Decode the instruction and operands - int size = Cpu.instructionSizes[ir]; - for (int i = 0; i < size-1; i++) { - operands[i] = bus.read(pc); - // Increment PC after reading - incrementPC(); - } + // Decode the instruction and operands + int size = Cpu.instructionSizes[ir]; + for (int i = 0; i < size-1; i++) { + operands[i] = bus.read(pc); + // Increment PC after reading + incrementPC(); + } - // Execute - switch(ir) { + // Execute + switch(ir) { - case 0x00: // BRK - Force Interrupt - Implied - if (!getIrqDisableFlag()) { - // Set the break flag before pushing. - setBreakFlag(); - // Push program counter + 2 onto the stack - stackPush((pc+2 >> 8) & 0xff); // PC high byte - stackPush(pc+2 & 0xff); // PC low byte - stackPush(getProcessorStatus()); - // Set the Interrupt Disabled flag. RTI will clear it. - setIrqDisableFlag(); - // Load interrupt vector address into PC - pc = address(bus.read(IRQ_VECTOR_L), bus.read(IRQ_VECTOR_H)); - } - break; - case 0x01: // n/a - break; - case 0x02: // n/a - break; - case 0x03: // n/a - break; - case 0x04: // n/a - break; - case 0x05: // ORA - Logical Inclusive OR - Zero Page - a |= bus.read(operands[0]); - setArithmeticFlags(a); - break; - case 0x06: // ASL - Arithmetic Shift Left - Zero Page - j = bus.read(operands[0]); - k = asl(j); - bus.write(operands[0], k); - setArithmeticFlags(k); - break; - case 0x07: // n/a - break; - case 0x08: // PHP - Push Processor Status - Implied - stackPush(getProcessorStatus()); - break; - case 0x09: // ORA - Logical Inclusive OR - Immediate - a |= operands[0]; - setArithmeticFlags(a); - break; - case 0x0a: // n/a - break; - case 0x0b: // n/a - break; - case 0x0c: // n/a - break; - case 0x0d: // n/a - break; - case 0x0e: // n/a - break; - case 0x0f: // n/a - break; + case 0x00: // BRK - Force Interrupt - Implied + if (!getIrqDisableFlag()) { + // Set the break flag before pushing. + setBreakFlag(); + // Push program counter + 2 onto the stack + stackPush((pc+2 >> 8) & 0xff); // PC high byte + stackPush(pc+2 & 0xff); // PC low byte + stackPush(getProcessorStatus()); + // Set the Interrupt Disabled flag. RTI will clear it. + setIrqDisableFlag(); + // Load interrupt vector address into PC + pc = address(bus.read(IRQ_VECTOR_L), bus.read(IRQ_VECTOR_H)); + } + break; + case 0x01: // n/a + break; + case 0x02: // n/a + break; + case 0x03: // n/a + break; + case 0x04: // n/a + break; + case 0x05: // ORA - Logical Inclusive OR - Zero Page + a |= bus.read(operands[0]); + setArithmeticFlags(a); + break; + case 0x06: // ASL - Arithmetic Shift Left - Zero Page + j = bus.read(operands[0]); + k = asl(j); + bus.write(operands[0], k); + setArithmeticFlags(k); + break; + case 0x07: // n/a + break; + case 0x08: // PHP - Push Processor Status - Implied + stackPush(getProcessorStatus()); + break; + case 0x09: // ORA - Logical Inclusive OR - Immediate + a |= operands[0]; + setArithmeticFlags(a); + break; + case 0x0a: // n/a + break; + case 0x0b: // n/a + break; + case 0x0c: // n/a + break; + case 0x0d: // n/a + break; + case 0x0e: // n/a + break; + case 0x0f: // n/a + break; - case 0x10: // n/a - break; - case 0x11: // n/a - break; - case 0x12: // n/a - break; - case 0x13: // n/a - break; - case 0x14: // n/a - break; - case 0x15: // n/a - break; - case 0x16: // n/a - break; - case 0x17: // n/a - break; - case 0x18: // CLC - Clear Carry Flag - Implied - clearCarryFlag(); - break; - case 0x19: // n/a - break; - case 0x1a: // n/a - break; - case 0x1b: // n/a - break; - case 0x1c: // n/a - break; - case 0x1d: // n/a - break; - case 0x1e: // n/a - break; - case 0x1f: // n/a - break; + case 0x10: // n/a + break; + case 0x11: // n/a + break; + case 0x12: // n/a + break; + case 0x13: // n/a + break; + case 0x14: // n/a + break; + case 0x15: // n/a + break; + case 0x16: // n/a + break; + case 0x17: // n/a + break; + case 0x18: // CLC - Clear Carry Flag - Implied + clearCarryFlag(); + break; + case 0x19: // n/a + break; + case 0x1a: // n/a + break; + case 0x1b: // n/a + break; + case 0x1c: // n/a + break; + case 0x1d: // n/a + break; + case 0x1e: // n/a + break; + case 0x1f: // n/a + break; - case 0x20: // n/a - break; - case 0x21: // n/a - break; - case 0x22: // n/a - break; - case 0x23: // n/a - break; - case 0x24: // BIT - Bit Test - Zero Page - j = bus.read(operands[0]); - k = a & j; - setZeroFlag(k == 0); - setNegativeFlag((k & 0x80) != 0); - setOverflowFlag((k & 0x40) != 0); - break; - case 0x25: // AND - Logical And - Zero Page - j = bus.read(operands[0]); - a &= j; - setArithmeticFlags(a); - break; - case 0x26: // ROL - Rotate Left - Zero Page - j = bus.read(operands[0]); - k = rol(j); - bus.write(operands[0], k); - setArithmeticFlags(k); - break; - case 0x27: // n/a - break; - case 0x28: // PLP - Pull Processor Status - Implied - setProcessorStatus(stackPop()); - break; - case 0x29: // AND - Logical And - Immediate - a &= operands[0]; - setArithmeticFlags(a); - break; - case 0x2a: // n/a - break; - case 0x2b: // n/a - break; - case 0x2c: // n/a - break; - case 0x2d: // n/a - break; - case 0x2e: // n/a - break; - case 0x2f: // n/a - break; + case 0x20: // n/a + break; + case 0x21: // n/a + break; + case 0x22: // n/a + break; + case 0x23: // n/a + break; + case 0x24: // BIT - Bit Test - Zero Page + j = bus.read(operands[0]); + k = a & j; + setZeroFlag(k == 0); + setNegativeFlag((k & 0x80) != 0); + setOverflowFlag((k & 0x40) != 0); + break; + case 0x25: // AND - Logical And - Zero Page + j = bus.read(operands[0]); + a &= j; + setArithmeticFlags(a); + break; + case 0x26: // ROL - Rotate Left - Zero Page + j = bus.read(operands[0]); + k = rol(j); + bus.write(operands[0], k); + setArithmeticFlags(k); + break; + case 0x27: // n/a + break; + case 0x28: // PLP - Pull Processor Status - Implied + setProcessorStatus(stackPop()); + break; + case 0x29: // AND - Logical And - Immediate + a &= operands[0]; + setArithmeticFlags(a); + break; + case 0x2a: // n/a + break; + case 0x2b: // n/a + break; + case 0x2c: // n/a + break; + case 0x2d: // n/a + break; + case 0x2e: // n/a + break; + case 0x2f: // n/a + break; - case 0x30: // n/a - break; - case 0x31: // n/a - break; - case 0x32: // n/a - break; - case 0x33: // n/a - break; - case 0x34: // n/a - break; - case 0x35: // n/a - break; - case 0x36: // n/a - break; - case 0x37: // n/a - break; - case 0x38: // SEC - Set Carry Flag - Implied - setCarryFlag(); - break; - case 0x39: // n/a - break; - case 0x3a: // n/a - break; - case 0x3b: // n/a - break; - case 0x3c: // n/a - break; - case 0x3d: // n/a - break; - case 0x3e: // n/a - break; - case 0x3f: // n/a - break; + case 0x30: // n/a + break; + case 0x31: // n/a + break; + case 0x32: // n/a + break; + case 0x33: // n/a + break; + case 0x34: // n/a + break; + case 0x35: // n/a + break; + case 0x36: // n/a + break; + case 0x37: // n/a + break; + case 0x38: // SEC - Set Carry Flag - Implied + setCarryFlag(); + break; + case 0x39: // n/a + break; + case 0x3a: // n/a + break; + case 0x3b: // n/a + break; + case 0x3c: // n/a + break; + case 0x3d: // n/a + break; + case 0x3e: // n/a + break; + case 0x3f: // n/a + break; - case 0x40: // RTI - Return from Interrupt - Implied - setProcessorStatus(stackPop()); - lo = stackPop(); - hi = stackPop(); - setProgramCounter(address(lo, hi)); - break; - case 0x41: // n/a - break; - case 0x42: // n/a - break; - case 0x43: // n/a - break; - case 0x44: // n/a - break; - case 0x45: // EOR - Exclusive OR - Zero Page - j = bus.read(operands[0]); - a ^= j; - setArithmeticFlags(a); - break; - case 0x46: // LSR - Logical Shift Right - Zero Page - j = bus.read(operands[0]); - k = lsr(j); - bus.write(operands[0], k); - setArithmeticFlags(k); - break; - case 0x47: // n/a - break; - case 0x48: // PHA - Push Accumulator - Implied - stackPush(a); - break; - case 0x49: // EOR - Exclusive OR - Immediate - a ^= operands[0]; - setArithmeticFlags(a); - break; - case 0x4a: // n/a - break; - case 0x4b: // n/a - break; - case 0x4c: // JMP - Jump - Absolute - pc = address(operands[0], operands[1]); - break; - case 0x4d: // n/a - break; - case 0x4e: // n/a - break; - case 0x4f: // n/a - break; + case 0x40: // RTI - Return from Interrupt - Implied + setProcessorStatus(stackPop()); + lo = stackPop(); + hi = stackPop(); + setProgramCounter(address(lo, hi)); + break; + case 0x41: // n/a + break; + case 0x42: // n/a + break; + case 0x43: // n/a + break; + case 0x44: // n/a + break; + case 0x45: // EOR - Exclusive OR - Zero Page + j = bus.read(operands[0]); + a ^= j; + setArithmeticFlags(a); + break; + case 0x46: // LSR - Logical Shift Right - Zero Page + j = bus.read(operands[0]); + k = lsr(j); + bus.write(operands[0], k); + setArithmeticFlags(k); + break; + case 0x47: // n/a + break; + case 0x48: // PHA - Push Accumulator - Implied + stackPush(a); + break; + case 0x49: // EOR - Exclusive OR - Immediate + a ^= operands[0]; + setArithmeticFlags(a); + break; + case 0x4a: // n/a + break; + case 0x4b: // n/a + break; + case 0x4c: // JMP - Jump - Absolute + pc = address(operands[0], operands[1]); + break; + case 0x4d: // n/a + break; + case 0x4e: // n/a + break; + case 0x4f: // n/a + break; - case 0x50: // n/a - break; - case 0x51: // n/a - break; - case 0x52: // n/a - break; - case 0x53: // n/a - break; - case 0x54: // n/a - break; - case 0x55: // n/a - break; - case 0x56: // n/a - break; - case 0x57: // n/a - break; - case 0x58: // CLI - Clear Interrupt Disable - Implied - clearIrqDisableFlag(); - break; - case 0x59: // n/a - break; - case 0x5a: // n/a - break; - case 0x5b: // n/a - break; - case 0x5c: // n/a - break; - case 0x5d: // n/a - break; - case 0x5e: // n/a - break; - case 0x5f: // n/a - break; + case 0x50: // n/a + break; + case 0x51: // n/a + break; + case 0x52: // n/a + break; + case 0x53: // n/a + break; + case 0x54: // n/a + break; + case 0x55: // n/a + break; + case 0x56: // n/a + break; + case 0x57: // n/a + break; + case 0x58: // CLI - Clear Interrupt Disable - Implied + clearIrqDisableFlag(); + break; + case 0x59: // n/a + break; + case 0x5a: // n/a + break; + case 0x5b: // n/a + break; + case 0x5c: // n/a + break; + case 0x5d: // n/a + break; + case 0x5e: // n/a + break; + case 0x5f: // n/a + break; - case 0x60: // RTS - Return from Subroutine - Implied - lo = stackPop(); - hi = stackPop(); - setProgramCounter((address(lo, hi) + 1) & 0xffff); - break; - case 0x61: // n/a - break; - case 0x62: // n/a - break; - case 0x63: // n/a - break; - case 0x64: // n/a - break; - case 0x65: // ADC - Add with Carry - Zero Page - j = bus.read(operands[0]); - if (decimalModeFlag) { - a = adcDecimal(a, j); - } else { - a = adc(a, j); - } - break; - case 0x66: // ROR - Rotate Right - Zero Page - j = bus.read(operands[0]); - k = ror(j); - bus.write(operands[0], k); - setArithmeticFlags(k); - break; - case 0x67: // n/a - break; - case 0x68: // PLA - Pull Accumulator - Implied - a = stackPop(); - setArithmeticFlags(a); - break; - case 0x69: // ADC - Add with Carry - Immediate - if (decimalModeFlag) { - a = adcDecimal(a, operands[0]); - } else { - a = adc(a, operands[0]); - } - break; - case 0x6a: // n/a - break; - case 0x6b: // n/a - break; - case 0x6c: // n/a - break; - case 0x6d: // n/a - break; - case 0x6e: // n/a - break; - case 0x6f: // n/a - break; + case 0x60: // RTS - Return from Subroutine - Implied + lo = stackPop(); + hi = stackPop(); + setProgramCounter((address(lo, hi) + 1) & 0xffff); + break; + case 0x61: // n/a + break; + case 0x62: // n/a + break; + case 0x63: // n/a + break; + case 0x64: // n/a + break; + case 0x65: // ADC - Add with Carry - Zero Page + j = bus.read(operands[0]); + if (decimalModeFlag) { + a = adcDecimal(a, j); + } else { + a = adc(a, j); + } + break; + case 0x66: // ROR - Rotate Right - Zero Page + j = bus.read(operands[0]); + k = ror(j); + bus.write(operands[0], k); + setArithmeticFlags(k); + break; + case 0x67: // n/a + break; + case 0x68: // PLA - Pull Accumulator - Implied + a = stackPop(); + setArithmeticFlags(a); + break; + case 0x69: // ADC - Add with Carry - Immediate + if (decimalModeFlag) { + a = adcDecimal(a, operands[0]); + } else { + a = adc(a, operands[0]); + } + break; + case 0x6a: // n/a + break; + case 0x6b: // n/a + break; + case 0x6c: // n/a + break; + case 0x6d: // n/a + break; + case 0x6e: // n/a + break; + case 0x6f: // n/a + break; - case 0x70: // n/a - break; - case 0x71: // n/a - break; - case 0x72: // n/a - break; - case 0x73: // n/a - break; - case 0x74: // n/a - break; - case 0x75: // n/a - break; - case 0x76: // n/a - break; - case 0x77: // n/a - break; - case 0x78: // SEI - Set Interrupt Disable - Implied - setIrqDisableFlag(); - break; - case 0x79: // n/a - break; - case 0x7a: // n/a - break; - case 0x7b: // n/a - break; - case 0x7c: // n/a - break; - case 0x7d: // n/a - break; - case 0x7e: // n/a - break; - case 0x7f: // n/a - break; + case 0x70: // n/a + break; + case 0x71: // n/a + break; + case 0x72: // n/a + break; + case 0x73: // n/a + break; + case 0x74: // n/a + break; + case 0x75: // n/a + break; + case 0x76: // n/a + break; + case 0x77: // n/a + break; + case 0x78: // SEI - Set Interrupt Disable - Implied + setIrqDisableFlag(); + break; + case 0x79: // n/a + break; + case 0x7a: // n/a + break; + case 0x7b: // n/a + break; + case 0x7c: // n/a + break; + case 0x7d: // n/a + break; + case 0x7e: // n/a + break; + case 0x7f: // n/a + break; - case 0x80: // n/a - break; - case 0x81: // n/a - break; - case 0x82: // n/a - break; - case 0x83: // n/a - break; - case 0x84: // STY - Store Y Register - Zero Page - bus.write(operands[0], y); - setArithmeticFlags(y); - break; - case 0x85: // STA - Store Accumulator - Zero Page - bus.write(operands[0], a); - setArithmeticFlags(a); - break; - case 0x86: // STX - Store X Register - Zero Page - bus.write(operands[0], x); - setArithmeticFlags(x); - break; - case 0x87: // n/a - break; - case 0x88: // DEY - Decrement Y Register - Implied - y = --y & 0xff; - setArithmeticFlags(y); - break; - case 0x89: // n/a - break; - case 0x8a: // TXA - Transfer X to Accumulator - Implied - a = x; - setArithmeticFlags(a); - break; - case 0x8b: // n/a - break; - case 0x8c: // n/a - break; - case 0x8d: // n/a - break; - case 0x8e: // n/a - break; - case 0x8f: // n/a - break; + case 0x80: // n/a + break; + case 0x81: // n/a + break; + case 0x82: // n/a + break; + case 0x83: // n/a + break; + case 0x84: // STY - Store Y Register - Zero Page + bus.write(operands[0], y); + setArithmeticFlags(y); + break; + case 0x85: // STA - Store Accumulator - Zero Page + bus.write(operands[0], a); + setArithmeticFlags(a); + break; + case 0x86: // STX - Store X Register - Zero Page + bus.write(operands[0], x); + setArithmeticFlags(x); + break; + case 0x87: // n/a + break; + case 0x88: // DEY - Decrement Y Register - Implied + y = --y & 0xff; + setArithmeticFlags(y); + break; + case 0x89: // n/a + break; + case 0x8a: // TXA - Transfer X to Accumulator - Implied + a = x; + setArithmeticFlags(a); + break; + case 0x8b: // n/a + break; + case 0x8c: // n/a + break; + case 0x8d: // n/a + break; + case 0x8e: // n/a + break; + case 0x8f: // n/a + break; - case 0x90: // n/a - break; - case 0x91: // n/a - break; - case 0x92: // n/a - break; - case 0x93: // n/a - break; - case 0x94: // n/a - break; - case 0x95: // n/a - break; - case 0x96: // n/a - break; - case 0x97: // n/a - break; - case 0x98: // TYA - Transfer Y to Accumulator - Implied - a = y; - setArithmeticFlags(a); - break; - case 0x99: // n/a - break; - case 0x9a: // TXS - Transfer X to Stack Pointer - Implied - setStackPointer(x); - break; - case 0x9b: // n/a - break; - case 0x9c: // n/a - break; - case 0x9d: // n/a - break; - case 0x9e: // n/a - break; - case 0x9f: // n/a - break; + case 0x90: // n/a + break; + case 0x91: // n/a + break; + case 0x92: // n/a + break; + case 0x93: // n/a + break; + case 0x94: // n/a + break; + case 0x95: // n/a + break; + case 0x96: // n/a + break; + case 0x97: // n/a + break; + case 0x98: // TYA - Transfer Y to Accumulator - Implied + a = y; + setArithmeticFlags(a); + break; + case 0x99: // n/a + break; + case 0x9a: // TXS - Transfer X to Stack Pointer - Implied + setStackPointer(x); + break; + case 0x9b: // n/a + break; + case 0x9c: // n/a + break; + case 0x9d: // n/a + break; + case 0x9e: // n/a + break; + case 0x9f: // n/a + break; - case 0xa0: // LDY - Load Y Register - Immediate - y = operands[0]; - setArithmeticFlags(y); - break; - case 0xa1: // n/a - break; - case 0xa2: // LDX - Load X Register - Immediate - x = operands[0]; - setArithmeticFlags(x); - break; - case 0xa3: // n/a - break; - case 0xa4: // LDY - Load Y Register - Zero Page - y = bus.read(operands[0]); - setArithmeticFlags(y); - break; - case 0xa5: // LDA - Load Accumulator - Zero Page - a = bus.read(operands[0]); - setArithmeticFlags(a); - break; - case 0xa6: // LDA - Load X Register - Zero Page - x = bus.read(operands[0]); - setArithmeticFlags(x); - break; - case 0xa7: // n/a - break; - case 0xa8: // TAY - Transfer Accumulator to Y - Implied - y = a; - setArithmeticFlags(y); - break; - case 0xa9: // LDA - Immediate - a = operands[0]; - setArithmeticFlags(a); - break; - case 0xaa: // TAX - Transfer Accumulator to X - Implied - x = a; - setArithmeticFlags(x); - break; - case 0xab: // n/a - break; - case 0xac: // n/a - break; - case 0xad: // n/a - break; - case 0xae: // n/a - break; - case 0xaf: // n/a - break; + case 0xa0: // LDY - Load Y Register - Immediate + y = operands[0]; + setArithmeticFlags(y); + break; + case 0xa1: // n/a + break; + case 0xa2: // LDX - Load X Register - Immediate + x = operands[0]; + setArithmeticFlags(x); + break; + case 0xa3: // n/a + break; + case 0xa4: // LDY - Load Y Register - Zero Page + y = bus.read(operands[0]); + setArithmeticFlags(y); + break; + case 0xa5: // LDA - Load Accumulator - Zero Page + a = bus.read(operands[0]); + setArithmeticFlags(a); + break; + case 0xa6: // LDA - Load X Register - Zero Page + x = bus.read(operands[0]); + setArithmeticFlags(x); + break; + case 0xa7: // n/a + break; + case 0xa8: // TAY - Transfer Accumulator to Y - Implied + y = a; + setArithmeticFlags(y); + break; + case 0xa9: // LDA - Immediate + a = operands[0]; + setArithmeticFlags(a); + break; + case 0xaa: // TAX - Transfer Accumulator to X - Implied + x = a; + setArithmeticFlags(x); + break; + case 0xab: // n/a + break; + case 0xac: // n/a + break; + case 0xad: // n/a + break; + case 0xae: // n/a + break; + case 0xaf: // n/a + break; - case 0xb0: // n/a - break; - case 0xb1: // n/a - break; - case 0xb2: // n/a - break; - case 0xb3: // n/a - break; - case 0xb4: // n/a - break; - case 0xb5: // n/a - break; - case 0xb6: // n/a - break; - case 0xb7: // n/a - break; - case 0xb8: // CLV - Clear Overflow Flag - Implied - clearOverflowFlag(); - break; - case 0xb9: // n/a - break; - case 0xba: // TSX - Transfer Stack Pointer to X - Implied - x = getStackPointer(); - setArithmeticFlags(x); - break; - case 0xbb: // n/a - break; - case 0xbc: // n/a - break; - case 0xbd: // n/a - break; - case 0xbe: // n/a - break; - case 0xbf: // n/a - break; + case 0xb0: // n/a + break; + case 0xb1: // n/a + break; + case 0xb2: // n/a + break; + case 0xb3: // n/a + break; + case 0xb4: // n/a + break; + case 0xb5: // n/a + break; + case 0xb6: // n/a + break; + case 0xb7: // n/a + break; + case 0xb8: // CLV - Clear Overflow Flag - Implied + clearOverflowFlag(); + break; + case 0xb9: // n/a + break; + case 0xba: // TSX - Transfer Stack Pointer to X - Implied + x = getStackPointer(); + setArithmeticFlags(x); + break; + case 0xbb: // n/a + break; + case 0xbc: // n/a + break; + case 0xbd: // n/a + break; + case 0xbe: // n/a + break; + case 0xbf: // n/a + break; - case 0xc0: // CPY - Compare Y Register - Immediate - cmp(y, operands[0]); - break; - case 0xc1: // n/a - break; - case 0xc2: // n/a - break; - case 0xc3: // n/a - break; - case 0xc4: // CPY - Compare Y Register - Zero Page - cmp(y, bus.read(operands[0])); - break; - case 0xc5: // CMP - Compare Accumulator - Zero Page - cmp(a, bus.read(operands[0])); - break; - case 0xc6: // DEC - Decrement Memory - Zero Page - j = bus.read(operands[0]); - k = --j & 0xff; - bus.write(operands[0], k); - setArithmeticFlags(k); - break; - case 0xc7: // n/a - break; - case 0xc8: // INY - Increment Y Register - Implied - y = ++y & 0xff; - setArithmeticFlags(y); - break; - case 0xc9: // CMP - Immediate - cmp(a, operands[0]); - break; - case 0xca: // DEX - Decrement X Register - Implied - x = --x & 0xff; - setArithmeticFlags(x); - break; - case 0xcb: // n/a - break; - case 0xcc: // n/a - break; - case 0xcd: // n/a - break; - case 0xce: // n/a - break; - case 0xcf: // n/a - break; + case 0xc0: // CPY - Compare Y Register - Immediate + cmp(y, operands[0]); + break; + case 0xc1: // n/a + break; + case 0xc2: // n/a + break; + case 0xc3: // n/a + break; + case 0xc4: // CPY - Compare Y Register - Zero Page + cmp(y, bus.read(operands[0])); + break; + case 0xc5: // CMP - Compare Accumulator - Zero Page + cmp(a, bus.read(operands[0])); + break; + case 0xc6: // DEC - Decrement Memory - Zero Page + j = bus.read(operands[0]); + k = --j & 0xff; + bus.write(operands[0], k); + setArithmeticFlags(k); + break; + case 0xc7: // n/a + break; + case 0xc8: // INY - Increment Y Register - Implied + y = ++y & 0xff; + setArithmeticFlags(y); + break; + case 0xc9: // CMP - Immediate + cmp(a, operands[0]); + break; + case 0xca: // DEX - Decrement X Register - Implied + x = --x & 0xff; + setArithmeticFlags(x); + break; + case 0xcb: // n/a + break; + case 0xcc: // n/a + break; + case 0xcd: // n/a + break; + case 0xce: // n/a + break; + case 0xcf: // n/a + break; - case 0xd0: // n/a - break; - case 0xd1: // n/a - break; - case 0xd2: // n/a - break; - case 0xd3: // n/a - break; - case 0xd4: // n/a - break; - case 0xd5: // n/a - break; - case 0xd6: // n/a - break; - case 0xd7: // n/a - break; - case 0xd8: // CLD - Clear Decimal Mode - Implied - clearDecimalModeFlag(); - break; - case 0xd9: // n/a - break; - case 0xda: // n/a - break; - case 0xdb: // n/a - break; - case 0xdc: // n/a - break; - case 0xdd: // n/a - break; - case 0xde: // n/a - break; - case 0xdf: // n/a - break; + case 0xd0: // n/a + break; + case 0xd1: // n/a + break; + case 0xd2: // n/a + break; + case 0xd3: // n/a + break; + case 0xd4: // n/a + break; + case 0xd5: // n/a + break; + case 0xd6: // n/a + break; + case 0xd7: // n/a + break; + case 0xd8: // CLD - Clear Decimal Mode - Implied + clearDecimalModeFlag(); + break; + case 0xd9: // n/a + break; + case 0xda: // n/a + break; + case 0xdb: // n/a + break; + case 0xdc: // n/a + break; + case 0xdd: // n/a + break; + case 0xde: // n/a + break; + case 0xdf: // n/a + break; - case 0xe0: // CPX - Compare X Register - Immediate - cmp(x, operands[0]); - break; - case 0xe1: // n/a - break; - case 0xe2: // n/a - break; - case 0xe3: // n/a - break; - case 0xe4: // CPX - Compare X Register - Zero Page - cmp(x, bus.read(operands[0])); - break; - case 0xe5: // SBC - Subtract with Carry (Borrow) - Zero Page - j = bus.read(operands[0]); - if (decimalModeFlag) { - a = sbcDecimal(a, j); - } else { - a = sbc(a, j); - } - break; - case 0xe6: // INC - Increment Memory - Zero Page - j = bus.read(operands[0]); - k = ++j & 0xff; - bus.write(operands[0], k); - setArithmeticFlags(k); - break; - case 0xe7: // n/a - break; - case 0xe8: // INX - Increment X Register - Implied - x = ++x & 0xff; - setArithmeticFlags(x); - break; - case 0xe9: // SBC - Subtract with Carry (Borrow) - Immediate - if (decimalModeFlag) { - a = sbcDecimal(a, operands[0]); - } else { - a = sbc(a, operands[0]); - } - break; - case 0xea: // NOP - // Does nothing. - break; - case 0xeb: // n/a - break; - case 0xec: // n/a - break; - case 0xed: // n/a - break; - case 0xee: // n/a - break; - case 0xef: // n/a - break; + case 0xe0: // CPX - Compare X Register - Immediate + cmp(x, operands[0]); + break; + case 0xe1: // n/a + break; + case 0xe2: // n/a + break; + case 0xe3: // n/a + break; + case 0xe4: // CPX - Compare X Register - Zero Page + cmp(x, bus.read(operands[0])); + break; + case 0xe5: // SBC - Subtract with Carry (Borrow) - Zero Page + j = bus.read(operands[0]); + if (decimalModeFlag) { + a = sbcDecimal(a, j); + } else { + a = sbc(a, j); + } + break; + case 0xe6: // INC - Increment Memory - Zero Page + j = bus.read(operands[0]); + k = ++j & 0xff; + bus.write(operands[0], k); + setArithmeticFlags(k); + break; + case 0xe7: // n/a + break; + case 0xe8: // INX - Increment X Register - Implied + x = ++x & 0xff; + setArithmeticFlags(x); + break; + case 0xe9: // SBC - Subtract with Carry (Borrow) - Immediate + if (decimalModeFlag) { + a = sbcDecimal(a, operands[0]); + } else { + a = sbc(a, operands[0]); + } + break; + case 0xea: // NOP + // Does nothing. + break; + case 0xeb: // n/a + break; + case 0xec: // n/a + break; + case 0xed: // n/a + break; + case 0xee: // n/a + break; + case 0xef: // n/a + break; - case 0xf0: // n/a - break; - case 0xf1: // n/a - break; - case 0xf2: // n/a - break; - case 0xf3: // n/a - break; - case 0xf4: // n/a - break; - case 0xf5: // n/a - break; - case 0xf6: // n/a - break; - case 0xf7: // n/a - break; - case 0xf8: // SED - Set Decimal Flag - Implied - setDecimalModeFlag(); - break; - case 0xf9: // n/a - break; - case 0xfa: // n/a - break; - case 0xfb: // n/a - break; - case 0xfc: // n/a - break; - case 0xfd: // n/a - break; - case 0xfe: // n/a - break; - case 0xff: // n/a - break; - } - } + case 0xf0: // n/a + break; + case 0xf1: // n/a + break; + case 0xf2: // n/a + break; + case 0xf3: // n/a + break; + case 0xf4: // n/a + break; + case 0xf5: // n/a + break; + case 0xf6: // n/a + break; + case 0xf7: // n/a + break; + case 0xf8: // SED - Set Decimal Flag - Implied + setDecimalModeFlag(); + break; + case 0xf9: // n/a + break; + case 0xfa: // n/a + break; + case 0xfb: // n/a + break; + case 0xfc: // n/a + break; + case 0xfd: // n/a + break; + case 0xfe: // n/a + break; + case 0xff: // n/a + break; + } + } - /** - * Add with Carry, used by all addressing mode implementations of ADC. - * As a side effect, this will set the overflow and carry flags as - * needed. - * - * @param acc The current value of the accumulator - * @param operand The operand - * @return - */ - public int adc(int acc, int operand) { - int result = (operand & 0xff) + (acc & 0xff) + getCarryBit(); - int carry6 = (operand & 0x7f) + (acc & 0x7f) + getCarryBit(); - setCarryFlag((result & 0x100) != 0); - setOverflowFlag(carryFlag ^ ((carry6 & 0x80) != 0)); - result &= 0xff; - setArithmeticFlags(result); - return result; - } + /** + * Add with Carry, used by all addressing mode implementations of ADC. + * As a side effect, this will set the overflow and carry flags as + * needed. + * + * @param acc The current value of the accumulator + * @param operand The operand + * @return + */ + public int adc(int acc, int operand) { + int result = (operand & 0xff) + (acc & 0xff) + getCarryBit(); + int carry6 = (operand & 0x7f) + (acc & 0x7f) + getCarryBit(); + setCarryFlag((result & 0x100) != 0); + setOverflowFlag(carryFlag ^ ((carry6 & 0x80) != 0)); + result &= 0xff; + setArithmeticFlags(result); + return result; + } - /** - * Add with Carry (BCD). - */ + /** + * Add with Carry (BCD). + */ - public int adcDecimal(int acc, int operand) { - int l, h, result; - l = (acc & 0x0f) + (operand & 0x0f) + getCarryBit(); - if ((l & 0xff) > 9) l += 6; - h = (acc >> 4) + (operand >> 4) + (l > 15 ? 1 : 0); - if ((h & 0xff) > 9) h += 6; - result = (l & 0x0f) | (h << 4); - result &= 0xff; - setCarryFlag(h > 15); - setZeroFlag(result == 0); - setNegativeFlag(false); // BCD is never negative - setOverflowFlag(false); // BCD never sets overflow flag - return result; - } + public int adcDecimal(int acc, int operand) { + int l, h, result; + l = (acc & 0x0f) + (operand & 0x0f) + getCarryBit(); + if ((l & 0xff) > 9) l += 6; + h = (acc >> 4) + (operand >> 4) + (l > 15 ? 1 : 0); + if ((h & 0xff) > 9) h += 6; + result = (l & 0x0f) | (h << 4); + result &= 0xff; + setCarryFlag(h > 15); + setZeroFlag(result == 0); + setNegativeFlag(false); // BCD is never negative + setOverflowFlag(false); // BCD never sets overflow flag + return result; + } - /** - * Common code for Subtract with Carry. Just calls ADC of the - * one's complement of the operand. This lets the N, V, C, and Z - * flags work out nicely without any additional logic. - * - * @param acc - * @param operand - * @return - */ - public int sbc(int acc, int operand) { - int result; - result = adc(acc, ~operand); - setArithmeticFlags(result); - return result; - } + /** + * Common code for Subtract with Carry. Just calls ADC of the + * one's complement of the operand. This lets the N, V, C, and Z + * flags work out nicely without any additional logic. + * + * @param acc + * @param operand + * @return + */ + public int sbc(int acc, int operand) { + int result; + result = adc(acc, ~operand); + setArithmeticFlags(result); + return result; + } - /** - * Subtract with Carry, BCD mode. - * - * @param acc - * @param operand - * @return - */ - public int sbcDecimal(int acc, int operand) { - int l, h, result; - l = (acc & 0x0f) - (operand & 0x0f) - (carryFlag ? 0 : 1); - if ((l & 0x10) != 0) l -= 6; - h = (acc >> 4) - (operand >> 4) - ((l & 0x10) != 0 ? 1 : 0); - if ((h & 0x10) != 0) h -= 6; - result = (l & 0x0f) | (h << 4); - setCarryFlag((h & 0xff) < 15); - setZeroFlag(result == 0); - setNegativeFlag(false); // BCD is never negative - setOverflowFlag(false); // BCD never sets overflow flag - return (result & 0xff); - } + /** + * Subtract with Carry, BCD mode. + * + * @param acc + * @param operand + * @return + */ + public int sbcDecimal(int acc, int operand) { + int l, h, result; + l = (acc & 0x0f) - (operand & 0x0f) - (carryFlag ? 0 : 1); + if ((l & 0x10) != 0) l -= 6; + h = (acc >> 4) - (operand >> 4) - ((l & 0x10) != 0 ? 1 : 0); + if ((h & 0x10) != 0) h -= 6; + result = (l & 0x0f) | (h << 4); + setCarryFlag((h & 0xff) < 15); + setZeroFlag(result == 0); + setNegativeFlag(false); // BCD is never negative + setOverflowFlag(false); // BCD never sets overflow flag + return (result & 0xff); + } - /** - * Compare two values, and set carry, zero, and negative flags - * appropriately. - * - * @param reg - * @param operand - */ - public void cmp(int reg, int operand) { - setCarryFlag(reg >= operand); - setZeroFlag(reg == operand); - setNegativeFlag((reg - operand) > 0); - } + /** + * Compare two values, and set carry, zero, and negative flags + * appropriately. + * + * @param reg + * @param operand + */ + public void cmp(int reg, int operand) { + setCarryFlag(reg >= operand); + setZeroFlag(reg == operand); + setNegativeFlag((reg - operand) > 0); + } - /** - * Set the Negative and Zero flags based on the current value of the - * register operand. - * - * @param reg The register. - */ - public void setArithmeticFlags(int reg) { - zeroFlag = (reg == 0); - negativeFlag = (reg & 0x80) != 0; - } + /** + * Set the Negative and Zero flags based on the current value of the + * register operand. + * + * @param reg The register. + */ + public void setArithmeticFlags(int reg) { + zeroFlag = (reg == 0); + negativeFlag = (reg & 0x80) != 0; + } - /** - * Shifts the given value left by one bit, and sets the carry - * flag to the high bit of the initial value. - * - * @param m The value to shift left. - * @return the left shifted value (m * 2). - */ + /** + * Shifts the given value left by one bit, and sets the carry + * flag to the high bit of the initial value. + * + * @param m The value to shift left. + * @return the left shifted value (m * 2). + */ private int asl(int m) { - setCarryFlag((m & 0x80) != 0); - return (m << 1) & 0xff; - } - - /** - * Shifts the given value right by one bit, filling with zeros, - * and sets the carry flag to the low bit of the initial value. - */ - private int lsr(int m) { - setCarryFlag((m & 0x01) != 0); - return (m >>> 1) & 0xff; - } - - /** - * Rotates the given value left by one bit, setting bit 0 to the value - * of the carry flag, and setting the carry flag to the original value - * of bit 7. - */ - private int rol(int m) { - int result = ((m << 1) | getCarryBit()) & 0xff; - setCarryFlag((m & 0x80) != 0); - return result; - } - - /** - * Rotates the given value right by one bit, setting bit 7 to the value - * of the carry flag, and setting the carry flag to the original value - * of bit 1. - */ - private int ror(int m) { - int result = ((m >>> 1) | (getCarryBit() << 7)) & 0xff; - setCarryFlag((m & 0x01) != 0); - return result; - } - - /** - * @return the negative flag - */ - public boolean getNegativeFlag() { - return negativeFlag; - } - - /** - * @return 1 if the negative flag is set, 0 if it is clear. - */ - public int getNegativeBit() { - return (negativeFlag ? 1 : 0); - } - - /** - * @param register the register value to test for negativity - */ - public void setNegativeFlag(int register) { - negativeFlag = (register < 0); - } - - /** - * @param negativeFlag the negative flag to set - */ - public void setNegativeFlag(boolean negativeFlag) { - this.negativeFlag = negativeFlag; - } - - public void setNegativeFlag() { - this.negativeFlag = true; - } - - public void clearNegativeFlag() { - this.negativeFlag = false; - } - - /** - * @return the carry flag - */ - public boolean getCarryFlag() { - return carryFlag; - } - - /** - * @return 1 if the carry flag is set, 0 if it is clear. - */ - public int getCarryBit() { - return (carryFlag ? 1 : 0); - } - - /** - * @param carryFlag the carry flag to set - */ - public void setCarryFlag(boolean carryFlag) { - this.carryFlag = carryFlag; - } - - /** - * Sets the Carry Flag - */ - public void setCarryFlag() { - this.carryFlag = true; - } - - /** - * Clears the Carry Flag - */ - public void clearCarryFlag() { - this.carryFlag = false; - } - - /** - * @return the zero flag - */ - public boolean getZeroFlag() { - return zeroFlag; - } - - /** - * @return 1 if the zero flag is set, 0 if it is clear. - */ - public int getZeroBit() { - return (zeroFlag ? 1 : 0); - } - - /** - * @param zeroFlag the zero flag to set - */ - public void setZeroFlag(boolean zeroFlag) { - this.zeroFlag = zeroFlag; - } - - /** - * Sets the Zero Flag - */ - public void setZeroFlag() { - this.zeroFlag = true; - } - - /** - * Clears the Zero Flag - */ - public void clearZeroFlag() { - this.zeroFlag = false; - } - - /** - * @return the irq disable flag - */ - public boolean getIrqDisableFlag() { - return irqDisableFlag; - } - - /** - * @return 1 if the interrupt disable flag is set, 0 if it is clear. - */ - public int getIrqDisableBit() { - return (irqDisableFlag ? 1 : 0); - } - - /** - * @param irqDisableFlag the irq disable flag to set - */ - public void setIrqDisableFlag(boolean irqDisableFlag) { - this.irqDisableFlag = irqDisableFlag; - } - - public void setIrqDisableFlag() { - this.irqDisableFlag = true; - } - - public void clearIrqDisableFlag() { - this.irqDisableFlag = false; - } - - - /** - * @return the decimal mode flag - */ - public boolean getDecimalModeFlag() { - return decimalModeFlag; - } - - /** - * @return 1 if the decimal mode flag is set, 0 if it is clear. - */ - public int getDecimalModeBit() { - return (decimalModeFlag ? 1 : 0); - } - - /** - * @param decimalModeFlag the decimal mode flag to set - */ - public void setDecimalModeFlag(boolean decimalModeFlag) { - this.decimalModeFlag = decimalModeFlag; - } - - /** - * Sets the Decimal Mode Flag to true. - */ - public void setDecimalModeFlag() { - this.decimalModeFlag = true; - } - - /** - * Clears the Decimal Mode Flag. - */ - public void clearDecimalModeFlag() { - this.decimalModeFlag = false; - } - - /** - * @return the break flag - */ - public boolean getBreakFlag() { - return breakFlag; - } - - /** - * @return 1 if the break flag is set, 0 if it is clear. - */ - public int getBreakBit() { - return (carryFlag ? 1 : 0); - } - - /** - * @param breakFlag the break flag to set - */ - public void setBreakFlag(boolean breakFlag) { - this.breakFlag = breakFlag; - } - - /** - * Sets the Break Flag - */ - public void setBreakFlag() { - this.breakFlag = true; - } - - /** - * Clears the Break Flag - */ - public void clearBreakFlag() { - this.breakFlag = false; - } - - /** - * @return the overflow flag - */ - public boolean getOverflowFlag() { - return overflowFlag; - } - - /** - * @return 1 if the overflow flag is set, 0 if it is clear. - */ - public int getOverflowBit() { - return (overflowFlag ? 1 : 0); - } - - /** - * @param overflowFlag the overflow flag to set - */ - public void setOverflowFlag(boolean overflowFlag) { - this.overflowFlag = overflowFlag; - } - - /** - * Sets the Overflow Flag - */ - public void setOverflowFlag() { - this.overflowFlag = true; - } - - /** - * Clears the Overflow Flag - */ - public void clearOverflowFlag() { - this.overflowFlag = false; - } - - public int getAccumulator() { - return a; - } - - public void setAccumulator(int val) { - this.a = val; - } - - public int getXRegister() { - return x; - } - - public void setXRegister(int val) { - this.x = val; - } - - public int getYRegister() { - return y; - } - - public void setYRegister(int val) { - this.y = val; - } - - public int getProgramCounter() { - return pc; - } - - public void setProgramCounter(int addr) { - this.pc = addr; - } - - public int getStackPointer() { - return sp; - } - - public void setStackPointer(int offset) { - this.sp = offset; - } - - /** - * @value The value of the Process Status Register bits to be set. - */ - public void setProcessorStatus(int value) { - if ((value&P_CARRY) != 0) - setCarryFlag(); - else - clearCarryFlag(); - - if ((value&P_ZERO) != 0) - setZeroFlag(); - else - clearZeroFlag(); - - if ((value&P_IRQ_DISABLE) != 0) - setIrqDisableFlag(); - else - clearIrqDisableFlag(); - - if ((value&P_DECIMAL) != 0) - setDecimalModeFlag(); - else - clearDecimalModeFlag(); - - if ((value&P_BREAK) != 0) - setBreakFlag(); - else - clearBreakFlag(); - - if ((value&P_OVERFLOW) != 0) - setOverflowFlag(); - else - clearOverflowFlag(); - - if ((value&P_NEGATIVE) != 0) - setNegativeFlag(); - else - clearNegativeFlag(); - } - - /** - * @returns The value of the Process Status Register, as a byte. - */ - public int getProcessorStatus() { - int status = 0x20; - if (getCarryFlag()) { status |= P_CARRY; } - if (getZeroFlag()) { status |= P_ZERO; } - if (getIrqDisableFlag()) { status |= P_IRQ_DISABLE; } - if (getDecimalModeFlag()) { status |= P_DECIMAL; } - if (getBreakFlag()) { status |= P_BREAK; } - if (getOverflowFlag()) { status |= P_OVERFLOW; } - if (getNegativeFlag()) { status |= P_NEGATIVE; } - return status; - } - - /** - * @return A string representing the current status register state. - */ - public String statusRegisterString() { - StringBuffer sb = new StringBuffer("["); - sb.append(getNegativeFlag() ? 'N' : '.'); // Bit 7 - sb.append(getOverflowFlag() ? 'V' : '.'); // Bit 6 - sb.append("-"); // Bit 5 (always 1) - sb.append(getBreakFlag() ? 'B' : '.'); // Bit 4 - sb.append(getDecimalModeFlag() ? 'D' : '.'); // Bit 3 - sb.append(getIrqDisableFlag() ? 'I' : '.'); // Bit 2 - sb.append(getZeroFlag() ? 'Z' : '.'); // Bit 1 - sb.append(getCarryFlag() ? 'C' : '.'); // Bit 0 - sb.append("]"); - return sb.toString(); - } - - /** - * Returns a string representing the CPU state. - */ - public String toString() { - String opcode = opcode(ir, operands[0], operands[1]); - StringBuffer sb = new StringBuffer(String.format("$%04X", addr) + - " "); - sb.append(String.format("%-14s", opcode)); - sb.append("A=" + String.format("$%02X", a) + " "); - sb.append("X=" + String.format("$%02X", x) + " "); - sb.append("Y=" + String.format("$%02X", y) + " "); - sb.append("PC=" + String.format("$%04X", pc)+ " "); - sb.append("P=" + statusRegisterString()); - return sb.toString(); - } - - /** - * Push an item onto the stack, and decrement the stack counter. - * Silently fails to push onto the stack if SP is - */ - void stackPush(int data) { - bus.write(0x100+sp, data); - - if (sp == 0) - sp = 0xff; - else - --sp; - } - - - /** - * Pre-increment the stack pointer, and return the top of the stack. - */ - int stackPop() { - if (sp == 0xff) - sp = 0x00; - else - ++sp; - - int data = bus.read(0x100+sp); - - return data; - } - - /** - * Peek at the value currently at the top of the stack - */ - int stackPeek() { - return bus.read(0x100+sp+1); - } - - /* - * Increment the PC, rolling over if necessary. - */ - void incrementPC() { - if (pc == 0xffff) { - pc = 0; - } else { - ++pc; - } - } - - /** - * Given two bytes, return an address. - */ - int address(int lowByte, int hiByte) { - return ((hiByte<<8)|lowByte); - } - - /** - * Given an opcode and its operands, return a formatted name. - * - * @param opcode - * @param operands - * @return - */ - String opcode(int opcode, int op1, int op2) { - String opcodeName = Cpu.opcodeNames[opcode]; - if (opcodeName == null) { return "???"; } - - StringBuffer sb = new StringBuffer(opcodeName); - - switch (Cpu.instructionModes[opcode]) { - case ABS: - sb.append(String.format(" $%04X", address(op1, op2))); - break; - case IMM: - sb.append(String.format(" #$%02X", op1)); - } - - return sb.toString(); - } + setCarryFlag((m & 0x80) != 0); + return (m << 1) & 0xff; + } + + /** + * Shifts the given value right by one bit, filling with zeros, + * and sets the carry flag to the low bit of the initial value. + */ + private int lsr(int m) { + setCarryFlag((m & 0x01) != 0); + return (m >>> 1) & 0xff; + } + + /** + * Rotates the given value left by one bit, setting bit 0 to the value + * of the carry flag, and setting the carry flag to the original value + * of bit 7. + */ + private int rol(int m) { + int result = ((m << 1) | getCarryBit()) & 0xff; + setCarryFlag((m & 0x80) != 0); + return result; + } + + /** + * Rotates the given value right by one bit, setting bit 7 to the value + * of the carry flag, and setting the carry flag to the original value + * of bit 1. + */ + private int ror(int m) { + int result = ((m >>> 1) | (getCarryBit() << 7)) & 0xff; + setCarryFlag((m & 0x01) != 0); + return result; + } + + /** + * @return the negative flag + */ + public boolean getNegativeFlag() { + return negativeFlag; + } + + /** + * @return 1 if the negative flag is set, 0 if it is clear. + */ + public int getNegativeBit() { + return (negativeFlag ? 1 : 0); + } + + /** + * @param register the register value to test for negativity + */ + public void setNegativeFlag(int register) { + negativeFlag = (register < 0); + } + + /** + * @param negativeFlag the negative flag to set + */ + public void setNegativeFlag(boolean negativeFlag) { + this.negativeFlag = negativeFlag; + } + + public void setNegativeFlag() { + this.negativeFlag = true; + } + + public void clearNegativeFlag() { + this.negativeFlag = false; + } + + /** + * @return the carry flag + */ + public boolean getCarryFlag() { + return carryFlag; + } + + /** + * @return 1 if the carry flag is set, 0 if it is clear. + */ + public int getCarryBit() { + return (carryFlag ? 1 : 0); + } + + /** + * @param carryFlag the carry flag to set + */ + public void setCarryFlag(boolean carryFlag) { + this.carryFlag = carryFlag; + } + + /** + * Sets the Carry Flag + */ + public void setCarryFlag() { + this.carryFlag = true; + } + + /** + * Clears the Carry Flag + */ + public void clearCarryFlag() { + this.carryFlag = false; + } + + /** + * @return the zero flag + */ + public boolean getZeroFlag() { + return zeroFlag; + } + + /** + * @return 1 if the zero flag is set, 0 if it is clear. + */ + public int getZeroBit() { + return (zeroFlag ? 1 : 0); + } + + /** + * @param zeroFlag the zero flag to set + */ + public void setZeroFlag(boolean zeroFlag) { + this.zeroFlag = zeroFlag; + } + + /** + * Sets the Zero Flag + */ + public void setZeroFlag() { + this.zeroFlag = true; + } + + /** + * Clears the Zero Flag + */ + public void clearZeroFlag() { + this.zeroFlag = false; + } + + /** + * @return the irq disable flag + */ + public boolean getIrqDisableFlag() { + return irqDisableFlag; + } + + /** + * @return 1 if the interrupt disable flag is set, 0 if it is clear. + */ + public int getIrqDisableBit() { + return (irqDisableFlag ? 1 : 0); + } + + /** + * @param irqDisableFlag the irq disable flag to set + */ + public void setIrqDisableFlag(boolean irqDisableFlag) { + this.irqDisableFlag = irqDisableFlag; + } + + public void setIrqDisableFlag() { + this.irqDisableFlag = true; + } + + public void clearIrqDisableFlag() { + this.irqDisableFlag = false; + } + + + /** + * @return the decimal mode flag + */ + public boolean getDecimalModeFlag() { + return decimalModeFlag; + } + + /** + * @return 1 if the decimal mode flag is set, 0 if it is clear. + */ + public int getDecimalModeBit() { + return (decimalModeFlag ? 1 : 0); + } + + /** + * @param decimalModeFlag the decimal mode flag to set + */ + public void setDecimalModeFlag(boolean decimalModeFlag) { + this.decimalModeFlag = decimalModeFlag; + } + + /** + * Sets the Decimal Mode Flag to true. + */ + public void setDecimalModeFlag() { + this.decimalModeFlag = true; + } + + /** + * Clears the Decimal Mode Flag. + */ + public void clearDecimalModeFlag() { + this.decimalModeFlag = false; + } + + /** + * @return the break flag + */ + public boolean getBreakFlag() { + return breakFlag; + } + + /** + * @return 1 if the break flag is set, 0 if it is clear. + */ + public int getBreakBit() { + return (carryFlag ? 1 : 0); + } + + /** + * @param breakFlag the break flag to set + */ + public void setBreakFlag(boolean breakFlag) { + this.breakFlag = breakFlag; + } + + /** + * Sets the Break Flag + */ + public void setBreakFlag() { + this.breakFlag = true; + } + + /** + * Clears the Break Flag + */ + public void clearBreakFlag() { + this.breakFlag = false; + } + + /** + * @return the overflow flag + */ + public boolean getOverflowFlag() { + return overflowFlag; + } + + /** + * @return 1 if the overflow flag is set, 0 if it is clear. + */ + public int getOverflowBit() { + return (overflowFlag ? 1 : 0); + } + + /** + * @param overflowFlag the overflow flag to set + */ + public void setOverflowFlag(boolean overflowFlag) { + this.overflowFlag = overflowFlag; + } + + /** + * Sets the Overflow Flag + */ + public void setOverflowFlag() { + this.overflowFlag = true; + } + + /** + * Clears the Overflow Flag + */ + public void clearOverflowFlag() { + this.overflowFlag = false; + } + + public int getAccumulator() { + return a; + } + + public void setAccumulator(int val) { + this.a = val; + } + + public int getXRegister() { + return x; + } + + public void setXRegister(int val) { + this.x = val; + } + + public int getYRegister() { + return y; + } + + public void setYRegister(int val) { + this.y = val; + } + + public int getProgramCounter() { + return pc; + } + + public void setProgramCounter(int addr) { + this.pc = addr; + } + + public int getStackPointer() { + return sp; + } + + public void setStackPointer(int offset) { + this.sp = offset; + } + + /** + * @value The value of the Process Status Register bits to be set. + */ + public void setProcessorStatus(int value) { + if ((value&P_CARRY) != 0) + setCarryFlag(); + else + clearCarryFlag(); + + if ((value&P_ZERO) != 0) + setZeroFlag(); + else + clearZeroFlag(); + + if ((value&P_IRQ_DISABLE) != 0) + setIrqDisableFlag(); + else + clearIrqDisableFlag(); + + if ((value&P_DECIMAL) != 0) + setDecimalModeFlag(); + else + clearDecimalModeFlag(); + + if ((value&P_BREAK) != 0) + setBreakFlag(); + else + clearBreakFlag(); + + if ((value&P_OVERFLOW) != 0) + setOverflowFlag(); + else + clearOverflowFlag(); + + if ((value&P_NEGATIVE) != 0) + setNegativeFlag(); + else + clearNegativeFlag(); + } + + /** + * @returns The value of the Process Status Register, as a byte. + */ + public int getProcessorStatus() { + int status = 0x20; + if (getCarryFlag()) { status |= P_CARRY; } + if (getZeroFlag()) { status |= P_ZERO; } + if (getIrqDisableFlag()) { status |= P_IRQ_DISABLE; } + if (getDecimalModeFlag()) { status |= P_DECIMAL; } + if (getBreakFlag()) { status |= P_BREAK; } + if (getOverflowFlag()) { status |= P_OVERFLOW; } + if (getNegativeFlag()) { status |= P_NEGATIVE; } + return status; + } + + /** + * @return A string representing the current status register state. + */ + public String statusRegisterString() { + StringBuffer sb = new StringBuffer("["); + sb.append(getNegativeFlag() ? 'N' : '.'); // Bit 7 + sb.append(getOverflowFlag() ? 'V' : '.'); // Bit 6 + sb.append("-"); // Bit 5 (always 1) + sb.append(getBreakFlag() ? 'B' : '.'); // Bit 4 + sb.append(getDecimalModeFlag() ? 'D' : '.'); // Bit 3 + sb.append(getIrqDisableFlag() ? 'I' : '.'); // Bit 2 + sb.append(getZeroFlag() ? 'Z' : '.'); // Bit 1 + sb.append(getCarryFlag() ? 'C' : '.'); // Bit 0 + sb.append("]"); + return sb.toString(); + } + + /** + * Returns a string representing the CPU state. + */ + public String toString() { + String opcode = opcode(ir, operands[0], operands[1]); + StringBuffer sb = new StringBuffer(String.format("$%04X", addr) + + " "); + sb.append(String.format("%-14s", opcode)); + sb.append("A=" + String.format("$%02X", a) + " "); + sb.append("X=" + String.format("$%02X", x) + " "); + sb.append("Y=" + String.format("$%02X", y) + " "); + sb.append("PC=" + String.format("$%04X", pc)+ " "); + sb.append("P=" + statusRegisterString()); + return sb.toString(); + } + + /** + * Push an item onto the stack, and decrement the stack counter. + * Silently fails to push onto the stack if SP is + */ + void stackPush(int data) { + bus.write(0x100+sp, data); + + if (sp == 0) + sp = 0xff; + else + --sp; + } + + + /** + * Pre-increment the stack pointer, and return the top of the stack. + */ + int stackPop() { + if (sp == 0xff) + sp = 0x00; + else + ++sp; + + int data = bus.read(0x100+sp); + + return data; + } + + /** + * Peek at the value currently at the top of the stack + */ + int stackPeek() { + return bus.read(0x100+sp+1); + } + + /* + * Increment the PC, rolling over if necessary. + */ + void incrementPC() { + if (pc == 0xffff) { + pc = 0; + } else { + ++pc; + } + } + + /** + * Given two bytes, return an address. + */ + int address(int lowByte, int hiByte) { + return ((hiByte<<8)|lowByte); + } + + /** + * Given an opcode and its operands, return a formatted name. + * + * @param opcode + * @param operands + * @return + */ + String opcode(int opcode, int op1, int op2) { + String opcodeName = Cpu.opcodeNames[opcode]; + if (opcodeName == null) { return "???"; } + + StringBuffer sb = new StringBuffer(opcodeName); + + switch (Cpu.instructionModes[opcode]) { + case ABS: + sb.append(String.format(" $%04X", address(op1, op2))); + break; + case IMM: + sb.append(String.format(" #$%02X", op1)); + } + + return sb.toString(); + } } \ No newline at end of file diff --git a/src/main/java/com/loomcom/symon/InstructionTable.java b/src/main/java/com/loomcom/symon/InstructionTable.java index 22e26a3..65e4870 100644 --- a/src/main/java/com/loomcom/symon/InstructionTable.java +++ b/src/main/java/com/loomcom/symon/InstructionTable.java @@ -2,248 +2,248 @@ package com.loomcom.symon; public interface InstructionTable { - /** - * Enumeration of Addressing Modes. - */ - public enum Mode { - ACC { - public String toString() { - return "Accumulator"; - } - }, + /** + * Enumeration of Addressing Modes. + */ + public enum Mode { + ACC { + public String toString() { + return "Accumulator"; + } + }, - ABS { - public String toString() { - return "Absolute"; - } - }, + ABS { + public String toString() { + return "Absolute"; + } + }, - ABX { - public String toString() { - return "Absolute, X-indexed"; - } - }, + ABX { + public String toString() { + return "Absolute, X-indexed"; + } + }, - ABY { - public String toString() { - return "Absolute, Y-indexed"; - } - }, + ABY { + public String toString() { + return "Absolute, Y-indexed"; + } + }, - IMM { - public String toString() { - return "Immediate"; - } - }, + IMM { + public String toString() { + return "Immediate"; + } + }, - IMP { - public String toString() { - return "Implied"; - } - }, + IMP { + public String toString() { + return "Implied"; + } + }, - IND { - public String toString() { - return "Indirect"; - } - }, + IND { + public String toString() { + return "Indirect"; + } + }, - XIN { - public String toString() { - return "X-indexed Indirect"; - } - }, + XIN { + public String toString() { + return "X-indexed Indirect"; + } + }, - INY { - public String toString() { - return "Indirect, Y-indexedY"; - } - }, + INY { + public String toString() { + return "Indirect, Y-indexedY"; + } + }, - REL { - public String toString() { - return "Relative"; - } - }, + REL { + public String toString() { + return "Relative"; + } + }, - ZPG { - public String toString() { - return "Zeropage"; - } - }, + ZPG { + public String toString() { + return "Zeropage"; + } + }, - ZPX { - public String toString() { - return "Zeropage, X-indexed"; - } - }, + ZPX { + public String toString() { + return "Zeropage, X-indexed"; + } + }, - ZPY { - public String toString() { - return "Zeropage, Y-indexed"; - } - }, + ZPY { + public String toString() { + return "Zeropage, Y-indexed"; + } + }, - NUL { - public String toString() { - return "NULL"; - } - } - } + NUL { + public String toString() { + return "NULL"; + } + } + } - // 6502 opcodes. No 65C02 opcodes implemented. - - /** - * Instruction opcode names. - */ - public static final String[] opcodeNames = { - "BRK", "ORA", null, null, null, "ORA", "ASL", null, - "PHP", "ORA", "ASL", null, null, "ORA", "ASL", null, - "BPL", "ORA", null, null, null, "ORA", "ASL", null, - "CLC", "ORA", null, null, null, "ORA", "ASL", null, - "JSR", "AND", null, null, "BIT", "AND", "ROL", null, - "PLP", "AND", "ROL", null, "BIT", "AND", "ROL", null, - "BMI", "AND", null, null, null, "AND", "ROL", null, - "SEC", "AND", null, null, null, "AND", "ROL", null, - "RTI", "EOR", null, null, null, "EOR", "LSR", null, - "PHA", "EOR", "LSR", null, "JMP", "EOR", "LSR", null, - "BVC", "EOR", null, null, null, "EOR", "LSR", null, - "CLI", "EOR", null, null, null, "EOR", "LSR", null, - "RTS", "ADC", null, null, null, "ADC", "ROR", null, - "PLA", "ADC", "ROR", null, "JMP", "ADC", "ROR", null, - "BVS", "ADC", null, null, null, "ADC", "ROR", null, - "SEI", "ADC", null, null, null, "ADC", "ROR", null, - "BCS", "STA", null, null, "STY", "STA", "STX", null, - "DEY", null, "TXA", null, "STY", "STA", "STX", null, - "BCC", "STA", null, null, "STY", "STA", "STX", null, - "TYA", "STA", "TXS", null, null, "STA", null, null, - "LDY", "LDA", "LDX", null, "LDY", "LDA", "LDX", null, - "TAY", "LDA", "TAX", null, "LDY", "LDA", "LDX", null, - null, "LDA", null, null, "LDY", "LDA", "LDX", null, - "CLV", "LDA", "TSX", null, "LDY", "LDA", "LDX", null, - "CPY", "CMP", null, null, "CPY", "CMP", "DEC", null, - "INY", "CMP", "DEX", null, "CPY", "CMP", "DEC", null, - "BNE", "CMP", null, null, null, "CMP", "DEC", null, - "CLD", "CMP", null, null, null, "CMP", "DEC", null, - "CPX", "SBC", null, null, "CPX", "SBC", "INC", null, - "INX", "SBC", "NOP", null, "CPX", "SBC", "INC", null, - "BEQ", "SBC", null, null, null, "SBC", "INC", null, - "SED", "SBC", null, null, null, "SBC", "INC", null - }; + // 6502 opcodes. No 65C02 opcodes implemented. - /** - * Instruction addressing modes. - */ - public static final Mode[] instructionModes = { - Mode.IMP, Mode.XIN, Mode.NUL, Mode.NUL, // 0x00-0x03 - Mode.NUL, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0x04-0x07 - Mode.IMP, Mode.IMM, Mode.ACC, Mode.NUL, // 0x08-0x0b - Mode.NUL, Mode.ABS, Mode.ABS, Mode.NUL, // 0x0c-0x0f - Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0x10-0x13 - Mode.NUL, Mode.ZPX, Mode.ZPX, Mode.NUL, // 0x14-0x17 - Mode.IMP, Mode.ABY, Mode.NUL, Mode.NUL, // 0x18-0x1b - Mode.NUL, Mode.ABX, Mode.ABX, Mode.NUL, // 0x1c-0x1f - Mode.ABS, Mode.XIN, Mode.NUL, Mode.NUL, // 0x20-0x23 - Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0x24-0x27 - Mode.IMP, Mode.IMM, Mode.ACC, Mode.NUL, // 0x28-0x2b - Mode.ABS, Mode.ABS, Mode.ABS, Mode.NUL, // 0x2c-0x2f - Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0x30-0x33 - Mode.NUL, Mode.ZPX, Mode.ZPX, Mode.NUL, // 0x34-0x37 - Mode.IMP, Mode.ABY, Mode.NUL, Mode.NUL, // 0x38-0x3b - Mode.NUL, Mode.ABX, Mode.ABX, Mode.NUL, // 0x3c-0x3f - Mode.IMP, Mode.XIN, Mode.NUL, Mode.NUL, // 0x40-0x43 - Mode.NUL, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0x44-0x47 - Mode.IMP, Mode.IMM, Mode.ACC, Mode.NUL, // 0x48-0x4b - Mode.ABS, Mode.ABS, Mode.ABS, Mode.NUL, // 0x4c-0x4f - Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0x50-0x53 - Mode.NUL, Mode.ZPX, Mode.ZPX, Mode.NUL, // 0x54-0x57 - Mode.IMP, Mode.ABY, Mode.NUL, Mode.NUL, // 0x58-0x5b - Mode.NUL, Mode.ABX, Mode.ABX, Mode.NUL, // 0x5c-0x5f - Mode.IMP, Mode.XIN, Mode.NUL, Mode.NUL, // 0x60-0x63 - Mode.NUL, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0x64-0x67 - Mode.IMP, Mode.IMM, Mode.ACC, Mode.NUL, // 0x68-0x6b - Mode.IND, Mode.ABS, Mode.ABS, Mode.NUL, // 0x6c-0x6f - Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0x70-0x73 - Mode.NUL, Mode.ZPX, Mode.ZPX, Mode.NUL, // 0x74-0x77 - Mode.IMP, Mode.ABY, Mode.NUL, Mode.NUL, // 0x78-0x7b - Mode.NUL, Mode.ABX, Mode.ABX, Mode.NUL, // 0x7c-0x7f - Mode.REL, Mode.XIN, Mode.NUL, Mode.NUL, // 0x80-0x83 - Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0x84-0x87 - Mode.IMP, Mode.NUL, Mode.IMP, Mode.NUL, // 0x88-0x8b - Mode.ABS, Mode.ABS, Mode.ABS, Mode.NUL, // 0x8c-0x8f - Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0x90-0x93 - Mode.ZPX, Mode.ZPX, Mode.ZPY, Mode.NUL, // 0x94-0x97 - Mode.IMP, Mode.ABX, Mode.IMP, Mode.NUL, // 0x98-0x9b - Mode.NUL, Mode.ABY, Mode.NUL, Mode.NUL, // 0x9c-0x9f - Mode.IMM, Mode.XIN, Mode.IMM, Mode.NUL, // 0xa0-0xa3 - Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0xa4-0xa7 - Mode.IMP, Mode.IMM, Mode.IMP, Mode.NUL, // 0xa8-0xab - Mode.ABS, Mode.ABS, Mode.ABS, Mode.NUL, // 0xac-0xaf - Mode.NUL, Mode.INY, Mode.NUL, Mode.NUL, // 0xb0-0xb3 - Mode.ZPX, Mode.ZPX, Mode.ZPY, Mode.NUL, // 0xb4-0xb7 - Mode.IMP, Mode.ABX, Mode.IMP, Mode.NUL, // 0xb8-0xbb - Mode.ABX, Mode.ABY, Mode.ABY, Mode.NUL, // 0xbc-0xbf - Mode.IMM, Mode.XIN, Mode.NUL, Mode.NUL, // 0xc0-0xc3 - Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0xc4-0xc7 - Mode.IMP, Mode.IMM, Mode.IMP, Mode.NUL, // 0xc8-0xcb - Mode.ABS, Mode.ABS, Mode.ABS, Mode.NUL, // 0xcc-0xcf - Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0xd0-0xd3 - Mode.NUL, Mode.ZPX, Mode.ZPX, Mode.NUL, // 0xd4-0xd7 - Mode.IMP, Mode.ABY, Mode.NUL, Mode.NUL, // 0xd8-0xdb - Mode.NUL, Mode.ABX, Mode.ABX, Mode.NUL, // 0xdc-0xdf - Mode.IMM, Mode.XIN, Mode.NUL, Mode.NUL, // 0xe0-0xe3 - Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0xe4-0xe7 - Mode.IMP, Mode.IMM, Mode.IMP, Mode.NUL, // 0xe8-0xeb - Mode.ABS, Mode.ABS, Mode.ABS, Mode.NUL, // 0xec-0xef - Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0xf0-0xf3 - Mode.NUL, Mode.ZPX, Mode.ZPX, Mode.NUL, // 0xf4-0xf7 - Mode.IMP, Mode.ABY, Mode.NUL, Mode.NUL, // 0xf8-0xfb - Mode.NUL, Mode.ABX, Mode.ABX, Mode.NUL // 0xfc-0xff - }; - + /** + * Instruction opcode names. + */ + public static final String[] opcodeNames = { + "BRK", "ORA", null, null, null, "ORA", "ASL", null, + "PHP", "ORA", "ASL", null, null, "ORA", "ASL", null, + "BPL", "ORA", null, null, null, "ORA", "ASL", null, + "CLC", "ORA", null, null, null, "ORA", "ASL", null, + "JSR", "AND", null, null, "BIT", "AND", "ROL", null, + "PLP", "AND", "ROL", null, "BIT", "AND", "ROL", null, + "BMI", "AND", null, null, null, "AND", "ROL", null, + "SEC", "AND", null, null, null, "AND", "ROL", null, + "RTI", "EOR", null, null, null, "EOR", "LSR", null, + "PHA", "EOR", "LSR", null, "JMP", "EOR", "LSR", null, + "BVC", "EOR", null, null, null, "EOR", "LSR", null, + "CLI", "EOR", null, null, null, "EOR", "LSR", null, + "RTS", "ADC", null, null, null, "ADC", "ROR", null, + "PLA", "ADC", "ROR", null, "JMP", "ADC", "ROR", null, + "BVS", "ADC", null, null, null, "ADC", "ROR", null, + "SEI", "ADC", null, null, null, "ADC", "ROR", null, + "BCS", "STA", null, null, "STY", "STA", "STX", null, + "DEY", null, "TXA", null, "STY", "STA", "STX", null, + "BCC", "STA", null, null, "STY", "STA", "STX", null, + "TYA", "STA", "TXS", null, null, "STA", null, null, + "LDY", "LDA", "LDX", null, "LDY", "LDA", "LDX", null, + "TAY", "LDA", "TAX", null, "LDY", "LDA", "LDX", null, + null, "LDA", null, null, "LDY", "LDA", "LDX", null, + "CLV", "LDA", "TSX", null, "LDY", "LDA", "LDX", null, + "CPY", "CMP", null, null, "CPY", "CMP", "DEC", null, + "INY", "CMP", "DEX", null, "CPY", "CMP", "DEC", null, + "BNE", "CMP", null, null, null, "CMP", "DEC", null, + "CLD", "CMP", null, null, null, "CMP", "DEC", null, + "CPX", "SBC", null, null, "CPX", "SBC", "INC", null, + "INX", "SBC", "NOP", null, "CPX", "SBC", "INC", null, + "BEQ", "SBC", null, null, null, "SBC", "INC", null, + "SED", "SBC", null, null, null, "SBC", "INC", null + }; - /** - * Size, in bytes, required for each instruction. - */ - public static final int[] instructionSizes = { - 1, 2, 0, 0, 0, 2, 2, 0, 1, 2, 1, 0, 0, 3, 3, 0, - 2, 2, 0, 0, 0, 2, 2, 0, 1, 3, 0, 0, 0, 3, 3, 0, - 3, 2, 0, 0, 2, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0, - 2, 2, 0, 0, 0, 2, 2, 0, 1, 3, 0, 0, 0, 3, 3, 0, - 1, 2, 0, 0, 0, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0, - 2, 2, 0, 0, 0, 2, 2, 0, 1, 3, 0, 0, 0, 3, 3, 0, - 1, 2, 0, 0, 0, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0, - 2, 2, 0, 0, 0, 2, 2, 0, 1, 3, 0, 0, 0, 3, 3, 0, - 2, 2, 0, 0, 2, 2, 2, 0, 1, 0, 1, 0, 3, 3, 3, 0, - 2, 2, 0, 0, 2, 2, 2, 0, 1, 3, 1, 0, 0, 3, 0, 0, - 2, 2, 2, 0, 2, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0, - 0, 2, 0, 0, 2, 2, 2, 0, 1, 3, 1, 0, 3, 3, 3, 0, - 2, 2, 0, 0, 2, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0, - 2, 2, 0, 0, 0, 2, 2, 0, 1, 3, 0, 0, 0, 3, 3, 0, - 2, 2, 0, 0, 2, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0, - 2, 2, 0, 0, 0, 2, 2, 0, 1, 3, 0, 0, 0, 3, 3, 0 - }; + /** + * Instruction addressing modes. + */ + public static final Mode[] instructionModes = { + Mode.IMP, Mode.XIN, Mode.NUL, Mode.NUL, // 0x00-0x03 + Mode.NUL, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0x04-0x07 + Mode.IMP, Mode.IMM, Mode.ACC, Mode.NUL, // 0x08-0x0b + Mode.NUL, Mode.ABS, Mode.ABS, Mode.NUL, // 0x0c-0x0f + Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0x10-0x13 + Mode.NUL, Mode.ZPX, Mode.ZPX, Mode.NUL, // 0x14-0x17 + Mode.IMP, Mode.ABY, Mode.NUL, Mode.NUL, // 0x18-0x1b + Mode.NUL, Mode.ABX, Mode.ABX, Mode.NUL, // 0x1c-0x1f + Mode.ABS, Mode.XIN, Mode.NUL, Mode.NUL, // 0x20-0x23 + Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0x24-0x27 + Mode.IMP, Mode.IMM, Mode.ACC, Mode.NUL, // 0x28-0x2b + Mode.ABS, Mode.ABS, Mode.ABS, Mode.NUL, // 0x2c-0x2f + Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0x30-0x33 + Mode.NUL, Mode.ZPX, Mode.ZPX, Mode.NUL, // 0x34-0x37 + Mode.IMP, Mode.ABY, Mode.NUL, Mode.NUL, // 0x38-0x3b + Mode.NUL, Mode.ABX, Mode.ABX, Mode.NUL, // 0x3c-0x3f + Mode.IMP, Mode.XIN, Mode.NUL, Mode.NUL, // 0x40-0x43 + Mode.NUL, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0x44-0x47 + Mode.IMP, Mode.IMM, Mode.ACC, Mode.NUL, // 0x48-0x4b + Mode.ABS, Mode.ABS, Mode.ABS, Mode.NUL, // 0x4c-0x4f + Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0x50-0x53 + Mode.NUL, Mode.ZPX, Mode.ZPX, Mode.NUL, // 0x54-0x57 + Mode.IMP, Mode.ABY, Mode.NUL, Mode.NUL, // 0x58-0x5b + Mode.NUL, Mode.ABX, Mode.ABX, Mode.NUL, // 0x5c-0x5f + Mode.IMP, Mode.XIN, Mode.NUL, Mode.NUL, // 0x60-0x63 + Mode.NUL, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0x64-0x67 + Mode.IMP, Mode.IMM, Mode.ACC, Mode.NUL, // 0x68-0x6b + Mode.IND, Mode.ABS, Mode.ABS, Mode.NUL, // 0x6c-0x6f + Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0x70-0x73 + Mode.NUL, Mode.ZPX, Mode.ZPX, Mode.NUL, // 0x74-0x77 + Mode.IMP, Mode.ABY, Mode.NUL, Mode.NUL, // 0x78-0x7b + Mode.NUL, Mode.ABX, Mode.ABX, Mode.NUL, // 0x7c-0x7f + Mode.REL, Mode.XIN, Mode.NUL, Mode.NUL, // 0x80-0x83 + Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0x84-0x87 + Mode.IMP, Mode.NUL, Mode.IMP, Mode.NUL, // 0x88-0x8b + Mode.ABS, Mode.ABS, Mode.ABS, Mode.NUL, // 0x8c-0x8f + Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0x90-0x93 + Mode.ZPX, Mode.ZPX, Mode.ZPY, Mode.NUL, // 0x94-0x97 + Mode.IMP, Mode.ABX, Mode.IMP, Mode.NUL, // 0x98-0x9b + Mode.NUL, Mode.ABY, Mode.NUL, Mode.NUL, // 0x9c-0x9f + Mode.IMM, Mode.XIN, Mode.IMM, Mode.NUL, // 0xa0-0xa3 + Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0xa4-0xa7 + Mode.IMP, Mode.IMM, Mode.IMP, Mode.NUL, // 0xa8-0xab + Mode.ABS, Mode.ABS, Mode.ABS, Mode.NUL, // 0xac-0xaf + Mode.NUL, Mode.INY, Mode.NUL, Mode.NUL, // 0xb0-0xb3 + Mode.ZPX, Mode.ZPX, Mode.ZPY, Mode.NUL, // 0xb4-0xb7 + Mode.IMP, Mode.ABX, Mode.IMP, Mode.NUL, // 0xb8-0xbb + Mode.ABX, Mode.ABY, Mode.ABY, Mode.NUL, // 0xbc-0xbf + Mode.IMM, Mode.XIN, Mode.NUL, Mode.NUL, // 0xc0-0xc3 + Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0xc4-0xc7 + Mode.IMP, Mode.IMM, Mode.IMP, Mode.NUL, // 0xc8-0xcb + Mode.ABS, Mode.ABS, Mode.ABS, Mode.NUL, // 0xcc-0xcf + Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0xd0-0xd3 + Mode.NUL, Mode.ZPX, Mode.ZPX, Mode.NUL, // 0xd4-0xd7 + Mode.IMP, Mode.ABY, Mode.NUL, Mode.NUL, // 0xd8-0xdb + Mode.NUL, Mode.ABX, Mode.ABX, Mode.NUL, // 0xdc-0xdf + Mode.IMM, Mode.XIN, Mode.NUL, Mode.NUL, // 0xe0-0xe3 + Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0xe4-0xe7 + Mode.IMP, Mode.IMM, Mode.IMP, Mode.NUL, // 0xe8-0xeb + Mode.ABS, Mode.ABS, Mode.ABS, Mode.NUL, // 0xec-0xef + Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0xf0-0xf3 + Mode.NUL, Mode.ZPX, Mode.ZPX, Mode.NUL, // 0xf4-0xf7 + Mode.IMP, Mode.ABY, Mode.NUL, Mode.NUL, // 0xf8-0xfb + Mode.NUL, Mode.ABX, Mode.ABX, Mode.NUL // 0xfc-0xff + }; - /** - * Number of clock cycles required for each instruction - */ - public static final int[] instructionClocks = { - 7, 6, 0, 0, 0, 3, 5, 0, 3, 2, 2, 0, 0, 4, 6, 0, - 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0, - 6, 6, 0, 0, 3, 3, 5, 0, 4, 2, 2, 0, 4, 4, 6, 0, - 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0, - 6, 6, 0, 0, 0, 3, 5, 0, 3, 2, 2, 0, 3, 4, 6, 0, - 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0, - 6, 6, 0, 0, 0, 3, 5, 0, 4, 2, 2, 0, 5, 4, 6, 0, - 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0, - 2, 6, 0, 0, 3, 3, 3, 0, 2, 0, 2, 0, 4, 4, 4, 0, - 2, 6, 0, 0, 4, 4, 4, 0, 2, 5, 2, 0, 0, 5, 0, 0, - 2, 6, 2, 0, 3, 3, 3, 0, 2, 2, 2, 0, 4, 4, 4, 0, - 0, 5, 0, 0, 4, 4, 4, 0, 2, 4, 2, 0, 4, 4, 4, 0, - 2, 6, 0, 0, 3, 3, 5, 0, 2, 2, 2, 0, 4, 4, 6, 0, - 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0, - 2, 6, 0, 0, 3, 3, 5, 0, 2, 2, 2, 0, 4, 4, 6, 0, - 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0 - }; + + /** + * Size, in bytes, required for each instruction. + */ + public static final int[] instructionSizes = { + 1, 2, 0, 0, 0, 2, 2, 0, 1, 2, 1, 0, 0, 3, 3, 0, + 2, 2, 0, 0, 0, 2, 2, 0, 1, 3, 0, 0, 0, 3, 3, 0, + 3, 2, 0, 0, 2, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0, + 2, 2, 0, 0, 0, 2, 2, 0, 1, 3, 0, 0, 0, 3, 3, 0, + 1, 2, 0, 0, 0, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0, + 2, 2, 0, 0, 0, 2, 2, 0, 1, 3, 0, 0, 0, 3, 3, 0, + 1, 2, 0, 0, 0, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0, + 2, 2, 0, 0, 0, 2, 2, 0, 1, 3, 0, 0, 0, 3, 3, 0, + 2, 2, 0, 0, 2, 2, 2, 0, 1, 0, 1, 0, 3, 3, 3, 0, + 2, 2, 0, 0, 2, 2, 2, 0, 1, 3, 1, 0, 0, 3, 0, 0, + 2, 2, 2, 0, 2, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0, + 0, 2, 0, 0, 2, 2, 2, 0, 1, 3, 1, 0, 3, 3, 3, 0, + 2, 2, 0, 0, 2, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0, + 2, 2, 0, 0, 0, 2, 2, 0, 1, 3, 0, 0, 0, 3, 3, 0, + 2, 2, 0, 0, 2, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0, + 2, 2, 0, 0, 0, 2, 2, 0, 1, 3, 0, 0, 0, 3, 3, 0 + }; + + /** + * Number of clock cycles required for each instruction + */ + public static final int[] instructionClocks = { + 7, 6, 0, 0, 0, 3, 5, 0, 3, 2, 2, 0, 0, 4, 6, 0, + 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0, + 6, 6, 0, 0, 3, 3, 5, 0, 4, 2, 2, 0, 4, 4, 6, 0, + 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0, + 6, 6, 0, 0, 0, 3, 5, 0, 3, 2, 2, 0, 3, 4, 6, 0, + 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0, + 6, 6, 0, 0, 0, 3, 5, 0, 4, 2, 2, 0, 5, 4, 6, 0, + 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0, + 2, 6, 0, 0, 3, 3, 3, 0, 2, 0, 2, 0, 4, 4, 4, 0, + 2, 6, 0, 0, 4, 4, 4, 0, 2, 5, 2, 0, 0, 5, 0, 0, + 2, 6, 2, 0, 3, 3, 3, 0, 2, 2, 2, 0, 4, 4, 4, 0, + 0, 5, 0, 0, 4, 4, 4, 0, 2, 4, 2, 0, 4, 4, 4, 0, + 2, 6, 0, 0, 3, 3, 5, 0, 2, 2, 2, 0, 4, 4, 6, 0, + 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0, + 2, 6, 0, 0, 3, 3, 5, 0, 2, 2, 2, 0, 4, 4, 6, 0, + 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0 + }; } \ No newline at end of file diff --git a/src/main/java/com/loomcom/symon/MemoryRange.java b/src/main/java/com/loomcom/symon/MemoryRange.java index 281e867..50c164e 100644 --- a/src/main/java/com/loomcom/symon/MemoryRange.java +++ b/src/main/java/com/loomcom/symon/MemoryRange.java @@ -11,77 +11,77 @@ import com.loomcom.symon.exceptions.*; */ public class MemoryRange implements Comparable { - /** The starting address of the memory range. */ - public int startAddress; - /** The ending address of the memory range. */ - public int endAddress; + /** The starting address of the memory range. */ + public int startAddress; + /** The ending address of the memory range. */ + public int endAddress; - public MemoryRange(int startAddress, int endAddress) - throws MemoryRangeException { - if (startAddress < 0 || endAddress < 0) { - throw new MemoryRangeException("Addresses cannot be less than 0."); - } - if (startAddress >= endAddress) { - throw new MemoryRangeException("End address must be greater " + - "than start address."); - } - this.startAddress = startAddress; - this.endAddress = endAddress; - } + public MemoryRange(int startAddress, int endAddress) + throws MemoryRangeException { + if (startAddress < 0 || endAddress < 0) { + throw new MemoryRangeException("Addresses cannot be less than 0."); + } + if (startAddress >= endAddress) { + throw new MemoryRangeException("End address must be greater " + + "than start address."); + } + this.startAddress = startAddress; + this.endAddress = endAddress; + } - /** - * @returns the starting address. - */ - public int startAddress() { - return startAddress; - } + /** + * @returns the starting address. + */ + public int startAddress() { + return startAddress; + } - /** - * @returns the ending address. - */ - public int endAddress() { - return endAddress; - } + /** + * @returns the ending address. + */ + public int endAddress() { + return endAddress; + } - /** - * Checks for address inclusion in the range. - * - * @returns true if the address is included within this range, - * false otherwise. - */ - public boolean includes(int address) { - return (address <= endAddress && - address >= startAddress); - } + /** + * Checks for address inclusion in the range. + * + * @returns true if the address is included within this range, + * false otherwise. + */ + public boolean includes(int address) { + return (address <= endAddress && + address >= startAddress); + } - /** - * Checks for overlapping memory ranges. - * - * @returns true if this range overlaps in any way with the other. - */ - public boolean overlaps(MemoryRange other) { - return (this.includes(other.startAddress()) || - other.includes(this.startAddress())); - } + /** + * Checks for overlapping memory ranges. + * + * @returns true if this range overlaps in any way with the other. + */ + public boolean overlaps(MemoryRange other) { + return (this.includes(other.startAddress()) || + other.includes(this.startAddress())); + } - // Implementation of Comparable interface - public int compareTo(MemoryRange other) { - if (other == null) { - throw new NullPointerException("Cannot compare to null."); - } - if (this == other) { - return 0; - } - Integer thisStartAddr = new Integer(this.startAddress()); - Integer thatStartAddr = new Integer(other.startAddress()); - return thisStartAddr.compareTo(thatStartAddr); - } + // Implementation of Comparable interface + public int compareTo(MemoryRange other) { + if (other == null) { + throw new NullPointerException("Cannot compare to null."); + } + if (this == other) { + return 0; + } + Integer thisStartAddr = new Integer(this.startAddress()); + Integer thatStartAddr = new Integer(other.startAddress()); + return thisStartAddr.compareTo(thatStartAddr); + } - public String toString() { - StringBuffer desc = new StringBuffer("@"); - desc.append(String.format("0x%04x", startAddress)); - desc.append("-"); - desc.append(String.format("0x%04x", endAddress)); - return desc.toString(); - } + public String toString() { + StringBuffer desc = new StringBuffer("@"); + desc.append(String.format("0x%04x", startAddress)); + desc.append("-"); + desc.append(String.format("0x%04x", endAddress)); + return desc.toString(); + } } diff --git a/src/main/java/com/loomcom/symon/Profiler.java b/src/main/java/com/loomcom/symon/Profiler.java index fbbf2b4..7dff966 100644 --- a/src/main/java/com/loomcom/symon/Profiler.java +++ b/src/main/java/com/loomcom/symon/Profiler.java @@ -10,151 +10,150 @@ import com.loomcom.symon.exceptions.*; public class Profiler implements InstructionTable { + public static void main(String[] args) { + // new Profiler().profileMemoryReads(); + // new Profiler().dumpOpCodes(); + new Profiler().profileProgram(); + } - public static void main(String[] args) { - // new Profiler().profileMemoryReads(); - // new Profiler().dumpOpCodes(); - new Profiler().profileProgram(); - } + public void dumpOpCodes() { + for (int i = 0; i < 0x100; i++) { + String name = opcodeNames[i]; + Mode mode = instructionModes[i]; - public void dumpOpCodes() { - for (int i = 0; i < 0x100; i++) { - String name = opcodeNames[i]; - Mode mode = instructionModes[i]; + System.out.print(String.format("0x%02x: ", i)); - System.out.print(String.format("0x%02x: ", i)); + if (name == null) { + System.out.println("n/a"); + } else { + System.out.println(name + " (" + mode + ")"); + } + } + } - if (name == null) { - System.out.println("n/a"); - } else { - System.out.println(name + " (" + mode + ")"); - } - } - } + public void profileProgram() { + Bus bus = new Bus(0, 65535); + Cpu cpu = new Cpu(); - public void profileProgram() { - Bus bus = new Bus(0, 65535); - Cpu cpu = new Cpu(); + bus.addCpu(cpu); - bus.addCpu(cpu); + try { + bus.addDevice(new Memory(0x0000, 0x10000)); + } catch (MemoryRangeException ex) { + System.err.println("Memory Range Exception! " + ex.getMessage()); + return; + } - try { - bus.addDevice(new Memory(0x0000, 0x10000)); - } catch (MemoryRangeException ex) { - System.err.println("Memory Range Exception! " + ex.getMessage()); - return; - } + // Start at 0x0300 + bus.write(0xfffc, 0x00); + bus.write(0xfffd, 0x03); - // Start at 0x0300 - bus.write(0xfffc, 0x00); - bus.write(0xfffd, 0x03); + // The program to run, in an infinite loop. + bus.write(0x0300, 0xa9); // LDA #$FF + bus.write(0x0301, 0xff); + bus.write(0x0302, 0xea); // NOP + bus.write(0x0303, 0xea); // NOP + bus.write(0x0304, 0xa0); // LDY #$1A + bus.write(0x0305, 0x1a); + bus.write(0x0306, 0xea); // NOP + bus.write(0x0307, 0xea); // NOP + bus.write(0x0308, 0xa2); // LDX #$03 + bus.write(0x0309, 0x03); - // The program to run, in an infinite loop. - bus.write(0x0300, 0xa9); // LDA #$FF - bus.write(0x0301, 0xff); - bus.write(0x0302, 0xea); // NOP - bus.write(0x0303, 0xea); // NOP - bus.write(0x0304, 0xa0); // LDY #$1A - bus.write(0x0305, 0x1a); - bus.write(0x0306, 0xea); // NOP - bus.write(0x0307, 0xea); // NOP - bus.write(0x0308, 0xa2); // LDX #$03 - bus.write(0x0309, 0x03); + bus.write(0x030a, 0xa9); // LDA #$00 + bus.write(0x030b, 0x00); + bus.write(0x030c, 0xa2); // LDX #$00 + bus.write(0x030d, 0x00); + bus.write(0x030e, 0xa0); // LDY #$00 + bus.write(0x030f, 0x00); - bus.write(0x030a, 0xa9); // LDA #$00 - bus.write(0x030b, 0x00); - bus.write(0x030c, 0xa2); // LDX #$00 - bus.write(0x030d, 0x00); - bus.write(0x030e, 0xa0); // LDY #$00 - bus.write(0x030f, 0x00); - - bus.write(0x0310, 0x4c); // JMP #$0300 - bus.write(0x0311, 0x00); - bus.write(0x0312, 0x03); + bus.write(0x0310, 0x4c); // JMP #$0300 + bus.write(0x0311, 0x00); + bus.write(0x0312, 0x03); - long sum = 0; + long sum = 0; - // The number of times to run the program - long iters = 1000; + // The number of times to run the program + long iters = 1000; - // The number of steps to take when running the program - long steps = 100000; + // The number of steps to take when running the program + long steps = 100000; - for (int i = 0; i < iters; i++) { - long startTime = System.nanoTime(); + for (int i = 0; i < iters; i++) { + long startTime = System.nanoTime(); - // Reset the CPU (does not clear memory) - cpu.reset(); + // Reset the CPU (does not clear memory) + cpu.reset(); - for (int j = 0; j < steps; j++) { - cpu.step(); - } + for (int j = 0; j < steps; j++) { + cpu.step(); + } - long endTime = System.nanoTime(); - long diff = endTime - startTime; + long endTime = System.nanoTime(); + long diff = endTime - startTime; - sum += diff; - } + sum += diff; + } - long average = sum / iters; - long totalSteps = steps * iters; - long avgStep = sum / totalSteps; + long average = sum / iters; + long totalSteps = steps * iters; + long avgStep = sum / totalSteps; - System.out.println("Total instructions executed: " + - String.format("%,d", totalSteps)); - System.out.println("Total time taken: " + - String.format("%,d us", sum / 1000)); - System.out.println("Average time per step: " + - avgStep + " ns "); - } + System.out.println("Total instructions executed: " + + String.format("%,d", totalSteps)); + System.out.println("Total time taken: " + + String.format("%,d us", sum / 1000)); + System.out.println("Average time per step: " + + avgStep + " ns "); + } - public void profileMemoryReads() { - // Create a bus. - Bus b = new Bus(0, 65535); + public void profileMemoryReads() { + // Create a bus. + Bus b = new Bus(0, 65535); - try { - // Create eight devices, each 8KB, to fill the bus. - b.addDevice(new Memory(0x0000, 0x2000)); // 8KB @ $0000-$1fff - b.addDevice(new Memory(0x2000, 0x2000)); // 8KB @ $2000-$3fff - b.addDevice(new Memory(0x4000, 0x2000)); // 8KB @ $4000-$5fff - b.addDevice(new Memory(0x6000, 0x2000)); // 8KB @ $6000-$7fff - b.addDevice(new Memory(0x8000, 0x2000)); // 8KB @ $8000-$9fff - b.addDevice(new Memory(0xa000, 0x2000)); // 8KB @ $a000-$bfff - b.addDevice(new Memory(0xc000, 0x2000)); // 8KB @ $c000-$dfff - b.addDevice(new Memory(0xe000, 0x2000)); // 8KB @ $e000-$ffff - } catch (MemoryRangeException ex) { - System.err.println("Memory Range Exception! " + ex.getMessage()); - return; - } + try { + // Create eight devices, each 8KB, to fill the bus. + b.addDevice(new Memory(0x0000, 0x2000)); // 8KB @ $0000-$1fff + b.addDevice(new Memory(0x2000, 0x2000)); // 8KB @ $2000-$3fff + b.addDevice(new Memory(0x4000, 0x2000)); // 8KB @ $4000-$5fff + b.addDevice(new Memory(0x6000, 0x2000)); // 8KB @ $6000-$7fff + b.addDevice(new Memory(0x8000, 0x2000)); // 8KB @ $8000-$9fff + b.addDevice(new Memory(0xa000, 0x2000)); // 8KB @ $a000-$bfff + b.addDevice(new Memory(0xc000, 0x2000)); // 8KB @ $c000-$dfff + b.addDevice(new Memory(0xe000, 0x2000)); // 8KB @ $e000-$ffff + } catch (MemoryRangeException ex) { + System.err.println("Memory Range Exception! " + ex.getMessage()); + return; + } - // Read memory - long sum = 0; - long average = 0; + // Read memory + long sum = 0; + long average = 0; - long iters = 500; - for (int i = 0; i < iters; i++) { - long startTime = System.nanoTime(); - // Read and assign to a buffer - int buf = 0; - for (int j = 0; j < 0xffff; j++) { - buf = b.read(j); - if (buf != 0xff) { - System.out.println("WARNING! MEMORY SHOULD HAVE " + - "BEEN $FF, WAS: " + buf); - System.exit(0); - } - } + long iters = 500; + for (int i = 0; i < iters; i++) { + long startTime = System.nanoTime(); + // Read and assign to a buffer + int buf = 0; + for (int j = 0; j < 0xffff; j++) { + buf = b.read(j); + if (buf != 0xff) { + System.out.println("WARNING! MEMORY SHOULD HAVE " + + "BEEN $FF, WAS: " + buf); + System.exit(0); + } + } - long endTime = System.nanoTime(); - long diff = endTime - startTime; + long endTime = System.nanoTime(); + long diff = endTime - startTime; - sum += diff; - average = sum / (i + 1); - } - System.out.println("Average time to read 64KB: " + average + - " ns (" + (average / 1000) + " us)"); - System.out.println("Average time to read one byte: " + - sum / (64 * 1024 * iters) + " ns"); - } + sum += diff; + average = sum / (i + 1); + } + System.out.println("Average time to read 64KB: " + average + + " ns (" + (average / 1000) + " us)"); + System.out.println("Average time to read one byte: " + + sum / (64 * 1024 * iters) + " ns"); + } } diff --git a/src/main/java/com/loomcom/symon/Simulator.java b/src/main/java/com/loomcom/symon/Simulator.java index 18e8e2a..9cfa062 100644 --- a/src/main/java/com/loomcom/symon/Simulator.java +++ b/src/main/java/com/loomcom/symon/Simulator.java @@ -8,107 +8,107 @@ import com.loomcom.symon.exceptions.*; */ public class Simulator { - /** - * Command-line parser used by this simulator. - */ - private CommandParser parser; + /** + * Command-line parser used by this simulator. + */ + private CommandParser parser; - /** - * The CPU itself. - */ - private Cpu cpu; + /** + * The CPU itself. + */ + private Cpu cpu; - /** - * The Bus responsible for routing memory read/write requests to the - * correct IO devices. - */ - private Bus bus; + /** + * The Bus responsible for routing memory read/write requests to the + * correct IO devices. + */ + private Bus bus; - public Simulator() throws MemoryRangeException { - cpu = new Cpu(); - bus = new Bus(0x0000, 0xffff); - bus.addCpu(cpu); - bus.addDevice(new Memory(0x0000, 0x10000)); - parser = new CommandParser(System.in, System.out, this); - } + public Simulator() throws MemoryRangeException { + cpu = new Cpu(); + bus = new Bus(0x0000, 0xffff); + bus.addCpu(cpu); + bus.addDevice(new Memory(0x0000, 0x10000)); + parser = new CommandParser(System.in, System.out, this); + } - public void run() { - parser.run(); - } + public void run() { + parser.run(); + } - public void step() { - } + public void step() { + } - public int read(int address) { - return 0; - } + public int read(int address) { + return 0; + } - public void write(int address, int value) { - } + public void write(int address, int value) { + } - public void loadProgram(int address, int[] program) { - // Reset interrupt vector - int hi = (address&0xff00)>>>8; - int lo = address&0x00ff; - bus.write(0xfffc, lo); - bus.write(0xfffd, hi); + public void loadProgram(int address, int[] program) { + // Reset interrupt vector + int hi = (address&0xff00)>>>8; + int lo = address&0x00ff; + bus.write(0xfffc, lo); + bus.write(0xfffd, hi); - int i = 0; - for (int d : program) { - bus.write(address + i++, d); - } - } + int i = 0; + for (int d : program) { + bus.write(address + i++, d); + } + } - /** - * A test method. - */ + /** + * A test method. + */ - public void runTest() { - int[] program = { - 0xa9, // LDA #$FF - 0xff, - 0xa0, // LDY #$1A - 0x1a, - 0xa2, // LDX #$90 - 0x90, - 0xa2, // LDX #$02 - 0x02, - 0x49, // EOR #$FF - 0xff, - 0xa9, // LDA #$00 - 0x00, - 0xa2, // LDX #$00 - 0x00, - 0x29, // AND #$FF - 0xff, - 0xa0, // LDY #$00 - 0x00, - 0x4c, // JMP #$0300 - 0x00, - 0x03 - }; + public void runTest() { + int[] program = { + 0xa9, // LDA #$FF + 0xff, + 0xa0, // LDY #$1A + 0x1a, + 0xa2, // LDX #$90 + 0x90, + 0xa2, // LDX #$02 + 0x02, + 0x49, // EOR #$FF + 0xff, + 0xa9, // LDA #$00 + 0x00, + 0xa2, // LDX #$00 + 0x00, + 0x29, // AND #$FF + 0xff, + 0xa0, // LDY #$00 + 0x00, + 0x4c, // JMP #$0300 + 0x00, + 0x03 + }; - loadProgram(0x0300, program); - cpu.reset(); + loadProgram(0x0300, program); + cpu.reset(); - int steps = program.length; + int steps = program.length; - for (int i = 0; i <= steps; i++) { - cpu.step(); - System.out.println(cpu.toString()); - } + for (int i = 0; i <= steps; i++) { + cpu.step(); + System.out.println(cpu.toString()); + } - } + } - /** - * Main simulator routine. - */ - public static void main(String[] args) { - try { - new Simulator().runTest(); - } catch (MemoryRangeException ex) { - System.err.println("Error: " + ex.toString()); - } - } + /** + * Main simulator routine. + */ + public static void main(String[] args) { + try { + new Simulator().runTest(); + } catch (MemoryRangeException ex) { + System.err.println("Error: " + ex.toString()); + } + } } diff --git a/src/main/java/com/loomcom/symon/devices/Device.java b/src/main/java/com/loomcom/symon/devices/Device.java index e5dfef6..2e7d76b 100644 --- a/src/main/java/com/loomcom/symon/devices/Device.java +++ b/src/main/java/com/loomcom/symon/devices/Device.java @@ -9,65 +9,65 @@ import com.loomcom.symon.exceptions.*; public abstract class Device implements Comparable { - /** The memory range for this device. */ - private MemoryRange memoryRange; + /** The memory range for this device. */ + private MemoryRange memoryRange; - /** The name of the device. */ - private String name; + /** The name of the device. */ + private String name; - /** Reference to the bus where this Device is attached. */ - private Bus bus; + /** Reference to the bus where this Device is attached. */ + private Bus bus; - public Device(int address, int size, String name) - throws MemoryRangeException { - this.memoryRange = new MemoryRange(address, address + size - 1); - this.name = name; - } + public Device(int address, int size, String name) + throws MemoryRangeException { + this.memoryRange = new MemoryRange(address, address + size - 1); + this.name = name; + } - public Device(int address, int size) throws MemoryRangeException { - this(address, size, null); - } + public Device(int address, int size) throws MemoryRangeException { + this(address, size, null); + } - /* Methods required to be implemented by inheriting classes. */ - public abstract void write(int address, int data); - public abstract int read(int address); - public abstract String toString(); + /* Methods required to be implemented by inheriting classes. */ + public abstract void write(int address, int data); + public abstract int read(int address); + public abstract String toString(); - public void setBus(Bus bus) { - this.bus = bus; - } + public void setBus(Bus bus) { + this.bus = bus; + } - public MemoryRange getMemoryRange() { - return memoryRange; - } + public MemoryRange getMemoryRange() { + return memoryRange; + } - public int endAddress() { - return memoryRange.endAddress(); - } + public int endAddress() { + return memoryRange.endAddress(); + } - public int startAddress() { - return memoryRange.startAddress(); - } + public int startAddress() { + return memoryRange.startAddress(); + } - public String getName() { - return name; - } + public String getName() { + return name; + } - public void setName(String name) { - this.name = name; - } + public void setName(String name) { + this.name = name; + } - /** - * Compares two devices. The sort order is defined by the sort - * order of the device's memory ranges. - */ - public int compareTo(Device other) { - if (other == null) { - throw new NullPointerException("Cannot compare to null."); - } - if (this == other) { - return 0; - } - return getMemoryRange().compareTo(other.getMemoryRange()); - } + /** + * Compares two devices. The sort order is defined by the sort + * order of the device's memory ranges. + */ + public int compareTo(Device other) { + if (other == null) { + throw new NullPointerException("Cannot compare to null."); + } + if (this == other) { + return 0; + } + return getMemoryRange().compareTo(other.getMemoryRange()); + } } diff --git a/src/main/java/com/loomcom/symon/devices/Memory.java b/src/main/java/com/loomcom/symon/devices/Memory.java index 58b257e..b6a3af0 100644 --- a/src/main/java/com/loomcom/symon/devices/Memory.java +++ b/src/main/java/com/loomcom/symon/devices/Memory.java @@ -7,33 +7,33 @@ import com.loomcom.symon.exceptions.*; public class Memory extends Device { - private boolean readOnly; - private int[] mem; + private boolean readOnly; + private int[] mem; - public Memory(int address, int size, boolean readOnly) - throws MemoryRangeException { - super(address, size, "RW Memory"); - this.readOnly = readOnly; - this.mem = new int[size]; - // Initialize all locations to 0xff - Arrays.fill(this.mem, 0xff); - } + public Memory(int address, int size, boolean readOnly) + throws MemoryRangeException { + super(address, size, "RW Memory"); + this.readOnly = readOnly; + this.mem = new int[size]; + // Initialize all locations to 0xff + Arrays.fill(this.mem, 0xff); + } - public Memory(int address, int size) - throws MemoryRangeException { - this(address, size, false); - } + public Memory(int address, int size) + throws MemoryRangeException { + this(address, size, false); + } - public void write(int address, int data) { - this.mem[address] = data; - } + public void write(int address, int data) { + this.mem[address] = data; + } - public int read(int address) { - return this.mem[address]; - } + public int read(int address) { + return this.mem[address]; + } - public String toString() { - return "Memory: " + getMemoryRange().toString(); - } + public String toString() { + return "Memory: " + getMemoryRange().toString(); + } } \ No newline at end of file diff --git a/src/main/java/com/loomcom/symon/exceptions/MemoryAccessException.java b/src/main/java/com/loomcom/symon/exceptions/MemoryAccessException.java index 4a40e9f..465136f 100644 --- a/src/main/java/com/loomcom/symon/exceptions/MemoryAccessException.java +++ b/src/main/java/com/loomcom/symon/exceptions/MemoryAccessException.java @@ -5,7 +5,7 @@ package com.loomcom.symon.exceptions; * accessed. */ public class MemoryAccessException extends Exception { - public MemoryAccessException(String msg) { - super(msg); - } + public MemoryAccessException(String msg) { + super(msg); + } } diff --git a/src/main/java/com/loomcom/symon/exceptions/MemoryRangeException.java b/src/main/java/com/loomcom/symon/exceptions/MemoryRangeException.java index 9adba68..02a109e 100644 --- a/src/main/java/com/loomcom/symon/exceptions/MemoryRangeException.java +++ b/src/main/java/com/loomcom/symon/exceptions/MemoryRangeException.java @@ -4,7 +4,7 @@ package com.loomcom.symon.exceptions; * Exception that will be thrown if devices conflict in the IO map. */ public class MemoryRangeException extends Exception { - public MemoryRangeException(String msg) { - super(msg); - } + public MemoryRangeException(String msg) { + super(msg); + } } \ No newline at end of file diff --git a/src/test/java/com/loomcom/symon/BusTest.java b/src/test/java/com/loomcom/symon/BusTest.java index 3a0bce6..9960e06 100644 --- a/src/test/java/com/loomcom/symon/BusTest.java +++ b/src/test/java/com/loomcom/symon/BusTest.java @@ -12,114 +12,114 @@ import java.util.*; */ public class BusTest extends TestCase { - public BusTest(String testName) { - super(testName); - } + public BusTest(String testName) { + super(testName); + } - public static Test suite() { - return new TestSuite(BusTest.class); - } + public static Test suite() { + return new TestSuite(BusTest.class); + } - public void testCreatingWithStartAndEndAddresses() { - Bus b = null; + public void testCreatingWithStartAndEndAddresses() { + Bus b = null; - b = new Bus(0x00, 0xff); - assertEquals(0x00, b.startAddress()); - assertEquals(0xff, b.endAddress()); + b = new Bus(0x00, 0xff); + assertEquals(0x00, b.startAddress()); + assertEquals(0xff, b.endAddress()); - b = new Bus(0x20, 0xea); - assertEquals(0x20, b.startAddress()); - assertEquals(0xea, b.endAddress()); - } + b = new Bus(0x20, 0xea); + assertEquals(0x20, b.startAddress()); + assertEquals(0xea, b.endAddress()); + } - public void testCreatingWithSize() { - Bus b = null; + public void testCreatingWithSize() { + Bus b = null; - b = new Bus(256); - assertEquals(0x00, b.startAddress()); - assertEquals(0xff, b.endAddress()); + b = new Bus(256); + assertEquals(0x00, b.startAddress()); + assertEquals(0xff, b.endAddress()); - b = new Bus(4096); - assertEquals(0x000, b.startAddress()); - assertEquals(0xfff, b.endAddress()); + b = new Bus(4096); + assertEquals(0x000, b.startAddress()); + assertEquals(0xfff, b.endAddress()); - b = new Bus(65536); - assertEquals(0x0000, b.startAddress()); - assertEquals(0xffff, b.endAddress()); - } + b = new Bus(65536); + assertEquals(0x0000, b.startAddress()); + assertEquals(0xffff, b.endAddress()); + } - public void testAddDevice() throws MemoryRangeException { - Device memory = new Memory(0x0000, 0x0100, true); - Device rom = new Memory(0x0100, 0x0200, false); + public void testAddDevice() throws MemoryRangeException { + Device memory = new Memory(0x0000, 0x0100, true); + Device rom = new Memory(0x0100, 0x0200, false); - Bus b = new Bus(0x0000, 0xffff); + Bus b = new Bus(0x0000, 0xffff); - assertEquals(0, b.getDevices().size()); - b.addDevice(memory); - assertEquals(1, b.getDevices().size()); - b.addDevice(rom); - assertEquals(2, b.getDevices().size()); - } + assertEquals(0, b.getDevices().size()); + b.addDevice(memory); + assertEquals(1, b.getDevices().size()); + b.addDevice(rom); + assertEquals(2, b.getDevices().size()); + } - public void testOverlappingDevicesShouldFail() throws MemoryRangeException { - Device memory = new Memory(0x0000, 0x0100, true); - Device rom = new Memory(0x00ff, 0x0200, false); + public void testOverlappingDevicesShouldFail() throws MemoryRangeException { + Device memory = new Memory(0x0000, 0x0100, true); + Device rom = new Memory(0x00ff, 0x0200, false); - Bus b = new Bus(0x0000, 0xffff); + Bus b = new Bus(0x0000, 0xffff); - b.addDevice(memory); + b.addDevice(memory); - try { - b.addDevice(rom); - fail("Should have thrown a MemoryRangeException."); - } catch (MemoryRangeException ex) { - // expected - } - } + try { + b.addDevice(rom); + fail("Should have thrown a MemoryRangeException."); + } catch (MemoryRangeException ex) { + // expected + } + } - public void testIsCompleteWithFirstDeviceNotStartingAtStartAddress() throws MemoryRangeException { - Device memory = new Memory(0x00ff, 0xff00, true); + public void testIsCompleteWithFirstDeviceNotStartingAtStartAddress() throws MemoryRangeException { + Device memory = new Memory(0x00ff, 0xff00, true); - Bus b = new Bus(0x0000, 0xffff); - assertFalse("Address space was unexpectedly complete!", b.isComplete()); - b.addDevice(memory); - assertFalse("Address space was unexpectedly complete!", b.isComplete()); - } + Bus b = new Bus(0x0000, 0xffff); + assertFalse("Address space was unexpectedly complete!", b.isComplete()); + b.addDevice(memory); + assertFalse("Address space was unexpectedly complete!", b.isComplete()); + } - public void testIsCompleteWithOneDevice() throws MemoryRangeException { - Device memory = new Memory(0x0000, 0x10000, true); + public void testIsCompleteWithOneDevice() throws MemoryRangeException { + Device memory = new Memory(0x0000, 0x10000, true); - Bus b = new Bus(0x0000, 0xffff); - assertFalse("Address space was unexpectedly complete!", b.isComplete()); - b.addDevice(memory); - assertTrue("Address space should have been complete!", b.isComplete()); - } + Bus b = new Bus(0x0000, 0xffff); + assertFalse("Address space was unexpectedly complete!", b.isComplete()); + b.addDevice(memory); + assertTrue("Address space should have been complete!", b.isComplete()); + } - public void testIsCompleteWithTwoDevices() throws MemoryRangeException { - Device memory = new Memory(0x0000, 0x8000, true); - Device rom = new Memory(0x8000, 0x8000, false); + public void testIsCompleteWithTwoDevices() throws MemoryRangeException { + Device memory = new Memory(0x0000, 0x8000, true); + Device rom = new Memory(0x8000, 0x8000, false); - Bus b = new Bus(0x0000, 0xffff); - assertFalse("Address space was unexpectedly complete!", b.isComplete()); - b.addDevice(memory); - assertFalse("Address space was unexpectedly complete!", b.isComplete()); - b.addDevice(rom); - assertTrue("Address space should have been complete!", b.isComplete()); - } + Bus b = new Bus(0x0000, 0xffff); + assertFalse("Address space was unexpectedly complete!", b.isComplete()); + b.addDevice(memory); + assertFalse("Address space was unexpectedly complete!", b.isComplete()); + b.addDevice(rom); + assertTrue("Address space should have been complete!", b.isComplete()); + } - public void testIsCompleteWithThreeDevices() throws MemoryRangeException { - Device memory = new Memory(0x0000, 0x8000, true); - Device rom1 = new Memory(0x8000, 0x4000, false); - Device rom2 = new Memory(0xC000, 0x4000, false); + public void testIsCompleteWithThreeDevices() throws MemoryRangeException { + Device memory = new Memory(0x0000, 0x8000, true); + Device rom1 = new Memory(0x8000, 0x4000, false); + Device rom2 = new Memory(0xC000, 0x4000, false); - Bus b = new Bus(0x0000, 0xffff); - assertFalse("Address space was unexpectedly complete!", b.isComplete()); - b.addDevice(memory); - assertFalse("Address space was unexpectedly complete!", b.isComplete()); - b.addDevice(rom1); - assertFalse("Address space was unexpectedly complete!", b.isComplete()); - b.addDevice(rom2); - assertTrue("Address space should have been complete!", b.isComplete()); - } + Bus b = new Bus(0x0000, 0xffff); + assertFalse("Address space was unexpectedly complete!", b.isComplete()); + b.addDevice(memory); + assertFalse("Address space was unexpectedly complete!", b.isComplete()); + b.addDevice(rom1); + assertFalse("Address space was unexpectedly complete!", b.isComplete()); + b.addDevice(rom2); + assertTrue("Address space should have been complete!", b.isComplete()); + } } diff --git a/src/test/java/com/loomcom/symon/CpuImmediateModeTest.java b/src/test/java/com/loomcom/symon/CpuImmediateModeTest.java index 19a5455..63d5d88 100644 --- a/src/test/java/com/loomcom/symon/CpuImmediateModeTest.java +++ b/src/test/java/com/loomcom/symon/CpuImmediateModeTest.java @@ -6,849 +6,849 @@ import junit.framework.*; public class CpuImmediateModeTest extends TestCase { - protected Cpu cpu; - protected Bus bus; - protected Memory mem; - - public void setUp() throws MemoryRangeException { - this.cpu = new Cpu(); - this.bus = new Bus(0x0000, 0xffff); - this.mem = new Memory(0x0000, 0x10000); - bus.addCpu(cpu); - bus.addDevice(mem); - - // Load the reset vector. - bus.write(0xfffc, Cpu.DEFAULT_BASE_ADDRESS & 0x00ff); - bus.write(0xfffd, (Cpu.DEFAULT_BASE_ADDRESS & 0xff00)>>>8); - - cpu.reset(); - // Assert initial state - assertEquals(0, cpu.getAccumulator()); - assertEquals(0, cpu.getXRegister()); - assertEquals(0, cpu.getYRegister()); - assertEquals(0x200, cpu.getProgramCounter()); - assertEquals(0xff, cpu.getStackPointer()); - assertEquals(0x20, cpu.getProcessorStatus()); - } - - /* - * The following opcodes are tested for correctness in this file: - * - * ORA - $09 - * AND - $29 - * EOR - $49 - * ADC - $69 - * LDY - $a0 - * - * LDX - $a2 - * LDA - $a9 - * CPY - $c0 - * CMP - $c9 - * CPX - $e0 - * - * SBC - $e9 - */ - - /* ORA Immediate Mode Tests - 0x09 */ - - public void test_ORA() { - bus.loadProgram(0x09, 0x00, // ORA #$00 - 0x09, 0x11, // ORA #$11 - 0x09, 0x22, // ORA #$22 - 0x09, 0x44, // ORA #$44 - 0x09, 0x88); // ORA #$88 - cpu.step(); - assertEquals(0x00, cpu.getAccumulator()); - - cpu.step(); - assertEquals(0x11, cpu.getAccumulator()); - - cpu.step(); - assertEquals(0x33, cpu.getAccumulator()); - - cpu.step(); - assertEquals(0x77, cpu.getAccumulator()); - - cpu.step(); - assertEquals(0xff, cpu.getAccumulator()); - } - - public void test_ORA_SetsZeroFlagIfResultIsZero() { - bus.loadProgram(0x09, 0x00); // ORA #$00 - cpu.step(); - assertTrue(cpu.getZeroFlag()); - } - - public void test_ORA_DoesNotSetZeroFlagIfResultNotZero() { - bus.loadProgram(0x09, 0x01); // ORA #$01 - cpu.step(); - assertFalse(cpu.getZeroFlag()); - } - - public void test_ORA_SetsNegativeFlagIfResultIsNegative() { - bus.loadProgram(0x09, 0x80); // ORA #$80 - cpu.step(); - assertTrue(cpu.getNegativeFlag()); - } - - public void test_ORA_DoesNotSetNegativeFlagIfResultNotNegative() { - bus.loadProgram(0x09, 0x7f); // ORA #$7F - cpu.step(); - assertFalse(cpu.getNegativeFlag()); - } - - /* AND Immediate Mode Tests - 0x29 */ - - public void test_AND() { - bus.loadProgram(0x29, 0x00, // AND #$00 - 0x29, 0x11, // AND #$11 - 0xa9, 0xaa, // LDA #$AA - 0x29, 0xff, // AND #$FF - 0x29, 0x99, // AND #$99 - 0x29, 0x11); // AND #$11 - cpu.step(); - assertEquals(0x00, cpu.getAccumulator()); - - cpu.step(); - assertEquals(0x00, cpu.getAccumulator()); - - cpu.step(2); - assertEquals(0xaa, cpu.getAccumulator()); - - cpu.step(); - assertEquals(0x88, cpu.getAccumulator()); - - cpu.step(); - assertEquals(0x00, cpu.getAccumulator()); - } - - public void test_AND_SetsZeroFlagIfResultIsZero() { - bus.loadProgram(0xa9, 0x88, // LDA #$88 - 0x29, 0x11); // AND #$11 - cpu.step(2); - assertTrue(cpu.getZeroFlag()); - } - - public void test_AND_DoesNotSetZeroFlagIfResultNotZero() { - bus.loadProgram(0xa9, 0x88, // LDA #$88 - 0x29, 0xf1); // AND #$F1 - cpu.step(2); - assertFalse(cpu.getZeroFlag()); - } - - public void test_AND_SetsNegativeFlagIfResultIsNegative() { - bus.loadProgram(0xa9, 0x88, // LDA #$88 - 0x29, 0xf0); // AND #$F0 - cpu.step(2); - assertTrue(cpu.getNegativeFlag()); - } - - public void test_AND_DoesNotSetNegativeFlagIfResultNotNegative() { - bus.loadProgram(0xa9, 0x88, // LDA #$88 - 0x29, 0x0f); // AND #$0F - cpu.step(2); - assertFalse(cpu.getNegativeFlag()); - } - - /* EOR Immediate Mode Tests - 0x49 */ - - public void test_EOR() { - bus.loadProgram(0xa9, 0x88, // LDA #$88 - 0x49, 0x00, // EOR #$00 - 0x49, 0xff, // EOR #$ff - 0x49, 0x33); // EOR #$33 - cpu.step(2); - assertEquals(0x88, cpu.getAccumulator()); - - cpu.step(); - assertEquals(0x77, cpu.getAccumulator()); - - cpu.step(); - assertEquals(0x44, cpu.getAccumulator()); - } - - public void test_EOR_SetsArithmeticFlags() { - bus.loadProgram(0xa9, 0x77, // LDA #$77 - 0x49, 0x77, // EOR #$77 - 0x49, 0xff); // EOR #$ff - cpu.step(2); - assertEquals(0x00, cpu.getAccumulator()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.step(); - assertEquals(0xff, cpu.getAccumulator()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - } - - /* ADC Immediate Mode Tests - 0x69 */ - - public void test_ADC() { - bus.loadProgram(0xa9, 0x00, // LDA #$00 - 0x69, 0x01); // ADC #$01 - cpu.step(2); - assertEquals(0x01, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0x7f, // LDA #$7f - 0x69, 0x01); // ADC #$01 - cpu.step(2); - assertEquals(0x80, cpu.getAccumulator()); - assertTrue(cpu.getNegativeFlag()); - assertTrue(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0x80, // LDA #$80 - 0x69, 0x01); // ADC #$01 - cpu.step(2); - assertEquals(0x81, cpu.getAccumulator()); - assertTrue(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0xff, // LDA #$ff - 0x69, 0x01); // ADC #$01 - cpu.step(2); - assertEquals(0x00, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertTrue(cpu.getZeroFlag()); - assertTrue(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0x00, // LDA #$00 - 0x69, 0xff); // ADC #$ff - cpu.step(2); - assertEquals(0xff, cpu.getAccumulator()); - assertTrue(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0x7f, // LDA #$7f - 0x69, 0xff); // ADC #$ff - cpu.step(2); - assertEquals(0x7e, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0x80, // LDA #$80 - 0x69, 0xff); // ADC #$ff - cpu.step(2); - assertEquals(0x7f, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertTrue(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0xff, // LDA #$ff - 0x69, 0xff); // ADC #$ff - cpu.step(2); - assertEquals(0xfe, cpu.getAccumulator()); - assertTrue(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getCarryFlag()); - } - - public void test_ADC_IncludesCarry() { - bus.loadProgram(0xa9, 0x00, // LDA #$01 - 0x38, // SEC - 0x69, 0x01); // ADC #$01 - cpu.step(3); - assertEquals(0x02, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getCarryFlag()); - } - - public void test_ADC_DecimalMode() { - bus.loadProgram(0xf8, // SED - 0xa9, 0x01, // LDA #$01 - 0x69, 0x01); // ADC #$01 - cpu.step(3); - assertEquals(0x02, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xf8, // SED - 0xa9, 0x49, // LDA #$49 - 0x69, 0x01); // ADC #$01 - cpu.step(3); - assertEquals(0x50, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xf8, // SED - 0xa9, 0x50, // LDA #$50 - 0x69, 0x01); // ADC #$01 - cpu.step(3); - assertEquals(0x51, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xf8, // SED - 0xa9, 0x99, // LDA #$99 - 0x69, 0x01); // ADC #$01 - cpu.step(3); - assertEquals(0x00, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertTrue(cpu.getZeroFlag()); - assertTrue(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xf8, // SED - 0xa9, 0x00, // LDA #$00 - 0x69, 0x99); // ADC #$01 - cpu.step(3); - assertEquals(0x99, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xf8, // SED - 0xa9, 0x49, // LDA #$49 - 0x69, 0x99); // ADC #$99 - cpu.step(3); - assertEquals(0x48, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xf8, // SED - 0xa9, 0x50, // LDA #$59 - 0x69, 0x99); // ADC #$99 - cpu.step(3); - assertEquals(0x49, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getCarryFlag()); - } - - /* LDY Immediate Mode Tests - 0xa0 */ - - public void test_LDY_SetsYRegister() { - bus.loadProgram(0xa0, 0x12); // LDY #$12 - cpu.step(); - assertEquals(0x12, cpu.getYRegister()); - } - - public void test_LDY_SetsZeroFlagIfArgIsZero() { - bus.loadProgram(0xa0, 0x00); // LDY #$00 - cpu.step(); - assertTrue(cpu.getZeroFlag()); - } - - public void test_LDY_DoesNotSetZeroFlagIfResultNotZero() { - bus.loadProgram(0xa0, 0x12); // LDY #$12 - cpu.step(); - assertFalse(cpu.getZeroFlag()); - } - - public void test_LDY_SetsNegativeFlagIfResultIsNegative() { - bus.loadProgram(0xa0, 0x80); // LDY #$80 - cpu.step(); - assertTrue(cpu.getNegativeFlag()); - } - - public void test_LDY_DoesNotSetNegativeFlagIfResultNotNegative() { - bus.loadProgram(0xa0, 0x7f); // LDY #$7F - cpu.step(); - assertFalse(cpu.getNegativeFlag()); - } - - /* LDX Immediate Mode Tests - 0xa2 */ - - public void test_LDX_SetsXRegister() { - bus.loadProgram(0xa2, 0x12); // LDX #$12 - cpu.step(); - assertEquals(0x12, cpu.getXRegister()); - } - - public void test_LDX_SetsZeroFlagIfResultIsZero() { - bus.loadProgram(0xa2, 0x00); // LDX #$00 - cpu.step(); - assertTrue(cpu.getZeroFlag()); - } - - public void test_LDX_DoesNotSetZeroFlagIfResultNotZero() { - bus.loadProgram(0xa2, 0x12); // LDX #$12 - cpu.step(); - assertFalse(cpu.getZeroFlag()); - } - - public void test_LDX_SetsNegativeFlagIfResultIsNegative() { - bus.loadProgram(0xa2, 0x80); // LDX #$80 - cpu.step(); - assertTrue(cpu.getNegativeFlag()); - } - - public void test_LDX_DoesNotSetNegativeFlagIfResultNotNegative() { - bus.loadProgram(0xa2, 0x7f); // LDX #$7F - cpu.step(); - assertFalse(cpu.getNegativeFlag()); - } - - /* LDA Immediate Mode Tests - 0xa9 */ - - public void test_LDA_SetsAccumulator() { - bus.loadProgram(0xa9, 0x12); // LDA #$12 - cpu.step(); - assertEquals(0x12, cpu.getAccumulator()); - } - - public void test_LDA_SetsZeroFlagIfResultIsZero() { - bus.loadProgram(0xa9, 0x00); // LDA #$00 - cpu.step(); - assertTrue(cpu.getZeroFlag()); - } - - public void test_LDA_DoesNotSetZeroFlagIfResultNotZero() { - bus.loadProgram(0xa9, 0x12); // LDA #$12 - cpu.step(); - assertFalse(cpu.getZeroFlag()); - } - - public void test_LDA_SetsNegativeFlagIfResultIsNegative() { - bus.loadProgram(0xa9, 0x80); // LDA #$80 - cpu.step(); - assertTrue(cpu.getNegativeFlag()); - } - - public void test_LDA_DoesNotSetNegativeFlagIfResultNotNegative() { - bus.loadProgram(0xa9, 0x7f); // LDA #$7F - cpu.step(); - assertFalse(cpu.getNegativeFlag()); - } - - /* CPY Immediate Mode Tests - 0xc0 */ - - public void test_CPY_SetsZeroAndCarryFlagsIfNumbersSame() { - bus.loadProgram(0xa0, 0x00, // LDY #$00 - 0xc0, 0x00); // CPY #$00 - cpu.step(2); - assertTrue(cpu.getCarryFlag()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.reset(); - bus.loadProgram(0xa0, 0x01, // LDY #$01 - 0xc0, 0x01); // CPY #$01 - cpu.step(2); - assertTrue(cpu.getCarryFlag()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.reset(); - bus.loadProgram(0xa0, 0x7f, // LDY #$7F - 0xc0, 0x7f); // CPY #$7F - cpu.step(2); - assertTrue(cpu.getCarryFlag()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.reset(); - bus.loadProgram(0xa0, 0xFF, // LDY #$FF - 0xc0, 0xFF); // CPY #$FF - cpu.step(2); - assertTrue(cpu.getCarryFlag()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - public void test_CPY_SetsCarryFlagIfYGreaterThanMemory() { - bus.loadProgram(0xa0, 0x0a, // LDY #$0A - 0xc0, 0x08); // CPY #$08 - cpu.step(2); - assertTrue(cpu.getCarryFlag()); - assertFalse(cpu.getZeroFlag()); - // $08 - $0a = negative - assertTrue(cpu.getNegativeFlag()); - - cpu.reset(); - bus.loadProgram(0xa0, 0xfa, // LDY #$FA - 0xc0, 0x80); // CPY #$80 - cpu.step(2); - assertTrue(cpu.getCarryFlag()); - assertFalse(cpu.getZeroFlag()); - // $80 - $FA = negative - assertTrue(cpu.getNegativeFlag()); - } - - public void test_CPY_DoesNotSetCarryFlagIfYLessThanThanMemory() { - bus.loadProgram(0xa0, 0x08, // LDY #$08 - 0xc0, 0x0a); // CPY #$0A - cpu.step(2); - assertFalse(cpu.getCarryFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.reset(); - bus.loadProgram(0xa0, 0x70, // LDY #$70 - 0xc0, 0x80); // CPY #$80 - cpu.step(2); - assertFalse(cpu.getCarryFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - /* CMP Immediate Mode Tests - 0xc9 */ - - public void test_CMP_SetsZeroAndCarryFlagsIfNumbersSame() { - bus.loadProgram(0xa9, 0x00, // LDA #$00 - 0xc9, 0x00); // CMP #$00 - cpu.step(2); - assertTrue(cpu.getCarryFlag()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0x01, // LDA #$01 - 0xc9, 0x01); // CMP #$01 - cpu.step(2); - assertTrue(cpu.getCarryFlag()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0x7f, // LDA #$7F - 0xc9, 0x7f); // CMP #$7F - cpu.step(2); - assertTrue(cpu.getCarryFlag()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0xFF, // LDA #$FF - 0xc9, 0xFF); // CMP #$FF - cpu.step(2); - assertTrue(cpu.getCarryFlag()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - public void test_CMP_SetsCarryFlagIfYGreaterThanMemory() { - bus.loadProgram(0xa9, 0x0a, // LDA #$0A - 0xc9, 0x08); // CMP #$08 - cpu.step(2); - assertTrue(cpu.getCarryFlag()); - assertFalse(cpu.getZeroFlag()); - // $08 - $0a = negative - assertTrue(cpu.getNegativeFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0xfa, // LDA #$FA - 0xc9, 0x80); // CMP #$80 - cpu.step(2); - assertTrue(cpu.getCarryFlag()); - assertFalse(cpu.getZeroFlag()); - // $80 - $FA = negative - assertTrue(cpu.getNegativeFlag()); - } - - public void test_CMP_DoesNotSetCarryFlagIfYGreaterThanMemory() { - bus.loadProgram(0xa9, 0x08, // LDA #$08 - 0xc9, 0x0a); // CMP #$0A - cpu.step(2); - assertFalse(cpu.getCarryFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0x70, // LDA #$70 - 0xc9, 0x80); // CMP #$80 - cpu.step(2); - assertFalse(cpu.getCarryFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - /* CPX Immediate Mode Tests - 0xe0 */ - - public void test_CPX_SetsZeroAndCarryFlagsIfNumbersSame() { - bus.loadProgram(0xa2, 0x00, // LDX #$00 - 0xe0, 0x00); // CPX #$00 - cpu.step(2); - assertTrue(cpu.getCarryFlag()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.reset(); - bus.loadProgram(0xa2, 0x01, // LDX #$01 - 0xe0, 0x01); // CPX #$01 - cpu.step(2); - assertTrue(cpu.getCarryFlag()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.reset(); - bus.loadProgram(0xa2, 0x7f, // LDX #$7F - 0xe0, 0x7f); // CPX #$7F - cpu.step(2); - assertTrue(cpu.getCarryFlag()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.reset(); - bus.loadProgram(0xa2, 0xFF, // LDX #$FF - 0xe0, 0xFF); // CPX #$FF - cpu.step(2); - assertTrue(cpu.getCarryFlag()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - public void test_CPX_SetsCarryFlagIfYGreaterThanMemory() { - bus.loadProgram(0xa2, 0x0a, // LDX #$0A - 0xe0, 0x08); // CPX #$08 - cpu.step(2); - assertTrue(cpu.getCarryFlag()); - assertFalse(cpu.getZeroFlag()); - // $08 - $0a = negative - assertTrue(cpu.getNegativeFlag()); - - cpu.reset(); - bus.loadProgram(0xa2, 0xfa, // LDX #$FA - 0xe0, 0x80); // CPX #$80 - cpu.step(2); - assertTrue(cpu.getCarryFlag()); - assertFalse(cpu.getZeroFlag()); - // $80 - $FA = negative - assertTrue(cpu.getNegativeFlag()); - } - - public void test_CPX_DoesNotSetCarryFlagIfYGreaterThanMemory() { - bus.loadProgram(0xa2, 0x08, // LDX #$08 - 0xe0, 0x0a); // CPX #$0A - cpu.step(2); - assertFalse(cpu.getCarryFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.reset(); - bus.loadProgram(0xa2, 0x70, // LDX #$70 - 0xe0, 0x80); // CMX #$80 - cpu.step(2); - assertFalse(cpu.getCarryFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - /* SBC Immediate Mode Tests - 0xe9 */ - - public void test_SBC() { - bus.loadProgram(0xa9, 0x00, // LDA #$00 - 0xe9, 0x01); // SBC #$01 - cpu.step(2); - assertEquals(0xfe, cpu.getAccumulator()); - assertTrue(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0x7f, // LDA #$7f - 0xe9, 0x01); // SBC #$01 - cpu.step(2); - assertEquals(0x7d, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0x80, // LDA #$80 - 0xe9, 0x01); // SBC #$01 - cpu.step(2); - assertEquals(0x7e, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertTrue(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0xff, // LDA #$ff - 0xe9, 0x01); // SBC #$01 - cpu.step(2); - assertEquals(0xfd, cpu.getAccumulator()); - assertTrue(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0x02, // LDA #$02 - 0xe9, 0x01); // SBC #$01 - cpu.step(2); - assertEquals(0x00, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertTrue(cpu.getZeroFlag()); - assertTrue(cpu.getCarryFlag()); - } - - public void test_SBC_IncludesNotOfCarry() { - // Subtrace with Carry Flag cleared - bus.loadProgram(0x18, // CLC - 0xa9, 0x05, // LDA #$00 - 0xe9, 0x01); // SBC #$01 - - cpu.step(3); - assertEquals(0x03, cpu.getAccumulator()); - - cpu.reset(); - - // Subtrace with Carry Flag cleared - bus.loadProgram(0x18, // CLC - 0xa9, 0x00, // LDA #$00 - 0xe9, 0x01); // SBC #$01 - - cpu.step(3); - assertEquals(0xfe, cpu.getAccumulator()); - - cpu.reset(); - - // Subtract with Carry Flag set - bus.loadProgram(0x38, // SEC - 0xa9, 0x05, // LDA #$00 - 0xe9, 0x01); // SBC #$01 - cpu.step(3); - assertEquals(0x04, cpu.getAccumulator()); - assertTrue(cpu.getCarryFlag()); - - cpu.reset(); - - // Subtract with Carry Flag set - bus.loadProgram(0x38, // SEC - 0xa9, 0x00, // LDA #$00 - 0xe9, 0x01); // SBC #$01 - cpu.step(3); - assertEquals(0xff, cpu.getAccumulator()); - assertFalse(cpu.getCarryFlag()); - - } - - public void test_SBC_DecimalMode() { - bus.loadProgram(0xf8, - 0xa9, 0x00, - 0xe9, 0x01); - cpu.step(3); - assertEquals(0x98, cpu.getAccumulator()); - assertFalse(cpu.getCarryFlag()); // borrow = set flag - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getDecimalModeFlag()); - - cpu.reset(); - - bus.loadProgram(0xf8, - 0xa9, 0x99, - 0xe9, 0x01); - cpu.step(3); - assertEquals(0x97, cpu.getAccumulator()); - assertTrue(cpu.getCarryFlag()); // No borrow = clear flag - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getDecimalModeFlag()); - - cpu.reset(); - - bus.loadProgram(0xf8, - 0xa9, 0x50, - 0xe9, 0x01); - cpu.step(3); - assertEquals(0x48, cpu.getAccumulator()); - assertTrue(cpu.getCarryFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getDecimalModeFlag()); - - - cpu.reset(); - - bus.loadProgram(0xf8, // SED - 0xa9, 0x02, // LDA #$02 - 0xe9, 0x01); // SBC #$01 - cpu.step(3); - assertEquals(0x00, cpu.getAccumulator()); - assertTrue(cpu.getCarryFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertTrue(cpu.getZeroFlag()); - assertTrue(cpu.getDecimalModeFlag()); - - cpu.reset(); - - bus.loadProgram(0xf8, // SED - 0xa9, 0x10, // LDA #$10 - 0xe9, 0x11); // SBC #$11 - cpu.step(3); - assertEquals(0x98, cpu.getAccumulator()); - assertFalse(cpu.getCarryFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getDecimalModeFlag()); - - cpu.reset(); - - bus.loadProgram(0x38, // SEC - 0xf8, // SED - 0xa9, 0x05, // LDA #$05 - 0xe9, 0x01); // SBC #$01 - cpu.step(4); - assertEquals(0x04, cpu.getAccumulator()); - assertTrue(cpu.getCarryFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getDecimalModeFlag()); - - cpu.reset(); - - bus.loadProgram(0x38, // SEC - 0xf8, // SED - 0xa9, 0x00, // LDA #$00 - 0xe9, 0x01); // SBC #$01 - cpu.step(4); - assertEquals(0x99, cpu.getAccumulator()); - assertFalse(cpu.getCarryFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getDecimalModeFlag()); - } + protected Cpu cpu; + protected Bus bus; + protected Memory mem; + + public void setUp() throws MemoryRangeException { + this.cpu = new Cpu(); + this.bus = new Bus(0x0000, 0xffff); + this.mem = new Memory(0x0000, 0x10000); + bus.addCpu(cpu); + bus.addDevice(mem); + + // Load the reset vector. + bus.write(0xfffc, Cpu.DEFAULT_BASE_ADDRESS & 0x00ff); + bus.write(0xfffd, (Cpu.DEFAULT_BASE_ADDRESS & 0xff00)>>>8); + + cpu.reset(); + // Assert initial state + assertEquals(0, cpu.getAccumulator()); + assertEquals(0, cpu.getXRegister()); + assertEquals(0, cpu.getYRegister()); + assertEquals(0x200, cpu.getProgramCounter()); + assertEquals(0xff, cpu.getStackPointer()); + assertEquals(0x20, cpu.getProcessorStatus()); + } + + /* + * The following opcodes are tested for correctness in this file: + * + * ORA - $09 + * AND - $29 + * EOR - $49 + * ADC - $69 + * LDY - $a0 + * + * LDX - $a2 + * LDA - $a9 + * CPY - $c0 + * CMP - $c9 + * CPX - $e0 + * + * SBC - $e9 + */ + + /* ORA Immediate Mode Tests - 0x09 */ + + public void test_ORA() { + bus.loadProgram(0x09, 0x00, // ORA #$00 + 0x09, 0x11, // ORA #$11 + 0x09, 0x22, // ORA #$22 + 0x09, 0x44, // ORA #$44 + 0x09, 0x88); // ORA #$88 + cpu.step(); + assertEquals(0x00, cpu.getAccumulator()); + + cpu.step(); + assertEquals(0x11, cpu.getAccumulator()); + + cpu.step(); + assertEquals(0x33, cpu.getAccumulator()); + + cpu.step(); + assertEquals(0x77, cpu.getAccumulator()); + + cpu.step(); + assertEquals(0xff, cpu.getAccumulator()); + } + + public void test_ORA_SetsZeroFlagIfResultIsZero() { + bus.loadProgram(0x09, 0x00); // ORA #$00 + cpu.step(); + assertTrue(cpu.getZeroFlag()); + } + + public void test_ORA_DoesNotSetZeroFlagIfResultNotZero() { + bus.loadProgram(0x09, 0x01); // ORA #$01 + cpu.step(); + assertFalse(cpu.getZeroFlag()); + } + + public void test_ORA_SetsNegativeFlagIfResultIsNegative() { + bus.loadProgram(0x09, 0x80); // ORA #$80 + cpu.step(); + assertTrue(cpu.getNegativeFlag()); + } + + public void test_ORA_DoesNotSetNegativeFlagIfResultNotNegative() { + bus.loadProgram(0x09, 0x7f); // ORA #$7F + cpu.step(); + assertFalse(cpu.getNegativeFlag()); + } + + /* AND Immediate Mode Tests - 0x29 */ + + public void test_AND() { + bus.loadProgram(0x29, 0x00, // AND #$00 + 0x29, 0x11, // AND #$11 + 0xa9, 0xaa, // LDA #$AA + 0x29, 0xff, // AND #$FF + 0x29, 0x99, // AND #$99 + 0x29, 0x11); // AND #$11 + cpu.step(); + assertEquals(0x00, cpu.getAccumulator()); + + cpu.step(); + assertEquals(0x00, cpu.getAccumulator()); + + cpu.step(2); + assertEquals(0xaa, cpu.getAccumulator()); + + cpu.step(); + assertEquals(0x88, cpu.getAccumulator()); + + cpu.step(); + assertEquals(0x00, cpu.getAccumulator()); + } + + public void test_AND_SetsZeroFlagIfResultIsZero() { + bus.loadProgram(0xa9, 0x88, // LDA #$88 + 0x29, 0x11); // AND #$11 + cpu.step(2); + assertTrue(cpu.getZeroFlag()); + } + + public void test_AND_DoesNotSetZeroFlagIfResultNotZero() { + bus.loadProgram(0xa9, 0x88, // LDA #$88 + 0x29, 0xf1); // AND #$F1 + cpu.step(2); + assertFalse(cpu.getZeroFlag()); + } + + public void test_AND_SetsNegativeFlagIfResultIsNegative() { + bus.loadProgram(0xa9, 0x88, // LDA #$88 + 0x29, 0xf0); // AND #$F0 + cpu.step(2); + assertTrue(cpu.getNegativeFlag()); + } + + public void test_AND_DoesNotSetNegativeFlagIfResultNotNegative() { + bus.loadProgram(0xa9, 0x88, // LDA #$88 + 0x29, 0x0f); // AND #$0F + cpu.step(2); + assertFalse(cpu.getNegativeFlag()); + } + + /* EOR Immediate Mode Tests - 0x49 */ + + public void test_EOR() { + bus.loadProgram(0xa9, 0x88, // LDA #$88 + 0x49, 0x00, // EOR #$00 + 0x49, 0xff, // EOR #$ff + 0x49, 0x33); // EOR #$33 + cpu.step(2); + assertEquals(0x88, cpu.getAccumulator()); + + cpu.step(); + assertEquals(0x77, cpu.getAccumulator()); + + cpu.step(); + assertEquals(0x44, cpu.getAccumulator()); + } + + public void test_EOR_SetsArithmeticFlags() { + bus.loadProgram(0xa9, 0x77, // LDA #$77 + 0x49, 0x77, // EOR #$77 + 0x49, 0xff); // EOR #$ff + cpu.step(2); + assertEquals(0x00, cpu.getAccumulator()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.step(); + assertEquals(0xff, cpu.getAccumulator()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + } + + /* ADC Immediate Mode Tests - 0x69 */ + + public void test_ADC() { + bus.loadProgram(0xa9, 0x00, // LDA #$00 + 0x69, 0x01); // ADC #$01 + cpu.step(2); + assertEquals(0x01, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0x7f, // LDA #$7f + 0x69, 0x01); // ADC #$01 + cpu.step(2); + assertEquals(0x80, cpu.getAccumulator()); + assertTrue(cpu.getNegativeFlag()); + assertTrue(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0x80, // LDA #$80 + 0x69, 0x01); // ADC #$01 + cpu.step(2); + assertEquals(0x81, cpu.getAccumulator()); + assertTrue(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0xff, // LDA #$ff + 0x69, 0x01); // ADC #$01 + cpu.step(2); + assertEquals(0x00, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertTrue(cpu.getZeroFlag()); + assertTrue(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0x00, // LDA #$00 + 0x69, 0xff); // ADC #$ff + cpu.step(2); + assertEquals(0xff, cpu.getAccumulator()); + assertTrue(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0x7f, // LDA #$7f + 0x69, 0xff); // ADC #$ff + cpu.step(2); + assertEquals(0x7e, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0x80, // LDA #$80 + 0x69, 0xff); // ADC #$ff + cpu.step(2); + assertEquals(0x7f, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertTrue(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0xff, // LDA #$ff + 0x69, 0xff); // ADC #$ff + cpu.step(2); + assertEquals(0xfe, cpu.getAccumulator()); + assertTrue(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getCarryFlag()); + } + + public void test_ADC_IncludesCarry() { + bus.loadProgram(0xa9, 0x00, // LDA #$01 + 0x38, // SEC + 0x69, 0x01); // ADC #$01 + cpu.step(3); + assertEquals(0x02, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getCarryFlag()); + } + + public void test_ADC_DecimalMode() { + bus.loadProgram(0xf8, // SED + 0xa9, 0x01, // LDA #$01 + 0x69, 0x01); // ADC #$01 + cpu.step(3); + assertEquals(0x02, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xf8, // SED + 0xa9, 0x49, // LDA #$49 + 0x69, 0x01); // ADC #$01 + cpu.step(3); + assertEquals(0x50, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xf8, // SED + 0xa9, 0x50, // LDA #$50 + 0x69, 0x01); // ADC #$01 + cpu.step(3); + assertEquals(0x51, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xf8, // SED + 0xa9, 0x99, // LDA #$99 + 0x69, 0x01); // ADC #$01 + cpu.step(3); + assertEquals(0x00, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertTrue(cpu.getZeroFlag()); + assertTrue(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xf8, // SED + 0xa9, 0x00, // LDA #$00 + 0x69, 0x99); // ADC #$01 + cpu.step(3); + assertEquals(0x99, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xf8, // SED + 0xa9, 0x49, // LDA #$49 + 0x69, 0x99); // ADC #$99 + cpu.step(3); + assertEquals(0x48, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xf8, // SED + 0xa9, 0x50, // LDA #$59 + 0x69, 0x99); // ADC #$99 + cpu.step(3); + assertEquals(0x49, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getCarryFlag()); + } + + /* LDY Immediate Mode Tests - 0xa0 */ + + public void test_LDY_SetsYRegister() { + bus.loadProgram(0xa0, 0x12); // LDY #$12 + cpu.step(); + assertEquals(0x12, cpu.getYRegister()); + } + + public void test_LDY_SetsZeroFlagIfArgIsZero() { + bus.loadProgram(0xa0, 0x00); // LDY #$00 + cpu.step(); + assertTrue(cpu.getZeroFlag()); + } + + public void test_LDY_DoesNotSetZeroFlagIfResultNotZero() { + bus.loadProgram(0xa0, 0x12); // LDY #$12 + cpu.step(); + assertFalse(cpu.getZeroFlag()); + } + + public void test_LDY_SetsNegativeFlagIfResultIsNegative() { + bus.loadProgram(0xa0, 0x80); // LDY #$80 + cpu.step(); + assertTrue(cpu.getNegativeFlag()); + } + + public void test_LDY_DoesNotSetNegativeFlagIfResultNotNegative() { + bus.loadProgram(0xa0, 0x7f); // LDY #$7F + cpu.step(); + assertFalse(cpu.getNegativeFlag()); + } + + /* LDX Immediate Mode Tests - 0xa2 */ + + public void test_LDX_SetsXRegister() { + bus.loadProgram(0xa2, 0x12); // LDX #$12 + cpu.step(); + assertEquals(0x12, cpu.getXRegister()); + } + + public void test_LDX_SetsZeroFlagIfResultIsZero() { + bus.loadProgram(0xa2, 0x00); // LDX #$00 + cpu.step(); + assertTrue(cpu.getZeroFlag()); + } + + public void test_LDX_DoesNotSetZeroFlagIfResultNotZero() { + bus.loadProgram(0xa2, 0x12); // LDX #$12 + cpu.step(); + assertFalse(cpu.getZeroFlag()); + } + + public void test_LDX_SetsNegativeFlagIfResultIsNegative() { + bus.loadProgram(0xa2, 0x80); // LDX #$80 + cpu.step(); + assertTrue(cpu.getNegativeFlag()); + } + + public void test_LDX_DoesNotSetNegativeFlagIfResultNotNegative() { + bus.loadProgram(0xa2, 0x7f); // LDX #$7F + cpu.step(); + assertFalse(cpu.getNegativeFlag()); + } + + /* LDA Immediate Mode Tests - 0xa9 */ + + public void test_LDA_SetsAccumulator() { + bus.loadProgram(0xa9, 0x12); // LDA #$12 + cpu.step(); + assertEquals(0x12, cpu.getAccumulator()); + } + + public void test_LDA_SetsZeroFlagIfResultIsZero() { + bus.loadProgram(0xa9, 0x00); // LDA #$00 + cpu.step(); + assertTrue(cpu.getZeroFlag()); + } + + public void test_LDA_DoesNotSetZeroFlagIfResultNotZero() { + bus.loadProgram(0xa9, 0x12); // LDA #$12 + cpu.step(); + assertFalse(cpu.getZeroFlag()); + } + + public void test_LDA_SetsNegativeFlagIfResultIsNegative() { + bus.loadProgram(0xa9, 0x80); // LDA #$80 + cpu.step(); + assertTrue(cpu.getNegativeFlag()); + } + + public void test_LDA_DoesNotSetNegativeFlagIfResultNotNegative() { + bus.loadProgram(0xa9, 0x7f); // LDA #$7F + cpu.step(); + assertFalse(cpu.getNegativeFlag()); + } + + /* CPY Immediate Mode Tests - 0xc0 */ + + public void test_CPY_SetsZeroAndCarryFlagsIfNumbersSame() { + bus.loadProgram(0xa0, 0x00, // LDY #$00 + 0xc0, 0x00); // CPY #$00 + cpu.step(2); + assertTrue(cpu.getCarryFlag()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.reset(); + bus.loadProgram(0xa0, 0x01, // LDY #$01 + 0xc0, 0x01); // CPY #$01 + cpu.step(2); + assertTrue(cpu.getCarryFlag()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.reset(); + bus.loadProgram(0xa0, 0x7f, // LDY #$7F + 0xc0, 0x7f); // CPY #$7F + cpu.step(2); + assertTrue(cpu.getCarryFlag()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.reset(); + bus.loadProgram(0xa0, 0xFF, // LDY #$FF + 0xc0, 0xFF); // CPY #$FF + cpu.step(2); + assertTrue(cpu.getCarryFlag()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_CPY_SetsCarryFlagIfYGreaterThanMemory() { + bus.loadProgram(0xa0, 0x0a, // LDY #$0A + 0xc0, 0x08); // CPY #$08 + cpu.step(2); + assertTrue(cpu.getCarryFlag()); + assertFalse(cpu.getZeroFlag()); + // $08 - $0a = negative + assertTrue(cpu.getNegativeFlag()); + + cpu.reset(); + bus.loadProgram(0xa0, 0xfa, // LDY #$FA + 0xc0, 0x80); // CPY #$80 + cpu.step(2); + assertTrue(cpu.getCarryFlag()); + assertFalse(cpu.getZeroFlag()); + // $80 - $FA = negative + assertTrue(cpu.getNegativeFlag()); + } + + public void test_CPY_DoesNotSetCarryFlagIfYLessThanThanMemory() { + bus.loadProgram(0xa0, 0x08, // LDY #$08 + 0xc0, 0x0a); // CPY #$0A + cpu.step(2); + assertFalse(cpu.getCarryFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.reset(); + bus.loadProgram(0xa0, 0x70, // LDY #$70 + 0xc0, 0x80); // CPY #$80 + cpu.step(2); + assertFalse(cpu.getCarryFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + /* CMP Immediate Mode Tests - 0xc9 */ + + public void test_CMP_SetsZeroAndCarryFlagsIfNumbersSame() { + bus.loadProgram(0xa9, 0x00, // LDA #$00 + 0xc9, 0x00); // CMP #$00 + cpu.step(2); + assertTrue(cpu.getCarryFlag()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0x01, // LDA #$01 + 0xc9, 0x01); // CMP #$01 + cpu.step(2); + assertTrue(cpu.getCarryFlag()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0x7f, // LDA #$7F + 0xc9, 0x7f); // CMP #$7F + cpu.step(2); + assertTrue(cpu.getCarryFlag()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0xFF, // LDA #$FF + 0xc9, 0xFF); // CMP #$FF + cpu.step(2); + assertTrue(cpu.getCarryFlag()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_CMP_SetsCarryFlagIfYGreaterThanMemory() { + bus.loadProgram(0xa9, 0x0a, // LDA #$0A + 0xc9, 0x08); // CMP #$08 + cpu.step(2); + assertTrue(cpu.getCarryFlag()); + assertFalse(cpu.getZeroFlag()); + // $08 - $0a = negative + assertTrue(cpu.getNegativeFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0xfa, // LDA #$FA + 0xc9, 0x80); // CMP #$80 + cpu.step(2); + assertTrue(cpu.getCarryFlag()); + assertFalse(cpu.getZeroFlag()); + // $80 - $FA = negative + assertTrue(cpu.getNegativeFlag()); + } + + public void test_CMP_DoesNotSetCarryFlagIfYGreaterThanMemory() { + bus.loadProgram(0xa9, 0x08, // LDA #$08 + 0xc9, 0x0a); // CMP #$0A + cpu.step(2); + assertFalse(cpu.getCarryFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0x70, // LDA #$70 + 0xc9, 0x80); // CMP #$80 + cpu.step(2); + assertFalse(cpu.getCarryFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + /* CPX Immediate Mode Tests - 0xe0 */ + + public void test_CPX_SetsZeroAndCarryFlagsIfNumbersSame() { + bus.loadProgram(0xa2, 0x00, // LDX #$00 + 0xe0, 0x00); // CPX #$00 + cpu.step(2); + assertTrue(cpu.getCarryFlag()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.reset(); + bus.loadProgram(0xa2, 0x01, // LDX #$01 + 0xe0, 0x01); // CPX #$01 + cpu.step(2); + assertTrue(cpu.getCarryFlag()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.reset(); + bus.loadProgram(0xa2, 0x7f, // LDX #$7F + 0xe0, 0x7f); // CPX #$7F + cpu.step(2); + assertTrue(cpu.getCarryFlag()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.reset(); + bus.loadProgram(0xa2, 0xFF, // LDX #$FF + 0xe0, 0xFF); // CPX #$FF + cpu.step(2); + assertTrue(cpu.getCarryFlag()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_CPX_SetsCarryFlagIfYGreaterThanMemory() { + bus.loadProgram(0xa2, 0x0a, // LDX #$0A + 0xe0, 0x08); // CPX #$08 + cpu.step(2); + assertTrue(cpu.getCarryFlag()); + assertFalse(cpu.getZeroFlag()); + // $08 - $0a = negative + assertTrue(cpu.getNegativeFlag()); + + cpu.reset(); + bus.loadProgram(0xa2, 0xfa, // LDX #$FA + 0xe0, 0x80); // CPX #$80 + cpu.step(2); + assertTrue(cpu.getCarryFlag()); + assertFalse(cpu.getZeroFlag()); + // $80 - $FA = negative + assertTrue(cpu.getNegativeFlag()); + } + + public void test_CPX_DoesNotSetCarryFlagIfYGreaterThanMemory() { + bus.loadProgram(0xa2, 0x08, // LDX #$08 + 0xe0, 0x0a); // CPX #$0A + cpu.step(2); + assertFalse(cpu.getCarryFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.reset(); + bus.loadProgram(0xa2, 0x70, // LDX #$70 + 0xe0, 0x80); // CMX #$80 + cpu.step(2); + assertFalse(cpu.getCarryFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + /* SBC Immediate Mode Tests - 0xe9 */ + + public void test_SBC() { + bus.loadProgram(0xa9, 0x00, // LDA #$00 + 0xe9, 0x01); // SBC #$01 + cpu.step(2); + assertEquals(0xfe, cpu.getAccumulator()); + assertTrue(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0x7f, // LDA #$7f + 0xe9, 0x01); // SBC #$01 + cpu.step(2); + assertEquals(0x7d, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0x80, // LDA #$80 + 0xe9, 0x01); // SBC #$01 + cpu.step(2); + assertEquals(0x7e, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertTrue(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0xff, // LDA #$ff + 0xe9, 0x01); // SBC #$01 + cpu.step(2); + assertEquals(0xfd, cpu.getAccumulator()); + assertTrue(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0x02, // LDA #$02 + 0xe9, 0x01); // SBC #$01 + cpu.step(2); + assertEquals(0x00, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertTrue(cpu.getZeroFlag()); + assertTrue(cpu.getCarryFlag()); + } + + public void test_SBC_IncludesNotOfCarry() { + // Subtrace with Carry Flag cleared + bus.loadProgram(0x18, // CLC + 0xa9, 0x05, // LDA #$00 + 0xe9, 0x01); // SBC #$01 + + cpu.step(3); + assertEquals(0x03, cpu.getAccumulator()); + + cpu.reset(); + + // Subtrace with Carry Flag cleared + bus.loadProgram(0x18, // CLC + 0xa9, 0x00, // LDA #$00 + 0xe9, 0x01); // SBC #$01 + + cpu.step(3); + assertEquals(0xfe, cpu.getAccumulator()); + + cpu.reset(); + + // Subtract with Carry Flag set + bus.loadProgram(0x38, // SEC + 0xa9, 0x05, // LDA #$00 + 0xe9, 0x01); // SBC #$01 + cpu.step(3); + assertEquals(0x04, cpu.getAccumulator()); + assertTrue(cpu.getCarryFlag()); + + cpu.reset(); + + // Subtract with Carry Flag set + bus.loadProgram(0x38, // SEC + 0xa9, 0x00, // LDA #$00 + 0xe9, 0x01); // SBC #$01 + cpu.step(3); + assertEquals(0xff, cpu.getAccumulator()); + assertFalse(cpu.getCarryFlag()); + + } + + public void test_SBC_DecimalMode() { + bus.loadProgram(0xf8, + 0xa9, 0x00, + 0xe9, 0x01); + cpu.step(3); + assertEquals(0x98, cpu.getAccumulator()); + assertFalse(cpu.getCarryFlag()); // borrow = set flag + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getDecimalModeFlag()); + + cpu.reset(); + + bus.loadProgram(0xf8, + 0xa9, 0x99, + 0xe9, 0x01); + cpu.step(3); + assertEquals(0x97, cpu.getAccumulator()); + assertTrue(cpu.getCarryFlag()); // No borrow = clear flag + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getDecimalModeFlag()); + + cpu.reset(); + + bus.loadProgram(0xf8, + 0xa9, 0x50, + 0xe9, 0x01); + cpu.step(3); + assertEquals(0x48, cpu.getAccumulator()); + assertTrue(cpu.getCarryFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getDecimalModeFlag()); + + + cpu.reset(); + + bus.loadProgram(0xf8, // SED + 0xa9, 0x02, // LDA #$02 + 0xe9, 0x01); // SBC #$01 + cpu.step(3); + assertEquals(0x00, cpu.getAccumulator()); + assertTrue(cpu.getCarryFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertTrue(cpu.getZeroFlag()); + assertTrue(cpu.getDecimalModeFlag()); + + cpu.reset(); + + bus.loadProgram(0xf8, // SED + 0xa9, 0x10, // LDA #$10 + 0xe9, 0x11); // SBC #$11 + cpu.step(3); + assertEquals(0x98, cpu.getAccumulator()); + assertFalse(cpu.getCarryFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getDecimalModeFlag()); + + cpu.reset(); + + bus.loadProgram(0x38, // SEC + 0xf8, // SED + 0xa9, 0x05, // LDA #$05 + 0xe9, 0x01); // SBC #$01 + cpu.step(4); + assertEquals(0x04, cpu.getAccumulator()); + assertTrue(cpu.getCarryFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getDecimalModeFlag()); + + cpu.reset(); + + bus.loadProgram(0x38, // SEC + 0xf8, // SED + 0xa9, 0x00, // LDA #$00 + 0xe9, 0x01); // SBC #$01 + cpu.step(4); + assertEquals(0x99, cpu.getAccumulator()); + assertFalse(cpu.getCarryFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getDecimalModeFlag()); + } } \ No newline at end of file diff --git a/src/test/java/com/loomcom/symon/CpuImpliedModeTest.java b/src/test/java/com/loomcom/symon/CpuImpliedModeTest.java index e999e35..bba6021 100644 --- a/src/test/java/com/loomcom/symon/CpuImpliedModeTest.java +++ b/src/test/java/com/loomcom/symon/CpuImpliedModeTest.java @@ -6,591 +6,591 @@ import junit.framework.*; public class CpuImpliedModeTest extends TestCase { - protected Cpu cpu; - protected Bus bus; - protected Memory mem; - - public void setUp() throws MemoryRangeException { - this.cpu = new Cpu(); - this.bus = new Bus(0x0000, 0xffff); - this.mem = new Memory(0x0000, 0x10000); - bus.addCpu(cpu); - bus.addDevice(mem); - - // Load the reset vector. - bus.write(0xfffc, Cpu.DEFAULT_BASE_ADDRESS & 0x00ff); - bus.write(0xfffd, (Cpu.DEFAULT_BASE_ADDRESS & 0xff00)>>>8); - - cpu.reset(); - - // Assert initial state - assertEquals(0, cpu.getAccumulator()); - assertEquals(0, cpu.getXRegister()); - assertEquals(0, cpu.getYRegister()); - assertEquals(0x200, cpu.getProgramCounter()); - assertEquals(0xff, cpu.getStackPointer()); - assertEquals(0x20, cpu.getProcessorStatus()); - } - - /* - * The following opcodes are tested for correctness in this file: - * - * BRK - $00 - * CLC - $18 - * CLD - $d8 - * CLI - $58 - * CLV - $B8 - * - * DEX - $ca - * DEY - $88 - * INX - $e8 - * INY - $c8 - * NOP - $ea - * - * PHA - $48 - * PHP - $08 - * PLA - $68 - * PLP - $28 - * RTI - $40 - * - * RTS - $60 - * SEC - $38 - * SED - $f8 - * SEI - $78 - * TAX - $aa - * - * TAY - $a8 - * TSX - $ba - * TXA - $8a - * TXS - $9a - * TYA - $98 - */ - - /* BRK Tests - 0x00 */ - - public void test_BRK() { - cpu.setCarryFlag(); - cpu.setOverflowFlag(); - assertEquals(0x20|Cpu.P_CARRY|Cpu.P_OVERFLOW, - cpu.getProcessorStatus()); - assertEquals(0xff, cpu.stackPeek()); - assertFalse(cpu.getBreakFlag()); - assertEquals(0x0200, cpu.getProgramCounter()); - assertEquals(0xff, cpu.getStackPointer()); - - // Set the IRQ vector - bus.write(Cpu.IRQ_VECTOR_H, 0x12); - bus.write(Cpu.IRQ_VECTOR_L, 0x34); - - bus.loadProgram(0xea, - 0xea, - 0xea, - 0x00, - 0xea, - 0xea); - - cpu.step(3); // Three NOP instructions - - assertEquals(0x203, cpu.getProgramCounter()); - - cpu.step(); // Triggers the BRK - - // Was at PC = 0x204. PC+2 should now be on the stack - assertEquals(0x02, bus.read(0x1ff)); // PC high byte - assertEquals(0x06, bus.read(0x1fe)); // PC low byte - assertEquals(0x20|Cpu.P_CARRY|Cpu.P_OVERFLOW|Cpu.P_BREAK, - bus.read(0x1fd)); // Processor Status, with B set - - // Interrupt vector held 0x1234, so we should be there. - assertEquals(0x1234, cpu.getProgramCounter()); - assertEquals(0xfc, cpu.getStackPointer()); - - // B and I flags should have been set on P - assertEquals(0x20|Cpu.P_CARRY|Cpu.P_OVERFLOW|Cpu.P_BREAK| - Cpu.P_IRQ_DISABLE, - cpu.getProcessorStatus()); - } - - public void test_BRK_HonorsIrqDisableFlag() { - cpu.setIrqDisableFlag(); - - bus.loadProgram(0xea, - 0xea, - 0xea, - 0x00, - 0xea, - 0xea); - - cpu.step(3); // Three NOP instructions - - assertEquals(0x203, cpu.getProgramCounter()); - - // Triggers the BRK, which should do nothing because - // of the Interrupt Disable flag - cpu.step(); - - // Reset to original contents of PC - assertEquals(0x0204, cpu.getProgramCounter()); - // Empty stack - assertEquals(0xff, cpu.getStackPointer()); - - cpu.step(2); // Two more NOPs - - // Reset to original contents of PC - assertEquals(0x0206, cpu.getProgramCounter()); - // Empty stack - assertEquals(0xff, cpu.getStackPointer()); - } - - /* CLC - Clear Carry Flag - $18 */ - public void test_CLC() { - cpu.setCarryFlag(); - assertTrue(cpu.getCarryFlag()); - - bus.loadProgram(0x18); - cpu.step(); - - assertFalse(cpu.getCarryFlag()); - } - - /* CLD - Clear Decimal Mode Flag - $d8 */ - public void test_CLD() { - cpu.setDecimalModeFlag(); - assertTrue(cpu.getDecimalModeFlag()); - - bus.loadProgram(0xd8); - cpu.step(); - - assertFalse(cpu.getDecimalModeFlag()); - } - - /* CLI - Clear Interrupt Disabled Flag - $58 */ - public void test_CLI() { - cpu.setIrqDisableFlag(); - assertTrue(cpu.getIrqDisableFlag()); - - bus.loadProgram(0x58); - cpu.step(); - - assertFalse(cpu.getIrqDisableFlag()); - } - - /* CLV - Clear Overflow Flag - $b8 */ - public void test_CLV() { - cpu.setOverflowFlag(); - assertTrue(cpu.getOverflowFlag()); - - bus.loadProgram(0xb8); - cpu.step(); - - assertFalse(cpu.getOverflowFlag()); - } - - /* DEX - Decrement the X register - $ca */ - - public void test_DEX() { - bus.loadProgram(0xca); - cpu.setXRegister(0x02); - cpu.step(); - assertEquals(0x01, cpu.getXRegister()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - public void test_DEX_SetsZeroFlagWhenZero() { - bus.loadProgram(0xca); - cpu.setXRegister(0x01); - cpu.step(); - assertEquals(0x00, cpu.getXRegister()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - public void test_DEX_SetsNegativeFlagWhen() { - bus.loadProgram(0xca); - cpu.step(); - assertEquals(0xff, cpu.getXRegister()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - } - - /* DEY - Decrement the Y register - $88 */ - - public void test_DEY() { - bus.loadProgram(0x88); - cpu.setYRegister(0x02); - cpu.step(); - assertEquals(0x01, cpu.getYRegister()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - public void test_DEY_SetsZeroFlagWhenZero() { - bus.loadProgram(0x88); - cpu.setYRegister(0x01); - cpu.step(); - assertEquals(0x00, cpu.getYRegister()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - public void test_DEY_SetsNegativeFlagWhen() { - bus.loadProgram(0x88); - cpu.step(); - assertEquals(0xff, cpu.getYRegister()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - } - - /* INX - Increment the X register - $e8 */ - - public void test_INX() { - bus.loadProgram(0xe8); - cpu.step(); - assertEquals(0x01, cpu.getXRegister()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - public void test_INX_SetsNegativeFlagWhenNegative() { - bus.loadProgram(0xe8); - cpu.setXRegister(0x7f); - cpu.step(); - assertEquals(0x80, cpu.getXRegister()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - } - - public void test_INX_SetsZeroFlagWhenZero() { - bus.loadProgram(0xe8); - cpu.setXRegister(0xff); - cpu.step(); - assertEquals(0x00, cpu.getXRegister()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - /* INY - Increment the Y register - $c8 */ - - public void test_INY() { - bus.loadProgram(0xc8); - cpu.step(); - assertEquals(0x01, cpu.getYRegister()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - public void test_INY_SetsNegativeFlagWhenNegative() { - bus.loadProgram(0xc8); - cpu.setYRegister(0x7f); - cpu.step(); - assertEquals(0x80, cpu.getYRegister()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - } - - public void test_INY_SetsZeroFlagWhenZero() { - bus.loadProgram(0xc8); - cpu.setYRegister(0xff); - cpu.step(); - assertEquals(0x00, cpu.getYRegister()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - /* NOP - No Operation - $ea */ - - public void test_NOP() { - bus.loadProgram(0xea); - cpu.step(); - // Should just not change anything except PC - assertEquals(0, cpu.getAccumulator()); - assertEquals(0, cpu.getXRegister()); - assertEquals(0, cpu.getYRegister()); - assertEquals(0x201, cpu.getProgramCounter()); - assertEquals(0xff, cpu.getStackPointer()); - assertEquals(0x20, cpu.getProcessorStatus()); - } - - /* PHA - Push Accumulator - $48 */ - - public void test_PHA() { - bus.loadProgram(0x48); - cpu.setAccumulator(0x3a); - cpu.step(); - assertEquals(0xfe, cpu.getStackPointer()); - assertEquals(0x3a, cpu.stackPeek()); - } - - /* PHP - Push Processor Status - $08 */ - - public void test_PHP() { - bus.loadProgram(0x08); - cpu.setProcessorStatus(0x27); - cpu.step(); - assertEquals(0xfe, cpu.getStackPointer()); - assertEquals(0x27, cpu.stackPeek()); - } - - /* PLA - Pul Accumulator - $68 */ - - public void test_PLA() { - cpu.stackPush(0x32); - bus.loadProgram(0x68); - cpu.step(); - assertEquals(0x32, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getZeroFlag()); - } - - public void test_PLA_SetsZeroIfAccumulatorIsZero() { - cpu.stackPush(0x00); - bus.loadProgram(0x68); - cpu.step(); - assertEquals(0x00, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertTrue(cpu.getZeroFlag()); - } - - public void test_PLA_SetsNegativeIfAccumulatorIsNegative() { - cpu.stackPush(0xff); - bus.loadProgram(0x68); - cpu.step(); - assertEquals(0xff, cpu.getAccumulator()); - assertTrue(cpu.getNegativeFlag()); - assertFalse(cpu.getZeroFlag()); - } - - /* PLP - Pull Processor Status - $28 */ - - public void test_PLP() { - cpu.stackPush(0x2f); - bus.loadProgram(0x28); - cpu.step(); - assertEquals(0x2f, cpu.getProcessorStatus()); - } - - /* RTI - Return from Interrupt - $40 */ - - public void test_RTI() { - cpu.stackPush(0x0f); // PC hi - cpu.stackPush(0x11); // PC lo - cpu.stackPush(0x29); // status - - bus.loadProgram(0x40); - cpu.step(); - - assertEquals(0x0f11, cpu.getProgramCounter()); - assertEquals(0x29, cpu.getProcessorStatus()); - } - - /* RTS - Return from Subroutine - $60 */ - - public void test_RTS() { - cpu.stackPush(0x0f); // PC hi - cpu.stackPush(0x11); // PC lo - - bus.loadProgram(0x60); - cpu.step(); - - assertEquals(0x0f12, cpu.getProgramCounter()); - assertEquals(0x20, cpu.getProcessorStatus()); - } - - /* SEC - Set Carry Flag - $38 */ - - public void test_SEC() { - bus.loadProgram(0x38); - cpu.step(); - assertTrue(cpu.getCarryFlag()); - } - - /* SED - Set Decimal Mode Flag - $f8 */ - - public void test_SED() { - bus.loadProgram(0xf8); - cpu.step(); - assertTrue(cpu.getDecimalModeFlag()); - } - - /* SEI - Set Interrupt Disable Flag - $78 */ - - public void test_SEI() { - bus.loadProgram(0x78); - cpu.step(); - assertTrue(cpu.getIrqDisableFlag()); - } - - /* TAX - Transfer Accumulator to X Register - $aa */ - - public void test_TAX() { - cpu.setAccumulator(0x32); - bus.loadProgram(0xaa); - cpu.step(); - assertEquals(0x32, cpu.getXRegister()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - public void test_TAX_SetsZeroFlagIfXIsZero() { - cpu.setAccumulator(0x00); - bus.loadProgram(0xaa); - cpu.step(); - assertEquals(0x00, cpu.getXRegister()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - public void test_TAX_SetsNegativeFlagIfXIsNegative() { - cpu.setAccumulator(0xff); - bus.loadProgram(0xaa); - cpu.step(); - assertEquals(0xff, cpu.getXRegister()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - } - - /* TAY - Transfer Accumulator to Y Register - $a8 */ - - public void test_TAY() { - cpu.setAccumulator(0x32); - bus.loadProgram(0xa8); - cpu.step(); - assertEquals(0x32, cpu.getYRegister()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - public void test_TAY_SetsZeroFlagIfYIsZero() { - cpu.setAccumulator(0x00); - bus.loadProgram(0xa8); - cpu.step(); - assertEquals(0x00, cpu.getYRegister()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - public void test_TAY_SetsNegativeFlagIfYIsNegative() { - cpu.setAccumulator(0xff); - bus.loadProgram(0xa8); - cpu.step(); - assertEquals(0xff, cpu.getYRegister()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - } - - /* TSX - Transfer Stack Pointer to X Register - $ba */ - - public void test_TSX() { - cpu.setStackPointer(0x32); - bus.loadProgram(0xba); - cpu.step(); - assertEquals(0x32, cpu.getXRegister()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - public void test_TSX_SetsZeroFlagIfXIsZero() { - cpu.setStackPointer(0x00); - bus.loadProgram(0xba); - cpu.step(); - assertEquals(0x00, cpu.getXRegister()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - public void test_TSX_SetsNegativeFlagIfXIsNegative() { - cpu.setStackPointer(0xff); - bus.loadProgram(0xba); - cpu.step(); - assertEquals(0xff, cpu.getXRegister()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - } - - /* TXA - Transfer X Register to Accumulator - $8a */ - - public void test_TXA() { - cpu.setXRegister(0x32); - bus.loadProgram(0x8a); - cpu.step(); - assertEquals(0x32, cpu.getAccumulator()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - public void test_TXA_SetsZeroFlagIfAccumulatorIsZero() { - cpu.setXRegister(0x00); - bus.loadProgram(0x8a); - cpu.step(); - assertEquals(0x00, cpu.getAccumulator()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - public void test_TXA_SetsNegativeFlagIfAccumulatorIsNegative() { - cpu.setXRegister(0xff); - bus.loadProgram(0x8a); - cpu.step(); - assertEquals(0xff, cpu.getAccumulator()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - } - - /* TXS - Transfer X Register to Stack Pointer - $9a */ - - public void test_TXS() { - cpu.setXRegister(0x32); - bus.loadProgram(0x9a); - cpu.step(); - assertEquals(0x32, cpu.getStackPointer()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - public void test_TXS_DoesNotAffectProcessorStatus() { - cpu.setXRegister(0x00); - bus.loadProgram(0x9a); - cpu.step(); - assertEquals(0x00, cpu.getStackPointer()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.setXRegister(0x80); - bus.loadProgram(0x9a); - cpu.step(); - assertEquals(0x80, cpu.getStackPointer()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - /* TYA - Transfer Y Register to Accumulator - $98 */ - - public void test_TYA() { - cpu.setYRegister(0x32); - bus.loadProgram(0x98); - cpu.step(); - assertEquals(0x32, cpu.getAccumulator()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - public void test_TYA_SetsZeroFlagIfAccumulatorIsZero() { - cpu.setYRegister(0x00); - bus.loadProgram(0x98); - cpu.step(); - assertEquals(0x00, cpu.getAccumulator()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - public void test_TYA_SetsNegativeFlagIfAccumulatorIsNegative() { - cpu.setYRegister(0xff); - bus.loadProgram(0x98); - cpu.step(); - assertEquals(0xff, cpu.getAccumulator()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - } + protected Cpu cpu; + protected Bus bus; + protected Memory mem; + + public void setUp() throws MemoryRangeException { + this.cpu = new Cpu(); + this.bus = new Bus(0x0000, 0xffff); + this.mem = new Memory(0x0000, 0x10000); + bus.addCpu(cpu); + bus.addDevice(mem); + + // Load the reset vector. + bus.write(0xfffc, Cpu.DEFAULT_BASE_ADDRESS & 0x00ff); + bus.write(0xfffd, (Cpu.DEFAULT_BASE_ADDRESS & 0xff00)>>>8); + + cpu.reset(); + + // Assert initial state + assertEquals(0, cpu.getAccumulator()); + assertEquals(0, cpu.getXRegister()); + assertEquals(0, cpu.getYRegister()); + assertEquals(0x200, cpu.getProgramCounter()); + assertEquals(0xff, cpu.getStackPointer()); + assertEquals(0x20, cpu.getProcessorStatus()); + } + + /* + * The following opcodes are tested for correctness in this file: + * + * BRK - $00 + * CLC - $18 + * CLD - $d8 + * CLI - $58 + * CLV - $B8 + * + * DEX - $ca + * DEY - $88 + * INX - $e8 + * INY - $c8 + * NOP - $ea + * + * PHA - $48 + * PHP - $08 + * PLA - $68 + * PLP - $28 + * RTI - $40 + * + * RTS - $60 + * SEC - $38 + * SED - $f8 + * SEI - $78 + * TAX - $aa + * + * TAY - $a8 + * TSX - $ba + * TXA - $8a + * TXS - $9a + * TYA - $98 + */ + + /* BRK Tests - 0x00 */ + + public void test_BRK() { + cpu.setCarryFlag(); + cpu.setOverflowFlag(); + assertEquals(0x20|Cpu.P_CARRY|Cpu.P_OVERFLOW, + cpu.getProcessorStatus()); + assertEquals(0xff, cpu.stackPeek()); + assertFalse(cpu.getBreakFlag()); + assertEquals(0x0200, cpu.getProgramCounter()); + assertEquals(0xff, cpu.getStackPointer()); + + // Set the IRQ vector + bus.write(Cpu.IRQ_VECTOR_H, 0x12); + bus.write(Cpu.IRQ_VECTOR_L, 0x34); + + bus.loadProgram(0xea, + 0xea, + 0xea, + 0x00, + 0xea, + 0xea); + + cpu.step(3); // Three NOP instructions + + assertEquals(0x203, cpu.getProgramCounter()); + + cpu.step(); // Triggers the BRK + + // Was at PC = 0x204. PC+2 should now be on the stack + assertEquals(0x02, bus.read(0x1ff)); // PC high byte + assertEquals(0x06, bus.read(0x1fe)); // PC low byte + assertEquals(0x20|Cpu.P_CARRY|Cpu.P_OVERFLOW|Cpu.P_BREAK, + bus.read(0x1fd)); // Processor Status, with B set + + // Interrupt vector held 0x1234, so we should be there. + assertEquals(0x1234, cpu.getProgramCounter()); + assertEquals(0xfc, cpu.getStackPointer()); + + // B and I flags should have been set on P + assertEquals(0x20|Cpu.P_CARRY|Cpu.P_OVERFLOW|Cpu.P_BREAK| + Cpu.P_IRQ_DISABLE, + cpu.getProcessorStatus()); + } + + public void test_BRK_HonorsIrqDisableFlag() { + cpu.setIrqDisableFlag(); + + bus.loadProgram(0xea, + 0xea, + 0xea, + 0x00, + 0xea, + 0xea); + + cpu.step(3); // Three NOP instructions + + assertEquals(0x203, cpu.getProgramCounter()); + + // Triggers the BRK, which should do nothing because + // of the Interrupt Disable flag + cpu.step(); + + // Reset to original contents of PC + assertEquals(0x0204, cpu.getProgramCounter()); + // Empty stack + assertEquals(0xff, cpu.getStackPointer()); + + cpu.step(2); // Two more NOPs + + // Reset to original contents of PC + assertEquals(0x0206, cpu.getProgramCounter()); + // Empty stack + assertEquals(0xff, cpu.getStackPointer()); + } + + /* CLC - Clear Carry Flag - $18 */ + public void test_CLC() { + cpu.setCarryFlag(); + assertTrue(cpu.getCarryFlag()); + + bus.loadProgram(0x18); + cpu.step(); + + assertFalse(cpu.getCarryFlag()); + } + + /* CLD - Clear Decimal Mode Flag - $d8 */ + public void test_CLD() { + cpu.setDecimalModeFlag(); + assertTrue(cpu.getDecimalModeFlag()); + + bus.loadProgram(0xd8); + cpu.step(); + + assertFalse(cpu.getDecimalModeFlag()); + } + + /* CLI - Clear Interrupt Disabled Flag - $58 */ + public void test_CLI() { + cpu.setIrqDisableFlag(); + assertTrue(cpu.getIrqDisableFlag()); + + bus.loadProgram(0x58); + cpu.step(); + + assertFalse(cpu.getIrqDisableFlag()); + } + + /* CLV - Clear Overflow Flag - $b8 */ + public void test_CLV() { + cpu.setOverflowFlag(); + assertTrue(cpu.getOverflowFlag()); + + bus.loadProgram(0xb8); + cpu.step(); + + assertFalse(cpu.getOverflowFlag()); + } + + /* DEX - Decrement the X register - $ca */ + + public void test_DEX() { + bus.loadProgram(0xca); + cpu.setXRegister(0x02); + cpu.step(); + assertEquals(0x01, cpu.getXRegister()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_DEX_SetsZeroFlagWhenZero() { + bus.loadProgram(0xca); + cpu.setXRegister(0x01); + cpu.step(); + assertEquals(0x00, cpu.getXRegister()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_DEX_SetsNegativeFlagWhen() { + bus.loadProgram(0xca); + cpu.step(); + assertEquals(0xff, cpu.getXRegister()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + } + + /* DEY - Decrement the Y register - $88 */ + + public void test_DEY() { + bus.loadProgram(0x88); + cpu.setYRegister(0x02); + cpu.step(); + assertEquals(0x01, cpu.getYRegister()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_DEY_SetsZeroFlagWhenZero() { + bus.loadProgram(0x88); + cpu.setYRegister(0x01); + cpu.step(); + assertEquals(0x00, cpu.getYRegister()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_DEY_SetsNegativeFlagWhen() { + bus.loadProgram(0x88); + cpu.step(); + assertEquals(0xff, cpu.getYRegister()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + } + + /* INX - Increment the X register - $e8 */ + + public void test_INX() { + bus.loadProgram(0xe8); + cpu.step(); + assertEquals(0x01, cpu.getXRegister()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_INX_SetsNegativeFlagWhenNegative() { + bus.loadProgram(0xe8); + cpu.setXRegister(0x7f); + cpu.step(); + assertEquals(0x80, cpu.getXRegister()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + } + + public void test_INX_SetsZeroFlagWhenZero() { + bus.loadProgram(0xe8); + cpu.setXRegister(0xff); + cpu.step(); + assertEquals(0x00, cpu.getXRegister()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + /* INY - Increment the Y register - $c8 */ + + public void test_INY() { + bus.loadProgram(0xc8); + cpu.step(); + assertEquals(0x01, cpu.getYRegister()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_INY_SetsNegativeFlagWhenNegative() { + bus.loadProgram(0xc8); + cpu.setYRegister(0x7f); + cpu.step(); + assertEquals(0x80, cpu.getYRegister()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + } + + public void test_INY_SetsZeroFlagWhenZero() { + bus.loadProgram(0xc8); + cpu.setYRegister(0xff); + cpu.step(); + assertEquals(0x00, cpu.getYRegister()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + /* NOP - No Operation - $ea */ + + public void test_NOP() { + bus.loadProgram(0xea); + cpu.step(); + // Should just not change anything except PC + assertEquals(0, cpu.getAccumulator()); + assertEquals(0, cpu.getXRegister()); + assertEquals(0, cpu.getYRegister()); + assertEquals(0x201, cpu.getProgramCounter()); + assertEquals(0xff, cpu.getStackPointer()); + assertEquals(0x20, cpu.getProcessorStatus()); + } + + /* PHA - Push Accumulator - $48 */ + + public void test_PHA() { + bus.loadProgram(0x48); + cpu.setAccumulator(0x3a); + cpu.step(); + assertEquals(0xfe, cpu.getStackPointer()); + assertEquals(0x3a, cpu.stackPeek()); + } + + /* PHP - Push Processor Status - $08 */ + + public void test_PHP() { + bus.loadProgram(0x08); + cpu.setProcessorStatus(0x27); + cpu.step(); + assertEquals(0xfe, cpu.getStackPointer()); + assertEquals(0x27, cpu.stackPeek()); + } + + /* PLA - Pul Accumulator - $68 */ + + public void test_PLA() { + cpu.stackPush(0x32); + bus.loadProgram(0x68); + cpu.step(); + assertEquals(0x32, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getZeroFlag()); + } + + public void test_PLA_SetsZeroIfAccumulatorIsZero() { + cpu.stackPush(0x00); + bus.loadProgram(0x68); + cpu.step(); + assertEquals(0x00, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertTrue(cpu.getZeroFlag()); + } + + public void test_PLA_SetsNegativeIfAccumulatorIsNegative() { + cpu.stackPush(0xff); + bus.loadProgram(0x68); + cpu.step(); + assertEquals(0xff, cpu.getAccumulator()); + assertTrue(cpu.getNegativeFlag()); + assertFalse(cpu.getZeroFlag()); + } + + /* PLP - Pull Processor Status - $28 */ + + public void test_PLP() { + cpu.stackPush(0x2f); + bus.loadProgram(0x28); + cpu.step(); + assertEquals(0x2f, cpu.getProcessorStatus()); + } + + /* RTI - Return from Interrupt - $40 */ + + public void test_RTI() { + cpu.stackPush(0x0f); // PC hi + cpu.stackPush(0x11); // PC lo + cpu.stackPush(0x29); // status + + bus.loadProgram(0x40); + cpu.step(); + + assertEquals(0x0f11, cpu.getProgramCounter()); + assertEquals(0x29, cpu.getProcessorStatus()); + } + + /* RTS - Return from Subroutine - $60 */ + + public void test_RTS() { + cpu.stackPush(0x0f); // PC hi + cpu.stackPush(0x11); // PC lo + + bus.loadProgram(0x60); + cpu.step(); + + assertEquals(0x0f12, cpu.getProgramCounter()); + assertEquals(0x20, cpu.getProcessorStatus()); + } + + /* SEC - Set Carry Flag - $38 */ + + public void test_SEC() { + bus.loadProgram(0x38); + cpu.step(); + assertTrue(cpu.getCarryFlag()); + } + + /* SED - Set Decimal Mode Flag - $f8 */ + + public void test_SED() { + bus.loadProgram(0xf8); + cpu.step(); + assertTrue(cpu.getDecimalModeFlag()); + } + + /* SEI - Set Interrupt Disable Flag - $78 */ + + public void test_SEI() { + bus.loadProgram(0x78); + cpu.step(); + assertTrue(cpu.getIrqDisableFlag()); + } + + /* TAX - Transfer Accumulator to X Register - $aa */ + + public void test_TAX() { + cpu.setAccumulator(0x32); + bus.loadProgram(0xaa); + cpu.step(); + assertEquals(0x32, cpu.getXRegister()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_TAX_SetsZeroFlagIfXIsZero() { + cpu.setAccumulator(0x00); + bus.loadProgram(0xaa); + cpu.step(); + assertEquals(0x00, cpu.getXRegister()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_TAX_SetsNegativeFlagIfXIsNegative() { + cpu.setAccumulator(0xff); + bus.loadProgram(0xaa); + cpu.step(); + assertEquals(0xff, cpu.getXRegister()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + } + + /* TAY - Transfer Accumulator to Y Register - $a8 */ + + public void test_TAY() { + cpu.setAccumulator(0x32); + bus.loadProgram(0xa8); + cpu.step(); + assertEquals(0x32, cpu.getYRegister()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_TAY_SetsZeroFlagIfYIsZero() { + cpu.setAccumulator(0x00); + bus.loadProgram(0xa8); + cpu.step(); + assertEquals(0x00, cpu.getYRegister()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_TAY_SetsNegativeFlagIfYIsNegative() { + cpu.setAccumulator(0xff); + bus.loadProgram(0xa8); + cpu.step(); + assertEquals(0xff, cpu.getYRegister()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + } + + /* TSX - Transfer Stack Pointer to X Register - $ba */ + + public void test_TSX() { + cpu.setStackPointer(0x32); + bus.loadProgram(0xba); + cpu.step(); + assertEquals(0x32, cpu.getXRegister()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_TSX_SetsZeroFlagIfXIsZero() { + cpu.setStackPointer(0x00); + bus.loadProgram(0xba); + cpu.step(); + assertEquals(0x00, cpu.getXRegister()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_TSX_SetsNegativeFlagIfXIsNegative() { + cpu.setStackPointer(0xff); + bus.loadProgram(0xba); + cpu.step(); + assertEquals(0xff, cpu.getXRegister()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + } + + /* TXA - Transfer X Register to Accumulator - $8a */ + + public void test_TXA() { + cpu.setXRegister(0x32); + bus.loadProgram(0x8a); + cpu.step(); + assertEquals(0x32, cpu.getAccumulator()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_TXA_SetsZeroFlagIfAccumulatorIsZero() { + cpu.setXRegister(0x00); + bus.loadProgram(0x8a); + cpu.step(); + assertEquals(0x00, cpu.getAccumulator()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_TXA_SetsNegativeFlagIfAccumulatorIsNegative() { + cpu.setXRegister(0xff); + bus.loadProgram(0x8a); + cpu.step(); + assertEquals(0xff, cpu.getAccumulator()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + } + + /* TXS - Transfer X Register to Stack Pointer - $9a */ + + public void test_TXS() { + cpu.setXRegister(0x32); + bus.loadProgram(0x9a); + cpu.step(); + assertEquals(0x32, cpu.getStackPointer()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_TXS_DoesNotAffectProcessorStatus() { + cpu.setXRegister(0x00); + bus.loadProgram(0x9a); + cpu.step(); + assertEquals(0x00, cpu.getStackPointer()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.setXRegister(0x80); + bus.loadProgram(0x9a); + cpu.step(); + assertEquals(0x80, cpu.getStackPointer()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + /* TYA - Transfer Y Register to Accumulator - $98 */ + + public void test_TYA() { + cpu.setYRegister(0x32); + bus.loadProgram(0x98); + cpu.step(); + assertEquals(0x32, cpu.getAccumulator()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_TYA_SetsZeroFlagIfAccumulatorIsZero() { + cpu.setYRegister(0x00); + bus.loadProgram(0x98); + cpu.step(); + assertEquals(0x00, cpu.getAccumulator()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_TYA_SetsNegativeFlagIfAccumulatorIsNegative() { + cpu.setYRegister(0xff); + bus.loadProgram(0x98); + cpu.step(); + assertEquals(0xff, cpu.getAccumulator()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + } } \ No newline at end of file diff --git a/src/test/java/com/loomcom/symon/CpuTest.java b/src/test/java/com/loomcom/symon/CpuTest.java index 9d818df..7dbb33b 100644 --- a/src/test/java/com/loomcom/symon/CpuTest.java +++ b/src/test/java/com/loomcom/symon/CpuTest.java @@ -10,349 +10,349 @@ import com.loomcom.symon.exceptions.*; */ public class CpuTest extends TestCase { - private Cpu cpu; - private Bus bus; - private Memory mem; - - public CpuTest(String testName) { - super(testName); - } - - public static Test suite() { - return new TestSuite(CpuTest.class); - } - - public void setUp() throws MemoryRangeException { - this.cpu = new Cpu(); - this.bus = new Bus(0x0000, 0xffff); - this.mem = new Memory(0x0000, 0x10000); - bus.addCpu(cpu); - bus.addDevice(mem); - - // All test programs start at 0x0200; - bus.write(0xfffc, 0x00); - bus.write(0xfffd, 0x02); - - cpu.reset(); - } - - public void testReset() { - assertEquals(0, cpu.getAccumulator()); - assertEquals(0, cpu.getXRegister()); - assertEquals(0, cpu.getYRegister()); - assertEquals(0x0200, cpu.getProgramCounter()); - assertFalse(cpu.getCarryFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getIrqDisableFlag()); - assertFalse(cpu.getDecimalModeFlag()); - assertFalse(cpu.getBreakFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - public void testStack() { - - cpu.stackPush(0x13); - assertEquals(0x13, cpu.stackPop()); - - cpu.stackPush(0x12); - assertEquals(0x12, cpu.stackPop()); - - for (int i = 0x00; i <= 0xff; i++) { - cpu.stackPush(i); - } - - for (int i = 0xff; i >= 0x00; i--) { - assertEquals(i, cpu.stackPop()); - } - - } - - public void testStackPush() { - assertEquals(0xff, cpu.getStackPointer()); - assertEquals(0xff, bus.read(0x1ff)); - - cpu.stackPush(0x06); - assertEquals(0xfe, cpu.getStackPointer()); - assertEquals(0x06, bus.read(0x1ff)); - - cpu.stackPush(0x05); - assertEquals(0xfd, cpu.getStackPointer()); - assertEquals(0x06, bus.read(0x1ff)); - assertEquals(0x05, bus.read(0x1fe)); - - cpu.stackPush(0x04); - assertEquals(0xfc, cpu.getStackPointer()); - assertEquals(0x06, bus.read(0x1ff)); - assertEquals(0x05, bus.read(0x1fe)); - assertEquals(0x04, bus.read(0x1fd)); - - cpu.stackPush(0x03); - assertEquals(0xfb, cpu.getStackPointer()); - assertEquals(0x06, bus.read(0x1ff)); - assertEquals(0x05, bus.read(0x1fe)); - assertEquals(0x04, bus.read(0x1fd)); - assertEquals(0x03, bus.read(0x1fc)); - - cpu.stackPush(0x02); - assertEquals(0xfa, cpu.getStackPointer()); - assertEquals(0x06, bus.read(0x1ff)); - assertEquals(0x05, bus.read(0x1fe)); - assertEquals(0x04, bus.read(0x1fd)); - assertEquals(0x03, bus.read(0x1fc)); - assertEquals(0x02, bus.read(0x1fb)); - - cpu.stackPush(0x01); - assertEquals(0xf9, cpu.getStackPointer()); - assertEquals(0x06, bus.read(0x1ff)); - assertEquals(0x05, bus.read(0x1fe)); - assertEquals(0x04, bus.read(0x1fd)); - assertEquals(0x03, bus.read(0x1fc)); - assertEquals(0x02, bus.read(0x1fb)); - assertEquals(0x01, bus.read(0x1fa)); - } - - public void testStackPushWrapsAroundToStackTop() { - cpu.setStackPointer(0x01); - - cpu.stackPush(0x01); - assertEquals(0x01, bus.read(0x101)); - assertEquals(0x00, cpu.getStackPointer()); - - cpu.stackPush(0x02); - assertEquals(0x02, bus.read(0x100)); - assertEquals(0xff, cpu.getStackPointer()); - - cpu.stackPush(0x03); - assertEquals(0x03, bus.read(0x1ff)); - assertEquals(0xfe, cpu.getStackPointer()); - } - - - public void testStackPop() { - bus.write(0x1ff, 0x06); - bus.write(0x1fe, 0x05); - bus.write(0x1fd, 0x04); - bus.write(0x1fc, 0x03); - bus.write(0x1fb, 0x02); - bus.write(0x1fa, 0x01); - cpu.setStackPointer(0xf9); - - assertEquals(0x01, cpu.stackPop()); - assertEquals(0xfa, cpu.getStackPointer()); - - assertEquals(0x02, cpu.stackPop()); - assertEquals(0xfb, cpu.getStackPointer()); - - assertEquals(0x03, cpu.stackPop()); - assertEquals(0xfc, cpu.getStackPointer()); - - assertEquals(0x04, cpu.stackPop()); - assertEquals(0xfd, cpu.getStackPointer()); - - assertEquals(0x05, cpu.stackPop()); - assertEquals(0xfe, cpu.getStackPointer()); - - assertEquals(0x06, cpu.stackPop()); - assertEquals(0xff, cpu.getStackPointer()); - } - - public void testStackPopWrapsAroundToStackBottom() { - bus.write(0x1ff, 0x0f); // top of stack - bus.write(0x100, 0xf0); // bottom of stack - bus.write(0x101, 0xf1); - bus.write(0x102, 0xf2); - - cpu.setStackPointer(0xfe); - - assertEquals(0x0f, cpu.stackPop()); - assertEquals(0xff, cpu.getStackPointer()); - - assertEquals(0xf0, cpu.stackPop()); - assertEquals(0x00, cpu.getStackPointer()); - - assertEquals(0xf1, cpu.stackPop()); - assertEquals(0x01, cpu.getStackPointer()); - - assertEquals(0xf2, cpu.stackPop()); - assertEquals(0x02, cpu.getStackPointer()); - } - - public void testStackPeekDoesNotAlterStackPointer() { - int val = 0; - - assertEquals(0xff, cpu.stackPeek()); - assertEquals(0xff, cpu.getStackPointer()); - - cpu.stackPush(0x01); - assertEquals(0x01, cpu.stackPeek()); - assertEquals(0xfe, cpu.getStackPointer()); - - cpu.stackPush(0x02); - assertEquals(0x02, cpu.stackPeek()); - assertEquals(0xfd, cpu.getStackPointer()); - - cpu.stackPush(0x03); - assertEquals(0x03, cpu.stackPeek()); - assertEquals(0xfc, cpu.getStackPointer()); - - cpu.stackPush(0x04); - assertEquals(0x04, cpu.stackPeek()); - assertEquals(0xfb, cpu.getStackPointer()); - assertEquals(0x04, cpu.stackPeek()); - assertEquals(0xfb, cpu.getStackPointer()); - assertEquals(0x04, cpu.stackPeek()); - assertEquals(0xfb, cpu.getStackPointer()); - } - - public void testGetProcessorStatus() { - // By default, no flags are set. Remember, bit 5 - // is always '1'. - assertEquals(0x20, cpu.getProcessorStatus()); - cpu.setCarryFlag(); - assertEquals(0x21, cpu.getProcessorStatus()); - cpu.setZeroFlag(); - assertEquals(0x23, cpu.getProcessorStatus()); - cpu.setIrqDisableFlag(); - assertEquals(0x27, cpu.getProcessorStatus()); - cpu.setDecimalModeFlag(); - assertEquals(0x2f, cpu.getProcessorStatus()); - cpu.setBreakFlag(); - assertEquals(0x3f, cpu.getProcessorStatus()); - cpu.setOverflowFlag(); - assertEquals(0x7f, cpu.getProcessorStatus()); - cpu.setNegativeFlag(); - assertEquals(0xff, cpu.getProcessorStatus()); - - cpu.clearCarryFlag(); - assertEquals(0xfe, cpu.getProcessorStatus()); - cpu.clearZeroFlag(); - assertEquals(0xfc, cpu.getProcessorStatus()); - cpu.clearIrqDisableFlag(); - assertEquals(0xf8, cpu.getProcessorStatus()); - cpu.clearDecimalModeFlag(); - assertEquals(0xf0, cpu.getProcessorStatus()); - cpu.clearBreakFlag(); - assertEquals(0xe0, cpu.getProcessorStatus()); - cpu.clearOverflowFlag(); - assertEquals(0xa0, cpu.getProcessorStatus()); - cpu.clearNegativeFlag(); - assertEquals(0x20, cpu.getProcessorStatus()); - } - - public void testSetProcessorStatus() { - // Default - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getIrqDisableFlag()); - assertFalse(cpu.getDecimalModeFlag()); - assertFalse(cpu.getBreakFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.setProcessorStatus(0x20|Cpu.P_CARRY); - - assertTrue(cpu.getCarryFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getIrqDisableFlag()); - assertFalse(cpu.getDecimalModeFlag()); - assertFalse(cpu.getBreakFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.setProcessorStatus(0x20|Cpu.P_CARRY|Cpu.P_NEGATIVE); - - assertTrue(cpu.getCarryFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getIrqDisableFlag()); - assertFalse(cpu.getDecimalModeFlag()); - assertFalse(cpu.getBreakFlag()); - assertFalse(cpu.getOverflowFlag()); - assertTrue(cpu.getNegativeFlag()); - - cpu.setProcessorStatus(0x20|Cpu.P_CARRY|Cpu.P_NEGATIVE|Cpu.P_ZERO); - - assertTrue(cpu.getCarryFlag()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getIrqDisableFlag()); - assertFalse(cpu.getDecimalModeFlag()); - assertFalse(cpu.getBreakFlag()); - assertFalse(cpu.getOverflowFlag()); - assertTrue(cpu.getNegativeFlag()); - - cpu.setProcessorStatus(0x20|Cpu.P_CARRY|Cpu.P_NEGATIVE|Cpu.P_ZERO| - Cpu.P_OVERFLOW); - - assertTrue(cpu.getCarryFlag()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getIrqDisableFlag()); - assertFalse(cpu.getDecimalModeFlag()); - assertFalse(cpu.getBreakFlag()); - assertTrue(cpu.getOverflowFlag()); - assertTrue(cpu.getNegativeFlag()); - - cpu.setProcessorStatus(0x20|Cpu.P_CARRY|Cpu.P_NEGATIVE|Cpu.P_ZERO| - Cpu.P_OVERFLOW|Cpu.P_BREAK); - - assertTrue(cpu.getCarryFlag()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getIrqDisableFlag()); - assertFalse(cpu.getDecimalModeFlag()); - assertTrue(cpu.getBreakFlag()); - assertTrue(cpu.getOverflowFlag()); - assertTrue(cpu.getNegativeFlag()); - - - cpu.setProcessorStatus(0x20|Cpu.P_CARRY|Cpu.P_NEGATIVE|Cpu.P_ZERO| - Cpu.P_OVERFLOW|Cpu.P_BREAK|Cpu.P_DECIMAL); - - assertTrue(cpu.getCarryFlag()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getIrqDisableFlag()); - assertTrue(cpu.getDecimalModeFlag()); - assertTrue(cpu.getBreakFlag()); - assertTrue(cpu.getOverflowFlag()); - assertTrue(cpu.getNegativeFlag()); - - cpu.setProcessorStatus(0x20|Cpu.P_CARRY|Cpu.P_NEGATIVE|Cpu.P_ZERO| - Cpu.P_OVERFLOW|Cpu.P_BREAK|Cpu.P_DECIMAL| - Cpu.P_IRQ_DISABLE); - - assertTrue(cpu.getCarryFlag()); - assertTrue(cpu.getZeroFlag()); - assertTrue(cpu.getIrqDisableFlag()); - assertTrue(cpu.getDecimalModeFlag()); - assertTrue(cpu.getBreakFlag()); - assertTrue(cpu.getOverflowFlag()); - assertTrue(cpu.getNegativeFlag()); - - cpu.setProcessorStatus(0x20); - - assertFalse(cpu.getCarryFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getIrqDisableFlag()); - assertFalse(cpu.getDecimalModeFlag()); - assertFalse(cpu.getBreakFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.setProcessorStatus(0x00); - - assertFalse(cpu.getCarryFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getIrqDisableFlag()); - assertFalse(cpu.getDecimalModeFlag()); - assertFalse(cpu.getBreakFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - public void testAddress() { - assertEquals(0xf1ea, cpu.address(0xea, 0xf1)); - assertEquals(0x00ea, cpu.address(0xea, 0x00)); - assertEquals(0xf100, cpu.address(0x00, 0xf1)); - assertEquals(0x1234, cpu.address(0x34, 0x12)); - assertEquals(0xffff, cpu.address(0xff, 0xff)); - } + private Cpu cpu; + private Bus bus; + private Memory mem; + + public CpuTest(String testName) { + super(testName); + } + + public static Test suite() { + return new TestSuite(CpuTest.class); + } + + public void setUp() throws MemoryRangeException { + this.cpu = new Cpu(); + this.bus = new Bus(0x0000, 0xffff); + this.mem = new Memory(0x0000, 0x10000); + bus.addCpu(cpu); + bus.addDevice(mem); + + // All test programs start at 0x0200; + bus.write(0xfffc, 0x00); + bus.write(0xfffd, 0x02); + + cpu.reset(); + } + + public void testReset() { + assertEquals(0, cpu.getAccumulator()); + assertEquals(0, cpu.getXRegister()); + assertEquals(0, cpu.getYRegister()); + assertEquals(0x0200, cpu.getProgramCounter()); + assertFalse(cpu.getCarryFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getIrqDisableFlag()); + assertFalse(cpu.getDecimalModeFlag()); + assertFalse(cpu.getBreakFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void testStack() { + + cpu.stackPush(0x13); + assertEquals(0x13, cpu.stackPop()); + + cpu.stackPush(0x12); + assertEquals(0x12, cpu.stackPop()); + + for (int i = 0x00; i <= 0xff; i++) { + cpu.stackPush(i); + } + + for (int i = 0xff; i >= 0x00; i--) { + assertEquals(i, cpu.stackPop()); + } + + } + + public void testStackPush() { + assertEquals(0xff, cpu.getStackPointer()); + assertEquals(0xff, bus.read(0x1ff)); + + cpu.stackPush(0x06); + assertEquals(0xfe, cpu.getStackPointer()); + assertEquals(0x06, bus.read(0x1ff)); + + cpu.stackPush(0x05); + assertEquals(0xfd, cpu.getStackPointer()); + assertEquals(0x06, bus.read(0x1ff)); + assertEquals(0x05, bus.read(0x1fe)); + + cpu.stackPush(0x04); + assertEquals(0xfc, cpu.getStackPointer()); + assertEquals(0x06, bus.read(0x1ff)); + assertEquals(0x05, bus.read(0x1fe)); + assertEquals(0x04, bus.read(0x1fd)); + + cpu.stackPush(0x03); + assertEquals(0xfb, cpu.getStackPointer()); + assertEquals(0x06, bus.read(0x1ff)); + assertEquals(0x05, bus.read(0x1fe)); + assertEquals(0x04, bus.read(0x1fd)); + assertEquals(0x03, bus.read(0x1fc)); + + cpu.stackPush(0x02); + assertEquals(0xfa, cpu.getStackPointer()); + assertEquals(0x06, bus.read(0x1ff)); + assertEquals(0x05, bus.read(0x1fe)); + assertEquals(0x04, bus.read(0x1fd)); + assertEquals(0x03, bus.read(0x1fc)); + assertEquals(0x02, bus.read(0x1fb)); + + cpu.stackPush(0x01); + assertEquals(0xf9, cpu.getStackPointer()); + assertEquals(0x06, bus.read(0x1ff)); + assertEquals(0x05, bus.read(0x1fe)); + assertEquals(0x04, bus.read(0x1fd)); + assertEquals(0x03, bus.read(0x1fc)); + assertEquals(0x02, bus.read(0x1fb)); + assertEquals(0x01, bus.read(0x1fa)); + } + + public void testStackPushWrapsAroundToStackTop() { + cpu.setStackPointer(0x01); + + cpu.stackPush(0x01); + assertEquals(0x01, bus.read(0x101)); + assertEquals(0x00, cpu.getStackPointer()); + + cpu.stackPush(0x02); + assertEquals(0x02, bus.read(0x100)); + assertEquals(0xff, cpu.getStackPointer()); + + cpu.stackPush(0x03); + assertEquals(0x03, bus.read(0x1ff)); + assertEquals(0xfe, cpu.getStackPointer()); + } + + + public void testStackPop() { + bus.write(0x1ff, 0x06); + bus.write(0x1fe, 0x05); + bus.write(0x1fd, 0x04); + bus.write(0x1fc, 0x03); + bus.write(0x1fb, 0x02); + bus.write(0x1fa, 0x01); + cpu.setStackPointer(0xf9); + + assertEquals(0x01, cpu.stackPop()); + assertEquals(0xfa, cpu.getStackPointer()); + + assertEquals(0x02, cpu.stackPop()); + assertEquals(0xfb, cpu.getStackPointer()); + + assertEquals(0x03, cpu.stackPop()); + assertEquals(0xfc, cpu.getStackPointer()); + + assertEquals(0x04, cpu.stackPop()); + assertEquals(0xfd, cpu.getStackPointer()); + + assertEquals(0x05, cpu.stackPop()); + assertEquals(0xfe, cpu.getStackPointer()); + + assertEquals(0x06, cpu.stackPop()); + assertEquals(0xff, cpu.getStackPointer()); + } + + public void testStackPopWrapsAroundToStackBottom() { + bus.write(0x1ff, 0x0f); // top of stack + bus.write(0x100, 0xf0); // bottom of stack + bus.write(0x101, 0xf1); + bus.write(0x102, 0xf2); + + cpu.setStackPointer(0xfe); + + assertEquals(0x0f, cpu.stackPop()); + assertEquals(0xff, cpu.getStackPointer()); + + assertEquals(0xf0, cpu.stackPop()); + assertEquals(0x00, cpu.getStackPointer()); + + assertEquals(0xf1, cpu.stackPop()); + assertEquals(0x01, cpu.getStackPointer()); + + assertEquals(0xf2, cpu.stackPop()); + assertEquals(0x02, cpu.getStackPointer()); + } + + public void testStackPeekDoesNotAlterStackPointer() { + int val = 0; + + assertEquals(0xff, cpu.stackPeek()); + assertEquals(0xff, cpu.getStackPointer()); + + cpu.stackPush(0x01); + assertEquals(0x01, cpu.stackPeek()); + assertEquals(0xfe, cpu.getStackPointer()); + + cpu.stackPush(0x02); + assertEquals(0x02, cpu.stackPeek()); + assertEquals(0xfd, cpu.getStackPointer()); + + cpu.stackPush(0x03); + assertEquals(0x03, cpu.stackPeek()); + assertEquals(0xfc, cpu.getStackPointer()); + + cpu.stackPush(0x04); + assertEquals(0x04, cpu.stackPeek()); + assertEquals(0xfb, cpu.getStackPointer()); + assertEquals(0x04, cpu.stackPeek()); + assertEquals(0xfb, cpu.getStackPointer()); + assertEquals(0x04, cpu.stackPeek()); + assertEquals(0xfb, cpu.getStackPointer()); + } + + public void testGetProcessorStatus() { + // By default, no flags are set. Remember, bit 5 + // is always '1'. + assertEquals(0x20, cpu.getProcessorStatus()); + cpu.setCarryFlag(); + assertEquals(0x21, cpu.getProcessorStatus()); + cpu.setZeroFlag(); + assertEquals(0x23, cpu.getProcessorStatus()); + cpu.setIrqDisableFlag(); + assertEquals(0x27, cpu.getProcessorStatus()); + cpu.setDecimalModeFlag(); + assertEquals(0x2f, cpu.getProcessorStatus()); + cpu.setBreakFlag(); + assertEquals(0x3f, cpu.getProcessorStatus()); + cpu.setOverflowFlag(); + assertEquals(0x7f, cpu.getProcessorStatus()); + cpu.setNegativeFlag(); + assertEquals(0xff, cpu.getProcessorStatus()); + + cpu.clearCarryFlag(); + assertEquals(0xfe, cpu.getProcessorStatus()); + cpu.clearZeroFlag(); + assertEquals(0xfc, cpu.getProcessorStatus()); + cpu.clearIrqDisableFlag(); + assertEquals(0xf8, cpu.getProcessorStatus()); + cpu.clearDecimalModeFlag(); + assertEquals(0xf0, cpu.getProcessorStatus()); + cpu.clearBreakFlag(); + assertEquals(0xe0, cpu.getProcessorStatus()); + cpu.clearOverflowFlag(); + assertEquals(0xa0, cpu.getProcessorStatus()); + cpu.clearNegativeFlag(); + assertEquals(0x20, cpu.getProcessorStatus()); + } + + public void testSetProcessorStatus() { + // Default + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getIrqDisableFlag()); + assertFalse(cpu.getDecimalModeFlag()); + assertFalse(cpu.getBreakFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.setProcessorStatus(0x20|Cpu.P_CARRY); + + assertTrue(cpu.getCarryFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getIrqDisableFlag()); + assertFalse(cpu.getDecimalModeFlag()); + assertFalse(cpu.getBreakFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.setProcessorStatus(0x20|Cpu.P_CARRY|Cpu.P_NEGATIVE); + + assertTrue(cpu.getCarryFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getIrqDisableFlag()); + assertFalse(cpu.getDecimalModeFlag()); + assertFalse(cpu.getBreakFlag()); + assertFalse(cpu.getOverflowFlag()); + assertTrue(cpu.getNegativeFlag()); + + cpu.setProcessorStatus(0x20|Cpu.P_CARRY|Cpu.P_NEGATIVE|Cpu.P_ZERO); + + assertTrue(cpu.getCarryFlag()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getIrqDisableFlag()); + assertFalse(cpu.getDecimalModeFlag()); + assertFalse(cpu.getBreakFlag()); + assertFalse(cpu.getOverflowFlag()); + assertTrue(cpu.getNegativeFlag()); + + cpu.setProcessorStatus(0x20|Cpu.P_CARRY|Cpu.P_NEGATIVE|Cpu.P_ZERO| + Cpu.P_OVERFLOW); + + assertTrue(cpu.getCarryFlag()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getIrqDisableFlag()); + assertFalse(cpu.getDecimalModeFlag()); + assertFalse(cpu.getBreakFlag()); + assertTrue(cpu.getOverflowFlag()); + assertTrue(cpu.getNegativeFlag()); + + cpu.setProcessorStatus(0x20|Cpu.P_CARRY|Cpu.P_NEGATIVE|Cpu.P_ZERO| + Cpu.P_OVERFLOW|Cpu.P_BREAK); + + assertTrue(cpu.getCarryFlag()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getIrqDisableFlag()); + assertFalse(cpu.getDecimalModeFlag()); + assertTrue(cpu.getBreakFlag()); + assertTrue(cpu.getOverflowFlag()); + assertTrue(cpu.getNegativeFlag()); + + + cpu.setProcessorStatus(0x20|Cpu.P_CARRY|Cpu.P_NEGATIVE|Cpu.P_ZERO| + Cpu.P_OVERFLOW|Cpu.P_BREAK|Cpu.P_DECIMAL); + + assertTrue(cpu.getCarryFlag()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getIrqDisableFlag()); + assertTrue(cpu.getDecimalModeFlag()); + assertTrue(cpu.getBreakFlag()); + assertTrue(cpu.getOverflowFlag()); + assertTrue(cpu.getNegativeFlag()); + + cpu.setProcessorStatus(0x20|Cpu.P_CARRY|Cpu.P_NEGATIVE|Cpu.P_ZERO| + Cpu.P_OVERFLOW|Cpu.P_BREAK|Cpu.P_DECIMAL| + Cpu.P_IRQ_DISABLE); + + assertTrue(cpu.getCarryFlag()); + assertTrue(cpu.getZeroFlag()); + assertTrue(cpu.getIrqDisableFlag()); + assertTrue(cpu.getDecimalModeFlag()); + assertTrue(cpu.getBreakFlag()); + assertTrue(cpu.getOverflowFlag()); + assertTrue(cpu.getNegativeFlag()); + + cpu.setProcessorStatus(0x20); + + assertFalse(cpu.getCarryFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getIrqDisableFlag()); + assertFalse(cpu.getDecimalModeFlag()); + assertFalse(cpu.getBreakFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.setProcessorStatus(0x00); + + assertFalse(cpu.getCarryFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getIrqDisableFlag()); + assertFalse(cpu.getDecimalModeFlag()); + assertFalse(cpu.getBreakFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void testAddress() { + assertEquals(0xf1ea, cpu.address(0xea, 0xf1)); + assertEquals(0x00ea, cpu.address(0xea, 0x00)); + assertEquals(0xf100, cpu.address(0x00, 0xf1)); + assertEquals(0x1234, cpu.address(0x34, 0x12)); + assertEquals(0xffff, cpu.address(0xff, 0xff)); + } } \ No newline at end of file diff --git a/src/test/java/com/loomcom/symon/CpuZeroPageModeTest.java b/src/test/java/com/loomcom/symon/CpuZeroPageModeTest.java index 68d3976..658accf 100644 --- a/src/test/java/com/loomcom/symon/CpuZeroPageModeTest.java +++ b/src/test/java/com/loomcom/symon/CpuZeroPageModeTest.java @@ -6,1189 +6,1189 @@ import junit.framework.TestCase; public class CpuZeroPageModeTest extends TestCase { - protected Cpu cpu; - protected Bus bus; - protected Memory mem; + protected Cpu cpu; + protected Bus bus; + protected Memory mem; - protected void setUp() throws Exception { - this.cpu = new Cpu(); - this.bus = new Bus(0x0000, 0xffff); - this.mem = new Memory(0x0000, 0x10000); - bus.addCpu(cpu); - bus.addDevice(mem); + protected void setUp() throws Exception { + this.cpu = new Cpu(); + this.bus = new Bus(0x0000, 0xffff); + this.mem = new Memory(0x0000, 0x10000); + bus.addCpu(cpu); + bus.addDevice(mem); - // Load the reset vector. - bus.write(0xfffc, Cpu.DEFAULT_BASE_ADDRESS & 0x00ff); - bus.write(0xfffd, (Cpu.DEFAULT_BASE_ADDRESS & 0xff00)>>>8); + // Load the reset vector. + bus.write(0xfffc, Cpu.DEFAULT_BASE_ADDRESS & 0x00ff); + bus.write(0xfffd, (Cpu.DEFAULT_BASE_ADDRESS & 0xff00)>>>8); - cpu.reset(); - // Assert initial state - assertEquals(0, cpu.getAccumulator()); - assertEquals(0, cpu.getXRegister()); - assertEquals(0, cpu.getYRegister()); - assertEquals(0x200, cpu.getProgramCounter()); - assertEquals(0xff, cpu.getStackPointer()); - assertEquals(0x20, cpu.getProcessorStatus()); - } - - /* - * The following opcodes are tested for correctness in this file: - * - * ORA - $05 - * ASL - $06 - * BIT - $24 - * AND - $25 - * ROL - $26 - * - * EOR - $45 - * LSR - $46 - * ADC - $65 - * ROR - $66 - * STY - $84 - * - * STA - $85 - * STX - $86 - * LDY - $a4 - * LDA - $a5 - * LDX - $a6 - * - * CPY - $c4 - * CMP - $c5 - * DEC - $c6 - * CPX - $e4 - * SBC - $e5 - * - * INC - $e6 - */ - - /* ORA - Logical Inclusive OR - $05 */ - public void test_ORA() { - // Set some initial values in zero page. - bus.write(0x0000, 0x00); - bus.write(0x0002, 0x11); - bus.write(0x0004, 0x22); - bus.write(0x0008, 0x44); - bus.write(0x0010, 0x88); - - bus.loadProgram(0x05, 0x00, // ORA $00 - 0x05, 0x02, // ORA $02 - 0x05, 0x04, // ORA $04 - 0x05, 0x08, // ORA $08 - 0x05, 0x10); // ORA $10 - cpu.step(); - assertEquals(0x00, cpu.getAccumulator()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.step(); - assertEquals(0x11, cpu.getAccumulator()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.step(); - assertEquals(0x33, cpu.getAccumulator()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.step(); - assertEquals(0x77, cpu.getAccumulator()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.step(); - assertEquals(0xff, cpu.getAccumulator()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - } - - /* ASL - Arithmetic Shift Left - $06 */ - - public void test_ASL() { - bus.write(0x0000, 0x00); - bus.write(0x0001, 0x01); - bus.write(0x0002, 0x02); - bus.write(0x0003, 0x44); - bus.write(0x0004, 0x80); - - bus.loadProgram(0x06, 0x00, - 0x06, 0x01, - 0x06, 0x02, - 0x06, 0x03, - 0x06, 0x04); - - cpu.step(); - assertEquals(0x00, bus.read(0x0000)); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x02, bus.read(0x0001)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x04, bus.read(0x0002)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x88, bus.read(0x0003)); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x00, bus.read(0x0004)); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertTrue(cpu.getCarryFlag()); - } - - /* BIT - Bit Test - $24 */ - - public void test_BIT() { - bus.write(0x0000, 0xc0); - - bus.loadProgram(0xa9, 0x01, // LDA #$01 - 0x24, 0x00, // BIT $00 - - 0xa9, 0x0f, // LDA #$0f - 0x24, 0x00, // BIT $00 - - 0xa9, 0x40, // LDA #$40 - 0x24, 0x00, // BIT $00 - - 0xa9, 0x80, // LDA #$80 - 0x24, 0x00, // BIT $00 - - 0xa9, 0xc0, // LDA #$c0 - 0x24, 0x00, // BIT $00 - - 0xa9, 0xff, // LDA #$ff - 0x24, 0x00); // BIT $00 - - cpu.step(2); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - - cpu.step(2); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - - cpu.step(2); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertTrue(cpu.getOverflowFlag()); - - cpu.step(2); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - - cpu.step(2); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - assertTrue(cpu.getOverflowFlag()); - - cpu.step(2); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - assertTrue(cpu.getOverflowFlag()); - } - - /* AND - Logical AND - $25 */ - - public void test_AND() { - bus.write(0x0000, 0x00); - bus.write(0x0001, 0x11); - bus.write(0x0002, 0xff); - bus.write(0x0003, 0x99); - bus.write(0x0004, 0x11); - bus.write(0x0005, 0x0f); - - bus.loadProgram(0x25, 0x00, // AND $00 - 0x25, 0x01, // AND $01 - 0xa9, 0xaa, // LDA #$aa - 0x25, 0x02, // AND $02 - 0x25, 0x03, // AND $03 - 0x25, 0x04, // AND $04 - 0xa9, 0xff, // LDA #$ff - 0x25, 0x05); // AND $05 - cpu.step(); - assertEquals(0x00, cpu.getAccumulator()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.step(); - assertEquals(0x00, cpu.getAccumulator()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.step(2); - assertEquals(0xaa, cpu.getAccumulator()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - - cpu.step(); - assertEquals(0x88, cpu.getAccumulator()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - - cpu.step(); - assertEquals(0x00, cpu.getAccumulator()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.step(2); - assertEquals(0x0f, cpu.getAccumulator()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } - - /* ROL - Rotate Shift Left - $26 */ - - public void test_ROL() { - - bus.write(0x0000, 0x00); - bus.write(0x0001, 0x01); - - bus.loadProgram(0x26, 0x00, // ROL $00 (m=%00000000, c=0) - 0x26, 0x01, // ROL $01 (m=%00000010, c=0) - 0x38, // SEC (m=%00000010, c=1) - 0x26, 0x01, // ROL $01 (m=%00000101, c=0) - 0x26, 0x01, // ROL $01 (m=%00001010, c=0) - 0x26, 0x01, // ROL $01 (m=%00010100, c=0) - 0x26, 0x01, // ROL $01 (m=%00101000, c=0) - 0x26, 0x01, // ROL $01 (m=%01010000, c=0) - 0x26, 0x01, // ROL $01 (m=%10100000, c=0) - 0x26, 0x01, // ROL $01 (m=%01000000, c=1) - 0x26, 0x01); // ROL $01 (m=%10000001, c=0) - - cpu.step(); - assertEquals(0x00, bus.read(0x0000)); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x02, bus.read(0x0001)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.step(2); - assertEquals(0x05, bus.read(0x0001)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x0a, bus.read(0x0001)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x14, bus.read(0x0001)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x28, bus.read(0x0001)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x50, bus.read(0x0001)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0xa0, bus.read(0x0001)); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x40, bus.read(0x0001)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertTrue(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x81, bus.read(0x0001)); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - } - - /* EOR - Exclusive OR - $45 */ - - public void test_EOR() { - bus.write(0x10, 0x00); - bus.write(0x11, 0xff); - bus.write(0x12, 0x33); - bus.write(0x13, 0x44); - - bus.loadProgram(0xa9, 0x88, // LDA #$88 - 0x45, 0x10, // EOR $10 - 0x45, 0x11, // EOR $11 - 0x45, 0x12, // EOR $12 - 0x45, 0x13); // EOR $13 - cpu.step(2); - assertEquals(0x88, cpu.getAccumulator()); - assertTrue(cpu.getNegativeFlag()); - assertFalse(cpu.getZeroFlag()); - - cpu.step(); - assertEquals(0x77, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getZeroFlag()); - - cpu.step(); - assertEquals(0x44, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getZeroFlag()); - - cpu.step(); - assertEquals(0x00, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertTrue(cpu.getZeroFlag()); - } - - /* LSR - Logical Shift Right - $46 */ - - public void test_LSR() { - bus.write(0x0000, 0x00); - bus.write(0x0001, 0x01); - bus.write(0x0002, 0x02); - bus.write(0x0003, 0x44); - bus.write(0x0004, 0x80); - bus.write(0x0005, 0x02); - - bus.loadProgram(0x46, 0x00, // LSR $00 - 0x46, 0x01, // LSR $01 - 0x46, 0x02, // LSR $02 - 0x46, 0x03, // LSR $03 - 0x46, 0x04, // LSR $04 - 0x38, // SEC - 0x46, 0x05); // LSR $05 - - cpu.step(); - assertEquals(0x00, bus.read(0x0000)); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x00, bus.read(0x0001)); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertTrue(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x01, bus.read(0x0002)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x22, bus.read(0x0003)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x40, bus.read(0x0004)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - // Setting Carry should not affect the result. - cpu.step(2); - assertEquals(0x01, bus.read(0x0005)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - } - - /* ADC - Add with Carry - $65 */ - - public void test_ADC() { - bus.write(0x10, 0x01); - bus.write(0x11, 0xff); - - bus.loadProgram(0xa9, 0x00, // LDA #$00 - 0x65, 0x10); // ADC $10 - cpu.step(2); - assertEquals(0x01, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0x7f, // LDA #$7f - 0x65, 0x10); // ADC $10 - cpu.step(2); - assertEquals(0x80, cpu.getAccumulator()); - assertTrue(cpu.getNegativeFlag()); - assertTrue(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0x80, // LDA #$80 - 0x65, 0x10); // ADC $10 - cpu.step(2); - assertEquals(0x81, cpu.getAccumulator()); - assertTrue(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0xff, // LDA #$ff - 0x65, 0x10); // ADC $10 - cpu.step(2); - assertEquals(0x00, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertTrue(cpu.getZeroFlag()); - assertTrue(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0x00, // LDA #$00 - 0x65, 0x11); // ADC $11 - cpu.step(2); - assertEquals(0xff, cpu.getAccumulator()); - assertTrue(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0x7f, // LDA #$7f - 0x65, 0x11); // ADC $11 - cpu.step(2); - assertEquals(0x7e, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0x80, // LDA #$80 - 0x65, 0x11); // ADC $11 - cpu.step(2); - assertEquals(0x7f, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertTrue(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0xff, // LDA #$ff - 0x65, 0x11); // ADC $11 - cpu.step(2); - assertEquals(0xfe, cpu.getAccumulator()); - assertTrue(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getCarryFlag()); + cpu.reset(); + // Assert initial state + assertEquals(0, cpu.getAccumulator()); + assertEquals(0, cpu.getXRegister()); + assertEquals(0, cpu.getYRegister()); + assertEquals(0x200, cpu.getProgramCounter()); + assertEquals(0xff, cpu.getStackPointer()); + assertEquals(0x20, cpu.getProcessorStatus()); } - + + /* + * The following opcodes are tested for correctness in this file: + * + * ORA - $05 + * ASL - $06 + * BIT - $24 + * AND - $25 + * ROL - $26 + * + * EOR - $45 + * LSR - $46 + * ADC - $65 + * ROR - $66 + * STY - $84 + * + * STA - $85 + * STX - $86 + * LDY - $a4 + * LDA - $a5 + * LDX - $a6 + * + * CPY - $c4 + * CMP - $c5 + * DEC - $c6 + * CPX - $e4 + * SBC - $e5 + * + * INC - $e6 + */ + + /* ORA - Logical Inclusive OR - $05 */ + public void test_ORA() { + // Set some initial values in zero page. + bus.write(0x0000, 0x00); + bus.write(0x0002, 0x11); + bus.write(0x0004, 0x22); + bus.write(0x0008, 0x44); + bus.write(0x0010, 0x88); + + bus.loadProgram(0x05, 0x00, // ORA $00 + 0x05, 0x02, // ORA $02 + 0x05, 0x04, // ORA $04 + 0x05, 0x08, // ORA $08 + 0x05, 0x10); // ORA $10 + cpu.step(); + assertEquals(0x00, cpu.getAccumulator()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.step(); + assertEquals(0x11, cpu.getAccumulator()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.step(); + assertEquals(0x33, cpu.getAccumulator()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.step(); + assertEquals(0x77, cpu.getAccumulator()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.step(); + assertEquals(0xff, cpu.getAccumulator()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + } + + /* ASL - Arithmetic Shift Left - $06 */ + + public void test_ASL() { + bus.write(0x0000, 0x00); + bus.write(0x0001, 0x01); + bus.write(0x0002, 0x02); + bus.write(0x0003, 0x44); + bus.write(0x0004, 0x80); + + bus.loadProgram(0x06, 0x00, + 0x06, 0x01, + 0x06, 0x02, + 0x06, 0x03, + 0x06, 0x04); + + cpu.step(); + assertEquals(0x00, bus.read(0x0000)); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x02, bus.read(0x0001)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x04, bus.read(0x0002)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x88, bus.read(0x0003)); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x00, bus.read(0x0004)); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertTrue(cpu.getCarryFlag()); + } + + /* BIT - Bit Test - $24 */ + + public void test_BIT() { + bus.write(0x0000, 0xc0); + + bus.loadProgram(0xa9, 0x01, // LDA #$01 + 0x24, 0x00, // BIT $00 + + 0xa9, 0x0f, // LDA #$0f + 0x24, 0x00, // BIT $00 + + 0xa9, 0x40, // LDA #$40 + 0x24, 0x00, // BIT $00 + + 0xa9, 0x80, // LDA #$80 + 0x24, 0x00, // BIT $00 + + 0xa9, 0xc0, // LDA #$c0 + 0x24, 0x00, // BIT $00 + + 0xa9, 0xff, // LDA #$ff + 0x24, 0x00); // BIT $00 + + cpu.step(2); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + + cpu.step(2); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + + cpu.step(2); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertTrue(cpu.getOverflowFlag()); + + cpu.step(2); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + + cpu.step(2); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + assertTrue(cpu.getOverflowFlag()); + + cpu.step(2); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + assertTrue(cpu.getOverflowFlag()); + } + + /* AND - Logical AND - $25 */ + + public void test_AND() { + bus.write(0x0000, 0x00); + bus.write(0x0001, 0x11); + bus.write(0x0002, 0xff); + bus.write(0x0003, 0x99); + bus.write(0x0004, 0x11); + bus.write(0x0005, 0x0f); + + bus.loadProgram(0x25, 0x00, // AND $00 + 0x25, 0x01, // AND $01 + 0xa9, 0xaa, // LDA #$aa + 0x25, 0x02, // AND $02 + 0x25, 0x03, // AND $03 + 0x25, 0x04, // AND $04 + 0xa9, 0xff, // LDA #$ff + 0x25, 0x05); // AND $05 + cpu.step(); + assertEquals(0x00, cpu.getAccumulator()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.step(); + assertEquals(0x00, cpu.getAccumulator()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.step(2); + assertEquals(0xaa, cpu.getAccumulator()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + + cpu.step(); + assertEquals(0x88, cpu.getAccumulator()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + + cpu.step(); + assertEquals(0x00, cpu.getAccumulator()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.step(2); + assertEquals(0x0f, cpu.getAccumulator()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + /* ROL - Rotate Shift Left - $26 */ + + public void test_ROL() { + + bus.write(0x0000, 0x00); + bus.write(0x0001, 0x01); + + bus.loadProgram(0x26, 0x00, // ROL $00 (m=%00000000, c=0) + 0x26, 0x01, // ROL $01 (m=%00000010, c=0) + 0x38, // SEC (m=%00000010, c=1) + 0x26, 0x01, // ROL $01 (m=%00000101, c=0) + 0x26, 0x01, // ROL $01 (m=%00001010, c=0) + 0x26, 0x01, // ROL $01 (m=%00010100, c=0) + 0x26, 0x01, // ROL $01 (m=%00101000, c=0) + 0x26, 0x01, // ROL $01 (m=%01010000, c=0) + 0x26, 0x01, // ROL $01 (m=%10100000, c=0) + 0x26, 0x01, // ROL $01 (m=%01000000, c=1) + 0x26, 0x01); // ROL $01 (m=%10000001, c=0) + + cpu.step(); + assertEquals(0x00, bus.read(0x0000)); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x02, bus.read(0x0001)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.step(2); + assertEquals(0x05, bus.read(0x0001)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x0a, bus.read(0x0001)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x14, bus.read(0x0001)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x28, bus.read(0x0001)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x50, bus.read(0x0001)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0xa0, bus.read(0x0001)); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x40, bus.read(0x0001)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertTrue(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x81, bus.read(0x0001)); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + } + + /* EOR - Exclusive OR - $45 */ + + public void test_EOR() { + bus.write(0x10, 0x00); + bus.write(0x11, 0xff); + bus.write(0x12, 0x33); + bus.write(0x13, 0x44); + + bus.loadProgram(0xa9, 0x88, // LDA #$88 + 0x45, 0x10, // EOR $10 + 0x45, 0x11, // EOR $11 + 0x45, 0x12, // EOR $12 + 0x45, 0x13); // EOR $13 + cpu.step(2); + assertEquals(0x88, cpu.getAccumulator()); + assertTrue(cpu.getNegativeFlag()); + assertFalse(cpu.getZeroFlag()); + + cpu.step(); + assertEquals(0x77, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getZeroFlag()); + + cpu.step(); + assertEquals(0x44, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getZeroFlag()); + + cpu.step(); + assertEquals(0x00, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertTrue(cpu.getZeroFlag()); + } + + /* LSR - Logical Shift Right - $46 */ + + public void test_LSR() { + bus.write(0x0000, 0x00); + bus.write(0x0001, 0x01); + bus.write(0x0002, 0x02); + bus.write(0x0003, 0x44); + bus.write(0x0004, 0x80); + bus.write(0x0005, 0x02); + + bus.loadProgram(0x46, 0x00, // LSR $00 + 0x46, 0x01, // LSR $01 + 0x46, 0x02, // LSR $02 + 0x46, 0x03, // LSR $03 + 0x46, 0x04, // LSR $04 + 0x38, // SEC + 0x46, 0x05); // LSR $05 + + cpu.step(); + assertEquals(0x00, bus.read(0x0000)); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x00, bus.read(0x0001)); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertTrue(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x01, bus.read(0x0002)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x22, bus.read(0x0003)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x40, bus.read(0x0004)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + // Setting Carry should not affect the result. + cpu.step(2); + assertEquals(0x01, bus.read(0x0005)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + } + + /* ADC - Add with Carry - $65 */ + + public void test_ADC() { + bus.write(0x10, 0x01); + bus.write(0x11, 0xff); + + bus.loadProgram(0xa9, 0x00, // LDA #$00 + 0x65, 0x10); // ADC $10 + cpu.step(2); + assertEquals(0x01, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0x7f, // LDA #$7f + 0x65, 0x10); // ADC $10 + cpu.step(2); + assertEquals(0x80, cpu.getAccumulator()); + assertTrue(cpu.getNegativeFlag()); + assertTrue(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0x80, // LDA #$80 + 0x65, 0x10); // ADC $10 + cpu.step(2); + assertEquals(0x81, cpu.getAccumulator()); + assertTrue(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0xff, // LDA #$ff + 0x65, 0x10); // ADC $10 + cpu.step(2); + assertEquals(0x00, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertTrue(cpu.getZeroFlag()); + assertTrue(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0x00, // LDA #$00 + 0x65, 0x11); // ADC $11 + cpu.step(2); + assertEquals(0xff, cpu.getAccumulator()); + assertTrue(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0x7f, // LDA #$7f + 0x65, 0x11); // ADC $11 + cpu.step(2); + assertEquals(0x7e, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0x80, // LDA #$80 + 0x65, 0x11); // ADC $11 + cpu.step(2); + assertEquals(0x7f, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertTrue(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0xff, // LDA #$ff + 0x65, 0x11); // ADC $11 + cpu.step(2); + assertEquals(0xfe, cpu.getAccumulator()); + assertTrue(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getCarryFlag()); + } + public void test_ADC_IncludesCarry() { - bus.write(0x10, 0x01); - - bus.loadProgram(0xa9, 0x00, // LDA #$00 - 0x38, // SEC - 0x65, 0x10); // ADC $10 - cpu.step(3); - assertEquals(0x02, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getCarryFlag()); + bus.write(0x10, 0x01); + + bus.loadProgram(0xa9, 0x00, // LDA #$00 + 0x38, // SEC + 0x65, 0x10); // ADC $10 + cpu.step(3); + assertEquals(0x02, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getCarryFlag()); } - + public void test_ADC_DecimalMode() { - bus.write(0x10, 0x01); - bus.write(0x11, 0x99); - - bus.loadProgram(0xf8, // SED - 0xa9, 0x01, // LDA #$01 - 0x65, 0x10); // ADC $10 - cpu.step(3); - assertEquals(0x02, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xf8, // SED - 0xa9, 0x49, // LDA #$49 - 0x65, 0x10); // ADC $10 - cpu.step(3); - assertEquals(0x50, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xf8, // SED - 0xa9, 0x50, // LDA #$50 - 0x65, 0x10); // ADC $10 - cpu.step(3); - assertEquals(0x51, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xf8, // SED - 0xa9, 0x99, // LDA #$99 - 0x65, 0x10); // ADC $10 - cpu.step(3); - assertEquals(0x00, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertTrue(cpu.getZeroFlag()); - assertTrue(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xf8, // SED - 0xa9, 0x00, // LDA #$00 - 0x65, 0x11); // ADC $10 - cpu.step(3); - assertEquals(0x99, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xf8, // SED - 0xa9, 0x49, // LDA #$49 - 0x65, 0x11); // ADC $11 - cpu.step(3); - assertEquals(0x48, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xf8, // SED - 0xa9, 0x50, // LDA #$59 - 0x65, 0x11); // ADC $11 - cpu.step(3); - assertEquals(0x49, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getCarryFlag()); + bus.write(0x10, 0x01); + bus.write(0x11, 0x99); + + bus.loadProgram(0xf8, // SED + 0xa9, 0x01, // LDA #$01 + 0x65, 0x10); // ADC $10 + cpu.step(3); + assertEquals(0x02, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xf8, // SED + 0xa9, 0x49, // LDA #$49 + 0x65, 0x10); // ADC $10 + cpu.step(3); + assertEquals(0x50, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xf8, // SED + 0xa9, 0x50, // LDA #$50 + 0x65, 0x10); // ADC $10 + cpu.step(3); + assertEquals(0x51, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xf8, // SED + 0xa9, 0x99, // LDA #$99 + 0x65, 0x10); // ADC $10 + cpu.step(3); + assertEquals(0x00, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertTrue(cpu.getZeroFlag()); + assertTrue(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xf8, // SED + 0xa9, 0x00, // LDA #$00 + 0x65, 0x11); // ADC $10 + cpu.step(3); + assertEquals(0x99, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xf8, // SED + 0xa9, 0x49, // LDA #$49 + 0x65, 0x11); // ADC $11 + cpu.step(3); + assertEquals(0x48, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xf8, // SED + 0xa9, 0x50, // LDA #$59 + 0x65, 0x11); // ADC $11 + cpu.step(3); + assertEquals(0x49, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getCarryFlag()); } - /* ROR - Rotate Right - $66 */ - - public void test_ROR() { - - bus.write(0x10, 0x00); - bus.write(0x11, 0x10); - - bus.loadProgram(0x66, 0x10, // ROR $00 (m=%00000000, c=0) - 0x66, 0x11, // ROR $01 (m=%00001000, c=0) - 0x66, 0x11, // ROR $01 (m=%00000100, c=0) - 0x66, 0x11, // ROR $01 (m=%00000010, c=0) - 0x66, 0x11, // ROR $01 (m=%00000001, c=0) - 0x66, 0x11, // ROR $01 (m=%00000000, c=1) - 0x66, 0x11, // ROR $01 (m=%10000000, c=0) - 0x66, 0x11, // ROR $01 (m=%01000000, c=0) - 0x66, 0x11, // ROR $01 (m=%00100000, c=0) - 0x66, 0x11); // ROR $01 (m=%00010000, c=0) - - cpu.step(); - assertEquals(0x00, bus.read(0x10)); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x08, bus.read(0x11)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x04, bus.read(0x11)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x02, bus.read(0x11)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x01, bus.read(0x11)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x00, bus.read(0x11)); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertTrue(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x80, bus.read(0x11)); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x40, bus.read(0x11)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x20, bus.read(0x11)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.step(); - assertEquals(0x10, bus.read(0x11)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getCarryFlag()); - } - - /* STY - Store Y Register - $84 */ - - public void test_STY() { - cpu.setYRegister(0x00); - bus.loadProgram(0x84, 0x10); - cpu.step(); - assertEquals(0x00, bus.read(0x10)); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.reset(); - - cpu.setYRegister(0x0f); - bus.loadProgram(0x84, 0x10); - cpu.step(); - assertEquals(0x0f, bus.read(0x10)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.reset(); - - cpu.setYRegister(0x80); - bus.loadProgram(0x84, 0x10); - cpu.step(); - assertEquals(0x80, bus.read(0x10)); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - } - - /* STA - Store Accumulator - $85 */ - - public void test_STA() { - cpu.setAccumulator(0x00); - bus.loadProgram(0x85, 0x10); - cpu.step(); - assertEquals(0x00, bus.read(0x10)); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.reset(); - - cpu.setAccumulator(0x0f); - bus.loadProgram(0x85, 0x10); - cpu.step(); - assertEquals(0x0f, bus.read(0x10)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.reset(); - - cpu.setAccumulator(0x80); - bus.loadProgram(0x85, 0x10); - cpu.step(); - assertEquals(0x80, bus.read(0x10)); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - } - - /* STX - Store X Register - $86 */ - - public void test_STX() { - cpu.setXRegister(0x00); - bus.loadProgram(0x86, 0x10); - cpu.step(); - assertEquals(0x00, bus.read(0x10)); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.reset(); - - cpu.setXRegister(0x0f); - bus.loadProgram(0x86, 0x10); - cpu.step(); - assertEquals(0x0f, bus.read(0x10)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.reset(); - - cpu.setXRegister(0x80); - bus.loadProgram(0x86, 0x10); - cpu.step(); - assertEquals(0x80, bus.read(0x10)); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - } - - /* LDY - Load Y Register - $a4 */ - - public void test_LDY() { - bus.write(0x10, 0x00); - bus.write(0x11, 0x0f); - bus.write(0x12, 0x80); - - bus.loadProgram(0xa4, 0x10, - 0xa4, 0x11, - 0xa4, 0x12); - - cpu.step(); - assertEquals(0x00, cpu.getYRegister()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.step(); - assertEquals(0x0f, cpu.getYRegister()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.step(); - assertEquals(0x80, cpu.getYRegister()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - } - - /* LDA - Load Accumulator - $a5 */ - - public void test_LDA() { - bus.write(0x10, 0x00); - bus.write(0x11, 0x0f); - bus.write(0x12, 0x80); - - bus.loadProgram(0xa5, 0x10, - 0xa5, 0x11, - 0xa5, 0x12); - - cpu.step(); - assertEquals(0x00, cpu.getAccumulator()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.step(); - assertEquals(0x0f, cpu.getAccumulator()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.step(); - assertEquals(0x80, cpu.getAccumulator()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - } - - /* LDX - Load X Register - $a6 */ - - public void test_LDX() { - bus.write(0x10, 0x00); - bus.write(0x11, 0x0f); - bus.write(0x12, 0x80); - - bus.loadProgram(0xa6, 0x10, - 0xa6, 0x11, - 0xa6, 0x12); - - cpu.step(); - assertEquals(0x00, cpu.getXRegister()); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.step(); - assertEquals(0x0f, cpu.getXRegister()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.step(); - assertEquals(0x80, cpu.getXRegister()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - } - - /* CPY - Compare Y Register - $c4 */ - - public void test_CPY() { - bus.write(0x10, 0x00); - bus.write(0x11, 0x80); - bus.write(0x12, 0xff); - - cpu.setYRegister(0x80); - - bus.loadProgram(0xc4, 0x10, - 0xc4, 0x11, - 0xc4, 0x12); - - cpu.step(); - assertTrue(cpu.getCarryFlag()); // m > y - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); // m - y < 0 - - cpu.step(); - assertTrue(cpu.getCarryFlag()); // m = y - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); // m - y == 0 - - cpu.step(); - assertFalse(cpu.getCarryFlag()); // m < y - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); // m - y > 0 - } - - /* CMP - Compare Accumulator - $c5 */ - - public void test_CMP() { - bus.write(0x10, 0x00); - bus.write(0x11, 0x80); - bus.write(0x12, 0xff); - - cpu.setAccumulator(0x80); - - bus.loadProgram(0xc5, 0x10, - 0xc5, 0x11, - 0xc5, 0x12); - - cpu.step(); - assertTrue(cpu.getCarryFlag()); // m > y - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); // m - y < 0 - - cpu.step(); - assertTrue(cpu.getCarryFlag()); // m = y - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); // m - y == 0 - - cpu.step(); - assertFalse(cpu.getCarryFlag()); // m < y - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); // m - y > 0 - } - - /* DEC - Decrement Memory Location - $c6 */ - - public void test_DEC() { - bus.write(0x10, 0x00); - bus.write(0x11, 0x01); - bus.write(0x12, 0x80); - bus.write(0x13, 0xff); - - bus.loadProgram(0xc6, 0x10, // DEC $10 - 0xc6, 0x11, // DEC $11 - 0xc6, 0x12, // DEC $12 - 0xc6, 0x13); // DEC $13 - - cpu.step(); - assertEquals(0xff, bus.read(0x10)); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - - cpu.step(); - assertEquals(0x00, bus.read(0x11)); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.step(); - assertEquals(0x7f, bus.read(0x12)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.step(); - assertEquals(0xfe, bus.read(0x13)); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - } - - /* CPX - Compare X Register - $e4 */ - - public void test_CPX() { - bus.write(0x10, 0x00); - bus.write(0x11, 0x80); - bus.write(0x12, 0xff); - - cpu.setXRegister(0x80); - - bus.loadProgram(0xe4, 0x10, - 0xe4, 0x11, - 0xe4, 0x12); - - cpu.step(); - assertTrue(cpu.getCarryFlag()); // m > y - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); // m - y < 0 - - cpu.step(); - assertTrue(cpu.getCarryFlag()); // m = y - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); // m - y == 0 - - cpu.step(); - assertFalse(cpu.getCarryFlag()); // m < y - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); // m - y > 0 - } - - /* SBC - Subtract with Carry - $e5 */ - - public void test_SBC() { - bus.write(0x10, 0x01); - - bus.loadProgram(0xa9, 0x00, // LDA #$00 - 0xe5, 0x10); // SBC $10 - cpu.step(2); - assertEquals(0xfe, cpu.getAccumulator()); - assertTrue(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0x7f, // LDA #$7f - 0xe5, 0x10); // SBC $10 - cpu.step(2); - assertEquals(0x7d, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0x80, // LDA #$80 - 0xe5, 0x10); // SBC $10 - cpu.step(2); - assertEquals(0x7e, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertTrue(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0xff, // LDA #$ff - 0xe5, 0x10); // SBC $10 - cpu.step(2); - assertEquals(0xfd, cpu.getAccumulator()); - assertTrue(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getCarryFlag()); - - cpu.reset(); - bus.loadProgram(0xa9, 0x02, // LDA #$02 - 0xe5, 0x10); // SBC $10 - cpu.step(2); - assertEquals(0x00, cpu.getAccumulator()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertTrue(cpu.getZeroFlag()); - assertTrue(cpu.getCarryFlag()); - } - - public void test_SBC_IncludesNotOfCarry() { - bus.write(0x10, 0x01); - - // Subtrace with Carry Flag cleared - bus.loadProgram(0x18, // CLC - 0xa9, 0x05, // LDA #$00 - 0xe5, 0x10); // SBC $10 - - cpu.step(3); - assertEquals(0x03, cpu.getAccumulator()); - - cpu.reset(); - - // Subtrace with Carry Flag cleared - bus.loadProgram(0x18, // CLC - 0xa9, 0x00, // LDA #$00 - 0xe5, 0x10); // SBC $10 - - cpu.step(3); - assertEquals(0xfe, cpu.getAccumulator()); - - cpu.reset(); - - // Subtract with Carry Flag set - bus.loadProgram(0x38, // SEC - 0xa9, 0x05, // LDA #$00 - 0xe5, 0x10); // SBC $10 - cpu.step(3); - assertEquals(0x04, cpu.getAccumulator()); - assertTrue(cpu.getCarryFlag()); - - cpu.reset(); - - // Subtract with Carry Flag set - bus.loadProgram(0x38, // SEC - 0xa9, 0x00, // LDA #$00 - 0xe5, 0x10); // SBC $10 - cpu.step(3); - assertEquals(0xff, cpu.getAccumulator()); - assertFalse(cpu.getCarryFlag()); - - } - - public void test_SBC_DecimalMode() { - bus.write(0x10, 0x01); - bus.write(0x20, 0x11); - - bus.loadProgram(0xf8, - 0xa9, 0x00, - 0xe5, 0x10); - cpu.step(3); - assertEquals(0x98, cpu.getAccumulator()); - assertFalse(cpu.getCarryFlag()); // borrow = set flag - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getDecimalModeFlag()); - - cpu.reset(); - - bus.loadProgram(0xf8, - 0xa9, 0x99, - 0xe5, 0x10); - cpu.step(3); - assertEquals(0x97, cpu.getAccumulator()); - assertTrue(cpu.getCarryFlag()); // No borrow = clear flag - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getDecimalModeFlag()); - - cpu.reset(); - - bus.loadProgram(0xf8, - 0xa9, 0x50, - 0xe5, 0x10); - cpu.step(3); - assertEquals(0x48, cpu.getAccumulator()); - assertTrue(cpu.getCarryFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getDecimalModeFlag()); - - - cpu.reset(); - - bus.loadProgram(0xf8, // SED - 0xa9, 0x02, // LDA #$02 - 0xe5, 0x10); // SBC $10 - cpu.step(3); - assertEquals(0x00, cpu.getAccumulator()); - assertTrue(cpu.getCarryFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertTrue(cpu.getZeroFlag()); - assertTrue(cpu.getDecimalModeFlag()); - - cpu.reset(); - - bus.loadProgram(0xf8, // SED - 0xa9, 0x10, // LDA #$10 - 0xe5, 0x20); // SBC $20 - cpu.step(3); - assertEquals(0x98, cpu.getAccumulator()); - assertFalse(cpu.getCarryFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getDecimalModeFlag()); - - cpu.reset(); - - bus.loadProgram(0x38, // SEC - 0xf8, // SED - 0xa9, 0x05, // LDA #$05 - 0xe5, 0x10); // SBC $10 - cpu.step(4); - assertEquals(0x04, cpu.getAccumulator()); - assertTrue(cpu.getCarryFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getDecimalModeFlag()); - - cpu.reset(); - - bus.loadProgram(0x38, // SEC - 0xf8, // SED - 0xa9, 0x00, // LDA #$00 - 0xe5, 0x10); // SBC $10 - cpu.step(4); - assertEquals(0x99, cpu.getAccumulator()); - assertFalse(cpu.getCarryFlag()); - assertFalse(cpu.getNegativeFlag()); - assertFalse(cpu.getOverflowFlag()); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getDecimalModeFlag()); - } - - /* INC - Increment Memory Location - $e6 */ - - public void test_INC() { - bus.write(0x10, 0x00); - bus.write(0x11, 0x7f); - bus.write(0x12, 0xff); - - bus.loadProgram(0xe6, 0x10, // INC $10 - 0xe6, 0x11, // INC $11 - 0xe6, 0x12); // INC $12 - - cpu.step(); - assertEquals(0x01, bus.read(0x10)); - assertFalse(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - - cpu.step(); - assertEquals(0x80, bus.read(0x11)); - assertFalse(cpu.getZeroFlag()); - assertTrue(cpu.getNegativeFlag()); - - cpu.step(); - assertEquals(0x00, bus.read(0x12)); - assertTrue(cpu.getZeroFlag()); - assertFalse(cpu.getNegativeFlag()); - } + /* ROR - Rotate Right - $66 */ + + public void test_ROR() { + + bus.write(0x10, 0x00); + bus.write(0x11, 0x10); + + bus.loadProgram(0x66, 0x10, // ROR $00 (m=%00000000, c=0) + 0x66, 0x11, // ROR $01 (m=%00001000, c=0) + 0x66, 0x11, // ROR $01 (m=%00000100, c=0) + 0x66, 0x11, // ROR $01 (m=%00000010, c=0) + 0x66, 0x11, // ROR $01 (m=%00000001, c=0) + 0x66, 0x11, // ROR $01 (m=%00000000, c=1) + 0x66, 0x11, // ROR $01 (m=%10000000, c=0) + 0x66, 0x11, // ROR $01 (m=%01000000, c=0) + 0x66, 0x11, // ROR $01 (m=%00100000, c=0) + 0x66, 0x11); // ROR $01 (m=%00010000, c=0) + + cpu.step(); + assertEquals(0x00, bus.read(0x10)); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x08, bus.read(0x11)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x04, bus.read(0x11)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x02, bus.read(0x11)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x01, bus.read(0x11)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x00, bus.read(0x11)); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertTrue(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x80, bus.read(0x11)); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x40, bus.read(0x11)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x20, bus.read(0x11)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.step(); + assertEquals(0x10, bus.read(0x11)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getCarryFlag()); + } + + /* STY - Store Y Register - $84 */ + + public void test_STY() { + cpu.setYRegister(0x00); + bus.loadProgram(0x84, 0x10); + cpu.step(); + assertEquals(0x00, bus.read(0x10)); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.reset(); + + cpu.setYRegister(0x0f); + bus.loadProgram(0x84, 0x10); + cpu.step(); + assertEquals(0x0f, bus.read(0x10)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.reset(); + + cpu.setYRegister(0x80); + bus.loadProgram(0x84, 0x10); + cpu.step(); + assertEquals(0x80, bus.read(0x10)); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + } + + /* STA - Store Accumulator - $85 */ + + public void test_STA() { + cpu.setAccumulator(0x00); + bus.loadProgram(0x85, 0x10); + cpu.step(); + assertEquals(0x00, bus.read(0x10)); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.reset(); + + cpu.setAccumulator(0x0f); + bus.loadProgram(0x85, 0x10); + cpu.step(); + assertEquals(0x0f, bus.read(0x10)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.reset(); + + cpu.setAccumulator(0x80); + bus.loadProgram(0x85, 0x10); + cpu.step(); + assertEquals(0x80, bus.read(0x10)); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + } + + /* STX - Store X Register - $86 */ + + public void test_STX() { + cpu.setXRegister(0x00); + bus.loadProgram(0x86, 0x10); + cpu.step(); + assertEquals(0x00, bus.read(0x10)); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.reset(); + + cpu.setXRegister(0x0f); + bus.loadProgram(0x86, 0x10); + cpu.step(); + assertEquals(0x0f, bus.read(0x10)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.reset(); + + cpu.setXRegister(0x80); + bus.loadProgram(0x86, 0x10); + cpu.step(); + assertEquals(0x80, bus.read(0x10)); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + } + + /* LDY - Load Y Register - $a4 */ + + public void test_LDY() { + bus.write(0x10, 0x00); + bus.write(0x11, 0x0f); + bus.write(0x12, 0x80); + + bus.loadProgram(0xa4, 0x10, + 0xa4, 0x11, + 0xa4, 0x12); + + cpu.step(); + assertEquals(0x00, cpu.getYRegister()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.step(); + assertEquals(0x0f, cpu.getYRegister()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.step(); + assertEquals(0x80, cpu.getYRegister()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + } + + /* LDA - Load Accumulator - $a5 */ + + public void test_LDA() { + bus.write(0x10, 0x00); + bus.write(0x11, 0x0f); + bus.write(0x12, 0x80); + + bus.loadProgram(0xa5, 0x10, + 0xa5, 0x11, + 0xa5, 0x12); + + cpu.step(); + assertEquals(0x00, cpu.getAccumulator()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.step(); + assertEquals(0x0f, cpu.getAccumulator()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.step(); + assertEquals(0x80, cpu.getAccumulator()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + } + + /* LDX - Load X Register - $a6 */ + + public void test_LDX() { + bus.write(0x10, 0x00); + bus.write(0x11, 0x0f); + bus.write(0x12, 0x80); + + bus.loadProgram(0xa6, 0x10, + 0xa6, 0x11, + 0xa6, 0x12); + + cpu.step(); + assertEquals(0x00, cpu.getXRegister()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.step(); + assertEquals(0x0f, cpu.getXRegister()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.step(); + assertEquals(0x80, cpu.getXRegister()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + } + + /* CPY - Compare Y Register - $c4 */ + + public void test_CPY() { + bus.write(0x10, 0x00); + bus.write(0x11, 0x80); + bus.write(0x12, 0xff); + + cpu.setYRegister(0x80); + + bus.loadProgram(0xc4, 0x10, + 0xc4, 0x11, + 0xc4, 0x12); + + cpu.step(); + assertTrue(cpu.getCarryFlag()); // m > y + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); // m - y < 0 + + cpu.step(); + assertTrue(cpu.getCarryFlag()); // m = y + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); // m - y == 0 + + cpu.step(); + assertFalse(cpu.getCarryFlag()); // m < y + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); // m - y > 0 + } + + /* CMP - Compare Accumulator - $c5 */ + + public void test_CMP() { + bus.write(0x10, 0x00); + bus.write(0x11, 0x80); + bus.write(0x12, 0xff); + + cpu.setAccumulator(0x80); + + bus.loadProgram(0xc5, 0x10, + 0xc5, 0x11, + 0xc5, 0x12); + + cpu.step(); + assertTrue(cpu.getCarryFlag()); // m > y + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); // m - y < 0 + + cpu.step(); + assertTrue(cpu.getCarryFlag()); // m = y + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); // m - y == 0 + + cpu.step(); + assertFalse(cpu.getCarryFlag()); // m < y + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); // m - y > 0 + } + + /* DEC - Decrement Memory Location - $c6 */ + + public void test_DEC() { + bus.write(0x10, 0x00); + bus.write(0x11, 0x01); + bus.write(0x12, 0x80); + bus.write(0x13, 0xff); + + bus.loadProgram(0xc6, 0x10, // DEC $10 + 0xc6, 0x11, // DEC $11 + 0xc6, 0x12, // DEC $12 + 0xc6, 0x13); // DEC $13 + + cpu.step(); + assertEquals(0xff, bus.read(0x10)); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + + cpu.step(); + assertEquals(0x00, bus.read(0x11)); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.step(); + assertEquals(0x7f, bus.read(0x12)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.step(); + assertEquals(0xfe, bus.read(0x13)); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + } + + /* CPX - Compare X Register - $e4 */ + + public void test_CPX() { + bus.write(0x10, 0x00); + bus.write(0x11, 0x80); + bus.write(0x12, 0xff); + + cpu.setXRegister(0x80); + + bus.loadProgram(0xe4, 0x10, + 0xe4, 0x11, + 0xe4, 0x12); + + cpu.step(); + assertTrue(cpu.getCarryFlag()); // m > y + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); // m - y < 0 + + cpu.step(); + assertTrue(cpu.getCarryFlag()); // m = y + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); // m - y == 0 + + cpu.step(); + assertFalse(cpu.getCarryFlag()); // m < y + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); // m - y > 0 + } + + /* SBC - Subtract with Carry - $e5 */ + + public void test_SBC() { + bus.write(0x10, 0x01); + + bus.loadProgram(0xa9, 0x00, // LDA #$00 + 0xe5, 0x10); // SBC $10 + cpu.step(2); + assertEquals(0xfe, cpu.getAccumulator()); + assertTrue(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0x7f, // LDA #$7f + 0xe5, 0x10); // SBC $10 + cpu.step(2); + assertEquals(0x7d, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0x80, // LDA #$80 + 0xe5, 0x10); // SBC $10 + cpu.step(2); + assertEquals(0x7e, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertTrue(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0xff, // LDA #$ff + 0xe5, 0x10); // SBC $10 + cpu.step(2); + assertEquals(0xfd, cpu.getAccumulator()); + assertTrue(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getCarryFlag()); + + cpu.reset(); + bus.loadProgram(0xa9, 0x02, // LDA #$02 + 0xe5, 0x10); // SBC $10 + cpu.step(2); + assertEquals(0x00, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertTrue(cpu.getZeroFlag()); + assertTrue(cpu.getCarryFlag()); + } + + public void test_SBC_IncludesNotOfCarry() { + bus.write(0x10, 0x01); + + // Subtrace with Carry Flag cleared + bus.loadProgram(0x18, // CLC + 0xa9, 0x05, // LDA #$00 + 0xe5, 0x10); // SBC $10 + + cpu.step(3); + assertEquals(0x03, cpu.getAccumulator()); + + cpu.reset(); + + // Subtrace with Carry Flag cleared + bus.loadProgram(0x18, // CLC + 0xa9, 0x00, // LDA #$00 + 0xe5, 0x10); // SBC $10 + + cpu.step(3); + assertEquals(0xfe, cpu.getAccumulator()); + + cpu.reset(); + + // Subtract with Carry Flag set + bus.loadProgram(0x38, // SEC + 0xa9, 0x05, // LDA #$00 + 0xe5, 0x10); // SBC $10 + cpu.step(3); + assertEquals(0x04, cpu.getAccumulator()); + assertTrue(cpu.getCarryFlag()); + + cpu.reset(); + + // Subtract with Carry Flag set + bus.loadProgram(0x38, // SEC + 0xa9, 0x00, // LDA #$00 + 0xe5, 0x10); // SBC $10 + cpu.step(3); + assertEquals(0xff, cpu.getAccumulator()); + assertFalse(cpu.getCarryFlag()); + + } + + public void test_SBC_DecimalMode() { + bus.write(0x10, 0x01); + bus.write(0x20, 0x11); + + bus.loadProgram(0xf8, + 0xa9, 0x00, + 0xe5, 0x10); + cpu.step(3); + assertEquals(0x98, cpu.getAccumulator()); + assertFalse(cpu.getCarryFlag()); // borrow = set flag + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getDecimalModeFlag()); + + cpu.reset(); + + bus.loadProgram(0xf8, + 0xa9, 0x99, + 0xe5, 0x10); + cpu.step(3); + assertEquals(0x97, cpu.getAccumulator()); + assertTrue(cpu.getCarryFlag()); // No borrow = clear flag + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getDecimalModeFlag()); + + cpu.reset(); + + bus.loadProgram(0xf8, + 0xa9, 0x50, + 0xe5, 0x10); + cpu.step(3); + assertEquals(0x48, cpu.getAccumulator()); + assertTrue(cpu.getCarryFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getDecimalModeFlag()); + + + cpu.reset(); + + bus.loadProgram(0xf8, // SED + 0xa9, 0x02, // LDA #$02 + 0xe5, 0x10); // SBC $10 + cpu.step(3); + assertEquals(0x00, cpu.getAccumulator()); + assertTrue(cpu.getCarryFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertTrue(cpu.getZeroFlag()); + assertTrue(cpu.getDecimalModeFlag()); + + cpu.reset(); + + bus.loadProgram(0xf8, // SED + 0xa9, 0x10, // LDA #$10 + 0xe5, 0x20); // SBC $20 + cpu.step(3); + assertEquals(0x98, cpu.getAccumulator()); + assertFalse(cpu.getCarryFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getDecimalModeFlag()); + + cpu.reset(); + + bus.loadProgram(0x38, // SEC + 0xf8, // SED + 0xa9, 0x05, // LDA #$05 + 0xe5, 0x10); // SBC $10 + cpu.step(4); + assertEquals(0x04, cpu.getAccumulator()); + assertTrue(cpu.getCarryFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getDecimalModeFlag()); + + cpu.reset(); + + bus.loadProgram(0x38, // SEC + 0xf8, // SED + 0xa9, 0x00, // LDA #$00 + 0xe5, 0x10); // SBC $10 + cpu.step(4); + assertEquals(0x99, cpu.getAccumulator()); + assertFalse(cpu.getCarryFlag()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getOverflowFlag()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getDecimalModeFlag()); + } + + /* INC - Increment Memory Location - $e6 */ + + public void test_INC() { + bus.write(0x10, 0x00); + bus.write(0x11, 0x7f); + bus.write(0x12, 0xff); + + bus.loadProgram(0xe6, 0x10, // INC $10 + 0xe6, 0x11, // INC $11 + 0xe6, 0x12); // INC $12 + + cpu.step(); + assertEquals(0x01, bus.read(0x10)); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + + cpu.step(); + assertEquals(0x80, bus.read(0x11)); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + + cpu.step(); + assertEquals(0x00, bus.read(0x12)); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } } diff --git a/src/test/java/com/loomcom/symon/MemoryRangeTest.java b/src/test/java/com/loomcom/symon/MemoryRangeTest.java index 43294fb..7adb395 100644 --- a/src/test/java/com/loomcom/symon/MemoryRangeTest.java +++ b/src/test/java/com/loomcom/symon/MemoryRangeTest.java @@ -12,129 +12,129 @@ import com.loomcom.symon.exceptions.*; */ public class MemoryRangeTest extends TestCase { - public MemoryRangeTest(String testName) { - super(testName); - } + public MemoryRangeTest(String testName) { + super(testName); + } - public static Test suite() { - return new TestSuite(MemoryRangeTest.class); - } + public static Test suite() { + return new TestSuite(MemoryRangeTest.class); + } - public void testConstructorThrowsWhenInvalid() { - // All of these should raise MemoryRangeException - doInvalidMemoryRangeTest(0, -1); - doInvalidMemoryRangeTest(-1, 0); - doInvalidMemoryRangeTest(0, 0); - doInvalidMemoryRangeTest(1, 1); - doInvalidMemoryRangeTest(1, 0); - doInvalidMemoryRangeTest(2, 1); - } + public void testConstructorThrowsWhenInvalid() { + // All of these should raise MemoryRangeException + doInvalidMemoryRangeTest(0, -1); + doInvalidMemoryRangeTest(-1, 0); + doInvalidMemoryRangeTest(0, 0); + doInvalidMemoryRangeTest(1, 1); + doInvalidMemoryRangeTest(1, 0); + doInvalidMemoryRangeTest(2, 1); + } - public void testConstructorShouldNotThrow() throws MemoryRangeException { - // None of these should throw. - new MemoryRange(0, 1); - new MemoryRange(0, 2); - new MemoryRange(1, 2); - new MemoryRange(2, 10); - } + public void testConstructorShouldNotThrow() throws MemoryRangeException { + // None of these should throw. + new MemoryRange(0, 1); + new MemoryRange(0, 2); + new MemoryRange(1, 2); + new MemoryRange(2, 10); + } - public void testStartAddress() throws MemoryRangeException { - MemoryRange r = new MemoryRange(0x101, 0x202); - assertEquals(0x101, r.startAddress()); - } + public void testStartAddress() throws MemoryRangeException { + MemoryRange r = new MemoryRange(0x101, 0x202); + assertEquals(0x101, r.startAddress()); + } - public void testEndAddress() throws MemoryRangeException { - MemoryRange r = new MemoryRange(0x101, 0x202); - assertEquals(0x202, r.endAddress()); - } + public void testEndAddress() throws MemoryRangeException { + MemoryRange r = new MemoryRange(0x101, 0x202); + assertEquals(0x202, r.endAddress()); + } - public void testOverlaps() throws MemoryRangeException { - MemoryRange a = new MemoryRange(0x0100, 0x01ff); - MemoryRange b = new MemoryRange(0x0200, 0x02ff); + public void testOverlaps() throws MemoryRangeException { + MemoryRange a = new MemoryRange(0x0100, 0x01ff); + MemoryRange b = new MemoryRange(0x0200, 0x02ff); - MemoryRange c = new MemoryRange(0x01a0, 0x01af); // inside a - MemoryRange d = new MemoryRange(0x00ff, 0x01a0); // overlaps a - MemoryRange e = new MemoryRange(0x01a0, 0x02ff); // overlaps a + MemoryRange c = new MemoryRange(0x01a0, 0x01af); // inside a + MemoryRange d = new MemoryRange(0x00ff, 0x01a0); // overlaps a + MemoryRange e = new MemoryRange(0x01a0, 0x02ff); // overlaps a - MemoryRange f = new MemoryRange(0x02a0, 0x02af); // inside b - MemoryRange g = new MemoryRange(0x01ff, 0x02a0); // overlaps b - MemoryRange h = new MemoryRange(0x02a0, 0x03ff); // overlaps b + MemoryRange f = new MemoryRange(0x02a0, 0x02af); // inside b + MemoryRange g = new MemoryRange(0x01ff, 0x02a0); // overlaps b + MemoryRange h = new MemoryRange(0x02a0, 0x03ff); // overlaps b - assertFalse(a.overlaps(b)); - assertFalse(b.overlaps(a)); + assertFalse(a.overlaps(b)); + assertFalse(b.overlaps(a)); - assertTrue(a.overlaps(c)); - assertTrue(c.overlaps(a)); + assertTrue(a.overlaps(c)); + assertTrue(c.overlaps(a)); - assertTrue(a.overlaps(d)); - assertTrue(d.overlaps(a)); + assertTrue(a.overlaps(d)); + assertTrue(d.overlaps(a)); - assertTrue(a.overlaps(e)); - assertTrue(e.overlaps(a)); + assertTrue(a.overlaps(e)); + assertTrue(e.overlaps(a)); - assertTrue(b.overlaps(f)); - assertTrue(f.overlaps(b)); + assertTrue(b.overlaps(f)); + assertTrue(f.overlaps(b)); - assertTrue(b.overlaps(g)); - assertTrue(g.overlaps(b)); + assertTrue(b.overlaps(g)); + assertTrue(g.overlaps(b)); - assertTrue(b.overlaps(h)); - assertTrue(h.overlaps(b)); - } + assertTrue(b.overlaps(h)); + assertTrue(h.overlaps(b)); + } - public void testToString() throws MemoryRangeException { - MemoryRange a = new MemoryRange(0x0abf, 0xff00); - assertEquals("@0x0abf-0xff00", a.toString()); + public void testToString() throws MemoryRangeException { + MemoryRange a = new MemoryRange(0x0abf, 0xff00); + assertEquals("@0x0abf-0xff00", a.toString()); - MemoryRange b = new MemoryRange(0, 255); - assertEquals("@0x0000-0x00ff", b.toString()); + MemoryRange b = new MemoryRange(0, 255); + assertEquals("@0x0000-0x00ff", b.toString()); - MemoryRange c = new MemoryRange(0, 65535); - assertEquals("@0x0000-0xffff", c.toString()); - } + MemoryRange c = new MemoryRange(0, 65535); + assertEquals("@0x0000-0xffff", c.toString()); + } - public void testIncluded() throws MemoryRangeException { - MemoryRange a = new MemoryRange(0x0100, 0x0fff); + public void testIncluded() throws MemoryRangeException { + MemoryRange a = new MemoryRange(0x0100, 0x0fff); - assertFalse(a.includes(0x0000)); - assertFalse(a.includes(0x00ff)); - assertTrue(a.includes(0x0100)); - assertTrue(a.includes(0x0fff)); - assertFalse(a.includes(0x1000)); - assertFalse(a.includes(0xffff)); - } + assertFalse(a.includes(0x0000)); + assertFalse(a.includes(0x00ff)); + assertTrue(a.includes(0x0100)); + assertTrue(a.includes(0x0fff)); + assertFalse(a.includes(0x1000)); + assertFalse(a.includes(0xffff)); + } - public void testCompareTo() throws MemoryRangeException { - MemoryRange a = new MemoryRange(0x0000, 0x0100); - MemoryRange b = new MemoryRange(0x0200, 0x0300); - MemoryRange c = new MemoryRange(0x0200, 0x0300); - // a < b - assertTrue(a.compareTo(b) == -1); - // b > a - assertTrue(b.compareTo(a) == 1); - // Identity - assertTrue(a.compareTo(a) == 0); - assertTrue(b.compareTo(b) == 0); - // Equality - assertTrue(b.compareTo(c) == 0); - assertTrue(c.compareTo(b) == 0); - // Null - try { - a.compareTo(null); - fail("Should have thrown NullPointerException"); - } catch (NullPointerException ex) { - // expected - } - } + public void testCompareTo() throws MemoryRangeException { + MemoryRange a = new MemoryRange(0x0000, 0x0100); + MemoryRange b = new MemoryRange(0x0200, 0x0300); + MemoryRange c = new MemoryRange(0x0200, 0x0300); + // a < b + assertTrue(a.compareTo(b) == -1); + // b > a + assertTrue(b.compareTo(a) == 1); + // Identity + assertTrue(a.compareTo(a) == 0); + assertTrue(b.compareTo(b) == 0); + // Equality + assertTrue(b.compareTo(c) == 0); + assertTrue(c.compareTo(b) == 0); + // Null + try { + a.compareTo(null); + fail("Should have thrown NullPointerException"); + } catch (NullPointerException ex) { + // expected + } + } - // Helper method. - public void doInvalidMemoryRangeTest(int start, int end) { - try { - new MemoryRange(start, end); - fail("MemoryRangeException should have been thrown."); - } catch (MemoryRangeException e) { - // Expected. - } - } + // Helper method. + public void doInvalidMemoryRangeTest(int start, int end) { + try { + new MemoryRange(start, end); + fail("MemoryRangeException should have been thrown."); + } catch (MemoryRangeException e) { + // Expected. + } + } } \ No newline at end of file diff --git a/src/test/java/com/loomcom/symon/SimulatorTest.java b/src/test/java/com/loomcom/symon/SimulatorTest.java index e760219..668f5a8 100644 --- a/src/test/java/com/loomcom/symon/SimulatorTest.java +++ b/src/test/java/com/loomcom/symon/SimulatorTest.java @@ -8,26 +8,26 @@ import junit.framework.TestSuite; * Unit test for the j6502 Simulator class. */ public class SimulatorTest extends TestCase { - /** - * Create the test case - * - * @param testName name of the test case - */ - public SimulatorTest(String testName) { - super(testName); - } + /** + * Create the test case + * + * @param testName name of the test case + */ + public SimulatorTest(String testName) { + super(testName); + } - /** - * @return the suite of tests being tested - */ - public static Test suite() { - return new TestSuite(SimulatorTest.class); - } + /** + * @return the suite of tests being tested + */ + public static Test suite() { + return new TestSuite(SimulatorTest.class); + } - /** - * Rigourous Test :-) - */ - public void testSimulator() { - assertTrue(true); - } + /** + * Rigourous Test :-) + */ + public void testSimulator() { + assertTrue(true); + } }