Compare commits

...

10 Commits

Author SHA1 Message Date
Seth Morabito 5a25750f46 Clarify how to load ROMs in README files 2023-07-23 10:16:36 -07:00
Tim Allen 4a8a803472 Document the quirks of Symon's ACIA emulation.
Fixes #7.
2023-06-11 08:21:37 -07:00
Tim Allen 4423623816 Writing 0 to the 6551 ACIA's control register is not a program reset.
So far as I can tell, ever since the first version of the ACIA emulation in
Symon, writing 0x00 to the control register has been interpreted as a request
to reset, rather than to actually set the control register to 0x00. This is
strange for a number of reasons:

- All-zeros is actually a very sensible value for the control register, and
  is in fact the hardware-reset default.
- I can't find any description of such behaviour in the 6551, W65C51S, or
  W65C51N data sheets.
- The 6551 already has a way to trigger "program reset" by writing to the
  status register.

So I've removed that quirk, and writing to the control register now just
writes to the control register and nothing else.
2023-06-11 08:21:37 -07:00
Tim Allen 5df775bbb0 Make the emulated 6551's soft ("program") reset state match the MOS datasheet.
The only description of the effects of "program reset" in the original MOS
datasheet is in the section for each register. The W65C51S and W65C51N
datasheets have a heading "PROGRAM RESET OPERATION", but it amounts to:

- internal registers are modified as described in the section for each register
- changes to the DTR, DCD, and DSR pins which Symon does not emulate
- the overrun flag is cleared

...which is what this new implementation does.

It would make *sense* for the reset to do things like "cancel transmission or
reception in progress" and stop asserting an interrupt, as the old code did,
but I can't find any evidence of such behaviour in the datasheets.
2023-06-11 08:21:37 -07:00
Tim Allen d076046f57 Make the emulated 6551's hardware reset state match the MOS datasheet. 2023-06-11 08:21:37 -07:00
Tim Allen b725fb5fdd Fix comment: The 6551 baud rate is in the lower *four* bits.
The code is correct, the comment is wrong.
2023-06-10 10:19:24 -07:00
Tim Allen 9351d785ae Fix comment: The 6551 ACIA *does* support interrupts. 2023-06-10 10:19:24 -07:00
Tim Allen 66a92f4196 Use ACIA register names where we can. 2023-06-10 10:19:24 -07:00
Seth Morabito cda9a218af
Merge pull request #6 from Screwtapello/irq-disabled-at-reset
Make the Processor Status register match a real 6502 at power-on.
2023-02-03 16:38:06 -08:00
Tim Allen b5a470d3ba Make the Processor Status register match a real 6502 at power-on.
When describing the CPU's reset pin, the W65C02S data sheet says:

> All Registers are initialized by software except the Decimal and Interrupt
> disable mode select bits of the Processor Status Register (P) are initialized
> by hardware.

It then has a diagram of the power-on state of the processor status register:

>     7 6 5 4 3 2 1 0
>     * * 1 1 0 1 * *
>     N V - B D I Z C
>
> * = software initialized

Confusingly the text indicates that only the D and I flags are initialised by
hardware, while the diagram indicates that the B flag is initialised too.

Meanwhile, https://www.nesdev.org/wiki/CPU_power_up_state says that
the power-on state of the NES CPU is $34 (exactly matching the diagram above)
but https://www.nesdev.org/wiki/Status_flags#The_B_flag says that the B flag
does not physically exist within P register, it's only relevant in the copy
of P that gets pushed to the stack by BRK (set), PHP (set), or an interrupt
signal (cleared).

As a result, the most sensible power-on state for the processor status register
is with the "interrupt disable" flag set and everything else cleared.
2023-02-03 18:16:57 +11:00
21 changed files with 224 additions and 130 deletions

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
*~
*.jar
*#
target
.DS_Store

View File

