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);