1
0
mirror of https://github.com/sethm/symon.git synced 2024-06-26 10:29:29 +00:00

Bug Fixes and Copyright Date Change

The simulator now passes Klaus Dormann's 6502 Functional Test suite for
the first time.

Bug Fixes:

- PHP was not correctly setting the Break bit on the stack copy of the
  processor status, so subsequent PLA's would not set the Break status
  flag.

- The CPU had swapped NMI and IRQ reset vectors, so RTI was failing.

- BRK was pushing PC + 2 onto the stack, instead of PC + 1

- (Zero Page,X) addressing mode did not correctly wrap on zero page
  boundaries.

- The instruction table used for disassembly had addressing modes
  of LDA $B9 and $BD reversed. This did not affect behavior, only
  disassembly of these instructions.

Other:

- Updated copyright date for 2013.

- Started migrating old JUnit 3 style tests to JUnit 4 annotations.
This commit is contained in:
Seth Morabito 2013-01-01 17:03:16 -08:00
parent 92b61e4839
commit da8250778e
25 changed files with 323 additions and 130 deletions

View File

@ -4,11 +4,11 @@ SYMON - A 6502 System Simulator
**NOTE: THIS IS BETA QUALITY SOFTWARE UNDER ACTIVE DEVELOPMENT. Feedback is **NOTE: THIS IS BETA QUALITY SOFTWARE UNDER ACTIVE DEVELOPMENT. Feedback is
welcome!** 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. 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, Symon simulates a complete system with a 1 MHz NMOS 6502, 32KB of RAM,
16KB of ROM, a 6551 ACIA, and a 6522 VIA. 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 ## 2.0 Requirements
- Java 1.5 or higher - Java 1.5 or higher
@ -135,14 +140,15 @@ running.
## 5.0 Revision History ## 5.0 Revision History
- 0.8.1: 30 December, 2012 - **0.8.2:** 01 January, 2013 - Fully passes Klaus Dormann's 6502 Functional Test suite!
- 0.8.0: 29 December, 2012 - **0.8.1:** 30 December, 2012
- 0.7.0: 9 December, 2012 - **0.8.0:** 29 December, 2012
- 0.6: 5 November, 2012 - **0.7.0:** 9 December, 2012
- 0.5: 21 October, 2012 - **0.6:** 5 November, 2012
- 0.3: 14 October, 2012 - **0.5:** 21 October, 2012 - Able to run Enhanced BASIC for the first time.
- 0.2: 22 April, 2012 - **0.3:** 14 October, 2012
- 0.1: 20 January, 2010 - **0.2:** 22 April, 2012
- **0.1:** 20 January, 2010
## 6.0 To Do ## 6.0 To Do

View File

@ -4,7 +4,7 @@
<groupId>com.loomcom.symon</groupId> <groupId>com.loomcom.symon</groupId>
<artifactId>symon</artifactId> <artifactId>symon</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<version>0.8.1</version> <version>0.8.2</version>
<name>symon</name> <name>symon</name>
<url>http://www.loomcom.com/symon</url> <url>http://www.loomcom.com/symon</url>
<properties> <properties>

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com> * Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the

View File

