diff --git a/src/main/java/com/loomcom/lm6502/Bus.java b/src/main/java/com/loomcom/lm6502/Bus.java index b4b419b..d27b92c 100644 --- a/src/main/java/com/loomcom/lm6502/Bus.java +++ b/src/main/java/com/loomcom/lm6502/Bus.java @@ -22,7 +22,7 @@ public class Bus { } public Bus(int startAddress, int endAddress) { - this.devices = new TreeSet(); + this.devices = new TreeSet(); this.startAddress = startAddress; this.endAddress = endAddress; } @@ -41,8 +41,9 @@ public class Bus { 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."); + throw new MemoryRangeException("The device being added " + + "overlaps with an existing " + + "device."); } } @@ -52,6 +53,7 @@ public class Bus { } public void addCpu(Cpu cpu) { + cpu.setBus(this); this.cpu = cpu; } @@ -123,8 +125,8 @@ public class Bus { throw new RuntimeException("Write failed! Device not found."); } - public SortedSet getDevices() { + public SortedSet getDevices() { // Expose a copy of the device list, not the original - return new TreeSet(devices); + return new TreeSet(devices); } } diff --git a/src/main/java/com/loomcom/lm6502/Cpu.java b/src/main/java/com/loomcom/lm6502/Cpu.java index e4623e8..ab105e6 100644 --- a/src/main/java/com/loomcom/lm6502/Cpu.java +++ b/src/main/java/com/loomcom/lm6502/Cpu.java @@ -18,11 +18,15 @@ public class Cpu implements InstructionTable { private int sp; // Stack Pointer register private int ir; // Instruction register + /* Operands for the current instruction */ + private int[] operands = new int[2]; + private int addr; // The address the most recent instruction + // was fetched from + /** * Construct a new CPU. */ public Cpu() { - reset(); } /** @@ -43,8 +47,13 @@ public class Cpu implements InstructionTable { * Reset the CPU to known initial values. */ public void reset() { + // Registers sp = 0x01ff; - pc = 0xfffc; + + // Set the PC to the address stored in 0xfffc + pc = CpuUtils.address(bus.read(0xfffc), bus.read(0xfffd)); + + // Clear instruction register. ir = 0; } @@ -52,15 +61,572 @@ public class Cpu implements InstructionTable { * Performs an individual machine cycle. */ public void step() { - // 1. Fetch memory + // Store the address from which the IR was read, for debugging + addr = pc; + + // Fetch memory location for this instruction. ir = bus.read(pc); - // 2. Decode the instruction and execute. - - // x. Increment PC + // TODO: The way we increment the PC may need + // to change when interrupts are implemented + + // Increment PC incProgramCounter(); - } + // Decode the instruction and operands + int size = instructionSizes[ir]; + for (int i = 0; i < size-1; i++) { + operands[i] = bus.read(pc); + // Increment PC after reading + incProgramCounter(); + } + + // Execute + switch(ir) { + + case 0x00: // HLT + break; + case 0x01: // n/a + break; + case 0x02: // n/a + break; + case 0x03: // n/a + break; + case 0x04: // n/a + break; + case 0x05: // n/a + break; + case 0x06: // n/a + break; + case 0x07: // n/a + break; + case 0x08: // n/a + break; + case 0x09: // n/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: // n/a + 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: // n/a + break; + case 0x25: // n/a + break; + case 0x26: // n/a + break; + case 0x27: // n/a + break; + case 0x28: // n/a + break; + case 0x29: // n/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: // n/a + 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: // n/a + break; + case 0x41: // n/a + break; + case 0x42: // n/a + break; + case 0x43: // n/a + break; + case 0x44: // n/a + break; + case 0x45: // n/a + break; + case 0x46: // n/a + break; + case 0x47: // n/a + break; + case 0x48: // n/a + break; + case 0x49: // n/a + break; + case 0x4a: // n/a + break; + case 0x4b: // n/a + break; + case 0x4c: // JMP - Absolute + pc = CpuUtils.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: // n/a + 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: // n/a + break; + case 0x61: // n/a + break; + case 0x62: // n/a + break; + case 0x63: // n/a + break; + case 0x64: // n/a + break; + case 0x65: // n/a + break; + case 0x66: // n/a + break; + case 0x67: // n/a + break; + case 0x68: // n/a + break; + case 0x69: // n/a + 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: // n/a + 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: // n/a + break; + case 0x85: // n/a + break; + case 0x86: // n/a + break; + case 0x87: // n/a + break; + case 0x88: // n/a + break; + case 0x89: // n/a + break; + case 0x8a: // n/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: // n/a + break; + case 0x99: // n/a + break; + case 0x9a: // n/a + 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: // n/a + break; + case 0xa1: // n/a + break; + case 0xa2: // n/a + break; + case 0xa3: // n/a + break; + case 0xa4: // n/a + break; + case 0xa5: // n/a + break; + case 0xa6: // n/a + break; + case 0xa7: // n/a + break; + case 0xa8: // n/a + break; + case 0xa9: // LDA - Immediate + a = operands[0]; + break; + case 0xaa: // n/a + 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: // n/a + break; + case 0xb9: // n/a + break; + case 0xba: // n/a + 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: // n/a + break; + case 0xc1: // n/a + break; + case 0xc2: // n/a + break; + case 0xc3: // n/a + break; + case 0xc4: // n/a + break; + case 0xc5: // n/a + break; + case 0xc6: // n/a + break; + case 0xc7: // n/a + break; + case 0xc8: // n/a + break; + case 0xc9: // n/a + break; + case 0xca: // n/a + 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: // n/a + 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: // n/a + break; + case 0xe1: // n/a + break; + case 0xe2: // n/a + break; + case 0xe3: // n/a + break; + case 0xe4: // n/a + break; + case 0xe5: // n/a + break; + case 0xe6: // n/a + break; + case 0xe7: // n/a + break; + case 0xe8: // n/a + break; + case 0xe9: // n/a + break; + case 0xea: // NOP + 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: // n/a + 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; + } + } + + public String statusString() { + String opcode = CpuUtils.opcode(ir, operands[0], operands[1]); + StringBuffer sb = new StringBuffer(String.format("$%04X", addr) + " "); + sb.append(String.format("%-12s", 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)); + return sb.toString(); + } + /* * Increment the PC, rolling over if necessary. */ @@ -71,6 +637,5 @@ public class Cpu implements InstructionTable { ++pc; } } - -} - + +} \ No newline at end of file diff --git a/src/main/java/com/loomcom/lm6502/CpuUtils.java b/src/main/java/com/loomcom/lm6502/CpuUtils.java new file mode 100644 index 0000000..9f187e6 --- /dev/null +++ b/src/main/java/com/loomcom/lm6502/CpuUtils.java @@ -0,0 +1,37 @@ +package com.loomcom.lm6502; + +import com.loomcom.lm6502.InstructionTable.Mode; + +public class CpuUtils { + + /** + * Given two bytes, return an address. + */ + public static 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 + */ + public static 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(); + } +} diff --git a/src/main/java/com/loomcom/lm6502/InstructionTable.java b/src/main/java/com/loomcom/lm6502/InstructionTable.java index c325a1a..ddefcff 100644 --- a/src/main/java/com/loomcom/lm6502/InstructionTable.java +++ b/src/main/java/com/loomcom/lm6502/InstructionTable.java @@ -92,6 +92,10 @@ public interface InstructionTable { } // 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, @@ -127,7 +131,10 @@ public interface InstructionTable { "SED", "SBC", null, null, null, "SBC", "INC", null }; - public static final Mode[] opcodeModes = { + /** + * 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 @@ -193,5 +200,50 @@ public interface InstructionTable { Mode.IMP, Mode.ABY, Mode.NUL, Mode.NUL, // 0xf8-0xfb Mode.NUL, Mode.ABX, Mode.ABX, Mode.NUL // 0xfc-0xff }; + + + /** + * 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/lm6502/Profiler.java b/src/main/java/com/loomcom/lm6502/Profiler.java index 76514c5..156c3f2 100644 --- a/src/main/java/com/loomcom/lm6502/Profiler.java +++ b/src/main/java/com/loomcom/lm6502/Profiler.java @@ -5,7 +5,6 @@ package com.loomcom.lm6502; -import java.util.*; import com.loomcom.lm6502.devices.*; import com.loomcom.lm6502.exceptions.*; @@ -21,7 +20,7 @@ public class Profiler implements InstructionTable { public void dumpOpCodes() { for (int i = 0; i < 0x100; i++) { String name = opcodeNames[i]; - Mode mode = opcodeModes[i]; + Mode mode = instructionModes[i]; System.out.print(String.format("0x%02x: ", i)); @@ -34,12 +33,10 @@ public class Profiler implements InstructionTable { } public void profileMemoryReads() { + // Create a bus. + Bus b = new Bus(0, 65535); try { - - // Create a bus. - Bus b = new Bus(0, 65535); - // 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 @@ -49,40 +46,37 @@ public class Profiler implements InstructionTable { 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 - - // 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 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"); } catch (MemoryRangeException ex) { - System.out.println("Memory Access Exception! " + ex.getMessage()); + System.out.println("Memory Range Exception! " + ex.getMessage()); } + + // 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 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"); } } diff --git a/src/main/java/com/loomcom/lm6502/Simulator.java b/src/main/java/com/loomcom/lm6502/Simulator.java index 3cdaba9..6fd6e0d 100644 --- a/src/main/java/com/loomcom/lm6502/Simulator.java +++ b/src/main/java/com/loomcom/lm6502/Simulator.java @@ -1,6 +1,7 @@ package com.loomcom.lm6502; -import java.io.IOException; +import com.loomcom.lm6502.devices.*; +import com.loomcom.lm6502.exceptions.*; /** * Main control class for the J6502 Simulator. @@ -23,8 +24,11 @@ public class Simulator { */ private Bus bus; - public Simulator() { + 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); } @@ -41,12 +45,51 @@ public class Simulator { public void write(int address, int value) { } + + /** + * A test method. + */ + + public void runTest() { + + // Start at 0x0300 + bus.write(0xfffc, 0x00); + bus.write(0xfffd, 0x03); + + bus.write(0x0300, 0xa9); // LDA #$FF + bus.write(0x0301, 0xff); + bus.write(0x0302, 0xea); // NOP + bus.write(0x0303, 0xea); // NOP + bus.write(0x0304, 0xea); // NOP + bus.write(0x0305, 0xea); // NOP + bus.write(0x0306, 0xa9); // LDA #$1A + bus.write(0x0307, 0x1a); + bus.write(0x0308, 0xea); // NOP + bus.write(0x0309, 0xea); // NOP + bus.write(0x030a, 0xa9); // LDA #$03 + bus.write(0x030b, 0x03); + bus.write(0x030c, 0x4c); // JMP #$0300 + bus.write(0x030d, 0x00); + bus.write(0x030e, 0x03); + + cpu.reset(); + + for (int i = 0; i < 60; i++) { + cpu.step(); + System.out.println(cpu.statusString()); + } + + } /** * Main simulator routine. */ public static void main(String[] args) { - new Simulator().run(); + try { + new Simulator().runTest(); + } catch (MemoryRangeException ex) { + System.err.println("Error: " + ex.toString()); + } } } diff --git a/src/test/java/com/loomcom/lm6502/CpuTest.java b/src/test/java/com/loomcom/lm6502/CpuTest.java index e8d2b24..29aab1e 100644 --- a/src/test/java/com/loomcom/lm6502/CpuTest.java +++ b/src/test/java/com/loomcom/lm6502/CpuTest.java @@ -2,9 +2,6 @@ package com.loomcom.lm6502; import junit.framework.*; -import java.util.HashMap; -import java.util.Map; - /** * */ diff --git a/src/test/java/com/loomcom/lm6502/CpuUtilsTest.java b/src/test/java/com/loomcom/lm6502/CpuUtilsTest.java new file mode 100644 index 0000000..ba5e369 --- /dev/null +++ b/src/test/java/com/loomcom/lm6502/CpuUtilsTest.java @@ -0,0 +1,15 @@ +package com.loomcom.lm6502; + +import junit.framework.TestCase; + +public class CpuUtilsTest extends TestCase { + + public void testAddress() { + assertEquals(0xf1ea, CpuUtils.address(0xea, 0xf1)); + assertEquals(0x00ea, CpuUtils.address(0xea, 0x00)); + assertEquals(0xf100, CpuUtils.address(0x00, 0xf1)); + assertEquals(0x1234, CpuUtils.address(0x34, 0x12)); + assertEquals(0xffff, CpuUtils.address(0xff, 0xff)); + } + +}