CPU bug fixes and Simulator enhancements.

Bug Fixes:

- Fixed several bugs in the CPU that caused processor status flags to
  be set incorrectly.  Instructions affected were: STA, STX, STY, CMP,
  CPX, CPY, BIT.

- Made some internal-use-only methods on the CPU class private.

- Fixed incorrect disassembly of (Indirect,X) and (Indirect),Y
  instructions. Although this didn't affect behavior, it certainly
  caused me some confusion in debugging.

- Added missing "BCS" instruction to instruction table.

Enhancements:

- Now includes a full version of Lee Davison's Enhanced 6502 BASIC
  bundled as source code and a ROM image. Get that REAL COMPUTER
  EXPERIENCE!(tm)

- If a file named "rom.bin" exists in the same directory where the
  simulator is executed, it will be loaded at addresses $d000-$ffff.

- Gave the CPU an idle loop to make simulated timing a little more
  realistic (but this is still an area needing major improvement)

- Changed the CPU's toString() method to give better debugging output.

- Added a small typeahead buffer to the Console.

- Better exception messaging.

Misc:

- Bumped version to 0.5, updated README.
This commit is contained in:
Seth Morabito committed 2012-10-21 20:05:05 -07:00
1 parent c1caf8c6b4
commit 795ccfde5d
25 files changed
+13622 -4508

No files matched your search