@ -69,14 +69,29 @@ memory.
![Serial Console](https://github.com/sethm/symon/raw/master/screenshots/console.png)
The main window of the simulator acts as the primary Input/Output
system through a virtual serial terminal. The terminal is attached to
a simulated ACIA, including a programmable baud rate generator that
tries to approximate the correct "feel" of the programmed baud rate.
(The sample Enhanced BASIC ROM image is programmed for 9600 baud)
system through a virtual serial terminal. It also provides CPU status.
Contents of the accumulator, index registers, processor status flags,
disassembly of the instruction register, and stack pointer are all displayed.
It also provides CPU status. Contents of the accumulator, index
registers, processor status flags, disassembly of the instruction
register, and stack pointer are all displayed.
The terminal is attached to a simulated MOS 6551 ACIA. It behaves very much
as described in the datasheet, with some exceptions:
- The simulated ACIA is permanently connected to the virtual terminal,
the Data Carrier Detect and Data Set Ready status bits always indicate
a connection is ready.
- The parity, stop-bits and bits-per-character settings are ignored. The
ACIA always sends and receives 8-bit characters, and parity errors
do not occur.
- The ACIA tries to honour the configured baud rate, but as a special case
the default "16x External Clock" rate is interpreted to mean "as fast as
possible" (The sample Enhanced BASIC ROM image is programmed for 9600 baud).
- The ACIA ignores the configured state of the Data Terminal Ready pin;
it is always ready to receive and transmit.
For more information on the MOS 6551 ACIA and its programming model,
see the official datasheet:
- [MOS 6551 ACIA](http://archive.6502.org/datasheets/mos_6551_acia.pdf)
![Font Selection](https://github.com/sethm/symon/raw/master/screenshots/font_selection.png)
@ -212,10 +227,9 @@ properly. Without a ROM in memory, the simulator will not be able to
reset, since the reset vector for the 6502 is located in the ROM
address space.
By default, any file named `rom.bin` that exists in the same directory
where Symon is launched will be loaded as a ROM image. ROM images can
also be swapped out at run-time with the "Load ROM Image..." in the
File menu.
ROM images can be loaded with the `-rom` argument when running
Symon from the command line. ROM images can also be swapped out at
run-time with the "Load ROM..." item in the File menu.
The "samples" directory contains a ROM image for the Symon
architecture named 'ehbasic.rom', containing Lee Davison's Enhanced

View File

@ -11,7 +11,6 @@ Sample Programs
When loaded at address $0300, this program will echo back to the console
anything typed.
Both hello.prg and echo_poll.prg were assembled with the Ophis assembler:
https://hkn.eecs.berkeley.edu/~mcmartin/ophis/
@ -19,23 +18,25 @@ Both hello.prg and echo_poll.prg were assembled with the Ophis assembler:
3. echo_irq.rom
This is another echo program, and behaves identically to echo_poll.prg,
except it is interrupt-driven.
except it is interrupt-driven. This ROM can be loaded either through the
"File->Load ROM..." menu in Symon, or by specifying the path to
"echo_irq.rom" with the "-jar" command line option when running Symon,
for example: `java -jar symon-1.3.2.jar -rom samples/echo_irq.rom`
4. ehbasic.rom
This is Lee Davison's Enhanced 6502 BASIC.
To use this ROM image, just copy the file 'ehbasic.rom' into the directory
where you run Symon. Rename the file to 'rom.bin'. When you start Symon,
the ROM file will be automatically loaded at address $d000.
The EhBASIC ROM can be loaded either through the "File -> Load ROM..."
menu in Symon, or by specifying the path to "ehbasic.rom" with
the "-jar" command line option when running Symon, for example:
`java -jar symon-1.3.2.jar -rom samples/ehbasic.rom`
Click the "Run" button and EhBASIC should automatically start running.
Type 'C' to do a cold start.
Then, type $C000 when prompted for the memory size.
NOTE: EhBASIC only wants upper-case input. This confused me at first!
Then, type '49152' (without the quotes) when prompted for the memory size.
More information can be found in the 'ehbasic' directory, and by visiting
the EhBASIC web page:

View File

@ -126,7 +126,7 @@ public class Cpu implements InstructionTable {
// Clear status register bits.
state.carryFlag = false;
state.zeroFlag = false;
state.irqDisableFlag = false;
state.irqDisableFlag = true;
state.decimalModeFlag = false;
state.breakFlag = false;
state.overflowFlag = false;

View File

@ -28,7 +28,7 @@ import com.loomcom.symon.exceptions.MemoryRangeException;
/**
* This is a simulation of the MOS 6551 ACIA, with limited
* functionality. Interrupts are not supported.
* functionality.
* <p/>
* Unlike a 16550 UART, the 6551 ACIA has only one-byte transmit and
* receive buffers. It is the programmer's responsibility to check the
@ -53,6 +53,14 @@ public class Acia6551 extends Acia {
public Acia6551(int address) throws MemoryRangeException {
super(address, ACIA_SIZE, "ACIA");
// Figure 6 in the 6551 ACIA data sheet says the "hardware reset"
// state of the Control Register is all zeros.
setControlRegister(0b00000000);
// Figure 7 of the 6551 ACIA data sheet says the "hardware reset"
// state of the Command Register is zeros, but Transmitter Control
// is set to "interrupt disabled, ready to send".
setCommandRegister(0b00000010);
}
@Override
@ -74,16 +82,16 @@ public class Acia6551 extends Acia {
@Override
public void write(int address, int data) throws MemoryAccessException {
switch (address) {
case 0:
case DATA_REG:
txWrite(data);
break;
case 1:
case STAT_REG:
reset();
break;
case 2:
case CMND_REG:
setCommandRegister(data);
break;
case 3:
case CTRL_REG:
setControlRegister(data);
break;
default:
@ -110,67 +118,60 @@ public class Acia6551 extends Acia {
controlRegister = data;
int rate = 0;
// If the value of the data is 0, this is a request to reset,
// otherwise it's a control update.
if (data == 0) {
reset();
} else {
// Mask the lower three bits to get the baud rate.
int baudSelector = data & 0x0f;
switch (baudSelector) {
case 0:
rate = 0;
break;
case 1:
rate = 50;
break;
case 2:
rate = 75;
break;
case 3:
rate = 110; // Real rate is actually 109.92
break;
case 4:
rate = 135; // Real rate is actually 134.58
break;
case 5:
rate = 150;
break;
case 6:
rate = 300;
break;
case 7:
rate = 600;
break;
case 8:
rate = 1200;
break;
case 9:
rate = 1800;
break;
case 10:
rate = 2400;
break;
case 11:
rate = 3600;
break;
case 12:
rate = 4800;
break;
case 13:
rate = 7200;
break;
case 14:
rate = 9600;
break;
case 15:
rate = 19200;
break;
}
setBaudRate(rate);
// Mask the lower four bits to get the baud rate.
int baudSelector = data & 0x0f;
switch (baudSelector) {
case 0:
rate = 0;
break;
case 1:
rate = 50;
break;
case 2:
rate = 75;
break;
case 3:
rate = 110; // Real rate is actually 109.92
break;
case 4:
rate = 135; // Real rate is actually 134.58
break;
case 5:
rate = 150;
break;
case 6:
rate = 300;
break;
case 7:
rate = 600;
break;
case 8:
rate = 1200;
break;
case 9:
rate = 1800;
break;
case 10:
rate = 2400;
break;
case 11:
rate = 3600;
break;
case 12:
rate = 4800;
break;
case 13:
rate = 7200;
break;
case 14:
rate = 9600;
break;
case 15:
rate = 19200;
break;
}
setBaudRate(rate);
}
@ -203,13 +204,16 @@ public class Acia6551 extends Acia {
private synchronized void reset() {
txChar = 0;
txEmpty = true;
rxChar = 0;
rxFull = false;
receiveIrqEnabled = false;
transmitIrqEnabled = false;
interrupt = false;
}
// Figure 6 in the 6551 ACIA data sheet says the "program reset"
// event does not modify the control register.
// Figure 7 in the 6551 ACIA data sheet says the "program reset"
// event keeps the "parity check" configuration in the command
// register, but resets the other bits to defaults.
setCommandRegister((commandRegister & 0xe0) | 0x02);
// Figure 8 in the 6551 ACIA data sheet says the "program reset"
// event clears the "overrun" flag but otherwise has no effect.
overrun = false;
}
}

View File

@ -254,4 +254,76 @@ public class AciaTest {
assertEquals(0x08, acia.read(0x0001, true));
}
@Test
public void statusRegisterInitializedAtHardwareReset() throws Exception {
Acia6551 acia = new Acia6551(0x0000);
assertEquals(0x10, acia.read(0x0001, false));
}
@Test
public void commandRegisterInitializedAtHardwareReset() throws Exception {
Acia6551 acia = new Acia6551(0x0000);
assertEquals(0x02, acia.read(0x0002, false));
}
@Test
public void controlRegisterInitializedAtHardwareReset() throws Exception {
Acia6551 acia = new Acia6551(0x0000);
assertEquals(0x00, acia.read(0x0003, false));
}
@Test
public void programResetClearsOverrunStatus() throws Exception {
Acia6551 acia = new Acia6551(0x0000);
Bus bus = new Bus(acia.ACIA_SIZE);
acia.setBus(bus);
// Change as many status bits as we can.
acia.write(0x0002, 0x00); // enable receive interrupt
acia.rxWrite('a');
acia.rxWrite('b'); // overrun, receive full, interrupt signalled
acia.write(0x0000, 'c'); // Transmitter Data Register not empty
// Check that all the bits we expected to be set actually are
assertEquals(0x8C, acia.read(0x0001, false));
// Do a "program reset". The value is ignored.
acia.write(0x0001, 0xFF);
// Check that only bit 2 was cleared.
assertEquals(0x88, acia.read(0x0001, false));
}
@Test
public void programResetKeepsParitySettings() throws Exception {
Acia6551 acia = new Acia6551(0x0000);
// Set all the command register bits
acia.write(0x0002, 0xFF);
// Do a "program reset". The value is ignored.
acia.write(0x0001, 0xFF);
// The top 3 bits should be kept as-is,
// the bottom 5 bits should be reset to defaults.
assertEquals(0xE2, acia.read(0x0002, false));
}
@Test
public void programResetLeavesControlRegisterUnchanged() throws Exception {
Acia6551 acia = new Acia6551(0x0000);
// Set all the control register bits
acia.write(0x0003, 0xFF);
// Do a "program reset". The value is ignored.
acia.write(0x0001, 0xFF);
// No bits should have changed.
assertEquals(0xFF, acia.read(0x0003, false));
}
}

View File

@ -29,7 +29,7 @@ public class CpuAbsoluteModeTest extends TestCase {
assertEquals(0, cpu.getYRegister());
assertEquals(0x200, cpu.getProgramCounter());
assertEquals(0xff, cpu.getStackPointer());
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
}
/*
@ -169,7 +169,7 @@ public class CpuAbsoluteModeTest extends TestCase {
assertEquals(0x04, bus.read(0x1fe, true));
// No flags should have changed.
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
}
/* BIT - Bit Test - $2c */
@ -362,7 +362,7 @@ public class CpuAbsoluteModeTest extends TestCase {
cpu.step();
assertEquals(0x3400, cpu.getProgramCounter());
// No change to status flags.
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
}
/* EOR - Exclusive OR - $4d */

View File

@ -29,7 +29,7 @@ public class CpuAbsoluteXModeTest extends TestCase {
assertEquals(0, cpu.getYRegister());
assertEquals(0x200, cpu.getProgramCounter());
assertEquals(0xff, cpu.getStackPointer());
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
}
/*

View File

@ -29,7 +29,7 @@ public class CpuAbsoluteYModeTest extends TestCase {
assertEquals(0, cpu.getYRegister());
assertEquals(0x200, cpu.getProgramCounter());
assertEquals(0xff, cpu.getStackPointer());
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
}
/*

View File

@ -30,7 +30,7 @@ public class CpuAccumulatorModeTest extends TestCase {
assertEquals(0, cpu.getYRegister());
assertEquals(0x200, cpu.getProgramCounter());
assertEquals(0xff, cpu.getStackPointer());
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
}
/*
@ -306,4 +306,4 @@ public class CpuAccumulatorModeTest extends TestCase {
assertFalse(cpu.getCarryFlag());
}
}
}

View File

@ -29,7 +29,7 @@ public class CpuImmediateModeTest extends TestCase {
assertEquals(0, cpu.getYRegister());
assertEquals(0x200, cpu.getProgramCounter());
assertEquals(0xff, cpu.getStackPointer());
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
}
/*

View File

@ -33,7 +33,7 @@ public class CpuImpliedModeTest {
assertEquals(0, cpu.getYRegister());
assertEquals(0x200, cpu.getProgramCounter());
assertEquals(0xff, cpu.getStackPointer());
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
}
/*
@ -76,6 +76,7 @@ public class CpuImpliedModeTest {
public void test_BRK() throws MemoryAccessException {
cpu.setCarryFlag();
cpu.setOverflowFlag();
cpu.clearIrqDisableFlag();
assertEquals(0x20 | Cpu.P_CARRY | Cpu.P_OVERFLOW,
cpu.getProcessorStatus());
assertEquals(0x00, cpu.stackPeek());
@ -343,7 +344,7 @@ public class CpuImpliedModeTest {
assertEquals(0, cpu.getYRegister());
assertEquals(0x201, cpu.getProgramCounter());
assertEquals(0xff, cpu.getStackPointer());
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
}
/* PHA - Push Accumulator - $48 */
@ -432,7 +433,7 @@ public class CpuImpliedModeTest {
cpu.step();
assertEquals(0x0f12, cpu.getProgramCounter());
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
}
/* SEC - Set Carry Flag - $38 */
@ -641,4 +642,4 @@ public class CpuImpliedModeTest {
assertFalse(cpu.getZeroFlag());
assertTrue(cpu.getNegativeFlag());
}
}
}

View File

@ -31,7 +31,7 @@ public class CpuIndexedIndirectModeTest {
assertEquals(0, cpu.getYRegister());
assertEquals(0x200, cpu.getProgramCounter());
assertEquals(0xff, cpu.getStackPointer());
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
}
@Test
@ -105,4 +105,4 @@ public class CpuIndexedIndirectModeTest {
assertEquals(0x11, cpu.getAccumulator());
assertEquals(0x31, bus.read(0xc51f, true));
}
}
}