@ -44,14 +44,14 @@ public class Cpu implements InstructionTable {
public static final int P_NEGATIVE = 0x80; public static final int P_NEGATIVE = 0x80;
// NMI vector // NMI vector
public static final int IRQ_VECTOR_L = 0xfffa; public static final int NMI_VECTOR_L = 0xfffa;
public static final int IRQ_VECTOR_H = 0xfffb; public static final int NMI_VECTOR_H = 0xfffb;
// Reset vector // Reset vector
public static final int RST_VECTOR_L = 0xfffc; public static final int RST_VECTOR_L = 0xfffc;
public static final int RST_VECTOR_H = 0xfffd; public static final int RST_VECTOR_H = 0xfffd;
// IRQ vector // IRQ vector
public static final int NMI_VECTOR_L = 0xfffe; public static final int IRQ_VECTOR_L = 0xfffe;
public static final int NMI_VECTOR_H = 0xffff; public static final int IRQ_VECTOR_H = 0xffff;
// The delay in microseconds between steps. // The delay in microseconds between steps.
// TODO: Make configurable // TODO: Make configurable
@ -214,7 +214,7 @@ public class Cpu implements InstructionTable {
case 1: case 1:
switch (irAddressMode) { switch (irAddressMode) {
case 0: // (Zero Page,X) 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)); effectiveAddress = address(bus.read(tmp), bus.read(tmp + 1));
break; break;
case 1: // Zero Page case 1: // Zero Page
@ -252,9 +252,9 @@ public class Cpu implements InstructionTable {
if (!getIrqDisableFlag()) { if (!getIrqDisableFlag()) {
// Set the break flag before pushing. // Set the break flag before pushing.
setBreakFlag(); setBreakFlag();
// Push program counter + 2 onto the stack // Push program counter + 1 onto the stack
stackPush((state.pc + 2 >> 8) & 0xff); // PC high byte stackPush((state.pc + 1 >> 8) & 0xff); // PC high byte
stackPush(state.pc + 2 & 0xff); // PC low byte stackPush(state.pc + 1 & 0xff); // PC low byte
stackPush(state.getStatusFlag()); stackPush(state.getStatusFlag());
// Set the Interrupt Disabled flag. RTI will clear it. // Set the Interrupt Disabled flag. RTI will clear it.
setIrqDisableFlag(); setIrqDisableFlag();
@ -263,7 +263,8 @@ public class Cpu implements InstructionTable {
} }
break; break;
case 0x08: // PHP - Push Processor Status - Implied case 0x08: // PHP - Push Processor Status - Implied
stackPush(state.getStatusFlag()); // Break flag is always set in the stack value.
stackPush(state.getStatusFlag() | 0x10);
break; break;
case 0x10: // BPL - Branch if Positive - Relative case 0x10: // BPL - Branch if Positive - Relative
if (!getNegativeFlag()) { if (!getNegativeFlag()) {
@ -1094,6 +1095,11 @@ public class Cpu implements InstructionTable {
public void setStackPointer(int offset) { public void setStackPointer(int offset) {
state.sp = offset; state.sp = offset;
} }
public int getInstruction() {
return state.ir;
}
/** /**
* @value The value of the Process Status Register bits to be set. * @value The value of the Process Status Register bits to be set.
*/ */

View File

@ -241,8 +241,8 @@ public interface InstructionTable {
Mode.ABS, Mode.ABS, Mode.ABS, Mode.NUL, // 0xac-0xaf Mode.ABS, Mode.ABS, Mode.ABS, Mode.NUL, // 0xac-0xaf
Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0xb0-0xb3 Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0xb0-0xb3
Mode.ZPX, Mode.ZPX, Mode.ZPY, Mode.NUL, // 0xb4-0xb7 Mode.ZPX, Mode.ZPX, Mode.ZPY, Mode.NUL, // 0xb4-0xb7
Mode.IMP, Mode.ABX, Mode.IMP, Mode.NUL, // 0xb8-0xbb Mode.IMP, Mode.ABY, Mode.IMP, Mode.NUL, // 0xb8-0xbb
Mode.ABX, Mode.ABY, Mode.ABY, Mode.NUL, // 0xbc-0xbf Mode.ABX, Mode.ABX, Mode.ABY, Mode.NUL, // 0xbc-0xbf
Mode.IMM, Mode.XIN, Mode.NUL, Mode.NUL, // 0xc0-0xc3 Mode.IMM, Mode.XIN, Mode.NUL, Mode.NUL, // 0xc0-0xc3
Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0xc4-0xc7 Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0xc4-0xc7
Mode.IMP, Mode.IMM, Mode.IMP, Mode.NUL, // 0xc8-0xcb Mode.IMP, Mode.IMM, Mode.IMP, Mode.NUL, // 0xc8-0xcb

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com> * Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com> * Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com> * Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the
@ -451,9 +451,9 @@ public class Simulator implements Observer {
}); });
try { try {
while (isRunning && !(preferences.getHaltOnBreak() && cpu.getBreakFlag())) { do {
step(); step();
} } while (shouldContinue());
} catch (SymonException ex) { } catch (SymonException ex) {
logger.log(Level.SEVERE, "Exception in main simulator run thread. Exiting run."); logger.log(Level.SEVERE, "Exception in main simulator run thread. Exiting run.");
ex.printStackTrace(); ex.printStackTrace();
@ -475,6 +475,15 @@ public class Simulator implements Observer {
isRunning = false; 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 { class LoadProgramAction extends AbstractAction {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com> * Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com> * Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com> * Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com> * Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com> * Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the

View File

@ -1,3 +1,26 @@
/*
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
*
* 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; package com.loomcom.symon.exceptions;
/** /**

View File

@ -1,3 +1,26 @@
/*
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
*
* 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; package com.loomcom.symon.exceptions;
/** /**

View File

@ -1,3 +1,26 @@
/*
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
*
* 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; package com.loomcom.symon.exceptions;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com> * Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com> * Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com> * Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com> * Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com> * Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the

View File

@ -1,3 +1,26 @@
/*
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
*
* 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; package com.loomcom.symon.util;
import com.loomcom.symon.exceptions.*; import com.loomcom.symon.exceptions.*;

View File

@ -1,3 +1,26 @@
/*
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
*
* 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; package com.loomcom.symon.util;
/** /**

View File

@ -3,14 +3,17 @@ package com.loomcom.symon;
import com.loomcom.symon.devices.Memory; import com.loomcom.symon.devices.Memory;
import com.loomcom.symon.exceptions.MemoryAccessException; import com.loomcom.symon.exceptions.MemoryAccessException;
import com.loomcom.symon.exceptions.MemoryRangeException; 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; public class CpuImpliedModeTest {
protected Bus bus;
protected Cpu cpu;
protected Bus bus;
protected Memory mem; protected Memory mem;
@Before
public void setUp() throws MemoryRangeException, MemoryAccessException { public void setUp() throws MemoryRangeException, MemoryAccessException {
this.cpu = new Cpu(); this.cpu = new Cpu();
this.bus = new Bus(0x0000, 0xffff); this.bus = new Bus(0x0000, 0xffff);
@ -33,42 +36,43 @@ public class CpuImpliedModeTest extends TestCase {
assertEquals(0x20, cpu.getProcessorStatus()); assertEquals(0x20, cpu.getProcessorStatus());
} }
/* /*
* The following opcodes are tested for correctness in this file: * The following opcodes are tested for correctness in this file:
* *
* BRK - $00 * BRK - $00
* CLC - $18 * CLC - $18
* CLD - $d8 * CLD - $d8
* CLI - $58 * CLI - $58
* CLV - $B8 * CLV - $B8
* *
* DEX - $ca * DEX - $ca
* DEY - $88 * DEY - $88
* INX - $e8 * INX - $e8
* INY - $c8 * INY - $c8
* NOP - $ea * NOP - $ea
* *
* PHA - $48 * PHA - $48
* PHP - $08 * PHP - $08
* PLA - $68 * PLA - $68
* PLP - $28 * PLP - $28
* RTI - $40 * RTI - $40
* *
* RTS - $60 * RTS - $60
* SEC - $38 * SEC - $38
* SED - $f8 * SED - $f8
* SEI - $78 * SEI - $78
* TAX - $aa * TAX - $aa
* *
* TAY - $a8 * TAY - $a8
* TSX - $ba * TSX - $ba
* TXA - $8a * TXA - $8a
* TXS - $9a * TXS - $9a
* TYA - $98 * TYA - $98
*/ */
/* BRK Tests - 0x00 */ /* BRK Tests - 0x00 */
@Test
public void test_BRK() throws MemoryAccessException { public void test_BRK() throws MemoryAccessException {
cpu.setCarryFlag(); cpu.setCarryFlag();
cpu.setOverflowFlag(); cpu.setOverflowFlag();
@ -80,15 +84,15 @@ public class CpuImpliedModeTest extends TestCase {
assertEquals(0xff, cpu.getStackPointer()); assertEquals(0xff, cpu.getStackPointer());
// Set the IRQ vector // Set the IRQ vector
bus.write(Cpu.IRQ_VECTOR_H, 0x12); bus.write(0xffff, 0x12);
bus.write(Cpu.IRQ_VECTOR_L, 0x34); bus.write(0xfffe, 0x34);
bus.loadProgram(0xea, bus.loadProgram(0xea, // NOP
0xea, 0xea, // NOP
0xea, 0xea, // NOP
0x00, 0x00, // BRK
0xea, 0xea, // NOP
0xea); 0xea); // NOP
cpu.step(3); // Three NOP instructions cpu.step(3); // Three NOP instructions
@ -96,9 +100,9 @@ public class CpuImpliedModeTest extends TestCase {
cpu.step(); // Triggers the BRK 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(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, assertEquals(0x20 | Cpu.P_CARRY | Cpu.P_OVERFLOW | Cpu.P_BREAK,
bus.read(0x1fd)); // Processor Status, with B set 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 // B and I flags should have been set on P
assertEquals(0x20 | Cpu.P_CARRY | Cpu.P_OVERFLOW | Cpu.P_BREAK | assertEquals(0x20 | Cpu.P_CARRY | Cpu.P_OVERFLOW | Cpu.P_BREAK |
Cpu.P_IRQ_DISABLE, Cpu.P_IRQ_DISABLE,
cpu.getProcessorStatus()); cpu.getProcessorStatus());
} }
@Test
public void test_BRK_HonorsIrqDisableFlag() throws MemoryAccessException { public void test_BRK_HonorsIrqDisableFlag() throws MemoryAccessException {
cpu.setIrqDisableFlag(); cpu.setIrqDisableFlag();
@ -144,6 +149,7 @@ public class CpuImpliedModeTest extends TestCase {
} }
/* CLC - Clear Carry Flag - $18 */ /* CLC - Clear Carry Flag - $18 */
@Test
public void test_CLC() throws MemoryAccessException { public void test_CLC() throws MemoryAccessException {
cpu.setCarryFlag(); cpu.setCarryFlag();
assertTrue(cpu.getCarryFlag()); assertTrue(cpu.getCarryFlag());
@ -155,6 +161,7 @@ public class CpuImpliedModeTest extends TestCase {
} }
/* CLD - Clear Decimal Mode Flag - $d8 */ /* CLD - Clear Decimal Mode Flag - $d8 */
@Test
public void test_CLD() throws MemoryAccessException { public void test_CLD() throws MemoryAccessException {
cpu.setDecimalModeFlag(); cpu.setDecimalModeFlag();
assertTrue(cpu.getDecimalModeFlag()); assertTrue(cpu.getDecimalModeFlag());
@ -166,6 +173,7 @@ public class CpuImpliedModeTest extends TestCase {
} }
/* CLI - Clear Interrupt Disabled Flag - $58 */ /* CLI - Clear Interrupt Disabled Flag - $58 */
@Test
public void test_CLI() throws MemoryAccessException { public void test_CLI() throws MemoryAccessException {
cpu.setIrqDisableFlag(); cpu.setIrqDisableFlag();
assertTrue(cpu.getIrqDisableFlag()); assertTrue(cpu.getIrqDisableFlag());
@ -177,6 +185,7 @@ public class CpuImpliedModeTest extends TestCase {
} }
/* CLV - Clear Overflow Flag - $b8 */ /* CLV - Clear Overflow Flag - $b8 */
@Test
public void test_CLV() throws MemoryAccessException { public void test_CLV() throws MemoryAccessException {
cpu.setOverflowFlag(); cpu.setOverflowFlag();
assertTrue(cpu.getOverflowFlag()); assertTrue(cpu.getOverflowFlag());
@ -187,8 +196,8 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getOverflowFlag()); assertFalse(cpu.getOverflowFlag());
} }
/* DEX - Decrement the X register - $ca */ /* DEX - Decrement the X register - $ca */
@Test
public void test_DEX() throws MemoryAccessException { public void test_DEX() throws MemoryAccessException {
bus.loadProgram(0xca); bus.loadProgram(0xca);
cpu.setXRegister(0x02); cpu.setXRegister(0x02);
@ -198,6 +207,7 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getNegativeFlag());
} }
@Test
public void test_DEX_SetsZeroFlagWhenZero() throws MemoryAccessException { public void test_DEX_SetsZeroFlagWhenZero() throws MemoryAccessException {
bus.loadProgram(0xca); bus.loadProgram(0xca);
cpu.setXRegister(0x01); cpu.setXRegister(0x01);
@ -207,6 +217,7 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getNegativeFlag());
} }
@Test
public void test_DEX_SetsNegativeFlagWhen() throws MemoryAccessException { public void test_DEX_SetsNegativeFlagWhen() throws MemoryAccessException {
bus.loadProgram(0xca); bus.loadProgram(0xca);
cpu.step(); cpu.step();
@ -215,8 +226,8 @@ public class CpuImpliedModeTest extends TestCase {
assertTrue(cpu.getNegativeFlag()); assertTrue(cpu.getNegativeFlag());
} }
/* DEY - Decrement the Y register - $88 */ /* DEY - Decrement the Y register - $88 */
@Test
public void test_DEY() throws MemoryAccessException { public void test_DEY() throws MemoryAccessException {
bus.loadProgram(0x88); bus.loadProgram(0x88);
cpu.setYRegister(0x02); cpu.setYRegister(0x02);
@ -226,6 +237,7 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getNegativeFlag());
} }
@Test
public void test_DEY_SetsZeroFlagWhenZero() throws MemoryAccessException { public void test_DEY_SetsZeroFlagWhenZero() throws MemoryAccessException {
bus.loadProgram(0x88); bus.loadProgram(0x88);
cpu.setYRegister(0x01); cpu.setYRegister(0x01);
@ -235,6 +247,7 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getNegativeFlag());
} }
@Test
public void test_DEY_SetsNegativeFlagWhen() throws MemoryAccessException { public void test_DEY_SetsNegativeFlagWhen() throws MemoryAccessException {
bus.loadProgram(0x88); bus.loadProgram(0x88);
cpu.step(); cpu.step();
@ -243,8 +256,8 @@ public class CpuImpliedModeTest extends TestCase {
assertTrue(cpu.getNegativeFlag()); assertTrue(cpu.getNegativeFlag());
} }
/* INX - Increment the X register - $e8 */ /* INX - Increment the X register - $e8 */
@Test
public void test_INX() throws MemoryAccessException { public void test_INX() throws MemoryAccessException {
bus.loadProgram(0xe8); bus.loadProgram(0xe8);
cpu.step(); cpu.step();
@ -253,6 +266,7 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getNegativeFlag());
} }
@Test
public void test_INX_SetsNegativeFlagWhenNegative() throws MemoryAccessException { public void test_INX_SetsNegativeFlagWhenNegative() throws MemoryAccessException {
bus.loadProgram(0xe8); bus.loadProgram(0xe8);
cpu.setXRegister(0x7f); cpu.setXRegister(0x7f);
@ -262,6 +276,7 @@ public class CpuImpliedModeTest extends TestCase {
assertTrue(cpu.getNegativeFlag()); assertTrue(cpu.getNegativeFlag());
} }
@Test
public void test_INX_SetsZeroFlagWhenZero() throws MemoryAccessException { public void test_INX_SetsZeroFlagWhenZero() throws MemoryAccessException {
bus.loadProgram(0xe8); bus.loadProgram(0xe8);
cpu.setXRegister(0xff); cpu.setXRegister(0xff);
@ -271,8 +286,8 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getNegativeFlag());
} }
/* INY - Increment the Y register - $c8 */ /* INY - Increment the Y register - $c8 */
@Test
public void test_INY() throws MemoryAccessException { public void test_INY() throws MemoryAccessException {
bus.loadProgram(0xc8); bus.loadProgram(0xc8);
cpu.step(); cpu.step();
@ -281,6 +296,7 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getNegativeFlag());
} }
@Test
public void test_INY_SetsNegativeFlagWhenNegative() throws MemoryAccessException { public void test_INY_SetsNegativeFlagWhenNegative() throws MemoryAccessException {
bus.loadProgram(0xc8); bus.loadProgram(0xc8);
cpu.setYRegister(0x7f); cpu.setYRegister(0x7f);
@ -290,6 +306,7 @@ public class CpuImpliedModeTest extends TestCase {
assertTrue(cpu.getNegativeFlag()); assertTrue(cpu.getNegativeFlag());
} }
@Test
public void test_INY_SetsZeroFlagWhenZero() throws MemoryAccessException { public void test_INY_SetsZeroFlagWhenZero() throws MemoryAccessException {
bus.loadProgram(0xc8); bus.loadProgram(0xc8);
cpu.setYRegister(0xff); cpu.setYRegister(0xff);
@ -299,8 +316,8 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getNegativeFlag());
} }
/* NOP - No Operation - $ea */ /* NOP - No Operation - $ea */
@Test
public void test_NOP() throws MemoryAccessException { public void test_NOP() throws MemoryAccessException {
bus.loadProgram(0xea); bus.loadProgram(0xea);
cpu.step(); cpu.step();
@ -313,8 +330,8 @@ public class CpuImpliedModeTest extends TestCase {
assertEquals(0x20, cpu.getProcessorStatus()); assertEquals(0x20, cpu.getProcessorStatus());
} }
/* PHA - Push Accumulator - $48 */ /* PHA - Push Accumulator - $48 */
@Test
public void test_PHA() throws MemoryAccessException { public void test_PHA() throws MemoryAccessException {
bus.loadProgram(0x48); bus.loadProgram(0x48);
cpu.setAccumulator(0x3a); cpu.setAccumulator(0x3a);
@ -323,18 +340,20 @@ public class CpuImpliedModeTest extends TestCase {
assertEquals(0x3a, cpu.stackPeek()); assertEquals(0x3a, cpu.stackPeek());
} }
/* PHP - Push Processor Status - $08 */ /* PHP - Push Processor Status - $08 */
@Test
public void test_PHP() throws MemoryAccessException { public void test_PHP() throws MemoryAccessException {
bus.loadProgram(0x08); bus.loadProgram(0x08);
cpu.setProcessorStatus(0x27); cpu.setProcessorStatus(0x27);
cpu.step(); cpu.step();
assertEquals(0xfe, cpu.getStackPointer()); 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 { public void test_PLA() throws MemoryAccessException {
cpu.stackPush(0x32); cpu.stackPush(0x32);
bus.loadProgram(0x68); bus.loadProgram(0x68);
@ -344,6 +363,7 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getZeroFlag()); assertFalse(cpu.getZeroFlag());
} }
@Test
public void test_PLA_SetsZeroIfAccumulatorIsZero() throws MemoryAccessException { public void test_PLA_SetsZeroIfAccumulatorIsZero() throws MemoryAccessException {
cpu.stackPush(0x00); cpu.stackPush(0x00);
bus.loadProgram(0x68); bus.loadProgram(0x68);
@ -353,6 +373,7 @@ public class CpuImpliedModeTest extends TestCase {
assertTrue(cpu.getZeroFlag()); assertTrue(cpu.getZeroFlag());
} }
@Test
public void test_PLA_SetsNegativeIfAccumulatorIsNegative() throws MemoryAccessException { public void test_PLA_SetsNegativeIfAccumulatorIsNegative() throws MemoryAccessException {
cpu.stackPush(0xff); cpu.stackPush(0xff);
bus.loadProgram(0x68); bus.loadProgram(0x68);
@ -362,8 +383,8 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getZeroFlag()); assertFalse(cpu.getZeroFlag());
} }
/* PLP - Pull Processor Status - $28 */ /* PLP - Pull Processor Status - $28 */
@Test
public void test_PLP() throws MemoryAccessException { public void test_PLP() throws MemoryAccessException {
cpu.stackPush(0x2f); cpu.stackPush(0x2f);
bus.loadProgram(0x28); bus.loadProgram(0x28);
@ -371,8 +392,8 @@ public class CpuImpliedModeTest extends TestCase {
assertEquals(0x2f, cpu.getProcessorStatus()); assertEquals(0x2f, cpu.getProcessorStatus());
} }
/* RTI - Return from Interrupt - $40 */ /* RTI - Return from Interrupt - $40 */
@Test
public void test_RTI() throws MemoryAccessException { public void test_RTI() throws MemoryAccessException {
cpu.stackPush(0x0f); // PC hi cpu.stackPush(0x0f); // PC hi
cpu.stackPush(0x11); // PC lo cpu.stackPush(0x11); // PC lo
@ -385,8 +406,8 @@ public class CpuImpliedModeTest extends TestCase {
assertEquals(0x29, cpu.getProcessorStatus()); assertEquals(0x29, cpu.getProcessorStatus());
} }
/* RTS - Return from Subroutine - $60 */ /* RTS - Return from Subroutine - $60 */
@Test
public void test_RTS() throws MemoryAccessException { public void test_RTS() throws MemoryAccessException {
cpu.stackPush(0x0f); // PC hi cpu.stackPush(0x0f); // PC hi
cpu.stackPush(0x11); // PC lo cpu.stackPush(0x11); // PC lo
@ -398,32 +419,32 @@ public class CpuImpliedModeTest extends TestCase {
assertEquals(0x20, cpu.getProcessorStatus()); assertEquals(0x20, cpu.getProcessorStatus());
} }
/* SEC - Set Carry Flag - $38 */ /* SEC - Set Carry Flag - $38 */
@Test
public void test_SEC() throws MemoryAccessException { public void test_SEC() throws MemoryAccessException {
bus.loadProgram(0x38); bus.loadProgram(0x38);
cpu.step(); cpu.step();
assertTrue(cpu.getCarryFlag()); assertTrue(cpu.getCarryFlag());
} }
/* SED - Set Decimal Mode Flag - $f8 */ /* SED - Set Decimal Mode Flag - $f8 */
@Test
public void test_SED() throws MemoryAccessException { public void test_SED() throws MemoryAccessException {
bus.loadProgram(0xf8); bus.loadProgram(0xf8);
cpu.step(); cpu.step();
assertTrue(cpu.getDecimalModeFlag()); assertTrue(cpu.getDecimalModeFlag());
} }
/* SEI - Set Interrupt Disable Flag - $78 */ /* SEI - Set Interrupt Disable Flag - $78 */
@Test
public void test_SEI() throws MemoryAccessException { public void test_SEI() throws MemoryAccessException {
bus.loadProgram(0x78); bus.loadProgram(0x78);
cpu.step(); cpu.step();
assertTrue(cpu.getIrqDisableFlag()); assertTrue(cpu.getIrqDisableFlag());
} }
/* TAX - Transfer Accumulator to X Register - $aa */ /* TAX - Transfer Accumulator to X Register - $aa */
@Test
public void test_TAX() throws MemoryAccessException { public void test_TAX() throws MemoryAccessException {
cpu.setAccumulator(0x32); cpu.setAccumulator(0x32);
bus.loadProgram(0xaa); bus.loadProgram(0xaa);
@ -433,6 +454,7 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getNegativeFlag());
} }
@Test
public void test_TAX_SetsZeroFlagIfXIsZero() throws MemoryAccessException { public void test_TAX_SetsZeroFlagIfXIsZero() throws MemoryAccessException {
cpu.setAccumulator(0x00); cpu.setAccumulator(0x00);
bus.loadProgram(0xaa); bus.loadProgram(0xaa);
@ -442,6 +464,7 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getNegativeFlag());
} }
@Test
public void test_TAX_SetsNegativeFlagIfXIsNegative() throws MemoryAccessException { public void test_TAX_SetsNegativeFlagIfXIsNegative() throws MemoryAccessException {
cpu.setAccumulator(0xff); cpu.setAccumulator(0xff);
bus.loadProgram(0xaa); bus.loadProgram(0xaa);
@ -451,8 +474,8 @@ public class CpuImpliedModeTest extends TestCase {
assertTrue(cpu.getNegativeFlag()); assertTrue(cpu.getNegativeFlag());
} }
/* TAY - Transfer Accumulator to Y Register - $a8 */ /* TAY - Transfer Accumulator to Y Register - $a8 */
@Test
public void test_TAY() throws MemoryAccessException { public void test_TAY() throws MemoryAccessException {
cpu.setAccumulator(0x32); cpu.setAccumulator(0x32);
bus.loadProgram(0xa8); bus.loadProgram(0xa8);
@ -462,6 +485,7 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getNegativeFlag());
} }
@Test
public void test_TAY_SetsZeroFlagIfYIsZero() throws MemoryAccessException { public void test_TAY_SetsZeroFlagIfYIsZero() throws MemoryAccessException {
cpu.setAccumulator(0x00); cpu.setAccumulator(0x00);
bus.loadProgram(0xa8); bus.loadProgram(0xa8);
@ -471,6 +495,7 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getNegativeFlag());
} }
@Test
public void test_TAY_SetsNegativeFlagIfYIsNegative() throws MemoryAccessException { public void test_TAY_SetsNegativeFlagIfYIsNegative() throws MemoryAccessException {
cpu.setAccumulator(0xff); cpu.setAccumulator(0xff);
bus.loadProgram(0xa8); bus.loadProgram(0xa8);
@ -480,8 +505,8 @@ public class CpuImpliedModeTest extends TestCase {
assertTrue(cpu.getNegativeFlag()); 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 { public void test_TSX() throws MemoryAccessException {
cpu.setStackPointer(0x32); cpu.setStackPointer(0x32);
bus.loadProgram(0xba); bus.loadProgram(0xba);
@ -491,6 +516,7 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getNegativeFlag());
} }
@Test
public void test_TSX_SetsZeroFlagIfXIsZero() throws MemoryAccessException { public void test_TSX_SetsZeroFlagIfXIsZero() throws MemoryAccessException {
cpu.setStackPointer(0x00); cpu.setStackPointer(0x00);
bus.loadProgram(0xba); bus.loadProgram(0xba);
@ -500,6 +526,7 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getNegativeFlag());
} }
@Test
public void test_TSX_SetsNegativeFlagIfXIsNegative() throws MemoryAccessException { public void test_TSX_SetsNegativeFlagIfXIsNegative() throws MemoryAccessException {
cpu.setStackPointer(0xff); cpu.setStackPointer(0xff);
bus.loadProgram(0xba); bus.loadProgram(0xba);
@ -509,8 +536,8 @@ public class CpuImpliedModeTest extends TestCase {
assertTrue(cpu.getNegativeFlag()); assertTrue(cpu.getNegativeFlag());
} }
/* TXA - Transfer X Register to Accumulator - $8a */ /* TXA - Transfer X Register to Accumulator - $8a */
@Test
public void test_TXA() throws MemoryAccessException { public void test_TXA() throws MemoryAccessException {
cpu.setXRegister(0x32); cpu.setXRegister(0x32);
bus.loadProgram(0x8a); bus.loadProgram(0x8a);
@ -520,6 +547,7 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getNegativeFlag());
} }
@Test
public void test_TXA_SetsZeroFlagIfAccumulatorIsZero() throws MemoryAccessException { public void test_TXA_SetsZeroFlagIfAccumulatorIsZero() throws MemoryAccessException {
cpu.setXRegister(0x00); cpu.setXRegister(0x00);
bus.loadProgram(0x8a); bus.loadProgram(0x8a);
@ -529,6 +557,7 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getNegativeFlag());
} }
@Test
public void test_TXA_SetsNegativeFlagIfAccumulatorIsNegative() throws MemoryAccessException { public void test_TXA_SetsNegativeFlagIfAccumulatorIsNegative() throws MemoryAccessException {
cpu.setXRegister(0xff); cpu.setXRegister(0xff);
bus.loadProgram(0x8a); bus.loadProgram(0x8a);
@ -538,8 +567,8 @@ public class CpuImpliedModeTest extends TestCase {
assertTrue(cpu.getNegativeFlag()); 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 { public void test_TXS() throws MemoryAccessException {
cpu.setXRegister(0x32); cpu.setXRegister(0x32);
bus.loadProgram(0x9a); bus.loadProgram(0x9a);
@ -549,6 +578,7 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getNegativeFlag());
} }
@Test
public void test_TXS_DoesNotAffectProcessorStatus() throws MemoryAccessException { public void test_TXS_DoesNotAffectProcessorStatus() throws MemoryAccessException {
cpu.setXRegister(0x00); cpu.setXRegister(0x00);
bus.loadProgram(0x9a); bus.loadProgram(0x9a);
@ -565,8 +595,8 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getNegativeFlag());
} }
/* TYA - Transfer Y Register to Accumulator - $98 */ /* TYA - Transfer Y Register to Accumulator - $98 */
@Test
public void test_TYA() throws MemoryAccessException { public void test_TYA() throws MemoryAccessException {
cpu.setYRegister(0x32); cpu.setYRegister(0x32);
bus.loadProgram(0x98); bus.loadProgram(0x98);
@ -576,6 +606,7 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getNegativeFlag());
} }
@Test
public void test_TYA_SetsZeroFlagIfAccumulatorIsZero() throws MemoryAccessException { public void test_TYA_SetsZeroFlagIfAccumulatorIsZero() throws MemoryAccessException {
cpu.setYRegister(0x00); cpu.setYRegister(0x00);
bus.loadProgram(0x98); bus.loadProgram(0x98);
@ -585,6 +616,7 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getNegativeFlag());
} }
@Test
public void test_TYA_SetsNegativeFlagIfAccumulatorIsNegative() throws MemoryAccessException { public void test_TYA_SetsNegativeFlagIfAccumulatorIsNegative() throws MemoryAccessException {
cpu.setYRegister(0xff); cpu.setYRegister(0xff);
bus.loadProgram(0x98); bus.loadProgram(0x98);
@ -593,5 +625,4 @@ public class CpuImpliedModeTest extends TestCase {
assertFalse(cpu.getZeroFlag()); assertFalse(cpu.getZeroFlag());
assertTrue(cpu.getNegativeFlag()); assertTrue(cpu.getNegativeFlag());
} }
} }

View File

@ -48,6 +48,32 @@ public class CpuIndexedIndirectModeTest {
assertEquals(0x45, cpu.getAccumulator()); 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 @Test
public void test_ORA() throws Exception { public void test_ORA() throws Exception {
bus.write(0x0012, 0x1f); bus.write(0x0012, 0x1f);