diff --git a/README.md b/README.md index bc9b2f9..1c4943d 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,11 @@ SYMON - A 6502 System Simulator **NOTE: THIS IS BETA QUALITY SOFTWARE UNDER ACTIVE DEVELOPMENT. Feedback is welcome!** -**Version:** 0.8.1 +**Version:** 0.8.2 -**Last Updated:** 30 December, 2012 +**Last Updated:** 01 January, 2013 -Copyright (c) 2008-2012 Seth J. Morabito <web@loomcom.com> +Copyright (c) 2008-2013 Seth J. Morabito <web@loomcom.com> See the file COPYING for license. @@ -25,6 +25,11 @@ documentation, and extensive test suites for validating correctness. Symon simulates a complete system with a 1 MHz NMOS 6502, 32KB of RAM, 16KB of ROM, a 6551 ACIA, and a 6522 VIA. +Symon has extensive unit tests to verify correctness, and fully passes +Klaus Dormann's 6502 Functional Test Suite as of version 0.8.2 +(See [this thread on the 6502.org Forums] (http://forum.6502.org/viewtopic.php?f=2&t=2241) +for more information about this functional test suite). + ## 2.0 Requirements - Java 1.5 or higher @@ -135,14 +140,15 @@ running. ## 5.0 Revision History - - 0.8.1: 30 December, 2012 - - 0.8.0: 29 December, 2012 - - 0.7.0: 9 December, 2012 - - 0.6: 5 November, 2012 - - 0.5: 21 October, 2012 - - 0.3: 14 October, 2012 - - 0.2: 22 April, 2012 - - 0.1: 20 January, 2010 + - **0.8.2:** 01 January, 2013 - Fully passes Klaus Dormann's 6502 Functional Test suite! + - **0.8.1:** 30 December, 2012 + - **0.8.0:** 29 December, 2012 + - **0.7.0:** 9 December, 2012 + - **0.6:** 5 November, 2012 + - **0.5:** 21 October, 2012 - Able to run Enhanced BASIC for the first time. + - **0.3:** 14 October, 2012 + - **0.2:** 22 April, 2012 + - **0.1:** 20 January, 2010 ## 6.0 To Do diff --git a/pom.xml b/pom.xml index 052977a..4aa1799 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.loomcom.symon symon jar - 0.8.1 + 0.8.2 symon http://www.loomcom.com/symon diff --git a/src/main/java/com/loomcom/symon/Bus.java b/src/main/java/com/loomcom/symon/Bus.java index b7ef5a6..ec8334b 100644 --- a/src/main/java/com/loomcom/symon/Bus.java +++ b/src/main/java/com/loomcom/symon/Bus.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2012 Seth J. Morabito + * Copyright (c) 2008-2013 Seth J. Morabito * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/src/main/java/com/loomcom/symon/Cpu.java b/src/main/java/com/loomcom/symon/Cpu.java index e4eb9dc..683b161 100644 --- a/src/main/java/com/loomcom/symon/Cpu.java +++ b/src/main/java/com/loomcom/symon/Cpu.java @@ -44,14 +44,14 @@ public class Cpu implements InstructionTable { 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; + public static final int NMI_VECTOR_L = 0xfffa; + public static final int NMI_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; + public static final int IRQ_VECTOR_L = 0xfffe; + public static final int IRQ_VECTOR_H = 0xffff; // The delay in microseconds between steps. // TODO: Make configurable @@ -214,7 +214,7 @@ public class Cpu implements InstructionTable { case 1: switch (irAddressMode) { case 0: // (Zero Page,X) - tmp = state.args[0] + state.x; + tmp = (state.args[0] + state.x) & 0xff; effectiveAddress = address(bus.read(tmp), bus.read(tmp + 1)); break; case 1: // Zero Page @@ -252,9 +252,9 @@ public class Cpu implements InstructionTable { if (!getIrqDisableFlag()) { // Set the break flag before pushing. setBreakFlag(); - // Push program counter + 2 onto the stack - stackPush((state.pc + 2 >> 8) & 0xff); // PC high byte - stackPush(state.pc + 2 & 0xff); // PC low byte + // Push program counter + 1 onto the stack + stackPush((state.pc + 1 >> 8) & 0xff); // PC high byte + stackPush(state.pc + 1 & 0xff); // PC low byte stackPush(state.getStatusFlag()); // Set the Interrupt Disabled flag. RTI will clear it. setIrqDisableFlag(); @@ -263,7 +263,8 @@ public class Cpu implements InstructionTable { } break; case 0x08: // PHP - Push Processor Status - Implied - stackPush(state.getStatusFlag()); + // Break flag is always set in the stack value. + stackPush(state.getStatusFlag() | 0x10); break; case 0x10: // BPL - Branch if Positive - Relative if (!getNegativeFlag()) { @@ -1094,6 +1095,11 @@ public class Cpu implements InstructionTable { public void setStackPointer(int offset) { state.sp = offset; } + + public int getInstruction() { + return state.ir; + } + /** * @value The value of the Process Status Register bits to be set. */ diff --git a/src/main/java/com/loomcom/symon/InstructionTable.java b/src/main/java/com/loomcom/symon/InstructionTable.java index bad6cbe..a0a5792 100644 --- a/src/main/java/com/loomcom/symon/InstructionTable.java +++ b/src/main/java/com/loomcom/symon/InstructionTable.java @@ -241,8 +241,8 @@ public interface InstructionTable { Mode.ABS, Mode.ABS, Mode.ABS, Mode.NUL, // 0xac-0xaf Mode.REL, 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.IMP, Mode.ABY, Mode.IMP, Mode.NUL, // 0xb8-0xbb + Mode.ABX, Mode.ABX, 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 diff --git a/src/main/java/com/loomcom/symon/MemoryRange.java b/src/main/java/com/loomcom/symon/MemoryRange.java index 1321fb1..bb22322 100644 --- a/src/main/java/com/loomcom/symon/MemoryRange.java +++ b/src/main/java/com/loomcom/symon/MemoryRange.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2012 Seth J. Morabito + * Copyright (c) 2008-2013 Seth J. Morabito * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/src/main/java/com/loomcom/symon/Preferences.java b/src/main/java/com/loomcom/symon/Preferences.java index e52bd16..914909f 100644 --- a/src/main/java/com/loomcom/symon/Preferences.java +++ b/src/main/java/com/loomcom/symon/Preferences.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2012 Seth J. Morabito + * Copyright (c) 2008-2013 Seth J. Morabito * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/src/main/java/com/loomcom/symon/Simulator.java b/src/main/java/com/loomcom/symon/Simulator.java index 13cfdf8..86ae106 100644 --- a/src/main/java/com/loomcom/symon/Simulator.java +++ b/src/main/java/com/loomcom/symon/Simulator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2012 Seth J. Morabito + * Copyright (c) 2008-2013 Seth J. Morabito * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -451,9 +451,9 @@ public class Simulator implements Observer { }); try { - while (isRunning && !(preferences.getHaltOnBreak() && cpu.getBreakFlag())) { + do { step(); - } + } while (shouldContinue()); } catch (SymonException ex) { logger.log(Level.SEVERE, "Exception in main simulator run thread. Exiting run."); ex.printStackTrace(); @@ -475,6 +475,15 @@ public class Simulator implements Observer { isRunning = false; } + + /** + * Returns true if the run loop should proceed to the next step. + * + * @return True if the run loop should proceed to the next step. + */ + private boolean shouldContinue() { + return isRunning && !(preferences.getHaltOnBreak() && cpu.getInstruction() == 0x00); + } } class LoadProgramAction extends AbstractAction { diff --git a/src/main/java/com/loomcom/symon/devices/Acia.java b/src/main/java/com/loomcom/symon/devices/Acia.java index ac87c55..c51f43d 100644 --- a/src/main/java/com/loomcom/symon/devices/Acia.java +++ b/src/main/java/com/loomcom/symon/devices/Acia.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2012 Seth J. Morabito + * Copyright (c) 2008-2013 Seth J. Morabito * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/src/main/java/com/loomcom/symon/devices/Device.java b/src/main/java/com/loomcom/symon/devices/Device.java index aeeb18f..7e995da 100644 --- a/src/main/java/com/loomcom/symon/devices/Device.java +++ b/src/main/java/com/loomcom/symon/devices/Device.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2012 Seth J. Morabito + * Copyright (c) 2008-2013 Seth J. Morabito * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/src/main/java/com/loomcom/symon/devices/Memory.java b/src/main/java/com/loomcom/symon/devices/Memory.java index 5f45593..8272652 100644 --- a/src/main/java/com/loomcom/symon/devices/Memory.java +++ b/src/main/java/com/loomcom/symon/devices/Memory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2012 Seth J. Morabito + * Copyright (c) 2008-2013 Seth J. Morabito * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/src/main/java/com/loomcom/symon/devices/Via.java b/src/main/java/com/loomcom/symon/devices/Via.java index d28d8ec..b1013cb 100644 --- a/src/main/java/com/loomcom/symon/devices/Via.java +++ b/src/main/java/com/loomcom/symon/devices/Via.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2012 Seth J. Morabito + * Copyright (c) 2008-2013 Seth J. Morabito * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/src/main/java/com/loomcom/symon/exceptions/FifoUnderrunException.java b/src/main/java/com/loomcom/symon/exceptions/FifoUnderrunException.java index c5b5b25..89a801c 100644 --- a/src/main/java/com/loomcom/symon/exceptions/FifoUnderrunException.java +++ b/src/main/java/com/loomcom/symon/exceptions/FifoUnderrunException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2012 Seth J. Morabito + * Copyright (c) 2008-2013 Seth J. Morabito * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/src/main/java/com/loomcom/symon/exceptions/MemoryAccessException.java b/src/main/java/com/loomcom/symon/exceptions/MemoryAccessException.java index 2f210eb..c9901b7 100644 --- a/src/main/java/com/loomcom/symon/exceptions/MemoryAccessException.java +++ b/src/main/java/com/loomcom/symon/exceptions/MemoryAccessException.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2008-2013 Seth J. Morabito + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + package com.loomcom.symon.exceptions; /** diff --git a/src/main/java/com/loomcom/symon/exceptions/MemoryRangeException.java b/src/main/java/com/loomcom/symon/exceptions/MemoryRangeException.java index 571c617..1e9af54 100644 --- a/src/main/java/com/loomcom/symon/exceptions/MemoryRangeException.java +++ b/src/main/java/com/loomcom/symon/exceptions/MemoryRangeException.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2008-2013 Seth J. Morabito + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + package com.loomcom.symon.exceptions; /** diff --git a/src/main/java/com/loomcom/symon/exceptions/SymonException.java b/src/main/java/com/loomcom/symon/exceptions/SymonException.java index bff91a8..6375415 100644 --- a/src/main/java/com/loomcom/symon/exceptions/SymonException.java +++ b/src/main/java/com/loomcom/symon/exceptions/SymonException.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2008-2013 Seth J. Morabito + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + package com.loomcom.symon.exceptions; diff --git a/src/main/java/com/loomcom/symon/ui/Console.java b/src/main/java/com/loomcom/symon/ui/Console.java index 854a7a8..0e5ef3b 100644 --- a/src/main/java/com/loomcom/symon/ui/Console.java +++ b/src/main/java/com/loomcom/symon/ui/Console.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2012 Seth J. Morabito + * Copyright (c) 2008-2013 Seth J. Morabito * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/src/main/java/com/loomcom/symon/ui/MemoryWindow.java b/src/main/java/com/loomcom/symon/ui/MemoryWindow.java index d8492ec..0bfe027 100644 --- a/src/main/java/com/loomcom/symon/ui/MemoryWindow.java +++ b/src/main/java/com/loomcom/symon/ui/MemoryWindow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2012 Seth J. Morabito + * Copyright (c) 2008-2013 Seth J. Morabito * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/src/main/java/com/loomcom/symon/ui/PreferencesDialog.java b/src/main/java/com/loomcom/symon/ui/PreferencesDialog.java index 863bae1..0651ccd 100644 --- a/src/main/java/com/loomcom/symon/ui/PreferencesDialog.java +++ b/src/main/java/com/loomcom/symon/ui/PreferencesDialog.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2012 Seth J. Morabito + * Copyright (c) 2008-2013 Seth J. Morabito * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/src/main/java/com/loomcom/symon/ui/StatusPanel.java b/src/main/java/com/loomcom/symon/ui/StatusPanel.java index 46d2e34..1c94055 100644 --- a/src/main/java/com/loomcom/symon/ui/StatusPanel.java +++ b/src/main/java/com/loomcom/symon/ui/StatusPanel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2012 Seth J. Morabito + * Copyright (c) 2008-2013 Seth J. Morabito * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/src/main/java/com/loomcom/symon/ui/TraceLog.java b/src/main/java/com/loomcom/symon/ui/TraceLog.java index f4b0a37..99db88a 100644 --- a/src/main/java/com/loomcom/symon/ui/TraceLog.java +++ b/src/main/java/com/loomcom/symon/ui/TraceLog.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2012 Seth J. Morabito + * Copyright (c) 2008-2013 Seth J. Morabito * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/src/main/java/com/loomcom/symon/util/FifoRingBuffer.java b/src/main/java/com/loomcom/symon/util/FifoRingBuffer.java index c130b51..0f385e1 100644 --- a/src/main/java/com/loomcom/symon/util/FifoRingBuffer.java +++ b/src/main/java/com/loomcom/symon/util/FifoRingBuffer.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2008-2013 Seth J. Morabito + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + package com.loomcom.symon.util; import com.loomcom.symon.exceptions.*; diff --git a/src/main/java/com/loomcom/symon/util/HexUtil.java b/src/main/java/com/loomcom/symon/util/HexUtil.java index e009b93..74c94b0 100644 --- a/src/main/java/com/loomcom/symon/util/HexUtil.java +++ b/src/main/java/com/loomcom/symon/util/HexUtil.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2008-2013 Seth J. Morabito + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + package com.loomcom.symon.util; /** diff --git a/src/test/java/com/loomcom/symon/CpuImpliedModeTest.java b/src/test/java/com/loomcom/symon/CpuImpliedModeTest.java index 41efbd3..ae3d141 100644 --- a/src/test/java/com/loomcom/symon/CpuImpliedModeTest.java +++ b/src/test/java/com/loomcom/symon/CpuImpliedModeTest.java @@ -3,14 +3,17 @@ package com.loomcom.symon; import com.loomcom.symon.devices.Memory; import com.loomcom.symon.exceptions.MemoryAccessException; import com.loomcom.symon.exceptions.MemoryRangeException; -import junit.framework.*; +import org.junit.*; -public class CpuImpliedModeTest extends TestCase { +import static org.junit.Assert.*; - protected Cpu cpu; - protected Bus bus; +public class CpuImpliedModeTest { + + protected Cpu cpu; + protected Bus bus; protected Memory mem; + @Before public void setUp() throws MemoryRangeException, MemoryAccessException { this.cpu = new Cpu(); this.bus = new Bus(0x0000, 0xffff); @@ -33,42 +36,43 @@ public class CpuImpliedModeTest extends TestCase { 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 - */ + /* + * 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 */ + /* BRK Tests - 0x00 */ + @Test public void test_BRK() throws MemoryAccessException { cpu.setCarryFlag(); cpu.setOverflowFlag(); @@ -80,15 +84,15 @@ public class CpuImpliedModeTest extends TestCase { assertEquals(0xff, cpu.getStackPointer()); // Set the IRQ vector - bus.write(Cpu.IRQ_VECTOR_H, 0x12); - bus.write(Cpu.IRQ_VECTOR_L, 0x34); + bus.write(0xffff, 0x12); + bus.write(0xfffe, 0x34); - bus.loadProgram(0xea, - 0xea, - 0xea, - 0x00, - 0xea, - 0xea); + bus.loadProgram(0xea, // NOP + 0xea, // NOP + 0xea, // NOP + 0x00, // BRK + 0xea, // NOP + 0xea); // NOP cpu.step(3); // Three NOP instructions @@ -96,9 +100,9 @@ public class CpuImpliedModeTest extends TestCase { cpu.step(); // Triggers the BRK - // Was at PC = 0x204. PC+2 should now be on the stack + // Was at PC = 0x204. PC+1 should now be on the stack assertEquals(0x02, bus.read(0x1ff)); // PC high byte - assertEquals(0x06, bus.read(0x1fe)); // PC low byte + assertEquals(0x05, 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 @@ -108,10 +112,11 @@ public class CpuImpliedModeTest extends TestCase { // 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.P_IRQ_DISABLE, cpu.getProcessorStatus()); } + @Test public void test_BRK_HonorsIrqDisableFlag() throws MemoryAccessException { cpu.setIrqDisableFlag(); @@ -144,6 +149,7 @@ public class CpuImpliedModeTest extends TestCase { } /* CLC - Clear Carry Flag - $18 */ + @Test public void test_CLC() throws MemoryAccessException { cpu.setCarryFlag(); assertTrue(cpu.getCarryFlag()); @@ -155,6 +161,7 @@ public class CpuImpliedModeTest extends TestCase { } /* CLD - Clear Decimal Mode Flag - $d8 */ + @Test public void test_CLD() throws MemoryAccessException { cpu.setDecimalModeFlag(); assertTrue(cpu.getDecimalModeFlag()); @@ -166,6 +173,7 @@ public class CpuImpliedModeTest extends TestCase { } /* CLI - Clear Interrupt Disabled Flag - $58 */ + @Test public void test_CLI() throws MemoryAccessException { cpu.setIrqDisableFlag(); assertTrue(cpu.getIrqDisableFlag()); @@ -177,6 +185,7 @@ public class CpuImpliedModeTest extends TestCase { } /* CLV - Clear Overflow Flag - $b8 */ + @Test public void test_CLV() throws MemoryAccessException { cpu.setOverflowFlag(); assertTrue(cpu.getOverflowFlag()); @@ -187,8 +196,8 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getOverflowFlag()); } - /* DEX - Decrement the X register - $ca */ - + /* DEX - Decrement the X register - $ca */ + @Test public void test_DEX() throws MemoryAccessException { bus.loadProgram(0xca); cpu.setXRegister(0x02); @@ -198,6 +207,7 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getNegativeFlag()); } + @Test public void test_DEX_SetsZeroFlagWhenZero() throws MemoryAccessException { bus.loadProgram(0xca); cpu.setXRegister(0x01); @@ -207,6 +217,7 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getNegativeFlag()); } + @Test public void test_DEX_SetsNegativeFlagWhen() throws MemoryAccessException { bus.loadProgram(0xca); cpu.step(); @@ -215,8 +226,8 @@ public class CpuImpliedModeTest extends TestCase { assertTrue(cpu.getNegativeFlag()); } - /* DEY - Decrement the Y register - $88 */ - + /* DEY - Decrement the Y register - $88 */ + @Test public void test_DEY() throws MemoryAccessException { bus.loadProgram(0x88); cpu.setYRegister(0x02); @@ -226,6 +237,7 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getNegativeFlag()); } + @Test public void test_DEY_SetsZeroFlagWhenZero() throws MemoryAccessException { bus.loadProgram(0x88); cpu.setYRegister(0x01); @@ -235,6 +247,7 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getNegativeFlag()); } + @Test public void test_DEY_SetsNegativeFlagWhen() throws MemoryAccessException { bus.loadProgram(0x88); cpu.step(); @@ -243,8 +256,8 @@ public class CpuImpliedModeTest extends TestCase { assertTrue(cpu.getNegativeFlag()); } - /* INX - Increment the X register - $e8 */ - + /* INX - Increment the X register - $e8 */ + @Test public void test_INX() throws MemoryAccessException { bus.loadProgram(0xe8); cpu.step(); @@ -253,6 +266,7 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getNegativeFlag()); } + @Test public void test_INX_SetsNegativeFlagWhenNegative() throws MemoryAccessException { bus.loadProgram(0xe8); cpu.setXRegister(0x7f); @@ -262,6 +276,7 @@ public class CpuImpliedModeTest extends TestCase { assertTrue(cpu.getNegativeFlag()); } + @Test public void test_INX_SetsZeroFlagWhenZero() throws MemoryAccessException { bus.loadProgram(0xe8); cpu.setXRegister(0xff); @@ -271,8 +286,8 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getNegativeFlag()); } - /* INY - Increment the Y register - $c8 */ - + /* INY - Increment the Y register - $c8 */ + @Test public void test_INY() throws MemoryAccessException { bus.loadProgram(0xc8); cpu.step(); @@ -281,6 +296,7 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getNegativeFlag()); } + @Test public void test_INY_SetsNegativeFlagWhenNegative() throws MemoryAccessException { bus.loadProgram(0xc8); cpu.setYRegister(0x7f); @@ -290,6 +306,7 @@ public class CpuImpliedModeTest extends TestCase { assertTrue(cpu.getNegativeFlag()); } + @Test public void test_INY_SetsZeroFlagWhenZero() throws MemoryAccessException { bus.loadProgram(0xc8); cpu.setYRegister(0xff); @@ -299,8 +316,8 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getNegativeFlag()); } - /* NOP - No Operation - $ea */ - + /* NOP - No Operation - $ea */ + @Test public void test_NOP() throws MemoryAccessException { bus.loadProgram(0xea); cpu.step(); @@ -313,8 +330,8 @@ public class CpuImpliedModeTest extends TestCase { assertEquals(0x20, cpu.getProcessorStatus()); } - /* PHA - Push Accumulator - $48 */ - + /* PHA - Push Accumulator - $48 */ + @Test public void test_PHA() throws MemoryAccessException { bus.loadProgram(0x48); cpu.setAccumulator(0x3a); @@ -323,18 +340,20 @@ public class CpuImpliedModeTest extends TestCase { assertEquals(0x3a, cpu.stackPeek()); } - /* PHP - Push Processor Status - $08 */ - + /* PHP - Push Processor Status - $08 */ + @Test public void test_PHP() throws MemoryAccessException { bus.loadProgram(0x08); cpu.setProcessorStatus(0x27); cpu.step(); assertEquals(0xfe, cpu.getStackPointer()); - assertEquals(0x27, cpu.stackPeek()); + // PHP should have set the BREAK flag _on the stack_ (but not in the CPU) + assertEquals(0x37, cpu.stackPeek()); + assertEquals(0x27, cpu.getProcessorStatus()); } - /* PLA - Pul Accumulator - $68 */ - + /* PLA - Pul Accumulator - $68 */ + @Test public void test_PLA() throws MemoryAccessException { cpu.stackPush(0x32); bus.loadProgram(0x68); @@ -344,6 +363,7 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getZeroFlag()); } + @Test public void test_PLA_SetsZeroIfAccumulatorIsZero() throws MemoryAccessException { cpu.stackPush(0x00); bus.loadProgram(0x68); @@ -353,6 +373,7 @@ public class CpuImpliedModeTest extends TestCase { assertTrue(cpu.getZeroFlag()); } + @Test public void test_PLA_SetsNegativeIfAccumulatorIsNegative() throws MemoryAccessException { cpu.stackPush(0xff); bus.loadProgram(0x68); @@ -362,8 +383,8 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getZeroFlag()); } - /* PLP - Pull Processor Status - $28 */ - + /* PLP - Pull Processor Status - $28 */ + @Test public void test_PLP() throws MemoryAccessException { cpu.stackPush(0x2f); bus.loadProgram(0x28); @@ -371,8 +392,8 @@ public class CpuImpliedModeTest extends TestCase { assertEquals(0x2f, cpu.getProcessorStatus()); } - /* RTI - Return from Interrupt - $40 */ - + /* RTI - Return from Interrupt - $40 */ + @Test public void test_RTI() throws MemoryAccessException { cpu.stackPush(0x0f); // PC hi cpu.stackPush(0x11); // PC lo @@ -385,8 +406,8 @@ public class CpuImpliedModeTest extends TestCase { assertEquals(0x29, cpu.getProcessorStatus()); } - /* RTS - Return from Subroutine - $60 */ - + /* RTS - Return from Subroutine - $60 */ + @Test public void test_RTS() throws MemoryAccessException { cpu.stackPush(0x0f); // PC hi cpu.stackPush(0x11); // PC lo @@ -398,32 +419,32 @@ public class CpuImpliedModeTest extends TestCase { assertEquals(0x20, cpu.getProcessorStatus()); } - /* SEC - Set Carry Flag - $38 */ - + /* SEC - Set Carry Flag - $38 */ + @Test public void test_SEC() throws MemoryAccessException { bus.loadProgram(0x38); cpu.step(); assertTrue(cpu.getCarryFlag()); } - /* SED - Set Decimal Mode Flag - $f8 */ - + /* SED - Set Decimal Mode Flag - $f8 */ + @Test public void test_SED() throws MemoryAccessException { bus.loadProgram(0xf8); cpu.step(); assertTrue(cpu.getDecimalModeFlag()); } - /* SEI - Set Interrupt Disable Flag - $78 */ - + /* SEI - Set Interrupt Disable Flag - $78 */ + @Test public void test_SEI() throws MemoryAccessException { bus.loadProgram(0x78); cpu.step(); assertTrue(cpu.getIrqDisableFlag()); } - /* TAX - Transfer Accumulator to X Register - $aa */ - + /* TAX - Transfer Accumulator to X Register - $aa */ + @Test public void test_TAX() throws MemoryAccessException { cpu.setAccumulator(0x32); bus.loadProgram(0xaa); @@ -433,6 +454,7 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getNegativeFlag()); } + @Test public void test_TAX_SetsZeroFlagIfXIsZero() throws MemoryAccessException { cpu.setAccumulator(0x00); bus.loadProgram(0xaa); @@ -442,6 +464,7 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getNegativeFlag()); } + @Test public void test_TAX_SetsNegativeFlagIfXIsNegative() throws MemoryAccessException { cpu.setAccumulator(0xff); bus.loadProgram(0xaa); @@ -451,8 +474,8 @@ public class CpuImpliedModeTest extends TestCase { assertTrue(cpu.getNegativeFlag()); } - /* TAY - Transfer Accumulator to Y Register - $a8 */ - + /* TAY - Transfer Accumulator to Y Register - $a8 */ + @Test public void test_TAY() throws MemoryAccessException { cpu.setAccumulator(0x32); bus.loadProgram(0xa8); @@ -462,6 +485,7 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getNegativeFlag()); } + @Test public void test_TAY_SetsZeroFlagIfYIsZero() throws MemoryAccessException { cpu.setAccumulator(0x00); bus.loadProgram(0xa8); @@ -471,6 +495,7 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getNegativeFlag()); } + @Test public void test_TAY_SetsNegativeFlagIfYIsNegative() throws MemoryAccessException { cpu.setAccumulator(0xff); bus.loadProgram(0xa8); @@ -480,8 +505,8 @@ public class CpuImpliedModeTest extends TestCase { assertTrue(cpu.getNegativeFlag()); } - /* TSX - Transfer Stack Pointer to X Register - $ba */ - + /* TSX - Transfer Stack Pointer to X Register - $ba */ + @Test public void test_TSX() throws MemoryAccessException { cpu.setStackPointer(0x32); bus.loadProgram(0xba); @@ -491,6 +516,7 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getNegativeFlag()); } + @Test public void test_TSX_SetsZeroFlagIfXIsZero() throws MemoryAccessException { cpu.setStackPointer(0x00); bus.loadProgram(0xba); @@ -500,6 +526,7 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getNegativeFlag()); } + @Test public void test_TSX_SetsNegativeFlagIfXIsNegative() throws MemoryAccessException { cpu.setStackPointer(0xff); bus.loadProgram(0xba); @@ -509,8 +536,8 @@ public class CpuImpliedModeTest extends TestCase { assertTrue(cpu.getNegativeFlag()); } - /* TXA - Transfer X Register to Accumulator - $8a */ - + /* TXA - Transfer X Register to Accumulator - $8a */ + @Test public void test_TXA() throws MemoryAccessException { cpu.setXRegister(0x32); bus.loadProgram(0x8a); @@ -520,6 +547,7 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getNegativeFlag()); } + @Test public void test_TXA_SetsZeroFlagIfAccumulatorIsZero() throws MemoryAccessException { cpu.setXRegister(0x00); bus.loadProgram(0x8a); @@ -529,6 +557,7 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getNegativeFlag()); } + @Test public void test_TXA_SetsNegativeFlagIfAccumulatorIsNegative() throws MemoryAccessException { cpu.setXRegister(0xff); bus.loadProgram(0x8a); @@ -538,8 +567,8 @@ public class CpuImpliedModeTest extends TestCase { assertTrue(cpu.getNegativeFlag()); } - /* TXS - Transfer X Register to Stack Pointer - $9a */ - + /* TXS - Transfer X Register to Stack Pointer - $9a */ + @Test public void test_TXS() throws MemoryAccessException { cpu.setXRegister(0x32); bus.loadProgram(0x9a); @@ -549,6 +578,7 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getNegativeFlag()); } + @Test public void test_TXS_DoesNotAffectProcessorStatus() throws MemoryAccessException { cpu.setXRegister(0x00); bus.loadProgram(0x9a); @@ -565,8 +595,8 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getNegativeFlag()); } - /* TYA - Transfer Y Register to Accumulator - $98 */ - + /* TYA - Transfer Y Register to Accumulator - $98 */ + @Test public void test_TYA() throws MemoryAccessException { cpu.setYRegister(0x32); bus.loadProgram(0x98); @@ -576,6 +606,7 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getNegativeFlag()); } + @Test public void test_TYA_SetsZeroFlagIfAccumulatorIsZero() throws MemoryAccessException { cpu.setYRegister(0x00); bus.loadProgram(0x98); @@ -585,6 +616,7 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getNegativeFlag()); } + @Test public void test_TYA_SetsNegativeFlagIfAccumulatorIsNegative() throws MemoryAccessException { cpu.setYRegister(0xff); bus.loadProgram(0x98); @@ -593,5 +625,4 @@ public class CpuImpliedModeTest extends TestCase { assertFalse(cpu.getZeroFlag()); assertTrue(cpu.getNegativeFlag()); } - } \ No newline at end of file diff --git a/src/test/java/com/loomcom/symon/CpuIndexedIndirectModeTest.java b/src/test/java/com/loomcom/symon/CpuIndexedIndirectModeTest.java index b33f8cd..346dd0c 100644 --- a/src/test/java/com/loomcom/symon/CpuIndexedIndirectModeTest.java +++ b/src/test/java/com/loomcom/symon/CpuIndexedIndirectModeTest.java @@ -48,6 +48,32 @@ public class CpuIndexedIndirectModeTest { assertEquals(0x45, cpu.getAccumulator()); } + @Test + public void testZeroPageWrap() throws Exception { + bus.write(0x0020, 0x01); + bus.write(0x0021, 0x07); // ($0701) + bus.write(0x0701, 0xaa); + + bus.write(0x000f, 0x02); + bus.write(0x0010, 0x08); // ($0802) + bus.write(0x0802, 0xbb); + + bus.write(0x010f, 0x03); + bus.write(0x0110, 0x09); // ($0903) + bus.write(0x0903, 0xcc); + + cpu.setXRegister(0x10); + + // No wrap needed + bus.loadProgram(0xa1, 0x10, // LDA ($10,X) = ($10 + $10) & $ff = $20 + 0xa1, 0xff); // LDA ($ff,X) = ($ff + $10) & $ff = $0f, NOT $10f! + cpu.step(1); + assertEquals(0xaa, cpu.getAccumulator()); + + cpu.step(1); + assertEquals(0xbb, cpu.getAccumulator()); + } + @Test public void test_ORA() throws Exception { bus.write(0x0012, 0x1f);