File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -412,7 +412,8 @@ public class CpuAbsoluteYModeTest extends TestCase {
bus.loadProgram(0x99, 0x10, 0xab); // STA $ab10,Y
cpu.step();
assertEquals(0x00, bus.read(0xab40));
assertTrue(cpu.getZeroFlag());
// STA should have NO effect on flags
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getNegativeFlag());
cpu.reset();
@@ -434,7 +435,7 @@ public class CpuAbsoluteYModeTest extends TestCase {
cpu.step();
assertEquals(0x80, bus.read(0xab40));
assertFalse(cpu.getZeroFlag());
assertTrue(cpu.getNegativeFlag());
assertFalse(cpu.getNegativeFlag());
}
/* LDX - Load X Register - $be */
@@ -523,7 +524,7 @@ public class CpuAbsoluteYModeTest extends TestCase {
cpu.step();
assertFalse(cpu.getCarryFlag()); // m < y
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getNegativeFlag()); // m - y > 0
assertTrue(cpu.getNegativeFlag()); // $80 - $ff = $81
}
/* SBC - Subtract with Carry - $f9 */
File diff suppressed because it is too large. Load diff
@@ -412,7 +412,7 @@ public class CpuIndirectXModeTest extends TestCase {
bus.loadProgram(0x9d, 0x10, 0xab); // STA $ab10,X
cpu.step();
assertEquals(0x00, bus.read(0xab40));
assertTrue(cpu.getZeroFlag());
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getNegativeFlag());
cpu.reset();
@@ -434,7 +434,7 @@ public class CpuIndirectXModeTest extends TestCase {
cpu.step();
assertEquals(0x80, bus.read(0xab40));
assertFalse(cpu.getZeroFlag());
assertTrue(cpu.getNegativeFlag());
assertFalse(cpu.getNegativeFlag());
}
/* LDA - Load Accumulator - $bd */
@@ -494,7 +494,7 @@ public class CpuIndirectXModeTest extends TestCase {
cpu.step();
assertFalse(cpu.getCarryFlag()); // m < y
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getNegativeFlag()); // m - y > 0
assertTrue(cpu.getNegativeFlag()); // m - y < 0
}
/* SBC - Subtract with Carry - $fd */
File diff suppressed because it is too large. Load diff
@@ -709,7 +709,8 @@ public class CpuZeroPageXModeTest extends TestCase {
bus.loadProgram(0x94, 0x10); // STY $10,X
cpu.step();
assertEquals(0x00, bus.read(0x40));
assertTrue(cpu.getZeroFlag());
// Should have no effect on flags.
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getNegativeFlag());
cpu.reset();
@@ -730,7 +731,7 @@ public class CpuZeroPageXModeTest extends TestCase {
cpu.step();
assertEquals(0x80, bus.read(0x40));
assertFalse(cpu.getZeroFlag());
assertTrue(cpu.getNegativeFlag());
assertFalse(cpu.getNegativeFlag());
}
/* STA - Store Accumulator - $95 */
@@ -742,7 +743,8 @@ public class CpuZeroPageXModeTest extends TestCase {
bus.loadProgram(0x95, 0x10); // STA $10,X
cpu.step();
assertEquals(0x00, bus.read(0x40));
assertTrue(cpu.getZeroFlag());
// Should have no effect on flags.
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getNegativeFlag());
cpu.reset();
@@ -763,7 +765,7 @@ public class CpuZeroPageXModeTest extends TestCase {
cpu.step();
assertEquals(0x80, bus.read(0x40));
assertFalse(cpu.getZeroFlag());
assertTrue(cpu.getNegativeFlag());
assertFalse(cpu.getNegativeFlag());
}
/* LDY - Load Y Register - $b4 */
@@ -852,7 +854,7 @@ public class CpuZeroPageXModeTest extends TestCase {
cpu.step();
assertFalse(cpu.getCarryFlag()); // m < y
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getNegativeFlag()); // m - y > 0
assertTrue(cpu.getNegativeFlag()); // m - y < 0
}
/* DEC - Decrement Memory Location - $d6 */
@@ -7,96 +7,97 @@ import junit.framework.TestCase;
public class CpuZeroPageYModeTest extends TestCase {
protected Cpu cpu;
protected Bus bus;
protected Memory mem;
protected Cpu cpu;
protected Bus bus;
protected Memory mem;
protected void setUp() throws Exception {
this.cpu = new Cpu();
this.bus = new Bus(0x0000, 0xffff);
this.mem = new Memory(0x0000, 0x10000);
bus.addCpu(cpu);
bus.addDevice(mem);
protected void setUp() throws Exception {
this.cpu = new Cpu();
this.bus = new Bus(0x0000, 0xffff);
this.mem = new Memory(0x0000, 0x10000);
bus.addCpu(cpu);
bus.addDevice(mem);
// Load the reset vector.
bus.write(0xfffc, Cpu.DEFAULT_BASE_ADDRESS & 0x00ff);
bus.write(0xfffd, (Cpu.DEFAULT_BASE_ADDRESS & 0xff00)>>>8);
// Load the reset vector.
bus.write(0xfffc, Cpu.DEFAULT_BASE_ADDRESS & 0x00ff);
bus.write(0xfffd, (Cpu.DEFAULT_BASE_ADDRESS & 0xff00) >>> 8);
cpu.reset();
// Assert initial state
assertEquals(0, cpu.getAccumulator());
assertEquals(0, cpu.getXRegister());
assertEquals(0, cpu.getYRegister());
assertEquals(0x200, cpu.getProgramCounter());
assertEquals(0xff, cpu.getStackPointer());
assertEquals(0x20, cpu.getProcessorStatus());
}
cpu.reset();
// Assert initial state
assertEquals(0, cpu.getAccumulator());
assertEquals(0, cpu.getXRegister());
assertEquals(0, cpu.getYRegister());
assertEquals(0x200, cpu.getProgramCounter());
assertEquals(0xff, cpu.getStackPointer());
assertEquals(0x20, cpu.getProcessorStatus());
}
/*
* The following opcodes are tested for correctness in this file:
*
* STX - $96
* LDX - $b6
*
*/
/*
* The following opcodes are tested for correctness in this file:
*
* STX - $96
* LDX - $b6
*
*/
/* STX - Store X Register - $96 */
/* STX - Store X Register - $96 */
public void test_STX() throws MemoryAccessException {
cpu.setYRegister(0x30);
cpu.setXRegister(0x00);
bus.loadProgram(0x96, 0x10); // STX $10,Y
cpu.step();
assertEquals(0x00, bus.read(0x40));
assertTrue(cpu.getZeroFlag());
assertFalse(cpu.getNegativeFlag());
public void test_STX() throws MemoryAccessException {
cpu.setYRegister(0x30);
cpu.setXRegister(0x00);
bus.loadProgram(0x96, 0x10); // STX $10,Y
cpu.step();
assertEquals(0x00, bus.read(0x40));
// Should have no effect on flags.
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getNegativeFlag());
cpu.reset();
cpu.setYRegister(0x30);
cpu.setXRegister(0x0f);
bus.loadProgram(0x96, 0x10); // STX $10,Y
cpu.step();
assertEquals(0x0f, bus.read(0x40));
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getNegativeFlag());
cpu.reset();
cpu.setYRegister(0x30);
cpu.setXRegister(0x0f);
bus.loadProgram(0x96, 0x10); // STX $10,Y
cpu.step();
assertEquals(0x0f, bus.read(0x40));
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getNegativeFlag());
cpu.reset();
cpu.setYRegister(0x30);
cpu.setXRegister(0x80);
bus.loadProgram(0x96, 0x10); // STX $10,Y
cpu.step();
assertEquals(0x80, bus.read(0x40));
assertFalse(cpu.getZeroFlag());
assertTrue(cpu.getNegativeFlag());
}
cpu.reset();
cpu.setYRegister(0x30);
cpu.setXRegister(0x80);
bus.loadProgram(0x96, 0x10); // STX $10,Y
cpu.step();
assertEquals(0x80, bus.read(0x40));
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getNegativeFlag());
}
/* LDX - Load X Register - $b6 */
/* LDX - Load X Register - $b6 */
public void test_LDX() throws MemoryAccessException {
bus.write(0x40, 0x00);
bus.write(0x41, 0x0f);
bus.write(0x42, 0x80);
public void test_LDX() throws MemoryAccessException {
bus.write(0x40, 0x00);
bus.write(0x41, 0x0f);
bus.write(0x42, 0x80);
bus.loadProgram(0xb6, 0x10,
0xb6, 0x11,
0xb6, 0x12);
bus.loadProgram(0xb6, 0x10,
0xb6, 0x11,
0xb6, 0x12);
cpu.setYRegister(0x30);
cpu.setYRegister(0x30);
cpu.step();
assertEquals(0x00, cpu.getXRegister());
assertTrue(cpu.getZeroFlag());
assertFalse(cpu.getNegativeFlag());
cpu.step();
assertEquals(0x00, cpu.getXRegister());
assertTrue(cpu.getZeroFlag());
assertFalse(cpu.getNegativeFlag());
cpu.step();
assertEquals(0x0f, cpu.getXRegister());
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getNegativeFlag());
cpu.step();
assertEquals(0x0f, cpu.getXRegister());
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getNegativeFlag());
cpu.step();
assertEquals(0x80, cpu.getXRegister());
assertFalse(cpu.getZeroFlag());
assertTrue(cpu.getNegativeFlag());
}
cpu.step();
assertEquals(0x80, cpu.getXRegister());
assertFalse(cpu.getZeroFlag());
assertTrue(cpu.getNegativeFlag());
}
}