View File

@ -31,7 +31,7 @@ public class CpuIndirectIndexedModeTest {
assertEquals(0, cpu.getYRegister());
assertEquals(0x200, cpu.getProgramCounter());
assertEquals(0xff, cpu.getStackPointer());
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
}
@Test
@ -81,4 +81,4 @@ public class CpuIndirectIndexedModeTest {
assertEquals(0xe3, bus.read(0xd828, true));
}
}
}

View File

@ -29,7 +29,7 @@ public class CpuIndirectModeTest extends TestCase {
assertEquals(0, cpu.getYRegister());
assertEquals(0x200, cpu.getProgramCounter());
assertEquals(0xff, cpu.getStackPointer());
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
}
/*
@ -48,7 +48,7 @@ public class CpuIndirectModeTest extends TestCase {
cpu.step();
assertEquals(0x5400, cpu.getProgramCounter());
// No change to status flags.
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
}
public void test_JMP_with_ROR_Bug() throws MemoryAccessException {
@ -60,7 +60,7 @@ public class CpuIndirectModeTest extends TestCase {
cpu.step();
assertEquals(0x2200, cpu.getProgramCounter());
// No change to status flags.
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
}
public void test_JMP_withIndirectBug() throws MemoryAccessException {
@ -72,7 +72,7 @@ public class CpuIndirectModeTest extends TestCase {
cpu.step();
assertEquals(0x2200, cpu.getProgramCounter());
// No change to status flags.
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
}
public void test_JMP_withOutIndirectBug() throws MemoryAccessException {
@ -84,7 +84,7 @@ public class CpuIndirectModeTest extends TestCase {
cpu.step();
assertEquals(0x5400, cpu.getProgramCounter());
// No change to status flags.
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
}
public void test_JMP_cmos() throws MemoryAccessException {
@ -96,7 +96,7 @@ public class CpuIndirectModeTest extends TestCase {
cpu.step();
assertEquals(0x5400, cpu.getProgramCounter());
// No change to status flags.
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
}
}
}

View File

@ -28,7 +28,7 @@ public class CpuIndirectXModeTest extends TestCase {
assertEquals(0, cpu.getYRegister());
assertEquals(0x200, cpu.getProgramCounter());
assertEquals(0xff, cpu.getStackPointer());
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
}
/*

View File

@ -29,7 +29,7 @@ public class CpuRelativeModeTest extends TestCase {
assertEquals(0, cpu.getYRegister());
assertEquals(0x200, cpu.getProgramCounter());
assertEquals(0xff, cpu.getStackPointer());
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
}
/*
@ -278,4 +278,4 @@ public class CpuRelativeModeTest extends TestCase {
assertEquals(0x202, cpu.getProgramCounter());
}
}
}

View File

@ -44,7 +44,7 @@ public class CpuTest extends TestCase {
assertEquals(0x0200, cpu.getProgramCounter());
assertFalse(cpu.getCarryFlag());
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getIrqDisableFlag());
assertTrue(cpu.getIrqDisableFlag());
assertFalse(cpu.getDecimalModeFlag());
assertFalse(cpu.getBreakFlag());
assertFalse(cpu.getOverflowFlag());
@ -205,14 +205,12 @@ public class CpuTest extends TestCase {
}
public void testGetProcessorStatus() {
// By default, no flags are set. Remember, bit 5
// By default, only "interrupt disable" is set. Remember, bit 5
// is always '1'.
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
cpu.setCarryFlag();
assertEquals(0x21, cpu.getProcessorStatus());
assertEquals(0x25, cpu.getProcessorStatus());
cpu.setZeroFlag();
assertEquals(0x23, cpu.getProcessorStatus());
cpu.setIrqDisableFlag();
assertEquals(0x27, cpu.getProcessorStatus());
cpu.setDecimalModeFlag();
assertEquals(0x2f, cpu.getProcessorStatus());
@ -237,13 +235,16 @@ public class CpuTest extends TestCase {
assertEquals(0xa0, cpu.getProcessorStatus());
cpu.clearNegativeFlag();
assertEquals(0x20, cpu.getProcessorStatus());
cpu.setIrqDisableFlag();
assertEquals(0x24, cpu.getProcessorStatus());
}
public void testSetProcessorStatus() {
// Default
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getIrqDisableFlag());
assertTrue(cpu.getIrqDisableFlag());
assertFalse(cpu.getDecimalModeFlag());
assertFalse(cpu.getBreakFlag());
assertFalse(cpu.getOverflowFlag());
@ -669,4 +670,4 @@ public class CpuTest extends TestCase {
cpu.step();
assertEquals(0x3E, cpu.getAccumulator());
}
}
}

View File

@ -29,7 +29,7 @@ public class CpuZeroPageModeTest extends TestCase {
assertEquals(0, cpu.getYRegister());
assertEquals(0x200, cpu.getProgramCounter());
assertEquals(0xff, cpu.getStackPointer());
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
}
/*

View File

@ -29,7 +29,7 @@ public class CpuZeroPageXModeTest extends TestCase {
assertEquals(0, cpu.getYRegister());
assertEquals(0x200, cpu.getProgramCounter());
assertEquals(0xff, cpu.getStackPointer());
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
}
/*

View File

@ -29,7 +29,7 @@ public class CpuZeroPageYModeTest extends TestCase {
assertEquals(0, cpu.getYRegister());
assertEquals(0x200, cpu.getProgramCounter());
assertEquals(0xff, cpu.getStackPointer());
assertEquals(0x20, cpu.getProcessorStatus());
assertEquals(0x24, cpu.getProcessorStatus());
}
/*