Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f8f743f7d | ||
|
|
4ce8bc86de | ||
|
|
4644fe9b55 | ||
|
|
655bbb3ab0 | ||
|
|
e2d31fd39c | ||
|
|
087ba28b82 | ||
|
|
8edca5d595 | ||
|
|
105a09067f | ||
|
|
08efd81be3 | ||
|
|
0aeb97bb56 | ||
|
|
d466a21b3e | ||
|
|
31d1f7c5e1 | ||
|
|
247f2ba2fc | ||
|
|
922810b34b | ||
|
|
9d6791330d | ||
|
|
73c474d606 | ||
|
|
71905fdb19 | ||
|
|
cb918c9906 | ||
|
|
be72c2ff09 | ||
|
|
18ce120984 | ||
|
|
8ffb130300 | ||
|
|
441f7349a0 | ||
|
|
4f27e78940 | ||
|
|
11f61f50a9 | ||
|
|
59f8ff1bc4 | ||
|
|
a9c6d5964f | ||
|
|
faf5d22660 | ||
|
|
3c3aee30a7 | ||
|
|
92f8fe3dd9 | ||
|
|
356822df71 | ||
|
|
f2ced29979 | ||
|
|
2e33756d49 | ||
|
|
079d3dbeae | ||
|
|
96819f1bf7 | ||
|
|
9cdd718e8d | ||
|
|
5554acd29c |
No files matched your search
@@ -4,3 +4,4 @@ target
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
.idea
|
.idea
|
||||||
symon.iml
|
symon.iml
|
||||||
|
/dependency-reduced-pom.xml
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
encoding//src/main/java=UTF-8
|
||||||
|
encoding//src/main/resources=UTF-8
|
||||||
|
encoding//src/test/java=UTF-8
|
||||||
|
encoding/<project>=UTF-8
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.7
|
||||||
|
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.7
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
activeProfiles=
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
resolveWorkspaceProjects=true
|
||||||
|
version=1
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
SYMON - A 6502 System Simulator
|
SYMON - A 6502 System Simulator
|
||||||
===============================
|
===============================
|
||||||
|
|
||||||
**Version:** 1.2.1
|
**Version:** 1.3.2
|
||||||
|
|
||||||
**Last Updated:** 8 January, 2016
|
**Last Updated:** 08 March, 2021
|
||||||
|
|
||||||
See the file COPYING for license.
|
See the file COPYING for license.
|
||||||
|
|
||||||
![Symon Simulator in Action] (https://github.com/sethm/symon/raw/master/screenshots/full.jpg)
|

|
||||||
|
|
||||||
## 1.0 About
|
## 1.0 About
|
||||||
|
|
||||||
@@ -16,13 +16,13 @@ Technologies 6502 microprocessor and compatibles. Symon is implemented
|
|||||||
in Java. Its core goals are accuracy, ease of development, clear
|
in Java. Its core goals are accuracy, ease of development, clear
|
||||||
documentation, and extensive test suites for validating correctness.
|
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 or CMOS
|
||||||
16KB of ROM, a MOS 6551 or Motorola 6850 ACIA, a MOS 6522 VIA, and an
|
65C02, 32KB of RAM, 16KB of ROM, a MOS 6551 or Motorola 6850 ACIA, a
|
||||||
experimental 6545 CRTC.
|
MOS 6522 VIA, and an experimental 6545 CRTC.
|
||||||
|
|
||||||
Symon has extensive unit tests to verify correctness, and fully passes
|
Symon has extensive unit tests to verify correctness, and fully passes
|
||||||
Klaus Dormann's 6502 Functional Test Suite as of version 0.8.2
|
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)
|
(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).
|
for more information about this functional test suite).
|
||||||
|
|
||||||
Symon is under constant, active development. Feedback and patches
|
Symon is under constant, active development. Feedback and patches
|
||||||
@@ -66,7 +66,7 @@ memory.
|
|||||||
|
|
||||||
### 3.2 Serial Console and CPU Status
|
### 3.2 Serial Console and CPU Status
|
||||||
|
|
||||||
![Serial Console] (https://github.com/sethm/symon/raw/master/screenshots/console.png)
|

|
||||||
|
|
||||||
The main window of the simulator acts as the primary Input/Output
|
The main window of the simulator acts as the primary Input/Output
|
||||||
system through a virtual serial terminal. The terminal is attached to
|
system through a virtual serial terminal. The terminal is attached to
|
||||||
@@ -78,13 +78,13 @@ It also provides CPU status. Contents of the accumulator, index
|
|||||||
registers, processor status flags, disassembly of the instruction
|
registers, processor status flags, disassembly of the instruction
|
||||||
register, and stack pointer are all displayed.
|
register, and stack pointer are all displayed.
|
||||||
|
|
||||||
![Font Selection] (https://github.com/sethm/symon/raw/master/screenshots/font_selection.png)
|

|
||||||
|
|
||||||
The console supports font sizes from 10 to 20 points.
|
The console supports font sizes from 10 to 20 points.
|
||||||
|
|
||||||
### 3.3 ROM Loading
|
### 3.3 ROM Loading
|
||||||
|
|
||||||
![ROM Loading] (https://github.com/sethm/symon/raw/master/screenshots/load_rom.png)
|

|
||||||
|
|
||||||
Symon can load any appropriately sized ROM image. The Symon
|
Symon can load any appropriately sized ROM image. The Symon
|
||||||
architecture expects as 16KB (16384 byte) ROM image, while the
|
architecture expects as 16KB (16384 byte) ROM image, while the
|
||||||
@@ -95,32 +95,32 @@ address.
|
|||||||
|
|
||||||
### 3.4 Memory Window
|
### 3.4 Memory Window
|
||||||
|
|
||||||
![Memory Window] (https://github.com/sethm/symon/raw/master/screenshots/memory_window.png)
|

|
||||||
|
|
||||||
Memory contents can be viewed (and edited) one page at a time through the Memory Window.
|
Memory contents can be viewed (and edited) one page at a time through the Memory Window.
|
||||||
|
|
||||||
### 3.5 Trace Log
|
### 3.5 Trace Log
|
||||||
|
|
||||||
![Trace Log] (https://github.com/sethm/symon/raw/master/screenshots/trace_log.png)
|

|
||||||
|
|
||||||
The last 20,000 execution steps are disassembled and logged to the Trace Log
|
The last 20,000 execution steps are disassembled and logged to the Trace Log
|
||||||
Window.
|
Window.
|
||||||
|
|
||||||
### 3.6 Simulator Speeds
|
### 3.6 Simulator Speeds
|
||||||
|
|
||||||
![Speeds] (https://github.com/sethm/symon/raw/master/screenshots/simulator_menu.png)
|

|
||||||
|
|
||||||
Simulated speeds may be set from 1MHz to 8MHz.
|
Simulated speeds may be set from 1MHz to 8MHz.
|
||||||
|
|
||||||
### 3.7 Breakpoints
|
### 3.7 Breakpoints
|
||||||
|
|
||||||
![Breakpoints] (https://github.com/sethm/symon/raw/master/screenshots/breakpoints.png)
|

|
||||||
|
|
||||||
Breakpoints can be set and removed through the Breakpoints window.
|
Breakpoints can be set and removed through the Breakpoints window.
|
||||||
|
|
||||||
### 3.8 Experimental 6545 CRTC Video
|
### 3.8 Experimental 6545 CRTC Video
|
||||||
|
|
||||||
![Composite Video] (https://github.com/sethm/symon/raw/master/screenshots/video_window.png)
|

|
||||||
|
|
||||||
This feature is highly experimental. It's possible to open a video window
|
This feature is highly experimental. It's possible to open a video window
|
||||||
from the "View" menu. This window simulates the output of a MOS 6545 CRT
|
from the "View" menu. This window simulates the output of a MOS 6545 CRT
|
||||||
@@ -154,13 +154,13 @@ between the simulated 6545 and a real 6545:
|
|||||||
of 6545 programming tricks that were achieved by updating the
|
of 6545 programming tricks that were achieved by updating the
|
||||||
frame address during vertical and horizontal sync times are not
|
frame address during vertical and horizontal sync times are not
|
||||||
achievable. There is no way (for example) to change the Display Start
|
achievable. There is no way (for example) to change the Display Start
|
||||||
Address (R12 and R13) while a frame is being drawn.
|
Address (R12 and R13) while a frame is being drawn.
|
||||||
|
|
||||||
For more information on the 6545 CRTC and its programming model, please see the following resources
|
For more information on the 6545 CRTC and its programming model, please see the following resources
|
||||||
|
|
||||||
- [CRTC 6545/6845 Information (André Fachat)] (http://6502.org/users/andre/hwinfo/crtc/index.html)
|
- [CRTC 6545/6845 Information (André Fachat)](http://6502.org/users/andre/hwinfo/crtc/index.html)
|
||||||
- [CRTC Operation (André Fachat)] (http://www.6502.org/users/andre/hwinfo/crtc/crtc.html)
|
- [CRTC Operation (André Fachat)](http://www.6502.org/users/andre/hwinfo/crtc/crtc.html)
|
||||||
- [MOS 6545 Datasheet (PDF)] (http://www.6502.org/users/andre/hwinfo/crtc/crtc.html)
|
- [MOS 6545 Datasheet (PDF)](http://www.6502.org/users/andre/hwinfo/crtc/crtc.html)
|
||||||
|
|
||||||
|
|
||||||
#### 3.8.1 Example BASIC Program to test Video
|
#### 3.8.1 Example BASIC Program to test Video
|
||||||
@@ -193,6 +193,18 @@ Java 1.8 or greater, just type:
|
|||||||
When Symon is running, you should be presented with a simple graphical
|
When Symon is running, you should be presented with a simple graphical
|
||||||
interface.
|
interface.
|
||||||
|
|
||||||
|
#### 4.1.1 Command Line Options
|
||||||
|
|
||||||
|
Two command line options may be passed to the JAR file on startup,
|
||||||
|
to specify machine type and CPU type. The options are:
|
||||||
|
|
||||||
|
- `-cpu 6502`: Use the NMOS 6502 CPU type by default.
|
||||||
|
- `-cpu 65c02`: Use the CMOS 65C02 CPU type by default.
|
||||||
|
- `-machine symon`: Use the **Symon** machine type by default.
|
||||||
|
- `-machine multicomp`: Use the **Multicomp** machine type by default.
|
||||||
|
- `-machine simple`: Use the **Simple** machine type by default.
|
||||||
|
- `-rom <file>`: Use the specified file as the ROM image.
|
||||||
|
|
||||||
### 4.2 ROM images
|
### 4.2 ROM images
|
||||||
|
|
||||||
The simulator requires a ROM image loaded into memory to work
|
The simulator requires a ROM image loaded into memory to work
|
||||||
@@ -235,16 +247,22 @@ running.
|
|||||||
|
|
||||||
## 5.0 Revision History
|
## 5.0 Revision History
|
||||||
|
|
||||||
|
- **1.3.1:** 12 October, 2019 - Add support for new command line
|
||||||
|
option `-cpu <type>` to specify one of `6502` or `65c02` on startup,
|
||||||
|
and new option `-rom <file>` to specify a ROM file to load.
|
||||||
|
|
||||||
|
- **1.3.0:** 24 February, 2018 - Adds support for 65C02 opcodes.
|
||||||
|
|
||||||
- **1.2.1:** 8 January, 2016 - Remove dependency on Java 8. Now
|
- **1.2.1:** 8 January, 2016 - Remove dependency on Java 8. Now
|
||||||
supports compiling and running under Java 1.7.
|
supports compiling and running under Java 1.7.
|
||||||
|
|
||||||
- **1.2.0:** 3 January, 2016 - Add symbolic disassembly to breakpoints
|
- **1.2.0:** 3 January, 2016 - Add symbolic disassembly to breakpoints
|
||||||
window.
|
window.
|
||||||
|
|
||||||
- **1.1.1:** 2 January, 2016 - Minor enhancement: Allows breakpoints
|
- **1.1.1:** 2 January, 2016 - Minor enhancement: Allows breakpoints
|
||||||
to be added with the Enter key.
|
to be added with the Enter key.
|
||||||
|
|
||||||
- **1.1.0:** 31 December, 2015 - Fixed delay loop to better
|
- **1.1.0:** 31 December, 2015 - Fixed delay loop to better
|
||||||
simulate various clock speeds. Added ability to select clock
|
simulate various clock speeds. Added ability to select clock
|
||||||
speed at runtime. Status display now shows the next instruction
|
speed at runtime. Status display now shows the next instruction
|
||||||
to be executed, instead of the last instruction executed.
|
to be executed, instead of the last instruction executed.
|
||||||
@@ -338,10 +356,10 @@ Additional components used in this project are copyright their respective owners
|
|||||||
|
|
||||||
This project would not have been possible without the following resources:
|
This project would not have been possible without the following resources:
|
||||||
|
|
||||||
- [Andrew Jacobs' 6502 Pages] (http://www.obelisk.demon.co.uk/6502/), for
|
- [Andrew Jacobs' 6502 Pages](http://obelisk.me.uk/6502/), for
|
||||||
wonderfully detailed information about the 6502
|
wonderfully detailed information about the 6502
|
||||||
|
|
||||||
- [Neil Parker's "The 6502/65C02/65C816 Instruction Set Decoded"] (http://www.llx.com/~nparker/a2/opcodes.html),
|
- [Neil Parker's "The 6502/65C02/65C816 Instruction Set Decoded"](http://www.llx.com/~nparker/a2/opcodes.html),
|
||||||
for information about how instructions are coded
|
for information about how instructions are coded
|
||||||
|
|
||||||
## 9.0 Licensing
|
## 9.0 Licensing
|
||||||
|
|||||||
@@ -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>1.3.0-SNAPSHOT</version>
|
<version>1.3.2</version>
|
||||||
<name>symon</name>
|
<name>symon</name>
|
||||||
<url>http://www.loomcom.com/symon</url>
|
<url>http://www.loomcom.com/symon</url>
|
||||||
<properties>
|
<properties>
|
||||||
@@ -15,72 +15,60 @@
|
|||||||
UTF-8
|
UTF-8
|
||||||
</project.reporting.outputEncoding>
|
</project.reporting.outputEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
<repositories>
|
|
||||||
<repository>
|
|
||||||
<id>jline</id>
|
|
||||||
<name>JLine Project Repository</name>
|
|
||||||
<url>http://jline.sourceforge.net/m2repo</url>
|
|
||||||
</repository>
|
|
||||||
<!-- Loomcom's Maven2 repository for JTerminal -->
|
|
||||||
<repository>
|
|
||||||
<releases>
|
|
||||||
<enabled>true</enabled>
|
|
||||||
<updatePolicy>always</updatePolicy>
|
|
||||||
<checksumPolicy>fail</checksumPolicy>
|
|
||||||
</releases>
|
|
||||||
<id>com.loomcom</id>
|
|
||||||
<name>Loom Communications Maven2 Repository</name>
|
|
||||||
<url>http://www.loomcom.com/maven2</url>
|
|
||||||
<layout>default</layout>
|
|
||||||
</repository>
|
|
||||||
</repositories>
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ch.qos.logback</groupId>
|
<groupId>ch.qos.logback</groupId>
|
||||||
<artifactId>logback-classic</artifactId>
|
<artifactId>logback-classic</artifactId>
|
||||||
<version>1.1.3</version>
|
<version>1.2.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<version>4.11</version>
|
<version>4.13.2</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.grahamedgecombe.jterminal</groupId>
|
|
||||||
<artifactId>jterminal</artifactId>
|
|
||||||
<version>1.0.2.3-loomcom</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mockito</groupId>
|
<groupId>org.mockito</groupId>
|
||||||
<artifactId>mockito-all</artifactId>
|
<artifactId>mockito-core</artifactId>
|
||||||
<version>1.9.5</version>
|
<version>3.12.4</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-cli</groupId>
|
||||||
|
<artifactId>commons-cli</artifactId>
|
||||||
|
<version>1.4</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
<version>2.6</version>
|
<version>3.2.0</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<descriptorRefs>
|
<transformers>
|
||||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||||
</descriptorRefs>
|
|
||||||
<appendAssemblyId>false</appendAssemblyId>
|
|
||||||
<archive>
|
|
||||||
<manifest>
|
|
||||||
<mainClass>com.loomcom.symon.Main</mainClass>
|
<mainClass>com.loomcom.symon.Main</mainClass>
|
||||||
</manifest>
|
</transformer>
|
||||||
</archive>
|
</transformers>
|
||||||
|
<filters>
|
||||||
|
<filter>
|
||||||
|
<artifact>*:*</artifact>
|
||||||
|
<excludes>
|
||||||
|
<exclude>META-INF/*.SF</exclude>
|
||||||
|
<exclude>META-INF/*.DSA</exclude>
|
||||||
|
<exclude>META-INF/*.RSA</exclude>
|
||||||
|
</excludes>
|
||||||
|
</filter>
|
||||||
|
</filters>
|
||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
|
<id>make-assembly</id>
|
||||||
<phase>package</phase>
|
<phase>package</phase>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>single</goal>
|
<goal>shade</goal>
|
||||||
</goals>
|
</goals>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
@@ -88,7 +76,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.1</version>
|
<version>3.7.0</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<compilerArgument>-Xlint:unchecked</compilerArgument>
|
<compilerArgument>-Xlint:unchecked</compilerArgument>
|
||||||
<source>1.7</source>
|
<source>1.7</source>
|
||||||
@@ -100,7 +88,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
<version>2.6</version>
|
<version>3.2.0</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<archive>
|
<archive>
|
||||||
<manifest>
|
<manifest>
|
||||||
|
|||||||
@@ -168,12 +168,12 @@ public class Bus {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int read(int address) throws MemoryAccessException {
|
public int read(int address, boolean cpuAccess) throws MemoryAccessException {
|
||||||
Device d = deviceAddressArray[address - this.startAddress];
|
Device d = deviceAddressArray[address - this.startAddress];
|
||||||
if (d != null) {
|
if (d != null) {
|
||||||
MemoryRange range = d.getMemoryRange();
|
MemoryRange range = d.getMemoryRange();
|
||||||
int devAddr = address - range.startAddress();
|
int devAddr = address - range.startAddress();
|
||||||
return d.read(devAddr) & 0xff;
|
return d.read(devAddr, cpuAccess) & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new MemoryAccessException("Bus read failed. No device at address " + String.format("$%04X", address));
|
throw new MemoryAccessException("Bus read failed. No device at address " + String.format("$%04X", address));
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -46,20 +46,17 @@ public interface InstructionTable {
|
|||||||
*
|
*
|
||||||
* NB: Does NOT implement "unimplemented" NMOS instructions.
|
* NB: Does NOT implement "unimplemented" NMOS instructions.
|
||||||
*/
|
*/
|
||||||
NMOS_WITH_INDIRECT_JMP_BUG,
|
NMOS_6502,
|
||||||
|
|
||||||
/**
|
|
||||||
* Emulate an NMOS 6502 without the indirect JMP bug. This type of 6502
|
|
||||||
* does not actually exist in the wild.
|
|
||||||
*
|
|
||||||
* NB: Does NOT implement "unimplemented" NMOS instructions.
|
|
||||||
*/
|
|
||||||
NMOS_WITHOUT_INDIRECT_JMP_BUG,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emulate a CMOS 65C02, with all CMOS instructions and addressing modes.
|
* Emulate a CMOS 65C02, with all CMOS instructions and addressing modes.
|
||||||
*/
|
*/
|
||||||
CMOS
|
CMOS_6502,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emulate a CMOS 65C816.
|
||||||
|
*/
|
||||||
|
CMOS_65816
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,7 +68,11 @@ public interface InstructionTable {
|
|||||||
return "Accumulator";
|
return "Accumulator";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
AIX {
|
||||||
|
public String toString() {
|
||||||
|
return "Absolute, X-Indexed Indirect";
|
||||||
|
}
|
||||||
|
},
|
||||||
ABS {
|
ABS {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Absolute";
|
return "Absolute";
|
||||||
@@ -128,19 +129,31 @@ public interface InstructionTable {
|
|||||||
|
|
||||||
ZPG {
|
ZPG {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Zeropage";
|
return "Zero Page";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
ZPR {
|
||||||
|
public String toString() {
|
||||||
|
return "Zero Page, Relative";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
ZPX {
|
ZPX {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Zeropage, X-indexed";
|
return "Zero Page, X-indexed";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
ZPY {
|
ZPY {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Zeropage, Y-indexed";
|
return "Zero Page, Y-indexed";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
ZPI {
|
||||||
|
public String toString() {
|
||||||
|
return "Zero Page Indirect";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -154,156 +167,185 @@ public interface InstructionTable {
|
|||||||
// 6502 opcodes. No 65C02 opcodes implemented.
|
// 6502 opcodes. No 65C02 opcodes implemented.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instruction opcode names.
|
* Instruction opcode names. This lists all opcodes for
|
||||||
|
* NMOS 6502, CMOS 65C02, and CMOS 65C816
|
||||||
*/
|
*/
|
||||||
String[] opcodeNames = {
|
String[] opcodeNames = {
|
||||||
"BRK", "ORA", null, null, null, "ORA", "ASL", null,
|
"BRK", "ORA", "NOP", "NOP", "TSB", "ORA", "ASL", "RMB0", // 0x00-0x07
|
||||||
"PHP", "ORA", "ASL", null, null, "ORA", "ASL", null,
|
"PHP", "ORA", "ASL", "NOP", "TSB", "ORA", "ASL", "BBR0", // 0x08-0x0f
|
||||||
"BPL", "ORA", null, null, null, "ORA", "ASL", null,
|
"BPL", "ORA", "ORA", "NOP", "TRB", "ORA", "ASL", "RMB1", // 0x10-0x17
|
||||||
"CLC", "ORA", null, null, null, "ORA", "ASL", null,
|
"CLC", "ORA", "INC", "NOP", "TRB", "ORA", "ASL", "BBR1", // 0x18-0x1f
|
||||||
"JSR", "AND", null, null, "BIT", "AND", "ROL", null,
|
"JSR", "AND", "NOP", "NOP", "BIT", "AND", "ROL", "RMB2", // 0x20-0x27
|
||||||
"PLP", "AND", "ROL", null, "BIT", "AND", "ROL", null,
|
"PLP", "AND", "ROL", "NOP", "BIT", "AND", "ROL", "BBR2", // 0x28-0x2f
|
||||||
"BMI", "AND", null, null, null, "AND", "ROL", null,
|
"BMI", "AND", "AND", "NOP", "BIT", "AND", "ROL", "RMB3", // 0x30-0x37
|
||||||
"SEC", "AND", null, null, null, "AND", "ROL", null,
|
"SEC", "AND", "DEC", "NOP", "BIT", "AND", "ROL", "BBR3", // 0x38-0x3f
|
||||||
"RTI", "EOR", null, null, null, "EOR", "LSR", null,
|
"RTI", "EOR", "NOP", "NOP", "NOP", "EOR", "LSR", "RMB4", // 0x40-0x47
|
||||||
"PHA", "EOR", "LSR", null, "JMP", "EOR", "LSR", null,
|
"PHA", "EOR", "LSR", "NOP", "JMP", "EOR", "LSR", "BBR4", // 0x48-0x4f
|
||||||
"BVC", "EOR", null, null, null, "EOR", "LSR", null,
|
"BVC", "EOR", "EOR", "NOP", "NOP", "EOR", "LSR", "RMB5", // 0x50-0x57
|
||||||
"CLI", "EOR", null, null, null, "EOR", "LSR", null,
|
"CLI", "EOR", "PHY", "NOP", "NOP", "EOR", "LSR", "BBR5", // 0x58-0x5f
|
||||||
"RTS", "ADC", null, null, null, "ADC", "ROR", null,
|
"RTS", "ADC", "NOP", "NOP", "STZ", "ADC", "ROR", "RMB6", // 0x60-0x67
|
||||||
"PLA", "ADC", "ROR", null, "JMP", "ADC", "ROR", null,
|
"PLA", "ADC", "ROR", "NOP", "JMP", "ADC", "ROR", "BBR6", // 0x68-0x6f
|
||||||
"BVS", "ADC", null, null, null, "ADC", "ROR", null,
|
"BVS", "ADC", "ADC", "NOP", "STZ", "ADC", "ROR", "RMB7", // 0x70-0x77
|
||||||
"SEI", "ADC", null, null, null, "ADC", "ROR", null,
|
"SEI", "ADC", "PLY", "NOP", "JMP", "ADC", "ROR", "BBR7", // 0x78-0x7f
|
||||||
"BCS", "STA", null, null, "STY", "STA", "STX", null,
|
"BRA", "STA", "NOP", "NOP", "STY", "STA", "STX", "SMB0", // 0x80-0x87
|
||||||
"DEY", null, "TXA", null, "STY", "STA", "STX", null,
|
"DEY", "BIT", "TXA", "NOP", "STY", "STA", "STX", "BBS0", // 0x88-0x8f
|
||||||
"BCC", "STA", null, null, "STY", "STA", "STX", null,
|
"BCC", "STA", "STA", "NOP", "STY", "STA", "STX", "SMB1", // 0x90-0x97
|
||||||
"TYA", "STA", "TXS", null, null, "STA", null, null,
|
"TYA", "STA", "TXS", "NOP", "STZ", "STA", "STZ", "BBS1", // 0x98-0x9f
|
||||||
"LDY", "LDA", "LDX", null, "LDY", "LDA", "LDX", null,
|
"LDY", "LDA", "LDX", "NOP", "LDY", "LDA", "LDX", "SMB2", // 0xa0-0xa7
|
||||||
"TAY", "LDA", "TAX", null, "LDY", "LDA", "LDX", null,
|
"TAY", "LDA", "TAX", "NOP", "LDY", "LDA", "LDX", "BBS2", // 0xa8-0xaf
|
||||||
"BCS", "LDA", null, null, "LDY", "LDA", "LDX", null,
|
"BCS", "LDA", "LDA", "NOP", "LDY", "LDA", "LDX", "SMB3", // 0xb0-0xb7
|
||||||
"CLV", "LDA", "TSX", null, "LDY", "LDA", "LDX", null,
|
"CLV", "LDA", "TSX", "NOP", "LDY", "LDA", "LDX", "BBS3", // 0xb8-0xbf
|
||||||
"CPY", "CMP", null, null, "CPY", "CMP", "DEC", null,
|
"CPY", "CMP", "NOP", "NOP", "CPY", "CMP", "DEC", "SMB4", // 0xc0-0xc7
|
||||||
"INY", "CMP", "DEX", null, "CPY", "CMP", "DEC", null,
|
"INY", "CMP", "DEX", "NOP", "CPY", "CMP", "DEC", "BBS4", // 0xc8-0xcf
|
||||||
"BNE", "CMP", null, null, null, "CMP", "DEC", null,
|
"BNE", "CMP", "CMP", "NOP", "NOP", "CMP", "DEC", "SMB5", // 0xd0-0xd7
|
||||||
"CLD", "CMP", null, null, null, "CMP", "DEC", null,
|
"CLD", "CMP", "PHX", "NOP", "NOP", "CMP", "DEC", "BBS5", // 0xd8-0xdf
|
||||||
"CPX", "SBC", null, null, "CPX", "SBC", "INC", null,
|
"CPX", "SBC", "NOP", "NOP", "CPX", "SBC", "INC", "SMB6", // 0xe0-0xe7
|
||||||
"INX", "SBC", "NOP", null, "CPX", "SBC", "INC", null,
|
"INX", "SBC", "NOP", "NOP", "CPX", "SBC", "INC", "BBS6", // 0xe8-0xef
|
||||||
"BEQ", "SBC", null, null, null, "SBC", "INC", null,
|
"BEQ", "SBC", "SBC", "NOP", "NOP", "SBC", "INC", "SMB7", // 0xf0-0xf7
|
||||||
"SED", "SBC", null, null, null, "SBC", "INC", null
|
"SED", "SBC", "PLX", "NOP", "NOP", "SBC", "INC", "BBS7" // 0xf8-0xff
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instruction addressing modes.
|
* Instruction addressing modes. This table includes sizes
|
||||||
|
* for all instructions for NMOS 6502, CMOS 65C02,
|
||||||
|
* and CMOS 65C816
|
||||||
*/
|
*/
|
||||||
Mode[] instructionModes = {
|
Mode[] instructionModes = {
|
||||||
Mode.IMP, Mode.XIN, Mode.NUL, Mode.NUL, // 0x00-0x03
|
Mode.IMP, Mode.XIN, Mode.NUL, Mode.NUL, // 0x00-0x03
|
||||||
Mode.NUL, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0x04-0x07
|
Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.ZPG, // 0x04-0x07
|
||||||
Mode.IMP, Mode.IMM, Mode.ACC, Mode.NUL, // 0x08-0x0b
|
Mode.IMP, Mode.IMM, Mode.ACC, Mode.NUL, // 0x08-0x0b
|
||||||
Mode.NUL, Mode.ABS, Mode.ABS, Mode.NUL, // 0x0c-0x0f
|
Mode.ABS, Mode.ABS, Mode.ABS, Mode.ZPR, // 0x0c-0x0f
|
||||||
Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0x10-0x13
|
Mode.REL, Mode.INY, Mode.ZPI, Mode.NUL, // 0x10-0x13
|
||||||
Mode.NUL, Mode.ZPX, Mode.ZPX, Mode.NUL, // 0x14-0x17
|
Mode.ZPG, Mode.ZPX, Mode.ZPX, Mode.ZPG, // 0x14-0x17
|
||||||
Mode.IMP, Mode.ABY, Mode.NUL, Mode.NUL, // 0x18-0x1b
|
Mode.IMP, Mode.ABY, Mode.IMP, Mode.NUL, // 0x18-0x1b
|
||||||
Mode.NUL, Mode.ABX, Mode.ABX, Mode.NUL, // 0x1c-0x1f
|
Mode.ABS, Mode.ABX, Mode.ABX, Mode.ZPR, // 0x1c-0x1f
|
||||||
Mode.ABS, Mode.XIN, Mode.NUL, Mode.NUL, // 0x20-0x23
|
Mode.ABS, Mode.XIN, Mode.NUL, Mode.NUL, // 0x20-0x23
|
||||||
Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0x24-0x27
|
Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.ZPG, // 0x24-0x27
|
||||||
Mode.IMP, Mode.IMM, Mode.ACC, Mode.NUL, // 0x28-0x2b
|
Mode.IMP, Mode.IMM, Mode.ACC, Mode.NUL, // 0x28-0x2b
|
||||||
Mode.ABS, Mode.ABS, Mode.ABS, Mode.NUL, // 0x2c-0x2f
|
Mode.ABS, Mode.ABS, Mode.ABS, Mode.ZPR, // 0x2c-0x2f
|
||||||
Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0x30-0x33
|
Mode.REL, Mode.INY, Mode.ZPI, Mode.NUL, // 0x30-0x33
|
||||||
Mode.NUL, Mode.ZPX, Mode.ZPX, Mode.NUL, // 0x34-0x37
|
Mode.ZPX, Mode.ZPX, Mode.ZPX, Mode.ZPG, // 0x34-0x37
|
||||||
Mode.IMP, Mode.ABY, Mode.NUL, Mode.NUL, // 0x38-0x3b
|
Mode.IMP, Mode.ABY, Mode.IMP, Mode.NUL, // 0x38-0x3b
|
||||||
Mode.NUL, Mode.ABX, Mode.ABX, Mode.NUL, // 0x3c-0x3f
|
Mode.NUL, Mode.ABX, Mode.ABX, Mode.ZPR, // 0x3c-0x3f
|
||||||
Mode.IMP, Mode.XIN, Mode.NUL, Mode.NUL, // 0x40-0x43
|
Mode.IMP, Mode.XIN, Mode.NUL, Mode.NUL, // 0x40-0x43
|
||||||
Mode.NUL, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0x44-0x47
|
Mode.NUL, Mode.ZPG, Mode.ZPG, Mode.ZPG, // 0x44-0x47
|
||||||
Mode.IMP, Mode.IMM, Mode.ACC, Mode.NUL, // 0x48-0x4b
|
Mode.IMP, Mode.IMM, Mode.ACC, Mode.NUL, // 0x48-0x4b
|
||||||
Mode.ABS, Mode.ABS, Mode.ABS, Mode.NUL, // 0x4c-0x4f
|
Mode.ABS, Mode.ABS, Mode.ABS, Mode.ZPR, // 0x4c-0x4f
|
||||||
Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0x50-0x53
|
Mode.REL, Mode.INY, Mode.ZPI, Mode.NUL, // 0x50-0x53
|
||||||
Mode.NUL, Mode.ZPX, Mode.ZPX, Mode.NUL, // 0x54-0x57
|
Mode.NUL, Mode.ZPX, Mode.ZPX, Mode.ZPG, // 0x54-0x57
|
||||||
Mode.IMP, Mode.ABY, Mode.NUL, Mode.NUL, // 0x58-0x5b
|
Mode.IMP, Mode.ABY, Mode.IMP, Mode.NUL, // 0x58-0x5b
|
||||||
Mode.NUL, Mode.ABX, Mode.ABX, Mode.NUL, // 0x5c-0x5f
|
Mode.NUL, Mode.ABX, Mode.ABX, Mode.ZPR, // 0x5c-0x5f
|
||||||
Mode.IMP, Mode.XIN, Mode.NUL, Mode.NUL, // 0x60-0x63
|
Mode.IMP, Mode.XIN, Mode.NUL, Mode.NUL, // 0x60-0x63
|
||||||
Mode.NUL, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0x64-0x67
|
Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.ZPG, // 0x64-0x67
|
||||||
Mode.IMP, Mode.IMM, Mode.ACC, Mode.NUL, // 0x68-0x6b
|
Mode.IMP, Mode.IMM, Mode.ACC, Mode.NUL, // 0x68-0x6b
|
||||||
Mode.IND, Mode.ABS, Mode.ABS, Mode.NUL, // 0x6c-0x6f
|
Mode.IND, Mode.ABS, Mode.ABS, Mode.ZPR, // 0x6c-0x6f
|
||||||
Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0x70-0x73
|
Mode.REL, Mode.INY, Mode.ZPI, Mode.NUL, // 0x70-0x73
|
||||||
Mode.NUL, Mode.ZPX, Mode.ZPX, Mode.NUL, // 0x74-0x77
|
Mode.ZPX, Mode.ZPX, Mode.ZPX, Mode.ZPG, // 0x74-0x77
|
||||||
Mode.IMP, Mode.ABY, Mode.NUL, Mode.NUL, // 0x78-0x7b
|
Mode.IMP, Mode.ABY, Mode.IMP, Mode.NUL, // 0x78-0x7b
|
||||||
Mode.NUL, Mode.ABX, Mode.ABX, Mode.NUL, // 0x7c-0x7f
|
Mode.AIX, Mode.ABX, Mode.ABX, Mode.ZPR, // 0x7c-0x7f
|
||||||
Mode.REL, Mode.XIN, Mode.NUL, Mode.NUL, // 0x80-0x83
|
Mode.REL, Mode.XIN, Mode.NUL, Mode.NUL, // 0x80-0x83
|
||||||
Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0x84-0x87
|
Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.ZPG, // 0x84-0x87
|
||||||
Mode.IMP, Mode.NUL, Mode.IMP, Mode.NUL, // 0x88-0x8b
|
Mode.IMP, Mode.IMM, Mode.IMP, Mode.NUL, // 0x88-0x8b
|
||||||
Mode.ABS, Mode.ABS, Mode.ABS, Mode.NUL, // 0x8c-0x8f
|
Mode.ABS, Mode.ABS, Mode.ABS, Mode.ZPR, // 0x8c-0x8f
|
||||||
Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0x90-0x93
|
Mode.REL, Mode.INY, Mode.ZPI, Mode.NUL, // 0x90-0x93
|
||||||
Mode.ZPX, Mode.ZPX, Mode.ZPY, Mode.NUL, // 0x94-0x97
|
Mode.ZPX, Mode.ZPX, Mode.ZPY, Mode.ZPG, // 0x94-0x97
|
||||||
Mode.IMP, Mode.ABY, Mode.IMP, Mode.NUL, // 0x98-0x9b
|
Mode.IMP, Mode.ABY, Mode.IMP, Mode.NUL, // 0x98-0x9b
|
||||||
Mode.NUL, Mode.ABX, Mode.NUL, Mode.NUL, // 0x9c-0x9f
|
Mode.ABS, Mode.ABX, Mode.ABX, Mode.ZPR, // 0x9c-0x9f
|
||||||
Mode.IMM, Mode.XIN, Mode.IMM, Mode.NUL, // 0xa0-0xa3
|
Mode.IMM, Mode.XIN, Mode.IMM, Mode.NUL, // 0xa0-0xa3
|
||||||
Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0xa4-0xa7
|
Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.ZPG, // 0xa4-0xa7
|
||||||
Mode.IMP, Mode.IMM, Mode.IMP, Mode.NUL, // 0xa8-0xab
|
Mode.IMP, Mode.IMM, Mode.IMP, Mode.NUL, // 0xa8-0xab
|
||||||
Mode.ABS, Mode.ABS, Mode.ABS, Mode.NUL, // 0xac-0xaf
|
Mode.ABS, Mode.ABS, Mode.ABS, Mode.ZPR, // 0xac-0xaf
|
||||||
Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0xb0-0xb3
|
Mode.REL, Mode.INY, Mode.ZPI, Mode.NUL, // 0xb0-0xb3
|
||||||
Mode.ZPX, Mode.ZPX, Mode.ZPY, Mode.NUL, // 0xb4-0xb7
|
Mode.ZPX, Mode.ZPX, Mode.ZPY, Mode.ZPG, // 0xb4-0xb7
|
||||||
Mode.IMP, Mode.ABY, Mode.IMP, Mode.NUL, // 0xb8-0xbb
|
Mode.IMP, Mode.ABY, Mode.IMP, Mode.NUL, // 0xb8-0xbb
|
||||||
Mode.ABX, Mode.ABX, Mode.ABY, Mode.NUL, // 0xbc-0xbf
|
Mode.ABX, Mode.ABX, Mode.ABY, Mode.ZPR, // 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.ZPG, // 0xc4-0xc7
|
||||||
Mode.IMP, Mode.IMM, Mode.IMP, Mode.NUL, // 0xc8-0xcb
|
Mode.IMP, Mode.IMM, Mode.IMP, Mode.NUL, // 0xc8-0xcb
|
||||||
Mode.ABS, Mode.ABS, Mode.ABS, Mode.NUL, // 0xcc-0xcf
|
Mode.ABS, Mode.ABS, Mode.ABS, Mode.ZPR, // 0xcc-0xcf
|
||||||
Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0xd0-0xd3
|
Mode.REL, Mode.INY, Mode.ZPI, Mode.NUL, // 0xd0-0xd3
|
||||||
Mode.NUL, Mode.ZPX, Mode.ZPX, Mode.NUL, // 0xd4-0xd7
|
Mode.NUL, Mode.ZPX, Mode.ZPX, Mode.ZPG, // 0xd4-0xd7
|
||||||
Mode.IMP, Mode.ABY, Mode.NUL, Mode.NUL, // 0xd8-0xdb
|
Mode.IMP, Mode.ABY, Mode.IMP, Mode.NUL, // 0xd8-0xdb
|
||||||
Mode.NUL, Mode.ABX, Mode.ABX, Mode.NUL, // 0xdc-0xdf
|
Mode.NUL, Mode.ABX, Mode.ABX, Mode.ZPR, // 0xdc-0xdf
|
||||||
Mode.IMM, Mode.XIN, Mode.NUL, Mode.NUL, // 0xe0-0xe3
|
Mode.IMM, Mode.XIN, Mode.NUL, Mode.NUL, // 0xe0-0xe3
|
||||||
Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0xe4-0xe7
|
Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.ZPG, // 0xe4-0xe7
|
||||||
Mode.IMP, Mode.IMM, Mode.IMP, Mode.NUL, // 0xe8-0xeb
|
Mode.IMP, Mode.IMM, Mode.IMP, Mode.NUL, // 0xe8-0xeb
|
||||||
Mode.ABS, Mode.ABS, Mode.ABS, Mode.NUL, // 0xec-0xef
|
Mode.ABS, Mode.ABS, Mode.ABS, Mode.ZPR, // 0xec-0xef
|
||||||
Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0xf0-0xf3
|
Mode.REL, Mode.INY, Mode.ZPI, Mode.NUL, // 0xf0-0xf3
|
||||||
Mode.NUL, Mode.ZPX, Mode.ZPX, Mode.NUL, // 0xf4-0xf7
|
Mode.NUL, Mode.ZPX, Mode.ZPX, Mode.ZPG, // 0xf4-0xf7
|
||||||
Mode.IMP, Mode.ABY, Mode.NUL, Mode.NUL, // 0xf8-0xfb
|
Mode.IMP, Mode.ABY, Mode.IMP, Mode.NUL, // 0xf8-0xfb
|
||||||
Mode.NUL, Mode.ABX, Mode.ABX, Mode.NUL // 0xfc-0xff
|
Mode.NUL, Mode.ABX, Mode.ABX, Mode.ZPR // 0xfc-0xff
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Size, in bytes, required for each instruction.
|
* Size, in bytes, required for each instruction. This table
|
||||||
|
* includes sizes for all instructions for NMOS 6502, CMOS 65C02,
|
||||||
|
* and CMOS 65C816
|
||||||
*/
|
*/
|
||||||
int[] instructionSizes = {
|
int[] instructionSizes = {
|
||||||
1, 2, 0, 0, 0, 2, 2, 0, 1, 2, 1, 0, 0, 3, 3, 0,
|
1, 2, 2, 1, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 3, // 0x00-0x0f
|
||||||
2, 2, 0, 0, 0, 2, 2, 0, 1, 3, 0, 0, 0, 3, 3, 0,
|
2, 2, 2, 1, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 3, // 0x10-0x1f
|
||||||
3, 2, 0, 0, 2, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0,
|
3, 2, 2, 1, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 3, // 0x20-0x2f
|
||||||
2, 2, 0, 0, 0, 2, 2, 0, 1, 3, 0, 0, 0, 3, 3, 0,
|
2, 2, 2, 1, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 3, // 0x30-0x3f
|
||||||
1, 2, 0, 0, 0, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0,
|
1, 2, 2, 1, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 3, // 0x40-0x4f
|
||||||
2, 2, 0, 0, 0, 2, 2, 0, 1, 3, 0, 0, 0, 3, 3, 0,
|
2, 2, 2, 1, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 3, // 0x50-0x5f
|
||||||
1, 2, 0, 0, 0, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0,
|
1, 2, 2, 1, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 3, // 0x60-0x6f
|
||||||
2, 2, 0, 0, 0, 2, 2, 0, 1, 3, 0, 0, 0, 3, 3, 0,
|
2, 2, 2, 1, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 3, // 0x70-0x7f
|
||||||
2, 2, 0, 0, 2, 2, 2, 0, 1, 0, 1, 0, 3, 3, 3, 0,
|
2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 3, // 0x80-0x8f
|
||||||
2, 2, 0, 0, 2, 2, 2, 0, 1, 3, 1, 0, 0, 3, 0, 0,
|
2, 2, 2, 1, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 3, // 0x90-0x9f
|
||||||
2, 2, 2, 0, 2, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0,
|
2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 3, // 0xa0-0xaf
|
||||||
2, 2, 0, 0, 2, 2, 2, 0, 1, 3, 1, 0, 3, 3, 3, 0,
|
2, 2, 2, 1, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 3, // 0xb0-0xbf
|
||||||
2, 2, 0, 0, 2, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0,
|
2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 3, // 0xc0-0xcf
|
||||||
2, 2, 0, 0, 0, 2, 2, 0, 1, 3, 0, 0, 0, 3, 3, 0,
|
2, 2, 2, 1, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 3, // 0xd0-0xdf
|
||||||
2, 2, 0, 0, 2, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0,
|
2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 3, // 0xe0-0xef
|
||||||
2, 2, 0, 0, 0, 2, 2, 0, 1, 3, 0, 0, 0, 3, 3, 0
|
2, 2, 2, 1, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 3 // 0xf0-0xff
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of clock cycles required for each instruction
|
* Number of clock cycles required for each instruction when
|
||||||
|
* in NMOS mode.
|
||||||
*/
|
*/
|
||||||
int[] instructionClocks = {
|
int[] instructionClocksNmos = {
|
||||||
7, 6, 0, 0, 0, 3, 5, 0, 3, 2, 2, 0, 0, 4, 6, 0,
|
7, 6, 1, 8, 3, 3, 5, 5, 3, 2, 2, 2, 4, 4, 6, 6, // 0x00-0x0f
|
||||||
2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0,
|
2, 5, 1, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, // 0x10-0x1f
|
||||||
6, 6, 0, 0, 3, 3, 5, 0, 4, 2, 2, 0, 4, 4, 6, 0,
|
6, 6, 1, 8, 3, 3, 5, 5, 4, 2, 2, 2, 4, 4, 6, 6, // 0x20-0x2f
|
||||||
2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0,
|
2, 5, 1, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, // 0x30-0x3f
|
||||||
6, 6, 0, 0, 0, 3, 5, 0, 3, 2, 2, 0, 3, 4, 6, 0,
|
6, 6, 1, 8, 3, 3, 5, 5, 3, 2, 2, 2, 3, 4, 6, 6, // 0x40-0x4f
|
||||||
2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0,
|
2, 5, 1, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, // 0x50-0x5f
|
||||||
6, 6, 0, 0, 0, 3, 5, 0, 4, 2, 2, 0, 5, 4, 6, 0,
|
6, 6, 1, 8, 3, 3, 5, 5, 4, 2, 2, 2, 5, 4, 6, 6, // 0x60-0x6f
|
||||||
2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0,
|
2, 5, 1, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, // 0x70-0x7f
|
||||||
2, 6, 0, 0, 3, 3, 3, 0, 2, 0, 2, 0, 4, 4, 4, 0,
|
2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4, // 0x80-0x8f
|
||||||
2, 6, 0, 0, 4, 4, 4, 0, 2, 5, 2, 0, 0, 5, 0, 0,
|
2, 6, 1, 6, 4, 4, 4, 4, 2, 5, 2, 5, 5, 5, 5, 5, // 0x90-0x9f
|
||||||
2, 6, 2, 0, 3, 3, 3, 0, 2, 2, 2, 0, 4, 4, 4, 0,
|
2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4, // 0xa0-0xaf
|
||||||
2, 5, 0, 0, 4, 4, 4, 0, 2, 4, 2, 0, 4, 4, 4, 0,
|
2, 5, 1, 5, 4, 4, 4, 4, 2, 4, 2, 4, 4, 4, 4, 4, // 0xb0-0xbf
|
||||||
2, 6, 0, 0, 3, 3, 5, 0, 2, 2, 2, 0, 4, 4, 6, 0,
|
2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6, // 0xc0-0xcf
|
||||||
2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0,
|
2, 5, 1, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, // 0xd0-0xdf
|
||||||
2, 6, 0, 0, 3, 3, 5, 0, 2, 2, 2, 0, 4, 4, 6, 0,
|
2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6, // 0xe0-0xef
|
||||||
2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0
|
2, 5, 1, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7 // 0xf0-0xff
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of clock cycles required for each instruction when
|
||||||
|
* in CMOS mode
|
||||||
|
*/
|
||||||
|
int[] instructionClocksCmos = {
|
||||||
|
7, 6, 2, 1, 5, 3, 5, 5, 3, 2, 2, 1, 6, 4, 6, 5, // 0x00-0x0f
|
||||||
|
2, 5, 5, 1, 5, 4, 6, 5, 2, 4, 2, 1, 6, 4, 6, 5, // 0x10-0x1f
|
||||||
|
6, 6, 2, 1, 3, 3, 5, 5, 4, 2, 2, 1, 4, 4, 6, 5, // 0x20-0x2f
|
||||||
|
2, 5, 5, 1, 4, 4, 6, 5, 2, 4, 2, 1, 4, 4, 6, 5, // 0x30-0x3f
|
||||||
|
6, 6, 2, 1, 2, 3, 5, 3, 3, 2, 2, 1, 3, 4, 6, 5, // 0x40-0x4f
|
||||||
|
2, 5, 5, 1, 4, 4, 6, 5, 2, 4, 3, 1, 8, 4, 6, 5, // 0x50-0x5f
|
||||||
|
6, 6, 2, 1, 3, 3, 5, 5, 4, 2, 2, 1, 6, 4, 6, 5, // 0x60-0x6f
|
||||||
|
2, 5, 5, 1, 4, 4, 6, 5, 2, 4, 4, 3, 6, 4, 6, 5, // 0x70-0x7f
|
||||||
|
3, 6, 2, 1, 3, 3, 3, 5, 2, 2, 2, 1, 4, 4, 4, 5, // 0x80-0x8f
|
||||||
|
2, 6, 5, 1, 4, 4, 4, 5, 2, 5, 2, 1, 4, 5, 5, 5, // 0x90-0x9f
|
||||||
|
2, 6, 2, 1, 3, 3, 3, 5, 2, 2, 2, 1, 4, 4, 4, 5, // 0xa0-0xaf
|
||||||
|
2, 5, 5, 1, 4, 4, 4, 5, 2, 4, 2, 1, 4, 4, 4, 5, // 0xb0-0xbf
|
||||||
|
2, 6, 2, 1, 3, 3, 5, 5, 2, 2, 2, 3, 4, 4, 6, 5, // 0xc0-0xcf
|
||||||
|
2, 5, 5, 1, 4, 4, 6, 5, 2, 4, 3, 3, 4, 4, 7, 5, // 0xd0-0xdf
|
||||||
|
2, 6, 2, 1, 3, 3, 5, 5, 2, 2, 2, 1, 4, 4, 6, 5, // 0xe0-0xef
|
||||||
|
2, 5, 5, 1, 4, 4, 6, 5, 2, 4, 4, 1, 4, 4, 7, 5 // 0xf0-0xff
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -28,6 +28,8 @@ package com.loomcom.symon;
|
|||||||
import com.loomcom.symon.machines.MulticompMachine;
|
import com.loomcom.symon.machines.MulticompMachine;
|
||||||
import com.loomcom.symon.machines.SimpleMachine;
|
import com.loomcom.symon.machines.SimpleMachine;
|
||||||
import com.loomcom.symon.machines.SymonMachine;
|
import com.loomcom.symon.machines.SymonMachine;
|
||||||
|
import org.apache.commons.cli.*;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
@@ -41,71 +43,115 @@ public class Main {
|
|||||||
*
|
*
|
||||||
* @param args Program arguments
|
* @param args Program arguments
|
||||||
*/
|
*/
|
||||||
public static void main(String args[]) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
Class machineClass = SymonMachine.class;
|
Class machineClass = SymonMachine.class;
|
||||||
for(int i = 0; i < args.length; ++i) {
|
|
||||||
String arg = args[i].toLowerCase(Locale.ENGLISH);
|
Options options = new Options();
|
||||||
if(arg.equals("-machine") && (i+1) < args.length) {
|
|
||||||
String machine = args[i+1].trim().toLowerCase(Locale.ENGLISH);
|
options.addOption(new Option("m", "machine", true, "Specify machine type."));
|
||||||
|
options.addOption(new Option("c", "cpu", true, "Specify CPU type."));
|
||||||
|
options.addOption(new Option("r", "rom", true, "Specify ROM file."));
|
||||||
|
|
||||||
|
CommandLineParser parser = new DefaultParser();
|
||||||
|
|
||||||
|
try {
|
||||||
|
CommandLine line = parser.parse(options, args);
|
||||||
|
InstructionTable.CpuBehavior cpuBehavior = null;
|
||||||
|
String romFile = null;
|
||||||
|
|
||||||
|
if (line.hasOption("machine")) {
|
||||||
|
String machine = line.getOptionValue("machine").toLowerCase(Locale.ENGLISH);
|
||||||
switch (machine) {
|
switch (machine) {
|
||||||
case "symon":
|
|
||||||
machineClass = SymonMachine.class;
|
|
||||||
break;
|
|
||||||
case "multicomp":
|
case "multicomp":
|
||||||
machineClass = MulticompMachine.class;
|
machineClass = MulticompMachine.class;
|
||||||
break;
|
break;
|
||||||
case "simple":
|
case "simple":
|
||||||
machineClass = SimpleMachine.class;
|
machineClass = SimpleMachine.class;
|
||||||
break;
|
break;
|
||||||
|
case "symon":
|
||||||
|
machineClass = SymonMachine.class;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
System.err.println("Could not start Symon. Unknown machine type " + machine);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
if (machineClass == null) {
|
|
||||||
Object[] possibilities = {"Symon", "Multicomp", "Simple"};
|
|
||||||
String s = (String)JOptionPane.showInputDialog(
|
|
||||||
null,
|
|
||||||
"Please choose the machine type to be emulated:",
|
|
||||||
"Machine selection",
|
|
||||||
JOptionPane.PLAIN_MESSAGE,
|
|
||||||
null,
|
|
||||||
possibilities,
|
|
||||||
"Symon");
|
|
||||||
|
|
||||||
|
|
||||||
if (s != null && s.equals("Multicomp")) {
|
if (line.hasOption("cpu")) {
|
||||||
machineClass = MulticompMachine.class;
|
String cpu = line.getOptionValue("cpu").toLowerCase(Locale.ENGLISH);
|
||||||
} else if (s != null && s.equals("Simple")) {
|
switch (cpu) {
|
||||||
machineClass = SimpleMachine.class;
|
case "6502":
|
||||||
} else {
|
cpuBehavior = InstructionTable.CpuBehavior.NMOS_6502;
|
||||||
machineClass = SymonMachine.class;
|
break;
|
||||||
|
case "65c02":
|
||||||
|
cpuBehavior = InstructionTable.CpuBehavior.CMOS_6502;
|
||||||
|
break;
|
||||||
|
case "65c816":
|
||||||
|
cpuBehavior = InstructionTable.CpuBehavior.CMOS_65816;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
System.err.println("Could not start Symon. Unknown cpu type " + cpu);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final Simulator simulator = new Simulator(machineClass);
|
if (line.hasOption("rom")) {
|
||||||
|
romFile = line.getOptionValue("rom");
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
}
|
||||||
@Override
|
|
||||||
public void run() {
|
while (true) {
|
||||||
try {
|
if (machineClass == null) {
|
||||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
Object[] possibilities = {"Symon", "Multicomp", "Simple"};
|
||||||
// Create the main UI window
|
String s = (String)JOptionPane.showInputDialog(
|
||||||
simulator.createAndShowUi();
|
null,
|
||||||
} catch (Exception e) {
|
"Please choose the machine type to be emulated:",
|
||||||
e.printStackTrace();
|
"Machine selection",
|
||||||
|
JOptionPane.PLAIN_MESSAGE,
|
||||||
|
null,
|
||||||
|
possibilities,
|
||||||
|
"Symon");
|
||||||
|
|
||||||
|
|
||||||
|
if (s != null && s.equals("Multicomp")) {
|
||||||
|
machineClass = MulticompMachine.class;
|
||||||
|
} else if (s != null && s.equals("Simple")) {
|
||||||
|
machineClass = SimpleMachine.class;
|
||||||
|
} else {
|
||||||
|
machineClass = SymonMachine.class;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
if (cpuBehavior == null) {
|
||||||
|
cpuBehavior = InstructionTable.CpuBehavior.NMOS_6502;
|
||||||
Simulator.MainCommand cmd = simulator.waitForCommand();
|
}
|
||||||
if (cmd.equals(Simulator.MainCommand.SELECTMACHINE)) {
|
|
||||||
machineClass = null;
|
final Simulator simulator = new Simulator(machineClass, cpuBehavior, romFile);
|
||||||
} else {
|
|
||||||
break;
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||||
|
// Create the main UI window
|
||||||
|
simulator.createAndShowUi();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
Simulator.MainCommand cmd = simulator.waitForCommand();
|
||||||
|
|
||||||
|
if (cmd.equals(Simulator.MainCommand.SELECTMACHINE)) {
|
||||||
|
machineClass = null;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (ParseException ex) {
|
||||||
|
System.err.println("Could not start Symon. Reason: " + ex.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,6 +31,7 @@ import com.loomcom.symon.ui.Console;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.management.monitor.CounterMonitor;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
@@ -136,9 +137,15 @@ public class Simulator {
|
|||||||
private static final String[] STEPS = {"1", "5", "10", "20", "50", "100"};
|
private static final String[] STEPS = {"1", "5", "10", "20", "50", "100"};
|
||||||
|
|
||||||
public Simulator(Class machineClass) throws Exception {
|
public Simulator(Class machineClass) throws Exception {
|
||||||
|
this(machineClass, InstructionTable.CpuBehavior.NMOS_6502, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Simulator(Class machineClass, InstructionTable.CpuBehavior cpuType, String romFile) throws Exception {
|
||||||
this.breakpoints = new Breakpoints(this);
|
this.breakpoints = new Breakpoints(this);
|
||||||
|
|
||||||
this.machine = (Machine) machineClass.getConstructors()[0].newInstance();
|
this.machine = (Machine) machineClass.getConstructors()[0].newInstance(romFile);
|
||||||
|
this.machine.getCpu().setBehavior(cpuType);
|
||||||
|
|
||||||
|
|
||||||
// Initialize final fields in the constructor.
|
// Initialize final fields in the constructor.
|
||||||
this.traceLog = new TraceLog();
|
this.traceLog = new TraceLog();
|
||||||
@@ -348,7 +355,7 @@ public class Simulator {
|
|||||||
// output ready.
|
// output ready.
|
||||||
if (machine.getAcia() != null && machine.getAcia().hasTxChar()) {
|
if (machine.getAcia() != null && machine.getAcia().hasTxChar()) {
|
||||||
// This is thread-safe
|
// This is thread-safe
|
||||||
console.print(Character.toString((char) machine.getAcia().txRead()));
|
console.print(Character.toString((char) machine.getAcia().txRead(true)));
|
||||||
console.repaint();
|
console.repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -678,6 +685,21 @@ public class Simulator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SetCpuAction extends AbstractAction {
|
||||||
|
private Cpu.CpuBehavior behavior;
|
||||||
|
|
||||||
|
public SetCpuAction(String cpu, Cpu.CpuBehavior behavior) {
|
||||||
|
super(cpu, null);
|
||||||
|
this.behavior = behavior;
|
||||||
|
putValue(SHORT_DESCRIPTION, "Set CPU to " + cpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
machine.getCpu().setBehavior(behavior);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ToggleTraceWindowAction extends AbstractAction {
|
class ToggleTraceWindowAction extends AbstractAction {
|
||||||
public ToggleTraceWindowAction() {
|
public ToggleTraceWindowAction() {
|
||||||
super("Trace Log", null);
|
super("Trace Log", null);
|
||||||
@@ -868,6 +890,14 @@ public class Simulator {
|
|||||||
JMenuItem selectMachineItem = new JMenuItem(new SelectMachineAction());
|
JMenuItem selectMachineItem = new JMenuItem(new SelectMachineAction());
|
||||||
simulatorMenu.add(selectMachineItem);
|
simulatorMenu.add(selectMachineItem);
|
||||||
|
|
||||||
|
// "CPU" sub-menu
|
||||||
|
JMenu cpuTypeMenu = new JMenu("CPU");
|
||||||
|
ButtonGroup cpuGroup = new ButtonGroup();
|
||||||
|
|
||||||
|
makeCpuMenuItem("6502", Cpu.CpuBehavior.NMOS_6502, cpuTypeMenu, cpuGroup);
|
||||||
|
makeCpuMenuItem("65C02", Cpu.CpuBehavior.CMOS_6502, cpuTypeMenu, cpuGroup);
|
||||||
|
makeCpuMenuItem("65C816", Cpu.CpuBehavior.CMOS_65816, cpuTypeMenu, cpuGroup);
|
||||||
|
|
||||||
// "Clock Speed" sub-menu
|
// "Clock Speed" sub-menu
|
||||||
JMenu speedSubMenu = new JMenu("Clock Speed");
|
JMenu speedSubMenu = new JMenu("Clock Speed");
|
||||||
ButtonGroup speedGroup = new ButtonGroup();
|
ButtonGroup speedGroup = new ButtonGroup();
|
||||||
@@ -878,6 +908,7 @@ public class Simulator {
|
|||||||
makeSpeedMenuItem(8, speedSubMenu, speedGroup);
|
makeSpeedMenuItem(8, speedSubMenu, speedGroup);
|
||||||
|
|
||||||
simulatorMenu.add(speedSubMenu);
|
simulatorMenu.add(speedSubMenu);
|
||||||
|
simulatorMenu.add(cpuTypeMenu);
|
||||||
|
|
||||||
// "Breakpoints"
|
// "Breakpoints"
|
||||||
final JCheckBoxMenuItem showBreakpoints = new JCheckBoxMenuItem(new ToggleBreakpointWindowAction());
|
final JCheckBoxMenuItem showBreakpoints = new JCheckBoxMenuItem(new ToggleBreakpointWindowAction());
|
||||||
@@ -914,6 +945,17 @@ public class Simulator {
|
|||||||
subMenu.add(item);
|
subMenu.add(item);
|
||||||
group.add(item);
|
group.add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void makeCpuMenuItem(String cpu, Cpu.CpuBehavior behavior, JMenu subMenu, ButtonGroup group) {
|
||||||
|
|
||||||
|
Action action = new SetCpuAction(cpu, behavior);
|
||||||
|
|
||||||
|
JCheckBoxMenuItem item = new JCheckBoxMenuItem(action);
|
||||||
|
item.setSelected(machine.getCpu().getBehavior() == behavior);
|
||||||
|
subMenu.add(item);
|
||||||
|
group.add(item);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateVisibleState() {
|
private void updateVisibleState() {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import com.loomcom.symon.exceptions.MemoryRangeException;
|
|||||||
public abstract class Acia extends Device {
|
public abstract class Acia extends Device {
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register addresses
|
* Register addresses
|
||||||
*/
|
*/
|
||||||
@@ -42,13 +42,14 @@ public abstract class Acia extends Device {
|
|||||||
boolean receiveIrqEnabled = false;
|
boolean receiveIrqEnabled = false;
|
||||||
boolean transmitIrqEnabled = false;
|
boolean transmitIrqEnabled = false;
|
||||||
boolean overrun = false;
|
boolean overrun = false;
|
||||||
|
boolean interrupt = false;
|
||||||
long lastTxWrite = 0;
|
|
||||||
|
long lastTxWrite = 0;
|
||||||
long lastRxRead = 0;
|
long lastRxRead = 0;
|
||||||
int baudRate = 0;
|
int baudRate = 0;
|
||||||
long baudRateDelay = 0;
|
long baudRateDelay = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read/Write buffers
|
* Read/Write buffers
|
||||||
*/
|
*/
|
||||||
int rxChar = 0;
|
int rxChar = 0;
|
||||||
@@ -56,8 +57,8 @@ public abstract class Acia extends Device {
|
|||||||
|
|
||||||
boolean rxFull = false;
|
boolean rxFull = false;
|
||||||
boolean txEmpty = true;
|
boolean txEmpty = true;
|
||||||
|
|
||||||
|
|
||||||
public Acia(int address, int size, String name) throws MemoryRangeException {
|
public Acia(int address, int size, String name) throws MemoryRangeException {
|
||||||
super(address, address + size - 1, name);
|
super(address, address + size - 1, name);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@@ -100,41 +101,46 @@ public abstract class Acia extends Device {
|
|||||||
/**
|
/**
|
||||||
* @return The contents of the status register.
|
* @return The contents of the status register.
|
||||||
*/
|
*/
|
||||||
public abstract int statusReg();
|
public abstract int statusReg(boolean cpuAccess);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return name + "@" + String.format("%04X", baseAddress);
|
return name + "@" + String.format("%04X", baseAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized int rxRead() {
|
public synchronized int rxRead(boolean cpuAccess) {
|
||||||
lastRxRead = System.nanoTime();
|
if (cpuAccess) {
|
||||||
overrun = false;
|
lastRxRead = System.nanoTime();
|
||||||
rxFull = false;
|
overrun = false;
|
||||||
|
rxFull = false;
|
||||||
|
}
|
||||||
return rxChar;
|
return rxChar;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void rxWrite(int data) {
|
public synchronized void rxWrite(int data) {
|
||||||
if(rxFull) {
|
if (rxFull) {
|
||||||
overrun = true;
|
overrun = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
rxFull = true;
|
rxFull = true;
|
||||||
|
|
||||||
if (receiveIrqEnabled) {
|
if (receiveIrqEnabled) {
|
||||||
|
interrupt = true;
|
||||||
getBus().assertIrq();
|
getBus().assertIrq();
|
||||||
}
|
}
|
||||||
|
|
||||||
rxChar = data;
|
rxChar = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized int txRead() {
|
public synchronized int txRead(boolean cpuAccess) {
|
||||||
txEmpty = true;
|
if (cpuAccess) {
|
||||||
|
txEmpty = true;
|
||||||
|
|
||||||
if (transmitIrqEnabled) {
|
if (transmitIrqEnabled) {
|
||||||
getBus().assertIrq();
|
interrupt = true;
|
||||||
|
getBus().assertIrq();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return txChar;
|
return txChar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,12 +56,12 @@ public class Acia6551 extends Acia {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(int address) throws MemoryAccessException {
|
public int read(int address, boolean cpuAccess) throws MemoryAccessException {
|
||||||
switch (address) {
|
switch (address) {
|
||||||
case DATA_REG:
|
case DATA_REG:
|
||||||
return rxRead();
|
return rxRead(cpuAccess);
|
||||||
case STAT_REG:
|
case STAT_REG:
|
||||||
return statusReg();
|
return statusReg(cpuAccess);
|
||||||
case CMND_REG:
|
case CMND_REG:
|
||||||
return commandRegister;
|
return commandRegister;
|
||||||
case CTRL_REG:
|
case CTRL_REG:
|
||||||
@@ -178,8 +178,8 @@ public class Acia6551 extends Acia {
|
|||||||
* @return The contents of the status register.
|
* @return The contents of the status register.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int statusReg() {
|
public int statusReg(boolean cpuAccess) {
|
||||||
// TODO: Parity Error, Framing Error, DTR, DSR, and Interrupt flags.
|
// TODO: Parity Error, Framing Error, DTR, and DSR flags.
|
||||||
int stat = 0;
|
int stat = 0;
|
||||||
if (rxFull && System.nanoTime() >= (lastRxRead + baudRateDelay)) {
|
if (rxFull && System.nanoTime() >= (lastRxRead + baudRateDelay)) {
|
||||||
stat |= 0x08;
|
stat |= 0x08;
|
||||||
@@ -190,6 +190,14 @@ public class Acia6551 extends Acia {
|
|||||||
if (overrun) {
|
if (overrun) {
|
||||||
stat |= 0x04;
|
stat |= 0x04;
|
||||||
}
|
}
|
||||||
|
if (interrupt) {
|
||||||
|
stat |= 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cpuAccess) {
|
||||||
|
interrupt = false;
|
||||||
|
}
|
||||||
|
|
||||||
return stat;
|
return stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,6 +209,7 @@ public class Acia6551 extends Acia {
|
|||||||
rxFull = false;
|
rxFull = false;
|
||||||
receiveIrqEnabled = false;
|
receiveIrqEnabled = false;
|
||||||
transmitIrqEnabled = false;
|
transmitIrqEnabled = false;
|
||||||
|
interrupt = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -30,8 +30,8 @@ import com.loomcom.symon.exceptions.MemoryRangeException;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a simulation of the Motorola 6850 ACIA, with limited
|
* This is a simulation of the Motorola 6850 ACIA, with limited
|
||||||
* functionality. Interrupts are not supported.
|
* functionality.
|
||||||
* <p/>
|
*
|
||||||
* Unlike a 16550 UART, the 6850 ACIA has only one-byte transmit and
|
* Unlike a 16550 UART, the 6850 ACIA has only one-byte transmit and
|
||||||
* receive buffers. It is the programmer's responsibility to check the
|
* receive buffers. It is the programmer's responsibility to check the
|
||||||
* status (full or empty) for transmit and receive buffers before
|
* status (full or empty) for transmit and receive buffers before
|
||||||
@@ -43,7 +43,7 @@ public class Acia6850 extends Acia {
|
|||||||
|
|
||||||
static final int STAT_REG = 0; // read-only
|
static final int STAT_REG = 0; // read-only
|
||||||
static final int CTRL_REG = 0; // write-only
|
static final int CTRL_REG = 0; // write-only
|
||||||
|
|
||||||
static final int RX_REG = 1; // read-only
|
static final int RX_REG = 1; // read-only
|
||||||
static final int TX_REG = 1; // write-only
|
static final int TX_REG = 1; // write-only
|
||||||
|
|
||||||
@@ -53,12 +53,12 @@ public class Acia6850 extends Acia {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(int address) throws MemoryAccessException {
|
public int read(int address, boolean cpuAccess) throws MemoryAccessException {
|
||||||
switch (address) {
|
switch (address) {
|
||||||
case RX_REG:
|
case RX_REG:
|
||||||
return rxRead();
|
return rxRead(cpuAccess);
|
||||||
case STAT_REG:
|
case STAT_REG:
|
||||||
return statusReg();
|
return statusReg(cpuAccess);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new MemoryAccessException("No register.");
|
throw new MemoryAccessException("No register.");
|
||||||
@@ -78,7 +78,7 @@ public class Acia6850 extends Acia {
|
|||||||
throw new MemoryAccessException("No register.");
|
throw new MemoryAccessException("No register.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setCommandRegister(int data) {
|
private void setCommandRegister(int data) {
|
||||||
// Bits 0 & 1 control the master reset
|
// Bits 0 & 1 control the master reset
|
||||||
if((data & 0x01) != 0 && (data & 0x02) != 0) {
|
if((data & 0x01) != 0 && (data & 0x02) != 0) {
|
||||||
@@ -97,8 +97,8 @@ public class Acia6850 extends Acia {
|
|||||||
* @return The contents of the status register.
|
* @return The contents of the status register.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int statusReg() {
|
public int statusReg(boolean cpuAccess) {
|
||||||
// TODO: Parity Error, Framing Error, DTR, DSR, and Interrupt flags.
|
// TODO: Parity Error, Framing Error, DTR, and DSR flags.
|
||||||
int stat = 0;
|
int stat = 0;
|
||||||
if (rxFull && System.nanoTime() >= (lastRxRead + baudRateDelay)) {
|
if (rxFull && System.nanoTime() >= (lastRxRead + baudRateDelay)) {
|
||||||
stat |= 0x01;
|
stat |= 0x01;
|
||||||
@@ -109,7 +109,14 @@ public class Acia6850 extends Acia {
|
|||||||
if (overrun) {
|
if (overrun) {
|
||||||
stat |= 0x20;
|
stat |= 0x20;
|
||||||
}
|
}
|
||||||
|
if (interrupt) {
|
||||||
|
stat |= 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cpuAccess) {
|
||||||
|
interrupt = false;
|
||||||
|
}
|
||||||
|
|
||||||
return stat;
|
return stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,6 +125,7 @@ public class Acia6850 extends Acia {
|
|||||||
overrun = false;
|
overrun = false;
|
||||||
rxFull = false;
|
rxFull = false;
|
||||||
txEmpty = true;
|
txEmpty = true;
|
||||||
|
interrupt = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -119,7 +119,7 @@ public class Crtc extends Device {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(int address) throws MemoryAccessException {
|
public int read(int address, boolean cpuAccess) throws MemoryAccessException {
|
||||||
switch (address) {
|
switch (address) {
|
||||||
case REGISTER_RW:
|
case REGISTER_RW:
|
||||||
switch (currentRegister) {
|
switch (currentRegister) {
|
||||||
@@ -142,7 +142,7 @@ public class Crtc extends Device {
|
|||||||
|
|
||||||
public int getCharAtAddress(int address) throws MemoryAccessException {
|
public int getCharAtAddress(int address) throws MemoryAccessException {
|
||||||
// TODO: Row/Column addressing
|
// TODO: Row/Column addressing
|
||||||
return memory.read(address);
|
return memory.read(address, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getHorizontalDisplayed() {
|
public int getHorizontalDisplayed() {
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ public abstract class Device implements Comparable<Device> {
|
|||||||
/* Methods required to be implemented by inheriting classes. */
|
/* Methods required to be implemented by inheriting classes. */
|
||||||
public abstract void write(int address, int data) throws MemoryAccessException;
|
public abstract void write(int address, int data) throws MemoryAccessException;
|
||||||
|
|
||||||
public abstract int read(int address) throws MemoryAccessException;
|
public abstract int read(int address, boolean cpuAccess) throws MemoryAccessException;
|
||||||
|
|
||||||
public abstract String toString();
|
public abstract String toString();
|
||||||
|
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ public class Memory extends Device {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int read(int address) throws MemoryAccessException {
|
public int read(int address, boolean cpuAccess) throws MemoryAccessException {
|
||||||
return this.mem[address];
|
return this.mem[address];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ public class SdController extends Device {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(int address) throws MemoryAccessException {
|
public int read(int address, boolean cpuAccess) throws MemoryAccessException {
|
||||||
switch (address) {
|
switch (address) {
|
||||||
case 0:
|
case 0:
|
||||||
return readData();
|
return readData();
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ public class Via6522 extends Pia {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(int address) throws MemoryAccessException {
|
public int read(int address, boolean cpuAccess) throws MemoryAccessException {
|
||||||
Register[] registers = Register.values();
|
Register[] registers = Register.values();
|
||||||
|
|
||||||
if (address >= registers.length) {
|
if (address >= registers.length) {
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011 Graham Edgecombe.
|
||||||
|
*
|
||||||
|
* 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.jterminal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link TerminalModel} which implements some common behaviour.
|
||||||
|
* @author Graham Edgecombe
|
||||||
|
*/
|
||||||
|
public abstract class AbstractTerminalModel implements TerminalModel {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
int rows = getRows(), columns = getColumns();
|
||||||
|
for (int column = 0; column < columns; column++) {
|
||||||
|
for (int row = 0; row < rows; row++) {
|
||||||
|
setCell(column, row, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void moveCursorBack(int n) {
|
||||||
|
if (n < 0) {
|
||||||
|
throw new IllegalArgumentException("n must be positive");
|
||||||
|
}
|
||||||
|
int cursorColumn = getCursorColumn() - n;
|
||||||
|
if (cursorColumn < 0) {
|
||||||
|
cursorColumn = 0;
|
||||||
|
}
|
||||||
|
setCursorColumn(cursorColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void moveCursorForward(int n) {
|
||||||
|
if (n < 0) {
|
||||||
|
throw new IllegalArgumentException("n must be positive");
|
||||||
|
}
|
||||||
|
int columns = getColumns();
|
||||||
|
int cursorColumn = getCursorColumn() + n;
|
||||||
|
if (cursorColumn >= columns) {
|
||||||
|
cursorColumn = columns - 1;
|
||||||
|
}
|
||||||
|
setCursorColumn(cursorColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void moveCursorDown(int n) {
|
||||||
|
if (n < 0) {
|
||||||
|
throw new IllegalArgumentException("n must be positive");
|
||||||
|
}
|
||||||
|
int bufferSize = getBufferSize();
|
||||||
|
int cursorRow = getCursorRow() + n;
|
||||||
|
if (cursorRow >= bufferSize) {
|
||||||
|
cursorRow = bufferSize - 1;
|
||||||
|
}
|
||||||
|
setCursorRow(cursorRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void moveCursorUp(int n) {
|
||||||
|
if (n < 0) {
|
||||||
|
throw new IllegalArgumentException("n must be positive");
|
||||||
|
}
|
||||||
|
int cursorRow = getCursorRow() - n;
|
||||||
|
if (cursorRow < 0) {
|
||||||
|
cursorRow = 0;
|
||||||
|
}
|
||||||
|
setCursorRow(cursorRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,198 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Seth J. Morabito <web@loomcom.com>
|
||||||
|
* Portions Copyright (c) 2009-2011 Graham Edgecombe
|
||||||
|
*
|
||||||
|
* 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.jterminal;
|
||||||
|
|
||||||
|
import com.loomcom.symon.jterminal.vt100.Vt100TerminalModel;
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.FontMetrics;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.event.AdjustmentEvent;
|
||||||
|
import java.awt.event.AdjustmentListener;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JScrollBar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swing terminal emulation component
|
||||||
|
* @author Seth J. Morabito
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class JTerminal extends JComponent {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 2871625194146986567L;
|
||||||
|
|
||||||
|
private int borderWidth = 0;
|
||||||
|
|
||||||
|
private JScrollBar scrollBar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The terminal emulation model
|
||||||
|
*/
|
||||||
|
private TerminalModel model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The font this terminal uses
|
||||||
|
*/
|
||||||
|
private Font font;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cell width in pixels
|
||||||
|
*/
|
||||||
|
private int cellWidth;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cell height in pixels
|
||||||
|
*/
|
||||||
|
private int cellHeight;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Max descender for font
|
||||||
|
*/
|
||||||
|
private int maxDescender;
|
||||||
|
|
||||||
|
public JTerminal(Font font) {
|
||||||
|
this(new Vt100TerminalModel(), font);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JTerminal(TerminalModel model, Font font) {
|
||||||
|
setModel(model);
|
||||||
|
setFont(font);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBorderWidth(int borderWidth) {
|
||||||
|
this.borderWidth = borderWidth;
|
||||||
|
revalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBorderWidth() {
|
||||||
|
return borderWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFont(Font font) {
|
||||||
|
this.font = font;
|
||||||
|
setCellWidthAndHeight(font);
|
||||||
|
revalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Font getFont() {
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setModel(TerminalModel model) {
|
||||||
|
if (model == null) {
|
||||||
|
throw new NullPointerException("model");
|
||||||
|
}
|
||||||
|
this.model = model;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TerminalModel getModel() {
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void println(String str) {
|
||||||
|
if (str == null) {
|
||||||
|
throw new NullPointerException("str");
|
||||||
|
}
|
||||||
|
print(str.concat("\r\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(String str) {
|
||||||
|
model.print(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dimension getMinimumSize() {
|
||||||
|
return new Dimension(model.getColumns() * cellWidth + borderWidth * 2,
|
||||||
|
model.getRows() * cellHeight + borderWidth * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dimension getMaximumSize() {
|
||||||
|
return getMinimumSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dimension getPreferredSize() {
|
||||||
|
return getMinimumSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void paint(Graphics g) {
|
||||||
|
g.setFont(font);
|
||||||
|
|
||||||
|
int width = model.getColumns();
|
||||||
|
int height = model.getBufferSize();
|
||||||
|
|
||||||
|
g.setColor(model.getDefaultBackgroundColor());
|
||||||
|
g.fillRect(0, 0, width * cellWidth + borderWidth * 2, height * cellHeight + borderWidth * 2);
|
||||||
|
|
||||||
|
int start = scrollBar == null ? 0 : scrollBar.getValue();
|
||||||
|
for (int y = start; y < height; y++) {
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
TerminalCell cell = model.getCell(x, y);
|
||||||
|
boolean cursorHere = (model.getCursorRow() == y) && (model.getCursorColumn() == x);
|
||||||
|
|
||||||
|
if ((cursorHere) && (cell == null)) {
|
||||||
|
cell = new TerminalCell(' ', model.getDefaultBackgroundColor(), model.getDefaultForegroundColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cell != null) {
|
||||||
|
int px = x * cellWidth + borderWidth;
|
||||||
|
int py = (y - start) * cellHeight + borderWidth;
|
||||||
|
|
||||||
|
g.setColor(cursorHere ? cell.getForegroundColor() : cell.getBackgroundColor());
|
||||||
|
g.fillRect(px, py, cellWidth, cellHeight);
|
||||||
|
|
||||||
|
g.setColor(cursorHere ? cell.getBackgroundColor() : cell.getForegroundColor());
|
||||||
|
g.drawChars(new char[] { cell.getCharacter() }, 0, 1, px, py + cellHeight - maxDescender);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
setLayout(new BorderLayout(0, 0));
|
||||||
|
|
||||||
|
int rows = model.getRows();
|
||||||
|
int bufferSize = model.getBufferSize();
|
||||||
|
|
||||||
|
if (bufferSize > rows) {
|
||||||
|
scrollBar = new JScrollBar(1, 0, rows, 0, bufferSize + 1);
|
||||||
|
scrollBar.addAdjustmentListener(new AdjustmentListener() {
|
||||||
|
public void adjustmentValueChanged(AdjustmentEvent evt) {
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
add("After", scrollBar);
|
||||||
|
}
|
||||||
|
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setCellWidthAndHeight(Font font) {
|
||||||
|
FontMetrics metrics = getFontMetrics(font);
|
||||||
|
cellWidth = metrics.charWidth('W');
|
||||||
|
cellHeight = metrics.getHeight();
|
||||||
|
maxDescender = metrics.getMaxDescent();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011 Graham Edgecombe.
|
||||||
|
*
|
||||||
|
* 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.jterminal;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a single terminal cell which contains a character, background
|
||||||
|
* color and foreground color.
|
||||||
|
* @author Graham Edgecombe
|
||||||
|
*/
|
||||||
|
public class TerminalCell {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The character.
|
||||||
|
*/
|
||||||
|
private final char character;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The background color.
|
||||||
|
*/
|
||||||
|
private final Color backgroundColor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The foreground color.
|
||||||
|
*/
|
||||||
|
private final Color foregroundColor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a terminal cell with the specified character, background color
|
||||||
|
* and foreground color.
|
||||||
|
* @param character The character.
|
||||||
|
* @param backgroundColor The background color.
|
||||||
|
* @param foregroundColor The foreground color.
|
||||||
|
* @throws NullPointerException if the background or foreground color(s)
|
||||||
|
* are {@code null}.
|
||||||
|
*/
|
||||||
|
public TerminalCell(char character, Color backgroundColor, Color foregroundColor) {
|
||||||
|
if (backgroundColor == null) {
|
||||||
|
throw new NullPointerException("backgroundColor");
|
||||||
|
}
|
||||||
|
if (foregroundColor == null) {
|
||||||
|
throw new NullPointerException("foregroundColor");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.character = character;
|
||||||
|
this.backgroundColor = backgroundColor;
|
||||||
|
this.foregroundColor = foregroundColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the character.
|
||||||
|
* @return The character.
|
||||||
|
*/
|
||||||
|
public char getCharacter() {
|
||||||
|
return character;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the background color.
|
||||||
|
* @return The background color.
|
||||||
|
*/
|
||||||
|
public Color getBackgroundColor() {
|
||||||
|
return backgroundColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the foreground color.
|
||||||
|
* @return The foreground color.
|
||||||
|
*/
|
||||||
|
public Color getForegroundColor() {
|
||||||
|
return foregroundColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011 Graham Edgecombe.
|
||||||
|
*
|
||||||
|
* 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.jterminal;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
|
||||||
|
import com.loomcom.symon.jterminal.bell.BellStrategy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model for terminals - defines methods for getting/setting cells, printing
|
||||||
|
* text to a terminal and getting the size of the terminal and buffer.
|
||||||
|
*/
|
||||||
|
public interface TerminalModel {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the bell strategy.
|
||||||
|
* @return The bell strategy.
|
||||||
|
*/
|
||||||
|
public BellStrategy getBellStrategy();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the bell strategy.
|
||||||
|
* @param strategy The bell strategy.
|
||||||
|
* @throws NullPointerException if the strategy is {@code null}.
|
||||||
|
*/
|
||||||
|
public void setBellStrategy(BellStrategy strategy);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the terminal.
|
||||||
|
*/
|
||||||
|
public void clear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the cursor back n characters.
|
||||||
|
* @param n The number of characters.
|
||||||
|
* @throws IllegalArgumentException if n is not positive.
|
||||||
|
*/
|
||||||
|
public void moveCursorBack(int n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the cursor forward n characters.
|
||||||
|
* @param n The number of characters.
|
||||||
|
* @throws IllegalArgumentException if n is not positive.
|
||||||
|
*/
|
||||||
|
public void moveCursorForward(int n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the cursor down n characters.
|
||||||
|
* @param n The number of characters.
|
||||||
|
* @throws IllegalArgumentException if n is not positive.
|
||||||
|
*/
|
||||||
|
public void moveCursorDown(int n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the cursor up n characters.
|
||||||
|
* @param n The number of characters.
|
||||||
|
* @throws IllegalArgumentException if n is not positive.
|
||||||
|
*/
|
||||||
|
public void moveCursorUp(int n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a cell.
|
||||||
|
* @param column The column.
|
||||||
|
* @param row The row.
|
||||||
|
* @param cell The cell.
|
||||||
|
* @throws IndexOutOfBoundsException if the column and/or row number(s) are
|
||||||
|
* out of bounds.
|
||||||
|
*/
|
||||||
|
public void setCell(int column, int row, TerminalCell cell);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a cell.
|
||||||
|
* @param column The column.
|
||||||
|
* @param row The row.
|
||||||
|
* @return The cell.
|
||||||
|
* @throws IndexOutOfBoundsException if the column and/or row number(s) are
|
||||||
|
* out of bounds.
|
||||||
|
*/
|
||||||
|
public TerminalCell getCell(int column, int row);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints the specified string to the terminal at the cursor position,
|
||||||
|
* interpreting any escape sequences/special ASCII codes the model may
|
||||||
|
* support. Lines will be wrapped if necessary.
|
||||||
|
* @param str The string to print.
|
||||||
|
* @throws NullPointerException if the string is {@code null}.
|
||||||
|
*/
|
||||||
|
public void print(String str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the number of columns.
|
||||||
|
* @return The number of columns.
|
||||||
|
*/
|
||||||
|
public int getColumns();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the number of rows.
|
||||||
|
* @return The number of rows.
|
||||||
|
*/
|
||||||
|
public int getRows();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the buffer size.
|
||||||
|
* @return The buffer size.
|
||||||
|
*/
|
||||||
|
public int getBufferSize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cursor row.
|
||||||
|
* @return The cursor row.
|
||||||
|
*/
|
||||||
|
public int getCursorRow();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the cursor row.
|
||||||
|
* @param row The cursor row.
|
||||||
|
* @throws IllegalArgumentException if the row is out of the valid range.
|
||||||
|
*/
|
||||||
|
public void setCursorRow(int row);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cursor column.
|
||||||
|
* @return The cursor column.
|
||||||
|
*/
|
||||||
|
public int getCursorColumn();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the cursor column.
|
||||||
|
* @param column The cursor column.
|
||||||
|
* @throws IllegalArgumentException if the column is out of the valid range.
|
||||||
|
*/
|
||||||
|
public void setCursorColumn(int column);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the default background color.
|
||||||
|
* @return The default background color.
|
||||||
|
*/
|
||||||
|
public Color getDefaultBackgroundColor();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the default foreground color.
|
||||||
|
* @return The default foreground color.
|
||||||
|
*/
|
||||||
|
public Color getDefaultForegroundColor();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011 Graham Edgecombe.
|
||||||
|
*
|
||||||
|
* 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.jterminal.bell;
|
||||||
|
|
||||||
|
import java.awt.Toolkit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link BellStrategy} which calls {@link Toolkit#beep()}.
|
||||||
|
* @author Graham Edgecombe
|
||||||
|
*/
|
||||||
|
public class BeepBellStrategy implements BellStrategy {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void soundBell() {
|
||||||
|
Toolkit.getDefaultToolkit().beep();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011 Graham Edgecombe.
|
||||||
|
*
|
||||||
|
* 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.jterminal.bell;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A 'strategy' used to sound the bell (US-ASCII character {@code 7}).
|
||||||
|
* @author Graham Edgecombe
|
||||||
|
*/
|
||||||
|
public interface BellStrategy {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sounds the bell.
|
||||||
|
*/
|
||||||
|
public void soundBell();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011 Graham Edgecombe.
|
||||||
|
*
|
||||||
|
* 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.jterminal.bell;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link BellStrategy} which does nothing.
|
||||||
|
* @author Graham Edgecombe
|
||||||
|
*/
|
||||||
|
public class NopBellStrategy implements BellStrategy {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void soundBell() {
|
||||||
|
/* ignore */
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011 Graham Edgecombe.
|
||||||
|
*
|
||||||
|
* 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.jterminal.vt100;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an ANSI control sequence.
|
||||||
|
* @author Graham Edgecombe
|
||||||
|
*/
|
||||||
|
public class AnsiControlSequence {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The command character.
|
||||||
|
*/
|
||||||
|
private final char command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parameters.
|
||||||
|
*/
|
||||||
|
private final String[] parameters;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an ANSI control sequence with the specified command and
|
||||||
|
* parameters.
|
||||||
|
* @param command The command character.
|
||||||
|
* @param parameters The parameters array.
|
||||||
|
* @throws NullPointerException if the parameters array is {@code null}.
|
||||||
|
*/
|
||||||
|
public AnsiControlSequence(char command, String[] parameters) {
|
||||||
|
if (parameters == null) {
|
||||||
|
throw new NullPointerException("parameters");
|
||||||
|
}
|
||||||
|
this.command = command;
|
||||||
|
if (parameters.length == 1 && parameters[0].equals("")) {
|
||||||
|
this.parameters = new String[0];
|
||||||
|
} else {
|
||||||
|
this.parameters = parameters.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the command character.
|
||||||
|
* @return The command character.
|
||||||
|
*/
|
||||||
|
public char getCommand() {
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the parameters array.
|
||||||
|
* @return The parameters array.
|
||||||
|
*/
|
||||||
|
public String[] getParameters() {
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011 Graham Edgecombe.
|
||||||
|
*
|
||||||
|
* 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.jterminal.vt100;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface which classes may use to listen to events from a
|
||||||
|
* {@link AnsiControlSequenceParser}.
|
||||||
|
*/
|
||||||
|
public interface AnsiControlSequenceListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a control sequence has been parsed.
|
||||||
|
* @param seq The control sequence.
|
||||||
|
*/
|
||||||
|
public void parsedControlSequence(AnsiControlSequence seq);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a string has been parsed.
|
||||||
|
* @param str The string.
|
||||||
|
*/
|
||||||
|
public void parsedString(String str);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011 Graham Edgecombe.
|
||||||
|
*
|
||||||
|
* 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.jterminal.vt100;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.io.StringReader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class which parses {@link AnsiControlSequence}s from {@link String}(s).
|
||||||
|
* @author Graham Edgecombe
|
||||||
|
*/
|
||||||
|
public class AnsiControlSequenceParser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The multi-byte control sequence introducer.
|
||||||
|
*/
|
||||||
|
private static final char[] MULTI_CSI = new char[] { 27, '[' };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The single-byte control sequence introducer.
|
||||||
|
*/
|
||||||
|
private static final char SINGLE_CSI = 155;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The buffer of data from the last call to {@link #parse()}. This is
|
||||||
|
* populated with data if an escape sequence is not complete.
|
||||||
|
*/
|
||||||
|
private StringBuilder buffer = new StringBuilder();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ANSI control sequence listener.
|
||||||
|
*/
|
||||||
|
private final AnsiControlSequenceListener listener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the ANSI control sequence parser.
|
||||||
|
* @param listener The listener.
|
||||||
|
*/
|
||||||
|
public AnsiControlSequenceParser(AnsiControlSequenceListener listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the specified string.
|
||||||
|
* @param str The string to parse.
|
||||||
|
*/
|
||||||
|
public void parse(String str) {
|
||||||
|
if (buffer.length() > 0) {
|
||||||
|
str = buffer.toString().concat(str);
|
||||||
|
buffer = new StringBuilder();
|
||||||
|
}
|
||||||
|
Reader reader = new StringReader(str);
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
parse(reader);
|
||||||
|
} finally {
|
||||||
|
reader.close();
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
/* ignore */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses characters from the specified character reader.
|
||||||
|
* @param reader The character reader.
|
||||||
|
* @throws IOException if an I/O error occurs.
|
||||||
|
*/
|
||||||
|
private void parse(Reader reader) throws IOException {
|
||||||
|
StringBuilder text = new StringBuilder();
|
||||||
|
int character;
|
||||||
|
while ((character = reader.read()) != -1) {
|
||||||
|
boolean introducedControlSequence = false;
|
||||||
|
if (character == SINGLE_CSI) {
|
||||||
|
introducedControlSequence = true;
|
||||||
|
} else if (character == MULTI_CSI[0]) {
|
||||||
|
int nextCharacter = reader.read();
|
||||||
|
if (nextCharacter == -1) {
|
||||||
|
buffer.append((char) character);
|
||||||
|
break;
|
||||||
|
} else if (nextCharacter == MULTI_CSI[1]) {
|
||||||
|
introducedControlSequence = true;
|
||||||
|
} else {
|
||||||
|
text.append((char) character);
|
||||||
|
text.append((char) nextCharacter);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
text.append((char) character);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (introducedControlSequence) {
|
||||||
|
if (text.length() > 0) {
|
||||||
|
listener.parsedString(text.toString());
|
||||||
|
text = new StringBuilder();
|
||||||
|
}
|
||||||
|
parseControlSequence(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (text.length() > 0) {
|
||||||
|
listener.parsedString(text.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a control sequence.
|
||||||
|
* @param reader The character reader.
|
||||||
|
* @throws IOException if an I/O error occurs.
|
||||||
|
*/
|
||||||
|
private void parseControlSequence(Reader reader) throws IOException {
|
||||||
|
boolean finishedSequence = false;
|
||||||
|
StringBuilder parameters = new StringBuilder();
|
||||||
|
int character;
|
||||||
|
while ((character = reader.read()) != -1) {
|
||||||
|
if ((character >= 'a' && character <= 'z') || (character >= 'A' && character <= 'Z')) {
|
||||||
|
String[] array = parameters.toString().split(";");
|
||||||
|
AnsiControlSequence seq = new AnsiControlSequence((char) character, array);
|
||||||
|
listener.parsedControlSequence(seq);
|
||||||
|
|
||||||
|
finishedSequence = true;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
parameters.append((char) character);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!finishedSequence) {
|
||||||
|
// not an ideal solution if they used the two byte CSI, but it's
|
||||||
|
// easier and cleaner than keeping track of it
|
||||||
|
buffer.append((char) SINGLE_CSI);
|
||||||
|
buffer.append(parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011 Graham Edgecombe.
|
||||||
|
*
|
||||||
|
* 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.jterminal.vt100;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains colors used by the SGR ANSI escape sequence.
|
||||||
|
* @author Graham Edgecombe
|
||||||
|
*/
|
||||||
|
final class SgrColor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of normal intensity colors.
|
||||||
|
*/
|
||||||
|
public static final Color[] COLOR_NORMAL = new Color[] {
|
||||||
|
new Color(0, 0, 0),
|
||||||
|
new Color(128, 0, 0),
|
||||||
|
new Color(0, 128, 0),
|
||||||
|
new Color(128, 128, 0),
|
||||||
|
new Color(0, 0, 128),
|
||||||
|
new Color(128, 0, 128),
|
||||||
|
new Color(0, 128, 128),
|
||||||
|
new Color(192, 192, 192)
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of bright intensity colors.
|
||||||
|
*/
|
||||||
|
public static final Color[] COLOR_BRIGHT = new Color[] {
|
||||||
|
new Color(128, 128, 128),
|
||||||
|
new Color(255, 0, 0),
|
||||||
|
new Color(0, 255, 0),
|
||||||
|
new Color(255, 255, 0),
|
||||||
|
new Color(0, 0, 255),
|
||||||
|
new Color(0, 0, 255),
|
||||||
|
new Color(255, 0, 255),
|
||||||
|
new Color(0, 255, 255),
|
||||||
|
new Color(255, 255, 255)
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default private constructor to prevent instantiation.
|
||||||
|
*/
|
||||||
|
private SgrColor() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,493 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011 Graham Edgecombe.
|
||||||
|
*
|
||||||
|
* 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.jterminal.vt100;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
|
||||||
|
import com.loomcom.symon.jterminal.AbstractTerminalModel;
|
||||||
|
import com.loomcom.symon.jterminal.TerminalCell;
|
||||||
|
import com.loomcom.symon.jterminal.TerminalModel;
|
||||||
|
import com.loomcom.symon.jterminal.bell.BellStrategy;
|
||||||
|
import com.loomcom.symon.jterminal.bell.NopBellStrategy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A VT100/ANSI-compatible terminal model.
|
||||||
|
* @author Graham Edgecombe
|
||||||
|
*/
|
||||||
|
public class Vt100TerminalModel extends AbstractTerminalModel {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link AnsiControlSequenceListener} which modifies the
|
||||||
|
* {@link TerminalModel} appropriately when an event happens.
|
||||||
|
* @author Graham Edgecombe
|
||||||
|
*/
|
||||||
|
private class Vt100Listener implements AnsiControlSequenceListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The saved cursor row.
|
||||||
|
*/
|
||||||
|
private int savedCursorRow = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The saved cursor column.
|
||||||
|
*/
|
||||||
|
private int savedCursorColumn = -1;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parsedControlSequence(AnsiControlSequence seq) {
|
||||||
|
char command = seq.getCommand();
|
||||||
|
String[] parameters = seq.getParameters();
|
||||||
|
|
||||||
|
switch (command) {
|
||||||
|
case 'A':
|
||||||
|
case 'B':
|
||||||
|
case 'C':
|
||||||
|
case 'D':
|
||||||
|
int n = 1;
|
||||||
|
if (parameters.length == 1) {
|
||||||
|
n = Integer.parseInt(parameters[0]);
|
||||||
|
}
|
||||||
|
if (command == 'A') {
|
||||||
|
moveCursorUp(n);
|
||||||
|
} else if (command == 'B') {
|
||||||
|
moveCursorDown(n);
|
||||||
|
} else if (command == 'C') {
|
||||||
|
moveCursorForward(n);
|
||||||
|
} else if (command == 'D') {
|
||||||
|
moveCursorBack(n);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'E':
|
||||||
|
case 'F':
|
||||||
|
n = 1;
|
||||||
|
if (parameters.length == 1) {
|
||||||
|
n = Integer.parseInt(parameters[0]);
|
||||||
|
}
|
||||||
|
if (command == 'E') {
|
||||||
|
moveCursorDown(n);
|
||||||
|
} else if (command == 'F') {
|
||||||
|
moveCursorUp(n);
|
||||||
|
}
|
||||||
|
setCursorColumn(0);
|
||||||
|
break;
|
||||||
|
case 'G':
|
||||||
|
if (parameters.length == 1) {
|
||||||
|
n = Integer.parseInt(parameters[0]);
|
||||||
|
setCursorColumn(n - 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'H':
|
||||||
|
case 'f':
|
||||||
|
if (parameters.length == 2) {
|
||||||
|
n = 1;
|
||||||
|
int m = 1;
|
||||||
|
if (parameters[0].length() > 0) {
|
||||||
|
n = Integer.parseInt(parameters[0]);
|
||||||
|
}
|
||||||
|
if (parameters[1].length() > 0) {
|
||||||
|
m = Integer.parseInt(parameters[1]);
|
||||||
|
}
|
||||||
|
setCursorRow(n - 1);
|
||||||
|
setCursorColumn(m - 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'J':
|
||||||
|
n = 0;
|
||||||
|
if (parameters.length == 1) {
|
||||||
|
n = Integer.parseInt(parameters[0]);
|
||||||
|
}
|
||||||
|
if (n == 0) {
|
||||||
|
int row = cursorRow;
|
||||||
|
int column = cursorColumn;
|
||||||
|
while(row < rows) {
|
||||||
|
while(column < columns) {
|
||||||
|
cells[row][column] = null;
|
||||||
|
column++;
|
||||||
|
}
|
||||||
|
column = 0;
|
||||||
|
row++;
|
||||||
|
}
|
||||||
|
} else if (n == 1) {
|
||||||
|
int row = cursorRow;
|
||||||
|
int column = cursorColumn;
|
||||||
|
while(row >= 0) {
|
||||||
|
while(column >= 0) {
|
||||||
|
cells[row][column] = null;
|
||||||
|
column--;
|
||||||
|
}
|
||||||
|
column = columns - 1;
|
||||||
|
row--;
|
||||||
|
}
|
||||||
|
} else if (n == 2) {
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'K':
|
||||||
|
n = 0;
|
||||||
|
if (parameters.length == 1) {
|
||||||
|
n = Integer.parseInt(parameters[0]);
|
||||||
|
}
|
||||||
|
if (n == 0) {
|
||||||
|
for (int row = cursorRow; row < rows; row++) {
|
||||||
|
cells[row][cursorColumn] = null;
|
||||||
|
}
|
||||||
|
} else if (n == 1) {
|
||||||
|
for (int row = cursorRow; row >= 0; row--) {
|
||||||
|
cells[row][cursorColumn] = null;
|
||||||
|
}
|
||||||
|
} else if (n == 2) {
|
||||||
|
for (int column = 0; column < columns; column++) {
|
||||||
|
cells[cursorRow][column] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
if (parameters.length == 0) {
|
||||||
|
parameters = new String[] { "0" };
|
||||||
|
}
|
||||||
|
for (String parameter : parameters) {
|
||||||
|
if (parameter.equals("0")) {
|
||||||
|
foregroundColor = DEFAULT_FOREGROUND_COLOR;
|
||||||
|
backgroundColor = DEFAULT_BACKGROUND_COLOR;
|
||||||
|
backgroundBold = DEFAULT_BACKGROUND_BOLD;
|
||||||
|
foregroundBold = DEFAULT_FOREGROUND_BOLD;
|
||||||
|
} else if (parameter.equals("2")) {
|
||||||
|
backgroundBold = true;
|
||||||
|
foregroundBold = true;
|
||||||
|
} else if (parameter.equals("22")) {
|
||||||
|
backgroundBold = false;
|
||||||
|
foregroundBold = false;
|
||||||
|
} else if ((parameter.startsWith("3") || parameter.startsWith("4")) && parameter.length() == 2) {
|
||||||
|
int color = Integer.parseInt(parameter.substring(1));
|
||||||
|
if (parameter.startsWith("3")) {
|
||||||
|
foregroundColor = color;
|
||||||
|
} else if (parameter.startsWith("4")) {
|
||||||
|
backgroundColor = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
if (savedCursorColumn != -1 && savedCursorRow != -1) {
|
||||||
|
cursorColumn = savedCursorColumn;
|
||||||
|
cursorRow = savedCursorRow;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
savedCursorColumn = cursorColumn;
|
||||||
|
savedCursorRow = cursorRow;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parsedString(String str) {
|
||||||
|
for (char ch : str.toCharArray()) {
|
||||||
|
switch (ch) {
|
||||||
|
case '\0':
|
||||||
|
continue;
|
||||||
|
case '\r':
|
||||||
|
cursorColumn = 0;
|
||||||
|
continue;
|
||||||
|
case '\n':
|
||||||
|
cursorRow++;
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
while ((++cursorColumn % TAB_WIDTH) != 0);
|
||||||
|
continue;
|
||||||
|
case 127:
|
||||||
|
if (cursorColumn > 0) {
|
||||||
|
cells[cursorRow][--cursorColumn] = null;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
case 7:
|
||||||
|
bellStrategy.soundBell();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursorColumn >= columns) {
|
||||||
|
cursorColumn = 0;
|
||||||
|
cursorRow++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursorRow >= bufferSize) {
|
||||||
|
for (int i = 1; i < bufferSize; i++) {
|
||||||
|
System.arraycopy(cells[i], 0, cells[i - 1], 0, columns);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < columns; i++) {
|
||||||
|
cells[bufferSize - 1][i] = null;
|
||||||
|
}
|
||||||
|
cursorRow--;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color back = backgroundBold ? SgrColor.COLOR_BRIGHT[backgroundColor] : SgrColor.COLOR_NORMAL[backgroundColor];
|
||||||
|
Color fore = foregroundBold ? SgrColor.COLOR_BRIGHT[foregroundColor] : SgrColor.COLOR_NORMAL[foregroundColor];
|
||||||
|
if (ch != '\n') {
|
||||||
|
cells[cursorRow][cursorColumn++] = new TerminalCell(ch, back, fore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default number of columns.
|
||||||
|
*/
|
||||||
|
private static final int DEFAULT_COLUMNS = 80;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default number of rows.
|
||||||
|
*/
|
||||||
|
private static final int DEFAULT_ROWS = 25;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tab width in characters.
|
||||||
|
*/
|
||||||
|
private static final int TAB_WIDTH = 8;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default foreground bold flag.
|
||||||
|
*/
|
||||||
|
private static final boolean DEFAULT_FOREGROUND_BOLD = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default background bold flag.
|
||||||
|
*/
|
||||||
|
private static final boolean DEFAULT_BACKGROUND_BOLD = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default foreground color.
|
||||||
|
*/
|
||||||
|
private static final int DEFAULT_FOREGROUND_COLOR = 7;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default background color.
|
||||||
|
*/
|
||||||
|
private static final int DEFAULT_BACKGROUND_COLOR = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ANSI control sequence listener.
|
||||||
|
*/
|
||||||
|
private final AnsiControlSequenceListener listener = this.new Vt100Listener();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ANSI control sequence parser.
|
||||||
|
*/
|
||||||
|
private final AnsiControlSequenceParser parser = new AnsiControlSequenceParser(listener);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current bell strategy.
|
||||||
|
*/
|
||||||
|
private BellStrategy bellStrategy = new NopBellStrategy();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The array of cells.
|
||||||
|
*/
|
||||||
|
private TerminalCell[][] cells;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of columns.
|
||||||
|
*/
|
||||||
|
private int columns;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of rows.
|
||||||
|
*/
|
||||||
|
private int rows;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The buffer size.
|
||||||
|
*/
|
||||||
|
private int bufferSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cursor row.
|
||||||
|
*/
|
||||||
|
private int cursorRow = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cursor column.
|
||||||
|
*/
|
||||||
|
private int cursorColumn = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current foreground bold flag.
|
||||||
|
*/
|
||||||
|
private boolean foregroundBold = DEFAULT_FOREGROUND_BOLD;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current background bold flag.
|
||||||
|
*/
|
||||||
|
private boolean backgroundBold = DEFAULT_BACKGROUND_BOLD;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current foreground color.
|
||||||
|
*/
|
||||||
|
private int foregroundColor = DEFAULT_FOREGROUND_COLOR;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current background color.
|
||||||
|
*/
|
||||||
|
private int backgroundColor = DEFAULT_BACKGROUND_COLOR;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the terminal model with the default number of columns and rows,
|
||||||
|
* and the default buffer size.
|
||||||
|
*/
|
||||||
|
public Vt100TerminalModel() {
|
||||||
|
this(DEFAULT_COLUMNS, DEFAULT_ROWS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the terminal model with the specified number of columns and
|
||||||
|
* rows. The buffer size is set to the number of rows.
|
||||||
|
* @param columns The number of columns.
|
||||||
|
* @param rows The number of rows.
|
||||||
|
* @throws IllegalArgumentException if the number of rows or columns is
|
||||||
|
* negative.
|
||||||
|
*/
|
||||||
|
public Vt100TerminalModel(int columns, int rows) {
|
||||||
|
this(columns, rows, rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the terminal model with the specified number of columns and rows
|
||||||
|
* and the specified buffer size.
|
||||||
|
* @param columns The number of columns.
|
||||||
|
* @param rows The number of rows.
|
||||||
|
* @param bufferSize The buffer size.
|
||||||
|
* @throws IllegalArgumentException if the number of rows or columns is
|
||||||
|
* negative, or if the buffer size is less than the number of rows.
|
||||||
|
*/
|
||||||
|
public Vt100TerminalModel(int columns, int rows, int bufferSize) {
|
||||||
|
if (columns < 0 || rows < 0 || bufferSize < 0) {
|
||||||
|
throw new IllegalArgumentException("Zero or positive values only allowed for columns, rows and buffer size.");
|
||||||
|
}
|
||||||
|
if (bufferSize < rows) {
|
||||||
|
throw new IllegalArgumentException("The buffer is too small");
|
||||||
|
}
|
||||||
|
this.columns = columns;
|
||||||
|
this.rows = rows;
|
||||||
|
this.bufferSize = bufferSize;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the terminal model.
|
||||||
|
*/
|
||||||
|
private void init() {
|
||||||
|
cells = new TerminalCell[bufferSize][columns];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCursorRow() {
|
||||||
|
return cursorRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCursorRow(int row) {
|
||||||
|
if (row < 0 || row >= bufferSize) {
|
||||||
|
throw new IllegalArgumentException("row out of range");
|
||||||
|
}
|
||||||
|
cursorRow = row;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCursorColumn() {
|
||||||
|
return cursorColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCursorColumn(int column) {
|
||||||
|
if (column < 0 || column >= columns) {
|
||||||
|
throw new IllegalArgumentException("column out of range");
|
||||||
|
}
|
||||||
|
cursorColumn = column;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TerminalCell getCell(int column, int row) {
|
||||||
|
if (column < 0 || row < 0 || column >= columns || row >= bufferSize) {
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
return cells[row][column];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCell(int column, int row, TerminalCell cell) {
|
||||||
|
if (column < 0 || row < 0 || column >= columns || row >= bufferSize) {
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
cells[row][column] = cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void print(String str) {
|
||||||
|
if (str == null) {
|
||||||
|
throw new NullPointerException("str");
|
||||||
|
}
|
||||||
|
parser.parse(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getColumns() {
|
||||||
|
return columns;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRows() {
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBufferSize() {
|
||||||
|
return bufferSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BellStrategy getBellStrategy() {
|
||||||
|
return bellStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBellStrategy(BellStrategy strategy) {
|
||||||
|
if (strategy == null) {
|
||||||
|
throw new NullPointerException("strategy");
|
||||||
|
}
|
||||||
|
this.bellStrategy = strategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Color getDefaultBackgroundColor() {
|
||||||
|
final int bg = DEFAULT_BACKGROUND_COLOR;
|
||||||
|
return DEFAULT_BACKGROUND_BOLD ? SgrColor.COLOR_BRIGHT[bg] : SgrColor.COLOR_NORMAL[bg];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Color getDefaultForegroundColor() {
|
||||||
|
final int fg = DEFAULT_FOREGROUND_COLOR;
|
||||||
|
return DEFAULT_FOREGROUND_BOLD ? SgrColor.COLOR_BRIGHT[fg] : SgrColor.COLOR_NORMAL[fg];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ public class MulticompMachine implements Machine {
|
|||||||
private Memory rom;
|
private Memory rom;
|
||||||
|
|
||||||
|
|
||||||
public MulticompMachine() throws Exception {
|
public MulticompMachine(String romFile) throws Exception {
|
||||||
this.bus = new Bus(BUS_BOTTOM, BUS_TOP);
|
this.bus = new Bus(BUS_BOTTOM, BUS_TOP);
|
||||||
this.cpu = new Cpu();
|
this.cpu = new Cpu();
|
||||||
this.ram = new Memory(MEMORY_BASE, MEMORY_BASE + MEMORY_SIZE - 1, false);
|
this.ram = new Memory(MEMORY_BASE, MEMORY_BASE + MEMORY_SIZE - 1, false);
|
||||||
@@ -79,20 +79,23 @@ public class MulticompMachine implements Machine {
|
|||||||
bus.addDevice(ram);
|
bus.addDevice(ram);
|
||||||
bus.addDevice(acia, 1);
|
bus.addDevice(acia, 1);
|
||||||
bus.addDevice(new SdController(SD_BASE), 1);
|
bus.addDevice(new SdController(SD_BASE), 1);
|
||||||
|
|
||||||
// TODO: Make this configurable, of course.
|
if (romFile != null) {
|
||||||
File romImage = new File("rom.bin");
|
File romImage = new File("rom.bin");
|
||||||
if (romImage.canRead()) {
|
if (romImage.canRead()) {
|
||||||
logger.info("Loading ROM image from file " + romImage);
|
logger.info("Loading ROM image from file " + romImage);
|
||||||
this.rom = Memory.makeROM(ROM_BASE, ROM_BASE + ROM_SIZE - 1, romImage);
|
this.rom = Memory.makeROM(ROM_BASE, ROM_BASE + ROM_SIZE - 1, romImage);
|
||||||
} else {
|
} else {
|
||||||
logger.info("Default ROM file " + romImage +
|
logger.info("Default ROM file " + romImage +
|
||||||
" not found, loading empty R/W memory image.");
|
" not found, loading empty R/W memory image.");
|
||||||
|
this.rom = Memory.makeRAM(ROM_BASE, ROM_BASE + ROM_SIZE - 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.info("No ROM file specified, loading empty R/W memory image.");
|
||||||
this.rom = Memory.makeRAM(ROM_BASE, ROM_BASE + ROM_SIZE - 1);
|
this.rom = Memory.makeRAM(ROM_BASE, ROM_BASE + ROM_SIZE - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bus.addDevice(rom);
|
bus.addDevice(rom);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public class SimpleMachine implements Machine {
|
|||||||
private final Memory ram;
|
private final Memory ram;
|
||||||
private final Cpu cpu;
|
private final Cpu cpu;
|
||||||
|
|
||||||
public SimpleMachine() throws MemoryRangeException {
|
public SimpleMachine(String romFile) throws MemoryRangeException {
|
||||||
this.bus = new Bus(BUS_BOTTOM, BUS_TOP);
|
this.bus = new Bus(BUS_BOTTOM, BUS_TOP);
|
||||||
this.ram = new Memory(BUS_BOTTOM, BUS_TOP, false);
|
this.ram = new Memory(BUS_BOTTOM, BUS_TOP, false);
|
||||||
this.cpu = new Cpu();
|
this.cpu = new Cpu();
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public class SymonMachine implements Machine {
|
|||||||
private Memory rom;
|
private Memory rom;
|
||||||
|
|
||||||
|
|
||||||
public SymonMachine() throws Exception {
|
public SymonMachine(String romFile) throws Exception {
|
||||||
this.bus = new Bus(BUS_BOTTOM, BUS_TOP);
|
this.bus = new Bus(BUS_BOTTOM, BUS_TOP);
|
||||||
this.cpu = new Cpu();
|
this.cpu = new Cpu();
|
||||||
this.ram = new Memory(MEMORY_BASE, MEMORY_BASE + MEMORY_SIZE - 1, false);
|
this.ram = new Memory(MEMORY_BASE, MEMORY_BASE + MEMORY_SIZE - 1, false);
|
||||||
@@ -83,14 +83,18 @@ public class SymonMachine implements Machine {
|
|||||||
bus.addDevice(pia);
|
bus.addDevice(pia);
|
||||||
bus.addDevice(acia);
|
bus.addDevice(acia);
|
||||||
bus.addDevice(crtc);
|
bus.addDevice(crtc);
|
||||||
|
|
||||||
// TODO: Make this configurable, of course.
|
if (romFile != null) {
|
||||||
File romImage = new File("rom.bin");
|
File romImage = new File(romFile);
|
||||||
if (romImage.canRead()) {
|
if (romImage.canRead()) {
|
||||||
logger.info("Loading ROM image from file {}", romImage);
|
logger.info("Loading ROM image from file {}", romImage);
|
||||||
this.rom = Memory.makeROM(ROM_BASE, ROM_BASE + ROM_SIZE - 1, romImage);
|
this.rom = Memory.makeROM(ROM_BASE, ROM_BASE + ROM_SIZE - 1, romImage);
|
||||||
|
} else {
|
||||||
|
logger.info("Default ROM file {} not found, loading empty R/W memory image.", romImage);
|
||||||
|
this.rom = Memory.makeRAM(ROM_BASE, ROM_BASE + ROM_SIZE - 1);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.info("Default ROM file {} not found, loading empty R/W memory image.", romImage);
|
logger.info("No ROM file specified, loading empty R/W memory image.");
|
||||||
this.rom = Memory.makeRAM(ROM_BASE, ROM_BASE + ROM_SIZE - 1);
|
this.rom = Memory.makeRAM(ROM_BASE, ROM_BASE + ROM_SIZE - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,8 @@
|
|||||||
|
|
||||||
package com.loomcom.symon.ui;
|
package com.loomcom.symon.ui;
|
||||||
|
|
||||||
import com.grahamedgecombe.jterminal.JTerminal;
|
import com.loomcom.symon.jterminal.JTerminal;
|
||||||
import com.grahamedgecombe.jterminal.vt100.Vt100TerminalModel;
|
import com.loomcom.symon.jterminal.vt100.Vt100TerminalModel;
|
||||||
import com.loomcom.symon.exceptions.FifoUnderrunException;
|
import com.loomcom.symon.exceptions.FifoUnderrunException;
|
||||||
import com.loomcom.symon.util.FifoRingBuffer;
|
import com.loomcom.symon.util.FifoRingBuffer;
|
||||||
|
|
||||||
@@ -44,16 +44,19 @@ import java.awt.event.MouseListener;
|
|||||||
|
|
||||||
public class Console extends JTerminal implements KeyListener, MouseListener {
|
public class Console extends JTerminal implements KeyListener, MouseListener {
|
||||||
|
|
||||||
private static final int DEFAULT_BORDER_WIDTH = 10;
|
private static final long serialVersionUID = 6633818486963338126L;
|
||||||
|
|
||||||
|
private static final int DEFAULT_BORDER_WIDTH = 10;
|
||||||
// If true, swap CR and LF characters.
|
// If true, swap CR and LF characters.
|
||||||
private static final boolean SWAP_CR_AND_LF = true;
|
private static final boolean SWAP_CR_AND_LF = true;
|
||||||
|
|
||||||
// If true, send CRLF (0x0d 0x0a) whenever CR is typed
|
// If true, send CRLF (0x0d 0x0a) whenever CR is typed
|
||||||
private boolean sendCrForLf = false;
|
private boolean sendCrForLf;
|
||||||
private FifoRingBuffer<Character> typeAheadBuffer;
|
private FifoRingBuffer<Character> typeAheadBuffer;
|
||||||
|
|
||||||
public Console(int columns, int rows, Font font, boolean sendCrForLf) {
|
public Console(int columns, int rows, Font font, boolean sendCrForLf) {
|
||||||
super(new Vt100TerminalModel(columns, rows), font);
|
super(new Vt100TerminalModel(columns, rows), font);
|
||||||
|
//super(new Vt100TerminalModel(columns, rows));
|
||||||
// A small type-ahead buffer, as might be found in any real
|
// A small type-ahead buffer, as might be found in any real
|
||||||
// VT100-style serial terminal.
|
// VT100-style serial terminal.
|
||||||
this.typeAheadBuffer = new FifoRingBuffer<>(128);
|
this.typeAheadBuffer = new FifoRingBuffer<>(128);
|
||||||
@@ -104,7 +107,7 @@ public class Console extends JTerminal implements KeyListener, MouseListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sendCrForLf && keyTyped == 0x0d) {
|
if (sendCrForLf && (keyTyped == 0x0d)) {
|
||||||
typeAheadBuffer.push((char) 0x0d);
|
typeAheadBuffer.push((char) 0x0d);
|
||||||
typeAheadBuffer.push((char) 0x0a);
|
typeAheadBuffer.push((char) 0x0a);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -331,10 +331,10 @@ public class MemoryWindow extends JFrame implements ActionListener {
|
|||||||
return Utils.wordToHex(fullAddress(row, 1));
|
return Utils.wordToHex(fullAddress(row, 1));
|
||||||
} else if (column < 9) {
|
} else if (column < 9) {
|
||||||
// Display hex value of the data
|
// Display hex value of the data
|
||||||
return Utils.byteToHex(bus.read(fullAddress(row, column)));
|
return Utils.byteToHex(bus.read(fullAddress(row, column), false));
|
||||||
} else {
|
} else {
|
||||||
// Display the ASCII equivalent (if printable)
|
// Display the ASCII equivalent (if printable)
|
||||||
return Utils.byteToAscii(bus.read(fullAddress(row, column - 8)));
|
return Utils.byteToAscii(bus.read(fullAddress(row, column - 8), false));
|
||||||
}
|
}
|
||||||
} catch (MemoryAccessException ex) {
|
} catch (MemoryAccessException ex) {
|
||||||
return "??";
|
return "??";
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import com.loomcom.symon.machines.Machine;
|
|||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.border.Border;
|
import javax.swing.border.Border;
|
||||||
import javax.swing.border.EtchedBorder;
|
import javax.swing.border.EtchedBorder;
|
||||||
|
import javax.swing.plaf.metal.MetalTextFieldUI;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
@@ -69,7 +70,7 @@ public class StatusPanel extends JPanel {
|
|||||||
private JTextField xField;
|
private JTextField xField;
|
||||||
private JTextField yField;
|
private JTextField yField;
|
||||||
|
|
||||||
private Machine machine;
|
private final Machine machine;
|
||||||
|
|
||||||
private static final int EMPTY_BORDER = 10;
|
private static final int EMPTY_BORDER = 10;
|
||||||
private static final Border LABEL_BORDER = BorderFactory.createEmptyBorder(0, 5, 0, 0);
|
private static final Border LABEL_BORDER = BorderFactory.createEmptyBorder(0, 5, 0, 0);
|
||||||
@@ -392,6 +393,13 @@ public class StatusPanel extends JPanel {
|
|||||||
textField.setMaximumSize(size);
|
textField.setMaximumSize(size);
|
||||||
textField.setPreferredSize(size);
|
textField.setPreferredSize(size);
|
||||||
textField.setBackground(Color.WHITE);
|
textField.setBackground(Color.WHITE);
|
||||||
|
// Although we usually defer to the system look-and-feel, for
|
||||||
|
// these small text fields in particular, we use a Metal
|
||||||
|
// look-and-feel because native look-and-feel breaks very small
|
||||||
|
// text fields under GTK+ (they are drawn with an inner margin
|
||||||
|
// even if the margin is set to 0)
|
||||||
|
textField.setUI(new MetalTextFieldUI());
|
||||||
|
|
||||||
return textField;
|
return textField;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+105
-15
@@ -7,7 +7,7 @@ import org.junit.Test;
|
|||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
public class AciaTest6850 {
|
public class Acia6850Test {
|
||||||
|
|
||||||
private final static int CMD_STAT_REG = 0;
|
private final static int CMD_STAT_REG = 0;
|
||||||
private final static int DATA_REG = 1;
|
private final static int DATA_REG = 1;
|
||||||
@@ -67,7 +67,7 @@ public class AciaTest6850 {
|
|||||||
verify(mockBus, never()).assertIrq();
|
verify(mockBus, never()).assertIrq();
|
||||||
|
|
||||||
// Transmission should cause IRQ
|
// Transmission should cause IRQ
|
||||||
acia.txRead();
|
acia.txRead(true);
|
||||||
|
|
||||||
verify(mockBus, atLeastOnce()).assertIrq();
|
verify(mockBus, atLeastOnce()).assertIrq();
|
||||||
}
|
}
|
||||||
@@ -86,16 +86,88 @@ public class AciaTest6850 {
|
|||||||
acia.write(DATA_REG, 'a');
|
acia.write(DATA_REG, 'a');
|
||||||
|
|
||||||
// Transmission should cause IRQ
|
// Transmission should cause IRQ
|
||||||
acia.txRead();
|
acia.txRead(true);
|
||||||
|
|
||||||
verify(mockBus, never()).assertIrq();
|
verify(mockBus, never()).assertIrq();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldTriggerInterruptFlagOnRxFullIfRxIrqEnabled() throws Exception {
|
||||||
|
Bus mockBus = mock(Bus.class);
|
||||||
|
|
||||||
|
Acia acia = newAcia();
|
||||||
|
acia.setBus(mockBus);
|
||||||
|
|
||||||
|
// Disable TX IRQ, Enable RX IRQ
|
||||||
|
acia.write(CMD_STAT_REG, 0x80);
|
||||||
|
|
||||||
|
acia.rxWrite('a');
|
||||||
|
|
||||||
|
// Receive should cause IRQ flag to be set
|
||||||
|
assertEquals(0x80, acia.read(0x0000, true) & 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotTriggerInterruptFlagOnRxFullIfRxIrqNotEnabled() throws Exception {
|
||||||
|
Bus mockBus = mock(Bus.class);
|
||||||
|
|
||||||
|
Acia acia = newAcia();
|
||||||
|
acia.setBus(mockBus);
|
||||||
|
|
||||||
|
// Disable TX IRQ, Disable RX IRQ
|
||||||
|
acia.write(CMD_STAT_REG, 0x00);
|
||||||
|
|
||||||
|
acia.rxWrite('a');
|
||||||
|
|
||||||
|
// Receive should not cause IRQ flag to be set
|
||||||
|
assertEquals(0x00, acia.read(0x0000, true) & 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldTriggerInterruptFlagOnTxEmptyIfTxIrqEnabled() throws Exception {
|
||||||
|
Bus mockBus = mock(Bus.class);
|
||||||
|
|
||||||
|
Acia acia = newAcia();
|
||||||
|
acia.setBus(mockBus);
|
||||||
|
|
||||||
|
// Enable TX IRQ, Disable RX IRQ
|
||||||
|
acia.write(CMD_STAT_REG, 0x20);
|
||||||
|
|
||||||
|
// Write data
|
||||||
|
acia.write(1, 'a');
|
||||||
|
|
||||||
|
verify(mockBus, never()).assertIrq();
|
||||||
|
|
||||||
|
// Transmission should cause IRQ flag to be set
|
||||||
|
acia.txRead(true);
|
||||||
|
|
||||||
|
assertEquals(0x80, acia.read(0x0000, true) & 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotTriggerInterruptFlagOnTxEmptyIfTxIrqNotEnabled() throws Exception {
|
||||||
|
Bus mockBus = mock(Bus.class);
|
||||||
|
|
||||||
|
Acia acia = newAcia();
|
||||||
|
acia.setBus(mockBus);
|
||||||
|
|
||||||
|
// Disable TX IRQ, Disable RX IRQ
|
||||||
|
acia.write(CMD_STAT_REG, 0x02);
|
||||||
|
|
||||||
|
// Write data
|
||||||
|
acia.write(DATA_REG, 'a');
|
||||||
|
|
||||||
|
// Transmission should not cause IRQ flag to be set
|
||||||
|
acia.txRead(true);
|
||||||
|
|
||||||
|
assertEquals(0x00, acia.read(0x0000, true) & 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void newAciaShouldHaveTxEmptyStatus() throws Exception {
|
public void newAciaShouldHaveTxEmptyStatus() throws Exception {
|
||||||
Acia acia = newAcia();
|
Acia acia = newAcia();
|
||||||
|
|
||||||
assertEquals(0x02, acia.read(CMD_STAT_REG) & 0x02);
|
assertEquals(0x02, acia.read(CMD_STAT_REG, true) & 0x02);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -103,7 +175,7 @@ public class AciaTest6850 {
|
|||||||
Acia acia = newAcia();
|
Acia acia = newAcia();
|
||||||
|
|
||||||
acia.txWrite('a');
|
acia.txWrite('a');
|
||||||
assertEquals(0x00, acia.read(CMD_STAT_REG) & 0x02);
|
assertEquals(0x00, acia.read(CMD_STAT_REG, true) & 0x02);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -112,7 +184,7 @@ public class AciaTest6850 {
|
|||||||
|
|
||||||
acia.rxWrite('a');
|
acia.rxWrite('a');
|
||||||
|
|
||||||
assertEquals(0x01, acia.read(CMD_STAT_REG) & 0x01);
|
assertEquals(0x01, acia.read(CMD_STAT_REG, true) & 0x01);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -123,12 +195,30 @@ public class AciaTest6850 {
|
|||||||
acia.rxWrite('a');
|
acia.rxWrite('a');
|
||||||
acia.txWrite('b');
|
acia.txWrite('b');
|
||||||
|
|
||||||
assertEquals(0x01, acia.read(CMD_STAT_REG) & 0x03);
|
assertEquals(0x01, acia.read(CMD_STAT_REG, true) & 0x03);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void aciaShouldOverrunAndReadShouldReset()
|
public void aciaShouldOverrunAndReadShouldReset()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
|
Acia acia = newAcia();
|
||||||
|
|
||||||
|
// overrun ACIA
|
||||||
|
acia.rxWrite('a');
|
||||||
|
acia.rxWrite('b');
|
||||||
|
|
||||||
|
assertEquals(0x20, acia.read(CMD_STAT_REG, true) & 0x20);
|
||||||
|
|
||||||
|
// read should reset
|
||||||
|
acia.rxRead(true);
|
||||||
|
assertEquals(0x00, acia.read(CMD_STAT_REG, true) & 0x20);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void aciaShouldOverrunAndMemoryWindowReadShouldNotReset()
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
Acia acia = newAcia();
|
Acia acia = newAcia();
|
||||||
|
|
||||||
@@ -136,11 +226,11 @@ public class AciaTest6850 {
|
|||||||
acia.rxWrite('a');
|
acia.rxWrite('a');
|
||||||
acia.rxWrite('b');
|
acia.rxWrite('b');
|
||||||
|
|
||||||
assertEquals(0x20, acia.read(CMD_STAT_REG) & 0x20);
|
assertEquals(0x20, acia.read(CMD_STAT_REG, true) & 0x20);
|
||||||
|
|
||||||
// read should reset
|
// memory window read should not reset
|
||||||
acia.rxRead();
|
acia.rxRead(false);
|
||||||
assertEquals(0x00, acia.read(CMD_STAT_REG) & 0x20);
|
assertEquals(0x20, acia.read(CMD_STAT_REG, true) & 0x20);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,15 +239,15 @@ public class AciaTest6850 {
|
|||||||
throws Exception {
|
throws Exception {
|
||||||
Acia acia = newAcia();
|
Acia acia = newAcia();
|
||||||
|
|
||||||
assertEquals(0x00, acia.read(CMD_STAT_REG) & 0x01);
|
assertEquals(0x00, acia.read(CMD_STAT_REG, true) & 0x01);
|
||||||
|
|
||||||
acia.rxWrite('a');
|
acia.rxWrite('a');
|
||||||
|
|
||||||
assertEquals(0x01, acia.read(CMD_STAT_REG) & 0x01);
|
assertEquals(0x01, acia.read(CMD_STAT_REG, true) & 0x01);
|
||||||
|
|
||||||
acia.rxRead();
|
acia.rxRead(true);
|
||||||
|
|
||||||
assertEquals(0x00, acia.read(CMD_STAT_REG) & 0x01);
|
assertEquals(0x00, acia.read(CMD_STAT_REG, true) & 0x01);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -55,7 +55,7 @@ public class AciaTest {
|
|||||||
verify(mockBus, never()).assertIrq();
|
verify(mockBus, never()).assertIrq();
|
||||||
|
|
||||||
// Transmission should cause IRQ
|
// Transmission should cause IRQ
|
||||||
acia.txRead();
|
acia.txRead(true);
|
||||||
|
|
||||||
verify(mockBus, atLeastOnce()).assertIrq();
|
verify(mockBus, atLeastOnce()).assertIrq();
|
||||||
}
|
}
|
||||||
@@ -73,17 +73,89 @@ public class AciaTest {
|
|||||||
// Write data
|
// Write data
|
||||||
acia.write(0, 'a');
|
acia.write(0, 'a');
|
||||||
|
|
||||||
// Transmission should cause IRQ
|
// Transmission should not cause IRQ
|
||||||
acia.txRead();
|
acia.txRead(true);
|
||||||
|
|
||||||
verify(mockBus, never()).assertIrq();
|
verify(mockBus, never()).assertIrq();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldTriggerInterruptFlagOnRxFullIfRxIrqEnabled() throws Exception {
|
||||||
|
Bus mockBus = mock(Bus.class);
|
||||||
|
|
||||||
|
Acia acia = new Acia6551(0x000);
|
||||||
|
acia.setBus(mockBus);
|
||||||
|
|
||||||
|
// Disable TX IRQ, Enable RX IRQ
|
||||||
|
acia.write(2, 0x00);
|
||||||
|
|
||||||
|
acia.rxWrite('a');
|
||||||
|
|
||||||
|
// Receive should cause IRQ flag to be set
|
||||||
|
assertEquals(0x80, acia.read(0x0001, true) & 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotTriggerInterruptFlagOnRxFullIfRxIrqNotEnabled() throws Exception {
|
||||||
|
Bus mockBus = mock(Bus.class);
|
||||||
|
|
||||||
|
Acia acia = new Acia6551(0x000);
|
||||||
|
acia.setBus(mockBus);
|
||||||
|
|
||||||
|
// Disable TX IRQ, Disable RX IRQ
|
||||||
|
acia.write(2, 0x02);
|
||||||
|
|
||||||
|
acia.rxWrite('a');
|
||||||
|
|
||||||
|
// Receive should not cause IRQ flag to be set
|
||||||
|
assertEquals(0x00, acia.read(0x0001, true) & 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldTriggerInterruptFlagOnTxEmptyIfTxIrqEnabled() throws Exception {
|
||||||
|
Bus mockBus = mock(Bus.class);
|
||||||
|
|
||||||
|
Acia acia = new Acia6551(0x000);
|
||||||
|
acia.setBus(mockBus);
|
||||||
|
|
||||||
|
// Enable TX IRQ, Disable RX IRQ
|
||||||
|
acia.write(2, 0x06);
|
||||||
|
|
||||||
|
// Write data
|
||||||
|
acia.write(0, 'a');
|
||||||
|
|
||||||
|
verify(mockBus, never()).assertIrq();
|
||||||
|
|
||||||
|
// Transmission should cause IRQ flag to be set
|
||||||
|
acia.txRead(true);
|
||||||
|
|
||||||
|
assertEquals(0x80, acia.read(0x0001, true) & 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotTriggerInterruptFlagOnTxEmptyIfTxIrqNotEnabled() throws Exception {
|
||||||
|
Bus mockBus = mock(Bus.class);
|
||||||
|
|
||||||
|
Acia acia = new Acia6551(0x000);
|
||||||
|
acia.setBus(mockBus);
|
||||||
|
|
||||||
|
// Disable TX IRQ, Disable RX IRQ
|
||||||
|
acia.write(2, 0x02);
|
||||||
|
|
||||||
|
// Write data
|
||||||
|
acia.write(0, 'a');
|
||||||
|
|
||||||
|
// Transmission should not cause IRQ flag to be set
|
||||||
|
acia.txRead(true);
|
||||||
|
|
||||||
|
assertEquals(0x00, acia.read(0x0001, true) & 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void newAciaShouldHaveTxEmptyStatus() throws Exception {
|
public void newAciaShouldHaveTxEmptyStatus() throws Exception {
|
||||||
Acia acia = new Acia6551(0x000);
|
Acia acia = new Acia6551(0x000);
|
||||||
|
|
||||||
assertEquals(0x10, acia.read(0x0001));
|
assertEquals(0x10, acia.read(0x0001, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -91,7 +163,7 @@ public class AciaTest {
|
|||||||
Acia acia = new Acia6551(0x000);
|
Acia acia = new Acia6551(0x000);
|
||||||
|
|
||||||
acia.txWrite('a');
|
acia.txWrite('a');
|
||||||
assertEquals(0x00, acia.read(0x0001));
|
assertEquals(0x00, acia.read(0x0001, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -99,7 +171,7 @@ public class AciaTest {
|
|||||||
Acia acia = new Acia6551(0x000);
|
Acia acia = new Acia6551(0x000);
|
||||||
|
|
||||||
acia.rxWrite('a');
|
acia.rxWrite('a');
|
||||||
assertEquals(0x18, acia.read(0x0001));
|
assertEquals(0x18, acia.read(0x0001, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -110,7 +182,7 @@ public class AciaTest {
|
|||||||
acia.rxWrite('a');
|
acia.rxWrite('a');
|
||||||
acia.txWrite('b');
|
acia.txWrite('b');
|
||||||
|
|
||||||
assertEquals(0x08, acia.read(0x0001));
|
assertEquals(0x08, acia.read(0x0001, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -123,14 +195,31 @@ public class AciaTest {
|
|||||||
acia.rxWrite('a');
|
acia.rxWrite('a');
|
||||||
acia.rxWrite('b');
|
acia.rxWrite('b');
|
||||||
|
|
||||||
assertEquals(0x04, acia.read(0x0001) & 0x04);
|
assertEquals(0x04, acia.read(0x0001, true) & 0x04);
|
||||||
|
|
||||||
// read should reset
|
// read should reset
|
||||||
acia.rxRead();
|
acia.rxRead(true);
|
||||||
assertEquals(0x00, acia.read(0x0001) & 0x04);
|
assertEquals(0x00, acia.read(0x0001, true) & 0x04);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void aciaShouldOverrunAndMemoryWindowReadShouldNotReset()
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
|
Acia acia = new Acia6551(0x0000);
|
||||||
|
|
||||||
|
// overrun ACIA
|
||||||
|
acia.rxWrite('a');
|
||||||
|
acia.rxWrite('b');
|
||||||
|
|
||||||
|
assertEquals(0x04, acia.read(0x0001, true) & 0x04);
|
||||||
|
|
||||||
|
// memory window read should not reset
|
||||||
|
acia.rxRead(false);
|
||||||
|
assertEquals(0x04, acia.read(0x0001, true) & 0x04);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void readingBuffersShouldResetStatus()
|
public void readingBuffersShouldResetStatus()
|
||||||
@@ -141,11 +230,28 @@ public class AciaTest {
|
|||||||
acia.txWrite('b');
|
acia.txWrite('b');
|
||||||
|
|
||||||
|
|
||||||
assertEquals(0x08, acia.read(0x0001));
|
assertEquals(0x08, acia.read(0x0001, true));
|
||||||
|
|
||||||
assertEquals('a', acia.rxRead());
|
assertEquals('a', acia.rxRead(true));
|
||||||
assertEquals('b', acia.txRead());
|
assertEquals('b', acia.txRead(true));
|
||||||
|
|
||||||
assertEquals(0x10, acia.read(0x0001));
|
assertEquals(0x10, acia.read(0x0001, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void A()
|
||||||
|
throws Exception {
|
||||||
|
Acia acia = new Acia6551(0x0000);
|
||||||
|
|
||||||
|
acia.rxWrite('a');
|
||||||
|
acia.txWrite('b');
|
||||||
|
|
||||||
|
|
||||||
|
assertEquals(0x08, acia.read(0x0001, true));
|
||||||
|
|
||||||
|
assertEquals('a', acia.rxRead(false));
|
||||||
|
assertEquals('b', acia.txRead(false));
|
||||||
|
|
||||||
|
assertEquals(0x08, acia.read(0x0001, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
package com.loomcom.symon;
|
||||||
|
|
||||||
|
import com.loomcom.symon.devices.Memory;
|
||||||
|
import com.loomcom.symon.exceptions.MemoryAccessException;
|
||||||
|
import junit.framework.*;
|
||||||
|
|
||||||
|
import static junit.framework.TestCase.assertFalse;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for Zero Page Indirect addressing mode, found on some instructions
|
||||||
|
* in the 65C02 and 65816
|
||||||
|
*/
|
||||||
|
public class Cpu65C02AbsoluteModeTest extends TestCase {
|
||||||
|
protected Cpu cpu;
|
||||||
|
protected Bus bus;
|
||||||
|
protected Memory mem;
|
||||||
|
|
||||||
|
private void makeCmosCpu() throws Exception {
|
||||||
|
makeCpu(InstructionTable.CpuBehavior.CMOS_6502);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeNmosCpu() throws Exception {
|
||||||
|
makeCpu(InstructionTable.CpuBehavior.NMOS_6502);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeCpu(InstructionTable.CpuBehavior behavior) throws Exception {
|
||||||
|
this.cpu = new Cpu(behavior);
|
||||||
|
this.bus = new Bus(0x0000, 0xffff);
|
||||||
|
this.mem = new Memory(0x0000, 0xffff);
|
||||||
|
bus.addCpu(cpu);
|
||||||
|
bus.addDevice(mem);
|
||||||
|
|
||||||
|
// Load the reset vector.
|
||||||
|
bus.write(0xfffc, Bus.DEFAULT_LOAD_ADDRESS & 0x00ff);
|
||||||
|
bus.write(0xfffd, (Bus.DEFAULT_LOAD_ADDRESS & 0xff00) >>> 8);
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_STZ() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
bus.write(0x0010,0xff);
|
||||||
|
|
||||||
|
bus.loadProgram(0x9c, 0x10, 0x00); // STZ Absolute
|
||||||
|
|
||||||
|
// Test STZ Absolute ($0010)
|
||||||
|
assertEquals(0xff, bus.read(0x0010, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00, bus.read(0x0010, true));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_STZRequiresCmosCpu() throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
bus.write(0x0010,0xff);
|
||||||
|
|
||||||
|
bus.loadProgram(0x9c, 0x10, 0x00); // STZ Absolute
|
||||||
|
|
||||||
|
// Test STZ Absolute ($0010)
|
||||||
|
assertEquals(0xff, bus.read(0x0010, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xff, bus.read(0x0010, true));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_TSB() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
bus.loadProgram(0x0c, 0x10, 0x00); // 65C02 TSB Absolute $0010
|
||||||
|
|
||||||
|
bus.write(0x10, 0x01);
|
||||||
|
cpu.setAccumulator(0x01);
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x01,bus.read(0x10,true)); // 0x01 & 0x01 = 0x01
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
cpu.setAccumulator(0x02);
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x03,bus.read(0x0010,true));
|
||||||
|
assertTrue(cpu.getZeroFlag());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_TSBRequiresCmosCpu() throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
bus.loadProgram(0x0c, 0x10, 0x00); // 65C02 TSB Absolute $0010
|
||||||
|
|
||||||
|
bus.write(0x10, 0x00);
|
||||||
|
cpu.setAccumulator(0x01);
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00,bus.read(0x0010,true));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_TRB() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
bus.loadProgram(0x1c, 0x00, 0x01); // 65C02 TRB Absolute $0010
|
||||||
|
|
||||||
|
bus.write(0x0100, 0x03);
|
||||||
|
cpu.setAccumulator(0x01);
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x02,bus.read(0x0100,true)); // $03 &= ~($01) = $02
|
||||||
|
assertFalse(cpu.getZeroFlag()); // Z = !(A & M)
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
cpu.setAccumulator(0x01);
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x02,bus.read(0x0100,true)); // $02 &= ~($01) = $02
|
||||||
|
assertTrue(cpu.getZeroFlag()); // Z = !(A & M)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_TRBRequiresCmosCpu() throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
bus.loadProgram(0x1c, 0x00, 0x01); // 65C02 TRB Absolute $0010
|
||||||
|
|
||||||
|
bus.write(0x0100, 0xff);
|
||||||
|
cpu.setAccumulator(0x01);
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xff,bus.read(0x0100,true));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
package com.loomcom.symon;
|
||||||
|
|
||||||
|
import com.loomcom.symon.devices.Memory;
|
||||||
|
import com.loomcom.symon.exceptions.MemoryAccessException;
|
||||||
|
import junit.framework.*;
|
||||||
|
|
||||||
|
import static junit.framework.TestCase.assertFalse;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for Zero Page Indirect addressing mode, found on some instructions
|
||||||
|
* in the 65C02 and 65816
|
||||||
|
*/
|
||||||
|
public class Cpu65C02AbsoluteXModeTest extends TestCase {
|
||||||
|
protected Cpu cpu;
|
||||||
|
protected Bus bus;
|
||||||
|
protected Memory mem;
|
||||||
|
|
||||||
|
private void makeCmosCpu() throws Exception {
|
||||||
|
makeCpu(InstructionTable.CpuBehavior.CMOS_6502);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeNmosCpu() throws Exception {
|
||||||
|
makeCpu(InstructionTable.CpuBehavior.NMOS_6502);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeCpu(InstructionTable.CpuBehavior behavior) throws Exception {
|
||||||
|
this.cpu = new Cpu(behavior);
|
||||||
|
this.bus = new Bus(0x0000, 0xffff);
|
||||||
|
this.mem = new Memory(0x0000, 0xffff);
|
||||||
|
bus.addCpu(cpu);
|
||||||
|
bus.addDevice(mem);
|
||||||
|
|
||||||
|
// Load the reset vector.
|
||||||
|
bus.write(0xfffc, Bus.DEFAULT_LOAD_ADDRESS & 0x00ff);
|
||||||
|
bus.write(0xfffd, (Bus.DEFAULT_LOAD_ADDRESS & 0xff00) >>> 8);
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_STZ() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
bus.write(0x0011,0xff);
|
||||||
|
|
||||||
|
bus.loadProgram(0x9e, 0x10, 0x00); // STZ Absolute,X
|
||||||
|
|
||||||
|
// Test STZ Absolute,X ($0011)
|
||||||
|
cpu.setXRegister(0x01);
|
||||||
|
assertEquals(0xff, bus.read(0x0011, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00, bus.read(0x0011, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_STZRequiresCmosCpu() throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
bus.write(0x0011,0xff);
|
||||||
|
|
||||||
|
bus.loadProgram(0x9e, 0x10, 0x00); // STZ Absolute,X
|
||||||
|
|
||||||
|
// Test STZ Absolute,X ($0011)
|
||||||
|
cpu.setXRegister(0x01);
|
||||||
|
assertEquals(0xff, bus.read(0x0011, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xff, bus.read(0x0011, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_JMP_Indirect_Absolute_X () throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
bus.write(0x304,00);
|
||||||
|
bus.write(0x0305,04);
|
||||||
|
bus.loadProgram(0x7c, 0x00, 0x03);
|
||||||
|
cpu.setXRegister(0x04);
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x0400,cpu.getProgramCounter());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_JMP_Indirect_Absolute_XRequiresCmosCpu () throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
bus.write(0x304,00);
|
||||||
|
bus.write(0x0305,04);
|
||||||
|
bus.loadProgram(0x7c, 0x00, 0x03);
|
||||||
|
cpu.setXRegister(0x04);
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x0203,cpu.getProgramCounter());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package com.loomcom.symon;
|
||||||
|
|
||||||
|
import com.loomcom.symon.devices.Memory;
|
||||||
|
import com.loomcom.symon.exceptions.MemoryAccessException;
|
||||||
|
import junit.framework.*;
|
||||||
|
|
||||||
|
import static junit.framework.TestCase.assertFalse;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for Zero Page Indirect addressing mode, found on some instructions
|
||||||
|
* in the 65C02 and 65816
|
||||||
|
*/
|
||||||
|
public class Cpu65C02ImmediateModeTest extends TestCase {
|
||||||
|
protected Cpu cpu;
|
||||||
|
protected Bus bus;
|
||||||
|
protected Memory mem;
|
||||||
|
|
||||||
|
private void makeCmosCpu() throws Exception {
|
||||||
|
makeCpu(InstructionTable.CpuBehavior.CMOS_6502);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeNmosCpu() throws Exception {
|
||||||
|
makeCpu(InstructionTable.CpuBehavior.NMOS_6502);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeCpu(InstructionTable.CpuBehavior behavior) throws Exception {
|
||||||
|
this.cpu = new Cpu(behavior);
|
||||||
|
this.bus = new Bus(0x0000, 0xffff);
|
||||||
|
this.mem = new Memory(0x0000, 0xffff);
|
||||||
|
bus.addCpu(cpu);
|
||||||
|
bus.addDevice(mem);
|
||||||
|
|
||||||
|
// Load the reset vector.
|
||||||
|
bus.write(0xfffc, Bus.DEFAULT_LOAD_ADDRESS & 0x00ff);
|
||||||
|
bus.write(0xfffd, (Bus.DEFAULT_LOAD_ADDRESS & 0xff00) >>> 8);
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_BIT_Immediate() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
bus.loadProgram(0x89, 0xF1); // 65C02 BIT #$01
|
||||||
|
cpu.setAccumulator(0x02);
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertTrue(cpu.getZeroFlag()); // #$02 & #$F1 = 0
|
||||||
|
assertEquals(0x02,cpu.getAccumulator()); // Accumulator should not be modified
|
||||||
|
assertFalse(cpu.getNegativeFlag()); // BIT #Immediate should not set N or V Flags
|
||||||
|
assertFalse(cpu.getOverflowFlag());
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
cpu.setAccumulator(0x01);
|
||||||
|
cpu.step();
|
||||||
|
assertFalse(cpu.getZeroFlag()); // #$F1 & #$01 = 1
|
||||||
|
assertEquals(0x01,cpu.getAccumulator());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_BIT_ImmediateRequiresCmosCpu() throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
bus.loadProgram(0x89, 0xF1); // 65C02 BIT #$01
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
cpu.setAccumulator(0x01);
|
||||||
|
assertTrue(cpu.getZeroFlag());
|
||||||
|
assertEquals(0x01,cpu.getAccumulator());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,252 @@
|
|||||||
|
package com.loomcom.symon;
|
||||||
|
|
||||||
|
import com.loomcom.symon.devices.Memory;
|
||||||
|
import com.loomcom.symon.exceptions.MemoryAccessException;
|
||||||
|
import junit.framework.*;
|
||||||
|
|
||||||
|
import static junit.framework.TestCase.assertFalse;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for Zero Page Indirect addressing mode, found on some instructions
|
||||||
|
* in the 65C02 and 65816
|
||||||
|
*/
|
||||||
|
public class Cpu65C02ImpliedModeTest extends TestCase {
|
||||||
|
protected Cpu cpu;
|
||||||
|
protected Bus bus;
|
||||||
|
protected Memory mem;
|
||||||
|
|
||||||
|
private void makeCmosCpu() throws Exception {
|
||||||
|
makeCpu(InstructionTable.CpuBehavior.CMOS_6502);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeNmosCpu() throws Exception {
|
||||||
|
makeCpu(InstructionTable.CpuBehavior.NMOS_6502);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeCpu(InstructionTable.CpuBehavior behavior) throws Exception {
|
||||||
|
this.cpu = new Cpu(behavior);
|
||||||
|
this.bus = new Bus(0x0000, 0xffff);
|
||||||
|
this.mem = new Memory(0x0000, 0xffff);
|
||||||
|
bus.addCpu(cpu);
|
||||||
|
bus.addDevice(mem);
|
||||||
|
|
||||||
|
// Load the reset vector.
|
||||||
|
bus.write(0xfffc, Bus.DEFAULT_LOAD_ADDRESS & 0x00ff);
|
||||||
|
bus.write(0xfffd, (Bus.DEFAULT_LOAD_ADDRESS & 0xff00) >>> 8);
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_PHX() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
cpu.stackPush(0x00);
|
||||||
|
cpu.setXRegister(0xff);
|
||||||
|
bus.loadProgram(0xda);
|
||||||
|
|
||||||
|
assertEquals(cpu.stackPeek(), 0x00);
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(cpu.stackPeek(), 0xff);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_PHXRequiresCmosCpu() throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
cpu.stackPush(0x00);
|
||||||
|
cpu.setXRegister(0xff);
|
||||||
|
bus.loadProgram(0xda);
|
||||||
|
|
||||||
|
assertEquals(cpu.stackPeek(), 0x00);
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(cpu.stackPeek(), 0x00);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_PLX() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
cpu.stackPush(0xff);
|
||||||
|
cpu.setXRegister(0x00);
|
||||||
|
bus.loadProgram(0xfa);
|
||||||
|
|
||||||
|
assertEquals(0x00, cpu.getXRegister());
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xff, cpu.getXRegister());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_PLXRequiresCmosCpu() throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
cpu.stackPush(0xff);
|
||||||
|
cpu.setXRegister(0x00);
|
||||||
|
bus.loadProgram(0xfa);
|
||||||
|
|
||||||
|
assertEquals(0x00, cpu.getXRegister());
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00, cpu.getXRegister());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_PHY() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
cpu.stackPush(0x00);
|
||||||
|
cpu.setYRegister(0xff);
|
||||||
|
bus.loadProgram(0x5a);
|
||||||
|
|
||||||
|
assertEquals(0x00, cpu.stackPeek());
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xff, cpu.stackPeek());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_PHYRequiresCmosCpu() throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
cpu.stackPush(0x00);
|
||||||
|
cpu.setYRegister(0xff);
|
||||||
|
bus.loadProgram(0x5a);
|
||||||
|
|
||||||
|
assertEquals(0x00, cpu.stackPeek());
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00, cpu.stackPeek());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_PLY() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
cpu.stackPush(0xff);
|
||||||
|
cpu.setYRegister(0x00);
|
||||||
|
bus.loadProgram(0x7a);
|
||||||
|
|
||||||
|
assertEquals(0x00, cpu.getYRegister());
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xff, cpu.getYRegister());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_PLYRequiresCmosCpu() throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
cpu.stackPush(0xff);
|
||||||
|
cpu.setYRegister(0x00);
|
||||||
|
bus.loadProgram(0x7a);
|
||||||
|
|
||||||
|
assertEquals(0x00, cpu.getYRegister());
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00, cpu.getYRegister());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_INC_A() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
cpu.setAccumulator(0x10);
|
||||||
|
bus.loadProgram(0x1a);
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x11, cpu.getAccumulator());
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
|
// Incrementing to 0 should set Zero Flag
|
||||||
|
cpu.reset();
|
||||||
|
cpu.setAccumulator(0xff);
|
||||||
|
cpu.step();
|
||||||
|
assertTrue(cpu.getZeroFlag());
|
||||||
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
|
// Should set Negative Flag
|
||||||
|
cpu.reset();
|
||||||
|
cpu.setAccumulator(0x7F);
|
||||||
|
cpu.step();
|
||||||
|
assertTrue(cpu.getNegativeFlag());
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_INC_ARequiresCmosCpu() throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
cpu.setAccumulator(0x10);
|
||||||
|
bus.loadProgram(0x1a);
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x10, cpu.getAccumulator());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_DEC_A() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
cpu.setAccumulator(0x10);
|
||||||
|
bus.loadProgram(0x3a);
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x0F, cpu.getAccumulator());
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
|
// Decrementing to 0 should set Zero Flag
|
||||||
|
cpu.reset();
|
||||||
|
cpu.setAccumulator(0x01);
|
||||||
|
cpu.step();
|
||||||
|
assertTrue(cpu.getZeroFlag());
|
||||||
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
|
// Should set Negative Flag
|
||||||
|
cpu.reset();
|
||||||
|
cpu.setAccumulator(0x00);
|
||||||
|
cpu.step();
|
||||||
|
assertTrue(cpu.getNegativeFlag());
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_DEC_ARequiresCmosCpu() throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
cpu.setAccumulator(0x10);
|
||||||
|
bus.loadProgram(0x3a);
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x10, cpu.getAccumulator());
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_BRK_clearsDecimalModeFlag() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
cpu.setDecimalModeFlag();
|
||||||
|
assertEquals(0x00, cpu.stackPeek());
|
||||||
|
assertFalse(cpu.getBreakFlag());
|
||||||
|
assertTrue(cpu.getDecimalModeFlag());
|
||||||
|
assertEquals(0x0200, cpu.getProgramCounter());
|
||||||
|
assertEquals(0xff, cpu.getStackPointer());
|
||||||
|
|
||||||
|
// Set the IRQ vector
|
||||||
|
bus.write(0xffff, 0x12);
|
||||||
|
bus.write(0xfffe, 0x34);
|
||||||
|
|
||||||
|
bus.loadProgram(0xea, // NOP
|
||||||
|
0xea, // NOP
|
||||||
|
0xea, // NOP
|
||||||
|
0x00, // BRK
|
||||||
|
0xea, // NOP
|
||||||
|
0xea); // NOP
|
||||||
|
|
||||||
|
cpu.step(3); // Three NOP instructions
|
||||||
|
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter());
|
||||||
|
assertTrue(cpu.getDecimalModeFlag());
|
||||||
|
cpu.step(); // Triggers the BRK
|
||||||
|
|
||||||
|
// Was at PC = 0x204. PC+1 should now be on the stack
|
||||||
|
assertEquals(0x02, bus.read(0x1ff, true)); // PC high byte
|
||||||
|
assertEquals(0x05, bus.read(0x1fe, true)); // PC low byte
|
||||||
|
|
||||||
|
|
||||||
|
// Interrupt vector held 0x1234, so we should be there.
|
||||||
|
assertEquals(0x1234, cpu.getProgramCounter());
|
||||||
|
assertEquals(0xfc, cpu.getStackPointer());
|
||||||
|
|
||||||
|
// B and I flags should have been set on P
|
||||||
|
assertTrue(cpu.getBreakFlag());
|
||||||
|
assertFalse(cpu.getDecimalModeFlag());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,372 @@
|
|||||||
|
package com.loomcom.symon;
|
||||||
|
|
||||||
|
import com.loomcom.symon.devices.Memory;
|
||||||
|
import com.loomcom.symon.exceptions.MemoryAccessException;
|
||||||
|
import junit.framework.*;
|
||||||
|
|
||||||
|
import static junit.framework.TestCase.assertFalse;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for Zero Page Indirect addressing mode, found on some instructions
|
||||||
|
* in the 65C02 and 65816
|
||||||
|
*/
|
||||||
|
public class Cpu65C02ZeroPageModeTest extends TestCase {
|
||||||
|
protected Cpu cpu;
|
||||||
|
protected Bus bus;
|
||||||
|
protected Memory mem;
|
||||||
|
|
||||||
|
private void makeCmosCpu() throws Exception {
|
||||||
|
makeCpu(InstructionTable.CpuBehavior.CMOS_6502);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeNmosCpu() throws Exception {
|
||||||
|
makeCpu(InstructionTable.CpuBehavior.NMOS_6502);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeCpu(InstructionTable.CpuBehavior behavior) throws Exception {
|
||||||
|
this.cpu = new Cpu(behavior);
|
||||||
|
this.bus = new Bus(0x0000, 0xffff);
|
||||||
|
this.mem = new Memory(0x0000, 0xffff);
|
||||||
|
bus.addCpu(cpu);
|
||||||
|
bus.addDevice(mem);
|
||||||
|
|
||||||
|
// Load the reset vector.
|
||||||
|
bus.write(0xfffc, Bus.DEFAULT_LOAD_ADDRESS & 0x00ff);
|
||||||
|
bus.write(0xfffd, (Bus.DEFAULT_LOAD_ADDRESS & 0xff00) >>> 8);
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_STZ() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
bus.write(0x0000,0xff);
|
||||||
|
|
||||||
|
bus.loadProgram(0x64,0x00); // STZ Zero Page $00
|
||||||
|
|
||||||
|
// Test STZ Zero Page
|
||||||
|
assertEquals(0xff,bus.read(0x00, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00,bus.read(0x00, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_STZRequiresCmosCpu() throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
bus.write(0x0000,0xff);
|
||||||
|
|
||||||
|
bus.loadProgram(0x64,0x00); // STZ Zero Page $00
|
||||||
|
|
||||||
|
// Test STZ Zero Page
|
||||||
|
assertEquals(0xff,bus.read(0x00, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xff,bus.read(0x00, true));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_SMB() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
bus.loadProgram(0x87,0x01, // SMB0 $01
|
||||||
|
0x97,0x01, // SMB1 $01
|
||||||
|
0xa7,0x01, // SMB2 $01
|
||||||
|
0xb7,0x01, // SMB3 $01
|
||||||
|
0xc7,0x01, // SMB4 $01
|
||||||
|
0xd7,0x01, // SMB5 $01
|
||||||
|
0xe7,0x01, // SMB6 $01
|
||||||
|
0xf7,0x01); // SMB7 $01
|
||||||
|
|
||||||
|
// SMB0
|
||||||
|
bus.write(0x01,0x00);
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(1 << 0,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// SMB1
|
||||||
|
bus.write(0x01,0x00);
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(1 << 1,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// SMB2
|
||||||
|
bus.write(0x01,0x00);
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(1 << 2,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// SMB3
|
||||||
|
bus.write(0x01,0x00);
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(1 << 3,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// SMB4
|
||||||
|
bus.write(0x01,0x00);
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(1 << 4,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// SMB5
|
||||||
|
bus.write(0x01,0x00);
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(1 << 5,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// SMB6
|
||||||
|
bus.write(0x01,0x00);
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(1 << 6,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// SMB7
|
||||||
|
bus.write(0x01,0x00);
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(1 << 7,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_SMBRequiresCmosCpu() throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
bus.loadProgram(0x87,0x01, // SMB0 $01
|
||||||
|
0x97,0x01, // SMB1 $01
|
||||||
|
0xa7,0x01, // SMB2 $01
|
||||||
|
0xb7,0x01, // SMB3 $01
|
||||||
|
0xc7,0x01, // SMB4 $01
|
||||||
|
0xd7,0x01, // SMB5 $01
|
||||||
|
0xe7,0x01, // SMB6 $01
|
||||||
|
0xf7,0x01); // SMB7 $01
|
||||||
|
|
||||||
|
// SMB0
|
||||||
|
bus.write(0x01,0x00);
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// SMB1
|
||||||
|
bus.write(0x01,0x00);
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// SMB2
|
||||||
|
bus.write(0x01,0x00);
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// SMB3
|
||||||
|
bus.write(0x01,0x00);
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// SMB4
|
||||||
|
bus.write(0x01,0x00);
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// SMB5
|
||||||
|
bus.write(0x01,0x00);
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// SMB6
|
||||||
|
bus.write(0x01,0x00);
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// SMB7
|
||||||
|
bus.write(0x01,0x00);
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_RMB() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
bus.loadProgram(0x07,0x01, // SMB0 $01
|
||||||
|
0x17,0x01, // SMB1 $01
|
||||||
|
0x27,0x01, // SMB2 $01
|
||||||
|
0x37,0x01, // SMB3 $01
|
||||||
|
0x47,0x01, // SMB4 $01
|
||||||
|
0x57,0x01, // SMB5 $01
|
||||||
|
0x67,0x01, // SMB6 $01
|
||||||
|
0x77,0x01); // SMB7 $01
|
||||||
|
|
||||||
|
// RMB0
|
||||||
|
bus.write(0x01,0xff);
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xfe,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// RMB1
|
||||||
|
bus.write(0x01,0xff);
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xfd,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// RMB2
|
||||||
|
bus.write(0x01,0xff);
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xfb,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// RMB3
|
||||||
|
bus.write(0x01,0xff);
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xf7,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// RMB4
|
||||||
|
bus.write(0x01,0xff);
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xef,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// RMB5
|
||||||
|
bus.write(0x01,0xff);
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xdf,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// RMB6
|
||||||
|
bus.write(0x01,0xff);
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xbf,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// RMB7
|
||||||
|
bus.write(0x01,0xff);
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x7f,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_RMBRequiresCmosCpu() throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
bus.loadProgram(0x07,0x01, // SMB0 $01
|
||||||
|
0x17,0x01, // SMB1 $01
|
||||||
|
0x27,0x01, // SMB2 $01
|
||||||
|
0x37,0x01, // SMB3 $01
|
||||||
|
0x47,0x01, // SMB4 $01
|
||||||
|
0x57,0x01, // SMB5 $01
|
||||||
|
0x67,0x01, // SMB6 $01
|
||||||
|
0x77,0x01); // SMB7 $01
|
||||||
|
|
||||||
|
// RMB0
|
||||||
|
bus.write(0x01,0xff);
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// RMB1
|
||||||
|
bus.write(0x01,0xff);
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// RMB2
|
||||||
|
bus.write(0x01,0xff);
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// RMB3
|
||||||
|
bus.write(0x01,0xff);
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// RMB4
|
||||||
|
bus.write(0x01,0xff);
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// RMB5
|
||||||
|
bus.write(0x01,0xff);
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// RMB6
|
||||||
|
bus.write(0x01,0xff);
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
// RMB7
|
||||||
|
bus.write(0x01,0xff);
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xff,bus.read(0x0001, true));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_TSB() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
bus.loadProgram(0x04, 0x10); // 65C02 TSB Zero Page $10
|
||||||
|
|
||||||
|
bus.write(0x10, 0x01);
|
||||||
|
cpu.setAccumulator(0x03);
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x03,bus.read(0x10,true));
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x10, 0x01);
|
||||||
|
cpu.setAccumulator(0x02);
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x03,bus.read(0x10,true));
|
||||||
|
assertTrue(cpu.getZeroFlag());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_TSBRequiresCmosCpu() throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
bus.loadProgram(0x04, 0x10); // 65C02 TSB Zero Page $10
|
||||||
|
|
||||||
|
bus.write(0x10, 0x01);
|
||||||
|
cpu.setAccumulator(0x03);
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x01,bus.read(0x10,true));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_TRB() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
cpu.reset();
|
||||||
|
bus.loadProgram(0x14, 0x40); // 65C02 TRB Zero Page $40
|
||||||
|
|
||||||
|
bus.write(0x0040, 0xff);
|
||||||
|
cpu.setAccumulator(0x01);
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xfe,bus.read(0x0040,true)); // $03 &= ~($01) = $02
|
||||||
|
assertFalse(cpu.getZeroFlag()); // Z = !(A & M)
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
cpu.setAccumulator(0x01);
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xfe,bus.read(0x0040,true)); // $02 &= ~($01) = $02
|
||||||
|
assertTrue(cpu.getZeroFlag()); // Z = !(A & M)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_TRBRequiresCmosCpu() throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
cpu.reset();
|
||||||
|
bus.loadProgram(0x14, 0x40); // 65C02 TRB Zero Page $40
|
||||||
|
|
||||||
|
bus.write(0x0040, 0xff);
|
||||||
|
cpu.setAccumulator(0x01);
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xff,bus.read(0x0040,true)); // $03 &= ~($01) = $02
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,585 @@
|
|||||||
|
package com.loomcom.symon;
|
||||||
|
|
||||||
|
import com.loomcom.symon.devices.Memory;
|
||||||
|
import com.loomcom.symon.exceptions.MemoryAccessException;
|
||||||
|
import junit.framework.*;
|
||||||
|
|
||||||
|
import static junit.framework.TestCase.assertFalse;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for Zero Page Indirect addressing mode, found on some instructions
|
||||||
|
* in the 65C02 and 65816
|
||||||
|
*/
|
||||||
|
public class Cpu65C02ZeroPageRelativeTest extends TestCase {
|
||||||
|
protected Cpu cpu;
|
||||||
|
protected Bus bus;
|
||||||
|
protected Memory mem;
|
||||||
|
|
||||||
|
private void makeCmosCpu() throws Exception {
|
||||||
|
makeCpu(InstructionTable.CpuBehavior.CMOS_6502);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeNmosCpu() throws Exception {
|
||||||
|
makeCpu(InstructionTable.CpuBehavior.NMOS_6502);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeCpu(InstructionTable.CpuBehavior behavior) throws Exception {
|
||||||
|
this.cpu = new Cpu(behavior);
|
||||||
|
this.bus = new Bus(0x0000, 0xffff);
|
||||||
|
this.mem = new Memory(0x0000, 0xffff);
|
||||||
|
bus.addCpu(cpu);
|
||||||
|
bus.addDevice(mem);
|
||||||
|
|
||||||
|
// Load the reset vector.
|
||||||
|
bus.write(0xfffc, Bus.DEFAULT_LOAD_ADDRESS & 0x00ff);
|
||||||
|
bus.write(0xfffd, (Bus.DEFAULT_LOAD_ADDRESS & 0xff00) >>> 8);
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
}
|
||||||
|
public void test_BRA() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
// Positive Offset
|
||||||
|
bus.loadProgram(0x80, 0x05); // 65C02 BRA $05 ; *=$0202+$05 ($0207)
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x207, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
// Negative Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.loadProgram(0x80, 0xfb); // 65C02 BRA $fb ; *=$0202-$05 ($01fd)
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x1fd, cpu.getProgramCounter());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_BRArequiresCmosCpu() throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
// Should be a NOOP on NMOS and end up at $0202
|
||||||
|
// Positive Offset
|
||||||
|
bus.loadProgram(0x80, 0x05); // BRA $05 ; *=$0202+$05 ($0207)
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x202, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
// Negative Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.loadProgram(0x80, 0xfb); // BRA $fb ; *=$0202-$05 ($01fd)
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x202, cpu.getProgramCounter());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_BBR() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
|
||||||
|
/* BBR0 */
|
||||||
|
// Positive Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xff);
|
||||||
|
bus.loadProgram(0x0f, 0x0a, 0x05); // 65C02 BBR0 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xfe);
|
||||||
|
bus.loadProgram(0x0f, 0x0a, 0x05); // 65C02 BBR0 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||||
|
|
||||||
|
// Negative Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xfe);
|
||||||
|
bus.loadProgram(0x0f, 0x0a, 0xfb); // 65C02 BBR0 $00 $fb ; *=$0203-$05 ($01fe)
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBR1 */
|
||||||
|
// Positive Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xff);
|
||||||
|
bus.loadProgram(0x1f, 0x0a, 0x05); // 65C02 BBR1 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xfd);
|
||||||
|
bus.loadProgram(0x1f, 0x0a, 0x05); // 65C02 BBR1 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||||
|
|
||||||
|
// Negative Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xfd);
|
||||||
|
bus.loadProgram(0x1f, 0x0a, 0xfb); // 65C02 BBR1 $00 $fb ; *=$0203-$05 ($01fe)
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBR2 */
|
||||||
|
// Positive Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xff);
|
||||||
|
bus.loadProgram(0x2f, 0x0a, 0x05); // 65C02 BBR2 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xfb);
|
||||||
|
bus.loadProgram(0x2f, 0x0a, 0x05); // 65C02 BBR2 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||||
|
|
||||||
|
// Negative Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xfb);
|
||||||
|
bus.loadProgram(0x2f, 0x0a, 0xfb); // 65C02 BBR2 $00 $fb ; *=$0203-$05 ($01fe)
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBR3 */
|
||||||
|
// Positive Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xff);
|
||||||
|
bus.loadProgram(0x3f, 0x0a, 0x05); // 65C02 BBR3 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xf7);
|
||||||
|
bus.loadProgram(0x3f, 0x0a, 0x05); // 65C02 BBR3 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||||
|
|
||||||
|
// Negative Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xf7);
|
||||||
|
bus.loadProgram(0x3f, 0x0a, 0xfb); // 65C02 BBR3 $00 $fb ; *=$0203-$05 ($01fe)
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBR4 */
|
||||||
|
// Positive Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xff);
|
||||||
|
bus.loadProgram(0x4f, 0x0a, 0x05); // 65C02 BBR4 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xef);
|
||||||
|
bus.loadProgram(0x4f, 0x0a, 0x05); // 65C02 BBR4 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||||
|
|
||||||
|
// Negative Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xef);
|
||||||
|
bus.loadProgram(0x4f, 0x0a, 0xfb); // 65C02 BBR4 $00 $fb ; *=$0203-$05 ($01fe)
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBR5 */
|
||||||
|
// Positive Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xff);
|
||||||
|
bus.loadProgram(0x5f, 0x0a, 0x05); // 65C02 BBR5 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xdf);
|
||||||
|
bus.loadProgram(0x5f, 0x0a, 0x05); // 65C02 BBR5 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||||
|
|
||||||
|
// Negative Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xdf);
|
||||||
|
bus.loadProgram(0x5f, 0x0a, 0xfb); // 65C02 BBR5 $00 $fb ; *=$0203-$05 ($01fe)
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBR6 */
|
||||||
|
// Positive Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xff);
|
||||||
|
bus.loadProgram(0x6f, 0x0a, 0x05); // 65C02 BBR6 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xbf);
|
||||||
|
bus.loadProgram(0x6f, 0x0a, 0x05); // 65C02 BBR6 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||||
|
|
||||||
|
// Negative Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xbf);
|
||||||
|
bus.loadProgram(0x6f, 0x0a, 0xfb); // 65C02 BBR6 $00 $fb ; *=$0203-$05 ($01fe)
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBR7 */
|
||||||
|
// Positive Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xff);
|
||||||
|
bus.loadProgram(0x7f, 0x0a, 0x05); // 65C02 BBR7 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x7f);
|
||||||
|
bus.loadProgram(0x7f, 0x0a, 0x05); // 65C02 BBR7 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||||
|
|
||||||
|
// Negative Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x7f);
|
||||||
|
bus.loadProgram(0x7f, 0x0a, 0xfb); // 65C02 BBR7 $00 $fb ; *=$0203-$05 ($01fe)
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_BBRNeedsCmosCpu() throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
|
||||||
|
/* BBR0 */
|
||||||
|
bus.write(0x0a,0xfe);
|
||||||
|
bus.loadProgram(0x0f, 0x0a, 0x05); // 65C02 BBR0 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBR1 */
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xfd);
|
||||||
|
bus.loadProgram(0x1f, 0x0a, 0x05); // 65C02 BBR1 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBR2 */
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xfb);
|
||||||
|
bus.loadProgram(0x2f, 0x0a, 0x05); // 65C02 BBR2 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBR3 */
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xf7);
|
||||||
|
bus.loadProgram(0x3f, 0x0a, 0x05); // 65C02 BBR3 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBR4 */
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xef);
|
||||||
|
bus.loadProgram(0x4f, 0x0a, 0x05); // 65C02 BBR4 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBR5 */
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xdf);
|
||||||
|
bus.loadProgram(0x5f, 0x0a, 0x05); // 65C02 BBR5 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBR6 */
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0xbf);
|
||||||
|
bus.loadProgram(0x6f, 0x0a, 0x05); // 65C02 BBR6 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBR7 */
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x7f);
|
||||||
|
bus.loadProgram(0x7f, 0x0a, 0x05); // 65C02 BBR7 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_BBS() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
|
||||||
|
/* BBS0 */
|
||||||
|
// Positive Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x00);
|
||||||
|
bus.loadProgram(0x8f, 0x0a, 0x05); // 65C02 BBS0 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x01);
|
||||||
|
bus.loadProgram(0x8f, 0x0a, 0x05); // 65C02 BBS0 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||||
|
|
||||||
|
// Negative Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x01);
|
||||||
|
bus.loadProgram(0x8f, 0x0a, 0xfb); // 65C02 BBS0 $00 $fb ; *=$0203-$05 ($01fe)
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBS1 */
|
||||||
|
// Positive Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x00);
|
||||||
|
bus.loadProgram(0x9f, 0x00, 0x05); // 65C02 BBS1 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x02);
|
||||||
|
bus.loadProgram(0x9f, 0x0a, 0x05); // 65C02 BBS1 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||||
|
|
||||||
|
// Negative Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x02);
|
||||||
|
bus.loadProgram(0x9f, 0x0a, 0xfb); // 65C02 BBS1 $00 $fb ; *=$0203-$05 ($01fe)
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBS2 */
|
||||||
|
// Positive Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x00);
|
||||||
|
bus.loadProgram(0xaf, 0x0a, 0x05); // 65C02 BBS2 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x04);
|
||||||
|
bus.loadProgram(0xaf, 0x0a, 0x05); // 65C02 BBS2 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||||
|
|
||||||
|
// Negative Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x04);
|
||||||
|
bus.loadProgram(0xaf, 0x0a, 0xfb); // 65C02 BBS2 $00 $fb ; *=$0203-$05 ($01fe)
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBS3 */
|
||||||
|
// Positive Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x00);
|
||||||
|
bus.loadProgram(0xbf, 0x0a, 0x05); // 65C02 BBS3 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x08);
|
||||||
|
bus.loadProgram(0xbf, 0x0a, 0x05); // 65C02 BBS3 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||||
|
|
||||||
|
// Negative Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x08);
|
||||||
|
bus.loadProgram(0xbf, 0x0a, 0xfb); // 65C02 BBS3 $00 $fb ; *=$0203-$05 ($01fe)
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBS4 */
|
||||||
|
// Positive Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x00);
|
||||||
|
bus.loadProgram(0xcf, 0x0a, 0x05); // 65C02 BBS4 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x10);
|
||||||
|
bus.loadProgram(0xcf, 0x0a, 0x05); // 65C02 BBS4 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||||
|
|
||||||
|
// Negative Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x10);
|
||||||
|
bus.loadProgram(0xcf, 0x0a, 0xfb); // 65C02 BBS4 $00 $fb ; *=$0203-$05 ($01fe)
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBS5 */
|
||||||
|
// Positive Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x00);
|
||||||
|
bus.loadProgram(0xdf, 0x0a, 0x05); // 65C02 BBS5 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x20);
|
||||||
|
bus.loadProgram(0xdf, 0x0a, 0x05); // 65C02 BBS5 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||||
|
|
||||||
|
// Negative Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x20);
|
||||||
|
bus.loadProgram(0xdf, 0x0a, 0xfb); // 65C02 BBS5 $00 $fb ; *=$0203-$05 ($01fe)
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBS6 */
|
||||||
|
// Positive Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x00);
|
||||||
|
bus.loadProgram(0xef, 0x0a, 0x05); // 65C02 BBS6 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x40);
|
||||||
|
bus.loadProgram(0xef, 0x0a, 0x05); // 65C02 BBS6 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||||
|
|
||||||
|
// Negative Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x40);
|
||||||
|
bus.loadProgram(0xef, 0x0a, 0xfb); // 65C02 BBS6 $00 $fb ; *=$0203-$05 ($01fe)
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBS7 */
|
||||||
|
// Positive Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x00);
|
||||||
|
bus.loadProgram(0xff, 0x0a, 0x05); // 65C02 BBS7 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x80);
|
||||||
|
bus.loadProgram(0xff, 0x0a, 0x05); // 65C02 BBS7 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||||
|
|
||||||
|
// Negative Offset
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x80);
|
||||||
|
bus.loadProgram(0xff, 0x0a, 0xfb); // 65C02 BBS7 $00 $fb ; *=$0203-$05 ($01fe)
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_BBSNeedsCmosCpu() throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
|
||||||
|
/* BBS0 */
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x01);
|
||||||
|
bus.loadProgram(0x8f, 0x0a, 0x05); // 65C02 BBS0 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBS1 */
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x02);
|
||||||
|
bus.loadProgram(0x9f, 0x0a, 0x05); // 65C02 BBS1 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBS2 */
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x04);
|
||||||
|
bus.loadProgram(0xaf, 0x0a, 0x05); // 65C02 BBS2 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBS3 */
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x08);
|
||||||
|
bus.loadProgram(0xbf, 0x0a, 0x05); // 65C02 BBS3 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBS4 */
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x10);
|
||||||
|
bus.loadProgram(0xcf, 0x0a, 0x05); // 65C02 BBS4 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBS5 */
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x20);
|
||||||
|
bus.loadProgram(0xdf, 0x0a, 0x05); // 65C02 BBS5 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBS6 */
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x40);
|
||||||
|
bus.loadProgram(0xef, 0x0a, 0x05); // 65C02 BBS6 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
/* BBS7 */
|
||||||
|
cpu.reset();
|
||||||
|
bus.write(0x0a,0x80);
|
||||||
|
bus.loadProgram(0xff, 0x0a, 0x05); // 65C02 BBS7 $00 $05 ; *=$0202+$05 ($0208)
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package com.loomcom.symon;
|
||||||
|
|
||||||
|
import com.loomcom.symon.devices.Memory;
|
||||||
|
import com.loomcom.symon.exceptions.MemoryAccessException;
|
||||||
|
import junit.framework.*;
|
||||||
|
|
||||||
|
import static junit.framework.TestCase.assertFalse;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for Zero Page Indirect addressing mode, found on some instructions
|
||||||
|
* in the 65C02 and 65816
|
||||||
|
*/
|
||||||
|
public class Cpu65C02ZeroPageXModeTest extends TestCase {
|
||||||
|
protected Cpu cpu;
|
||||||
|
protected Bus bus;
|
||||||
|
protected Memory mem;
|
||||||
|
|
||||||
|
private void makeCmosCpu() throws Exception {
|
||||||
|
makeCpu(InstructionTable.CpuBehavior.CMOS_6502);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeNmosCpu() throws Exception {
|
||||||
|
makeCpu(InstructionTable.CpuBehavior.NMOS_6502);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeCpu(InstructionTable.CpuBehavior behavior) throws Exception {
|
||||||
|
this.cpu = new Cpu(behavior);
|
||||||
|
this.bus = new Bus(0x0000, 0xffff);
|
||||||
|
this.mem = new Memory(0x0000, 0xffff);
|
||||||
|
bus.addCpu(cpu);
|
||||||
|
bus.addDevice(mem);
|
||||||
|
|
||||||
|
// Load the reset vector.
|
||||||
|
bus.write(0xfffc, Bus.DEFAULT_LOAD_ADDRESS & 0x00ff);
|
||||||
|
bus.write(0xfffd, (Bus.DEFAULT_LOAD_ADDRESS & 0xff00) >>> 8);
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_STZ() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
bus.write(0x0002,0xff);
|
||||||
|
|
||||||
|
bus.loadProgram(0x74,0x01); // STZ Zero Page,X $01
|
||||||
|
|
||||||
|
// Test STZ Zero Page,X ($01+1)
|
||||||
|
assertEquals(0xff,bus.read(0x02, true));
|
||||||
|
cpu.setXRegister(0x01);
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00,bus.read(0x02, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_STZRequiresCmosCpu() throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
bus.write(0x0002,0xff);
|
||||||
|
|
||||||
|
bus.loadProgram(0x74,0x01); // STZ Zero Page,X $01
|
||||||
|
|
||||||
|
// Test STZ Zero Page,X ($01+1)
|
||||||
|
assertEquals(0xff,bus.read(0x02, true));
|
||||||
|
cpu.setXRegister(0x01);
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xff,bus.read(0x02, true));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -121,31 +121,31 @@ public class CpuAbsoluteModeTest extends TestCase {
|
|||||||
0x0e, 0x04, 0x12); // ASL $1204
|
0x0e, 0x04, 0x12); // ASL $1204
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x7f00));
|
assertEquals(0x00, bus.read(0x7f00, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x02, bus.read(0x7f01));
|
assertEquals(0x02, bus.read(0x7f01, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x04, bus.read(0x3502));
|
assertEquals(0x04, bus.read(0x3502, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x88, bus.read(0x3503));
|
assertEquals(0x88, bus.read(0x3503, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x1204));
|
assertEquals(0x00, bus.read(0x1204, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertTrue(cpu.getCarryFlag());
|
assertTrue(cpu.getCarryFlag());
|
||||||
@@ -165,8 +165,8 @@ public class CpuAbsoluteModeTest extends TestCase {
|
|||||||
|
|
||||||
// Old PC-1 should be on stack (i.e.: address of third byte of the
|
// Old PC-1 should be on stack (i.e.: address of third byte of the
|
||||||
// JSR instruction, 0x0204)
|
// JSR instruction, 0x0204)
|
||||||
assertEquals(0x02, bus.read(0x1ff));
|
assertEquals(0x02, bus.read(0x1ff, true));
|
||||||
assertEquals(0x04, bus.read(0x1fe));
|
assertEquals(0x04, bus.read(0x1fe, true));
|
||||||
|
|
||||||
// No flags should have changed.
|
// No flags should have changed.
|
||||||
assertEquals(0x20, cpu.getProcessorStatus());
|
assertEquals(0x20, cpu.getProcessorStatus());
|
||||||
@@ -295,61 +295,61 @@ public class CpuAbsoluteModeTest extends TestCase {
|
|||||||
0x2e, 0x01, 0x12); // ROL $1201 (m=%10000001, c=0)
|
0x2e, 0x01, 0x12); // ROL $1201 (m=%10000001, c=0)
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x1200));
|
assertEquals(0x00, bus.read(0x1200, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x02, bus.read(0x1201));
|
assertEquals(0x02, bus.read(0x1201, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step(2);
|
cpu.step(2);
|
||||||
assertEquals(0x05, bus.read(0x1201));
|
assertEquals(0x05, bus.read(0x1201, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x0a, bus.read(0x1201));
|
assertEquals(0x0a, bus.read(0x1201, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x14, bus.read(0x1201));
|
assertEquals(0x14, bus.read(0x1201, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x28, bus.read(0x1201));
|
assertEquals(0x28, bus.read(0x1201, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x50, bus.read(0x1201));
|
assertEquals(0x50, bus.read(0x1201, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0xa0, bus.read(0x1201));
|
assertEquals(0xa0, bus.read(0x1201, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x40, bus.read(0x1201));
|
assertEquals(0x40, bus.read(0x1201, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertTrue(cpu.getCarryFlag());
|
assertTrue(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x81, bus.read(0x1201));
|
assertEquals(0x81, bus.read(0x1201, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
@@ -418,38 +418,38 @@ public class CpuAbsoluteModeTest extends TestCase {
|
|||||||
0x4e, 0x05, 0x12); // LSR $1205
|
0x4e, 0x05, 0x12); // LSR $1205
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x1200));
|
assertEquals(0x00, bus.read(0x1200, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x1201));
|
assertEquals(0x00, bus.read(0x1201, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertTrue(cpu.getCarryFlag());
|
assertTrue(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x01, bus.read(0x1202));
|
assertEquals(0x01, bus.read(0x1202, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x22, bus.read(0x1203));
|
assertEquals(0x22, bus.read(0x1203, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x40, bus.read(0x1204));
|
assertEquals(0x40, bus.read(0x1204, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
// Setting Carry should not affect the result.
|
// Setting Carry should not affect the result.
|
||||||
cpu.step(2);
|
cpu.step(2);
|
||||||
assertEquals(0x01, bus.read(0x1205));
|
assertEquals(0x01, bus.read(0x1205, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
@@ -654,61 +654,61 @@ public class CpuAbsoluteModeTest extends TestCase {
|
|||||||
0x6e, 0x11, 0x12); // ROR $1201 (m=%00010000, c=0)
|
0x6e, 0x11, 0x12); // ROR $1201 (m=%00010000, c=0)
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x1210));
|
assertEquals(0x00, bus.read(0x1210, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x08, bus.read(0x1211));
|
assertEquals(0x08, bus.read(0x1211, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x04, bus.read(0x1211));
|
assertEquals(0x04, bus.read(0x1211, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x02, bus.read(0x1211));
|
assertEquals(0x02, bus.read(0x1211, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x01, bus.read(0x1211));
|
assertEquals(0x01, bus.read(0x1211, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x1211));
|
assertEquals(0x00, bus.read(0x1211, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertTrue(cpu.getCarryFlag());
|
assertTrue(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x80, bus.read(0x1211));
|
assertEquals(0x80, bus.read(0x1211, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x40, bus.read(0x1211));
|
assertEquals(0x40, bus.read(0x1211, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x20, bus.read(0x1211));
|
assertEquals(0x20, bus.read(0x1211, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x10, bus.read(0x1211));
|
assertEquals(0x10, bus.read(0x1211, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
@@ -720,7 +720,7 @@ public class CpuAbsoluteModeTest extends TestCase {
|
|||||||
cpu.setYRegister(0x00);
|
cpu.setYRegister(0x00);
|
||||||
bus.loadProgram(0x8c, 0x10, 0x12);
|
bus.loadProgram(0x8c, 0x10, 0x12);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x1210));
|
assertEquals(0x00, bus.read(0x1210, true));
|
||||||
// STY should have NO effect on flags.
|
// STY should have NO effect on flags.
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
@@ -730,7 +730,7 @@ public class CpuAbsoluteModeTest extends TestCase {
|
|||||||
cpu.setYRegister(0x0f);
|
cpu.setYRegister(0x0f);
|
||||||
bus.loadProgram(0x8c, 0x10, 0x12);
|
bus.loadProgram(0x8c, 0x10, 0x12);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x0f, bus.read(0x1210));
|
assertEquals(0x0f, bus.read(0x1210, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
@@ -739,7 +739,7 @@ public class CpuAbsoluteModeTest extends TestCase {
|
|||||||
cpu.setYRegister(0x80);
|
cpu.setYRegister(0x80);
|
||||||
bus.loadProgram(0x8c, 0x10, 0x12);
|
bus.loadProgram(0x8c, 0x10, 0x12);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x80, bus.read(0x1210));
|
assertEquals(0x80, bus.read(0x1210, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
@@ -750,7 +750,7 @@ public class CpuAbsoluteModeTest extends TestCase {
|
|||||||
cpu.setAccumulator(0x00);
|
cpu.setAccumulator(0x00);
|
||||||
bus.loadProgram(0x8d, 0x10, 0x12);
|
bus.loadProgram(0x8d, 0x10, 0x12);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x1210));
|
assertEquals(0x00, bus.read(0x1210, true));
|
||||||
// STA should have NO effect on flags.
|
// STA should have NO effect on flags.
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
@@ -760,7 +760,7 @@ public class CpuAbsoluteModeTest extends TestCase {
|
|||||||
cpu.setAccumulator(0x0f);
|
cpu.setAccumulator(0x0f);
|
||||||
bus.loadProgram(0x8d, 0x10, 0x12);
|
bus.loadProgram(0x8d, 0x10, 0x12);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x0f, bus.read(0x1210));
|
assertEquals(0x0f, bus.read(0x1210, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
@@ -769,7 +769,7 @@ public class CpuAbsoluteModeTest extends TestCase {
|
|||||||
cpu.setAccumulator(0x80);
|
cpu.setAccumulator(0x80);
|
||||||
bus.loadProgram(0x8d, 0x10, 0x12);
|
bus.loadProgram(0x8d, 0x10, 0x12);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x80, bus.read(0x1210));
|
assertEquals(0x80, bus.read(0x1210, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
@@ -780,7 +780,7 @@ public class CpuAbsoluteModeTest extends TestCase {
|
|||||||
cpu.setXRegister(0x00);
|
cpu.setXRegister(0x00);
|
||||||
bus.loadProgram(0x8e, 0x10, 0x12);
|
bus.loadProgram(0x8e, 0x10, 0x12);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x1210));
|
assertEquals(0x00, bus.read(0x1210, true));
|
||||||
// STX should have NO effect on flags.
|
// STX should have NO effect on flags.
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
@@ -790,7 +790,7 @@ public class CpuAbsoluteModeTest extends TestCase {
|
|||||||
cpu.setXRegister(0x0f);
|
cpu.setXRegister(0x0f);
|
||||||
bus.loadProgram(0x8e, 0x10, 0x12);
|
bus.loadProgram(0x8e, 0x10, 0x12);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x0f, bus.read(0x1210));
|
assertEquals(0x0f, bus.read(0x1210, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
@@ -799,7 +799,7 @@ public class CpuAbsoluteModeTest extends TestCase {
|
|||||||
cpu.setXRegister(0x80);
|
cpu.setXRegister(0x80);
|
||||||
bus.loadProgram(0x8e, 0x10, 0x12);
|
bus.loadProgram(0x8e, 0x10, 0x12);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x80, bus.read(0x1210));
|
assertEquals(0x80, bus.read(0x1210, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
@@ -957,22 +957,22 @@ public class CpuAbsoluteModeTest extends TestCase {
|
|||||||
0xce, 0x13, 0x12); // DEC $1213
|
0xce, 0x13, 0x12); // DEC $1213
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0xff, bus.read(0x1210));
|
assertEquals(0xff, bus.read(0x1210, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x1211));
|
assertEquals(0x00, bus.read(0x1211, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x7f, bus.read(0x1212));
|
assertEquals(0x7f, bus.read(0x1212, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0xfe, bus.read(0x1213));
|
assertEquals(0xfe, bus.read(0x1213, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
@@ -1213,17 +1213,17 @@ public class CpuAbsoluteModeTest extends TestCase {
|
|||||||
0xee, 0x12, 0x12); // INC $1212
|
0xee, 0x12, 0x12); // INC $1212
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x01, bus.read(0x1210));
|
assertEquals(0x01, bus.read(0x1210, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x80, bus.read(0x1211));
|
assertEquals(0x80, bus.read(0x1211, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x1212));
|
assertEquals(0x00, bus.read(0x1212, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
|
|||||||
@@ -117,31 +117,31 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
|||||||
0x1e, 0x04, 0x2c); // ASL $2c04,X
|
0x1e, 0x04, 0x2c); // ASL $2c04,X
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x2c30));
|
assertEquals(0x00, bus.read(0x2c30, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x02, bus.read(0x2c31));
|
assertEquals(0x02, bus.read(0x2c31, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x04, bus.read(0x2c32));
|
assertEquals(0x04, bus.read(0x2c32, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x88, bus.read(0x2c33));
|
assertEquals(0x88, bus.read(0x2c33, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x2c34));
|
assertEquals(0x00, bus.read(0x2c34, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertTrue(cpu.getCarryFlag());
|
assertTrue(cpu.getCarryFlag());
|
||||||
@@ -229,61 +229,61 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
|||||||
0x3e, 0x01, 0x10); // ROL $1001,X (m=%10000001, c=0)
|
0x3e, 0x01, 0x10); // ROL $1001,X (m=%10000001, c=0)
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x1070));
|
assertEquals(0x00, bus.read(0x1070, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x02, bus.read(0x1071));
|
assertEquals(0x02, bus.read(0x1071, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step(2);
|
cpu.step(2);
|
||||||
assertEquals(0x05, bus.read(0x1071));
|
assertEquals(0x05, bus.read(0x1071, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x0a, bus.read(0x1071));
|
assertEquals(0x0a, bus.read(0x1071, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x14, bus.read(0x1071));
|
assertEquals(0x14, bus.read(0x1071, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x28, bus.read(0x1071));
|
assertEquals(0x28, bus.read(0x1071, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x50, bus.read(0x1071));
|
assertEquals(0x50, bus.read(0x1071, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0xa0, bus.read(0x1071));
|
assertEquals(0xa0, bus.read(0x1071, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x40, bus.read(0x1071));
|
assertEquals(0x40, bus.read(0x1071, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertTrue(cpu.getCarryFlag());
|
assertTrue(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x81, bus.read(0x1071));
|
assertEquals(0x81, bus.read(0x1071, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
@@ -346,38 +346,38 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
|||||||
0x5e, 0x05, 0xab); // LSR $ab05,X
|
0x5e, 0x05, 0xab); // LSR $ab05,X
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0xab30));
|
assertEquals(0x00, bus.read(0xab30, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0xab31));
|
assertEquals(0x00, bus.read(0xab31, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertTrue(cpu.getCarryFlag());
|
assertTrue(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x01, bus.read(0xab32));
|
assertEquals(0x01, bus.read(0xab32, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x22, bus.read(0xab33));
|
assertEquals(0x22, bus.read(0xab33, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x40, bus.read(0xab34));
|
assertEquals(0x40, bus.read(0xab34, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
// Setting Carry should not affect the result.
|
// Setting Carry should not affect the result.
|
||||||
cpu.step(2);
|
cpu.step(2);
|
||||||
assertEquals(0x01, bus.read(0xab35));
|
assertEquals(0x01, bus.read(0xab35, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
@@ -609,61 +609,61 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
|||||||
cpu.setXRegister(0x30);
|
cpu.setXRegister(0x30);
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0xab40));
|
assertEquals(0x00, bus.read(0xab40, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x08, bus.read(0xab41));
|
assertEquals(0x08, bus.read(0xab41, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x04, bus.read(0xab41));
|
assertEquals(0x04, bus.read(0xab41, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x02, bus.read(0xab41));
|
assertEquals(0x02, bus.read(0xab41, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x01, bus.read(0xab41));
|
assertEquals(0x01, bus.read(0xab41, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0xab41));
|
assertEquals(0x00, bus.read(0xab41, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertTrue(cpu.getCarryFlag());
|
assertTrue(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x80, bus.read(0xab41));
|
assertEquals(0x80, bus.read(0xab41, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x40, bus.read(0xab41));
|
assertEquals(0x40, bus.read(0xab41, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x20, bus.read(0xab41));
|
assertEquals(0x20, bus.read(0xab41, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x10, bus.read(0xab41));
|
assertEquals(0x10, bus.read(0xab41, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
@@ -677,7 +677,7 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
|||||||
cpu.setAccumulator(0x00);
|
cpu.setAccumulator(0x00);
|
||||||
bus.loadProgram(0x9d, 0x10, 0xab); // STA $ab10,X
|
bus.loadProgram(0x9d, 0x10, 0xab); // STA $ab10,X
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0xab40));
|
assertEquals(0x00, bus.read(0xab40, true));
|
||||||
// STA should have NO affect on flags.
|
// STA should have NO affect on flags.
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
@@ -688,7 +688,7 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
|||||||
cpu.setAccumulator(0x0f);
|
cpu.setAccumulator(0x0f);
|
||||||
bus.loadProgram(0x9d, 0x10, 0xab); // STA $ab10,X
|
bus.loadProgram(0x9d, 0x10, 0xab); // STA $ab10,X
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x0f, bus.read(0xab40));
|
assertEquals(0x0f, bus.read(0xab40, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
@@ -698,7 +698,7 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
|||||||
cpu.setAccumulator(0x80);
|
cpu.setAccumulator(0x80);
|
||||||
bus.loadProgram(0x9d, 0x10, 0xab); // STA $ab10,X
|
bus.loadProgram(0x9d, 0x10, 0xab); // STA $ab10,X
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x80, bus.read(0xab40));
|
assertEquals(0x80, bus.read(0xab40, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
@@ -808,22 +808,22 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
|||||||
cpu.setXRegister(0x30);
|
cpu.setXRegister(0x30);
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0xff, bus.read(0xab40));
|
assertEquals(0xff, bus.read(0xab40, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0xab41));
|
assertEquals(0x00, bus.read(0xab41, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x7f, bus.read(0xab42));
|
assertEquals(0x7f, bus.read(0xab42, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0xfe, bus.read(0xab43));
|
assertEquals(0xfe, bus.read(0xab43, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
@@ -1051,17 +1051,17 @@ public class CpuAbsoluteXModeTest extends TestCase {
|
|||||||
0xfe, 0x12, 0xab); // INC $ab12,X
|
0xfe, 0x12, 0xab); // INC $ab12,X
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x01, bus.read(0xab30));
|
assertEquals(0x01, bus.read(0xab30, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x80, bus.read(0xab31));
|
assertEquals(0x80, bus.read(0xab31, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0xab32));
|
assertEquals(0x00, bus.read(0xab32, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -411,7 +411,7 @@ public class CpuAbsoluteYModeTest extends TestCase {
|
|||||||
cpu.setAccumulator(0x00);
|
cpu.setAccumulator(0x00);
|
||||||
bus.loadProgram(0x99, 0x10, 0xab); // STA $ab10,Y
|
bus.loadProgram(0x99, 0x10, 0xab); // STA $ab10,Y
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0xab40));
|
assertEquals(0x00, bus.read(0xab40, true));
|
||||||
// STA should have NO effect on flags
|
// STA should have NO effect on flags
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
@@ -423,7 +423,7 @@ public class CpuAbsoluteYModeTest extends TestCase {
|
|||||||
cpu.setAccumulator(0x0f);
|
cpu.setAccumulator(0x0f);
|
||||||
bus.loadProgram(0x99, 0x10, 0xab); // STA $ab10,Y
|
bus.loadProgram(0x99, 0x10, 0xab); // STA $ab10,Y
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x0f, bus.read(0xab40));
|
assertEquals(0x0f, bus.read(0xab40, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
@@ -433,7 +433,7 @@ public class CpuAbsoluteYModeTest extends TestCase {
|
|||||||
cpu.setAccumulator(0x80);
|
cpu.setAccumulator(0x80);
|
||||||
bus.loadProgram(0x99, 0x10, 0xab); // STA $ab10,Y
|
bus.loadProgram(0x99, 0x10, 0xab); // STA $ab10,Y
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x80, bus.read(0xab40));
|
assertEquals(0x80, bus.read(0xab40, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,10 +101,10 @@ public class CpuImpliedModeTest {
|
|||||||
cpu.step(); // Triggers the BRK
|
cpu.step(); // Triggers the BRK
|
||||||
|
|
||||||
// Was at PC = 0x204. PC+1 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, true)); // PC high byte
|
||||||
assertEquals(0x05, bus.read(0x1fe)); // PC low byte
|
assertEquals(0x05, bus.read(0x1fe, true)); // 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, true)); // Processor Status, with B set
|
||||||
|
|
||||||
// Interrupt vector held 0x1234, so we should be there.
|
// Interrupt vector held 0x1234, so we should be there.
|
||||||
assertEquals(0x1234, cpu.getProgramCounter());
|
assertEquals(0x1234, cpu.getProgramCounter());
|
||||||
@@ -149,10 +149,10 @@ public class CpuImpliedModeTest {
|
|||||||
|
|
||||||
|
|
||||||
// Was at PC = 0x204. PC+1 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, true)); // PC high byte
|
||||||
assertEquals(0x05, bus.read(0x1fe)); // PC low byte
|
assertEquals(0x05, bus.read(0x1fe, true)); // PC low byte
|
||||||
assertEquals(0x20 | Cpu.P_CARRY | Cpu.P_OVERFLOW | Cpu.P_BREAK | Cpu.P_IRQ_DISABLE,
|
assertEquals(0x20 | Cpu.P_CARRY | Cpu.P_OVERFLOW | Cpu.P_BREAK | Cpu.P_IRQ_DISABLE,
|
||||||
bus.read(0x1fd)); // Processor Status, with B set
|
bus.read(0x1fd, true)); // Processor Status, with B set
|
||||||
|
|
||||||
// Interrupt vector held 0x1234, so we should be there.
|
// Interrupt vector held 0x1234, so we should be there.
|
||||||
assertEquals(0x1234, cpu.getProgramCounter());
|
assertEquals(0x1234, cpu.getProgramCounter());
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ public class CpuIndexedIndirectModeTest {
|
|||||||
cpu.step(1);
|
cpu.step(1);
|
||||||
|
|
||||||
assertEquals(0x35, cpu.getAccumulator());
|
assertEquals(0x35, cpu.getAccumulator());
|
||||||
assertEquals(0x31, bus.read(0xc51f));
|
assertEquals(0x31, bus.read(0xc51f, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -103,6 +103,6 @@ public class CpuIndexedIndirectModeTest {
|
|||||||
cpu.step(1);
|
cpu.step(1);
|
||||||
|
|
||||||
assertEquals(0x11, cpu.getAccumulator());
|
assertEquals(0x11, cpu.getAccumulator());
|
||||||
assertEquals(0x31, bus.read(0xc51f));
|
assertEquals(0x31, bus.read(0xc51f, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,7 +62,7 @@ public class CpuIndirectIndexedModeTest {
|
|||||||
cpu.step(1);
|
cpu.step(1);
|
||||||
|
|
||||||
assertEquals(0xf3, cpu.getAccumulator());
|
assertEquals(0xf3, cpu.getAccumulator());
|
||||||
assertEquals(0xe3, bus.read(0xd828));
|
assertEquals(0xe3, bus.read(0xd828, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -78,7 +78,7 @@ public class CpuIndirectIndexedModeTest {
|
|||||||
cpu.step(1);
|
cpu.step(1);
|
||||||
|
|
||||||
assertEquals(0x22, cpu.getAccumulator());
|
assertEquals(0x22, cpu.getAccumulator());
|
||||||
assertEquals(0xe3, bus.read(0xd828));
|
assertEquals(0xe3, bus.read(0xd828, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ public class CpuIndirectModeTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void test_JMP_withIndirectBug() throws MemoryAccessException {
|
public void test_JMP_withIndirectBug() throws MemoryAccessException {
|
||||||
cpu.setBehavior(Cpu.CpuBehavior.NMOS_WITH_INDIRECT_JMP_BUG);
|
cpu.setBehavior(Cpu.CpuBehavior.NMOS_6502);
|
||||||
bus.write(0x3400, 0x22);
|
bus.write(0x3400, 0x22);
|
||||||
bus.write(0x34ff, 0x00);
|
bus.write(0x34ff, 0x00);
|
||||||
bus.write(0x3500, 0x54);
|
bus.write(0x3500, 0x54);
|
||||||
@@ -76,7 +76,7 @@ public class CpuIndirectModeTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void test_JMP_withOutIndirectBug() throws MemoryAccessException {
|
public void test_JMP_withOutIndirectBug() throws MemoryAccessException {
|
||||||
cpu.setBehavior(Cpu.CpuBehavior.NMOS_WITHOUT_INDIRECT_JMP_BUG);
|
cpu.setBehavior(Cpu.CpuBehavior.CMOS_6502);
|
||||||
bus.write(0x3400, 0x22);
|
bus.write(0x3400, 0x22);
|
||||||
bus.write(0x34ff, 0x00);
|
bus.write(0x34ff, 0x00);
|
||||||
bus.write(0x3500, 0x54);
|
bus.write(0x3500, 0x54);
|
||||||
@@ -88,7 +88,7 @@ public class CpuIndirectModeTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void test_JMP_cmos() throws MemoryAccessException {
|
public void test_JMP_cmos() throws MemoryAccessException {
|
||||||
cpu.setBehavior(Cpu.CpuBehavior.CMOS);
|
cpu.setBehavior(Cpu.CpuBehavior.CMOS_6502);
|
||||||
bus.write(0x3400, 0x22);
|
bus.write(0x3400, 0x22);
|
||||||
bus.write(0x34ff, 0x00);
|
bus.write(0x34ff, 0x00);
|
||||||
bus.write(0x3500, 0x54);
|
bus.write(0x3500, 0x54);
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ public class CpuIndirectXModeTest extends TestCase {
|
|||||||
|
|
||||||
cpu.setXRegister(0x30);
|
cpu.setXRegister(0x30);
|
||||||
|
|
||||||
bus.loadProgram(0xa9, 0x88, // LDA #$88
|
bus.loadProgram(0xa9, 0x88, // LDA #$88
|
||||||
0x5d, 0x10, 0xab, // EOR $ab10,X
|
0x5d, 0x10, 0xab, // EOR $ab10,X
|
||||||
0x5d, 0x11, 0xab, // EOR $ab11,X
|
0x5d, 0x11, 0xab, // EOR $ab11,X
|
||||||
0x5d, 0x12, 0xab, // EOR $ab12,X
|
0x5d, 0x12, 0xab, // EOR $ab12,X
|
||||||
@@ -411,7 +411,7 @@ public class CpuIndirectXModeTest extends TestCase {
|
|||||||
cpu.setAccumulator(0x00);
|
cpu.setAccumulator(0x00);
|
||||||
bus.loadProgram(0x9d, 0x10, 0xab); // STA $ab10,X
|
bus.loadProgram(0x9d, 0x10, 0xab); // STA $ab10,X
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0xab40));
|
assertEquals(0x00, bus.read(0xab40, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
@@ -422,7 +422,7 @@ public class CpuIndirectXModeTest extends TestCase {
|
|||||||
cpu.setAccumulator(0x0f);
|
cpu.setAccumulator(0x0f);
|
||||||
bus.loadProgram(0x9d, 0x10, 0xab); // STA $ab10,X
|
bus.loadProgram(0x9d, 0x10, 0xab); // STA $ab10,X
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x0f, bus.read(0xab40));
|
assertEquals(0x0f, bus.read(0xab40, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
@@ -432,7 +432,7 @@ public class CpuIndirectXModeTest extends TestCase {
|
|||||||
cpu.setAccumulator(0x80);
|
cpu.setAccumulator(0x80);
|
||||||
bus.loadProgram(0x9d, 0x10, 0xab); // STA $ab10,X
|
bus.loadProgram(0x9d, 0x10, 0xab); // STA $ab10,X
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x80, bus.read(0xab40));
|
assertEquals(0x80, bus.read(0xab40, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,61 +71,61 @@ public class CpuTest extends TestCase {
|
|||||||
|
|
||||||
public void testStackPush() throws MemoryAccessException {
|
public void testStackPush() throws MemoryAccessException {
|
||||||
assertEquals(0xff, cpu.getStackPointer());
|
assertEquals(0xff, cpu.getStackPointer());
|
||||||
assertEquals(0x00, bus.read(0x1ff));
|
assertEquals(0x00, bus.read(0x1ff, true));
|
||||||
|
|
||||||
cpu.stackPush(0x06);
|
cpu.stackPush(0x06);
|
||||||
assertEquals(0xfe, cpu.getStackPointer());
|
assertEquals(0xfe, cpu.getStackPointer());
|
||||||
assertEquals(0x06, bus.read(0x1ff));
|
assertEquals(0x06, bus.read(0x1ff, true));
|
||||||
|
|
||||||
cpu.stackPush(0x05);
|
cpu.stackPush(0x05);
|
||||||
assertEquals(0xfd, cpu.getStackPointer());
|
assertEquals(0xfd, cpu.getStackPointer());
|
||||||
assertEquals(0x06, bus.read(0x1ff));
|
assertEquals(0x06, bus.read(0x1ff, true));
|
||||||
assertEquals(0x05, bus.read(0x1fe));
|
assertEquals(0x05, bus.read(0x1fe, true));
|
||||||
|
|
||||||
cpu.stackPush(0x04);
|
cpu.stackPush(0x04);
|
||||||
assertEquals(0xfc, cpu.getStackPointer());
|
assertEquals(0xfc, cpu.getStackPointer());
|
||||||
assertEquals(0x06, bus.read(0x1ff));
|
assertEquals(0x06, bus.read(0x1ff, true));
|
||||||
assertEquals(0x05, bus.read(0x1fe));
|
assertEquals(0x05, bus.read(0x1fe, true));
|
||||||
assertEquals(0x04, bus.read(0x1fd));
|
assertEquals(0x04, bus.read(0x1fd, true));
|
||||||
|
|
||||||
cpu.stackPush(0x03);
|
cpu.stackPush(0x03);
|
||||||
assertEquals(0xfb, cpu.getStackPointer());
|
assertEquals(0xfb, cpu.getStackPointer());
|
||||||
assertEquals(0x06, bus.read(0x1ff));
|
assertEquals(0x06, bus.read(0x1ff, true));
|
||||||
assertEquals(0x05, bus.read(0x1fe));
|
assertEquals(0x05, bus.read(0x1fe, true));
|
||||||
assertEquals(0x04, bus.read(0x1fd));
|
assertEquals(0x04, bus.read(0x1fd, true));
|
||||||
assertEquals(0x03, bus.read(0x1fc));
|
assertEquals(0x03, bus.read(0x1fc, true));
|
||||||
|
|
||||||
cpu.stackPush(0x02);
|
cpu.stackPush(0x02);
|
||||||
assertEquals(0xfa, cpu.getStackPointer());
|
assertEquals(0xfa, cpu.getStackPointer());
|
||||||
assertEquals(0x06, bus.read(0x1ff));
|
assertEquals(0x06, bus.read(0x1ff, true));
|
||||||
assertEquals(0x05, bus.read(0x1fe));
|
assertEquals(0x05, bus.read(0x1fe, true));
|
||||||
assertEquals(0x04, bus.read(0x1fd));
|
assertEquals(0x04, bus.read(0x1fd, true));
|
||||||
assertEquals(0x03, bus.read(0x1fc));
|
assertEquals(0x03, bus.read(0x1fc, true));
|
||||||
assertEquals(0x02, bus.read(0x1fb));
|
assertEquals(0x02, bus.read(0x1fb, true));
|
||||||
|
|
||||||
cpu.stackPush(0x01);
|
cpu.stackPush(0x01);
|
||||||
assertEquals(0xf9, cpu.getStackPointer());
|
assertEquals(0xf9, cpu.getStackPointer());
|
||||||
assertEquals(0x06, bus.read(0x1ff));
|
assertEquals(0x06, bus.read(0x1ff, true));
|
||||||
assertEquals(0x05, bus.read(0x1fe));
|
assertEquals(0x05, bus.read(0x1fe, true));
|
||||||
assertEquals(0x04, bus.read(0x1fd));
|
assertEquals(0x04, bus.read(0x1fd, true));
|
||||||
assertEquals(0x03, bus.read(0x1fc));
|
assertEquals(0x03, bus.read(0x1fc, true));
|
||||||
assertEquals(0x02, bus.read(0x1fb));
|
assertEquals(0x02, bus.read(0x1fb, true));
|
||||||
assertEquals(0x01, bus.read(0x1fa));
|
assertEquals(0x01, bus.read(0x1fa, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testStackPushWrapsAroundToStackTop() throws MemoryAccessException {
|
public void testStackPushWrapsAroundToStackTop() throws MemoryAccessException {
|
||||||
cpu.setStackPointer(0x01);
|
cpu.setStackPointer(0x01);
|
||||||
|
|
||||||
cpu.stackPush(0x01);
|
cpu.stackPush(0x01);
|
||||||
assertEquals(0x01, bus.read(0x101));
|
assertEquals(0x01, bus.read(0x101, true));
|
||||||
assertEquals(0x00, cpu.getStackPointer());
|
assertEquals(0x00, cpu.getStackPointer());
|
||||||
|
|
||||||
cpu.stackPush(0x02);
|
cpu.stackPush(0x02);
|
||||||
assertEquals(0x02, bus.read(0x100));
|
assertEquals(0x02, bus.read(0x100, true));
|
||||||
assertEquals(0xff, cpu.getStackPointer());
|
assertEquals(0xff, cpu.getStackPointer());
|
||||||
|
|
||||||
cpu.stackPush(0x03);
|
cpu.stackPush(0x03);
|
||||||
assertEquals(0x03, bus.read(0x1ff));
|
assertEquals(0x03, bus.read(0x1ff, true));
|
||||||
assertEquals(0xfe, cpu.getStackPointer());
|
assertEquals(0xfe, cpu.getStackPointer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,329 @@
|
|||||||
|
package com.loomcom.symon;
|
||||||
|
|
||||||
|
import com.loomcom.symon.devices.Memory;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static junit.framework.TestCase.assertFalse;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for Zero Page Indirect addressing mode, found on some instructions
|
||||||
|
* in the 65C02 and 65816
|
||||||
|
*/
|
||||||
|
public class CpuZeroPageIndirectTest {
|
||||||
|
protected Cpu cpu;
|
||||||
|
protected Bus bus;
|
||||||
|
protected Memory mem;
|
||||||
|
|
||||||
|
private void makeCmosCpu() throws Exception {
|
||||||
|
makeCpu(InstructionTable.CpuBehavior.CMOS_6502);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeNmosCpu() throws Exception {
|
||||||
|
makeCpu(InstructionTable.CpuBehavior.NMOS_6502);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeCpu(InstructionTable.CpuBehavior behavior) throws Exception {
|
||||||
|
this.cpu = new Cpu(behavior);
|
||||||
|
this.bus = new Bus(0x0000, 0xffff);
|
||||||
|
this.mem = new Memory(0x0000, 0xffff);
|
||||||
|
bus.addCpu(cpu);
|
||||||
|
bus.addDevice(mem);
|
||||||
|
|
||||||
|
// Load the reset vector.
|
||||||
|
bus.write(0xfffc, Bus.DEFAULT_LOAD_ADDRESS & 0x00ff);
|
||||||
|
bus.write(0xfffd, (Bus.DEFAULT_LOAD_ADDRESS & 0xff00) >>> 8);
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_ora() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
|
||||||
|
// Set some initial values in zero page.
|
||||||
|
bus.write(0x30, 0x00);
|
||||||
|
bus.write(0x31, 0x10);
|
||||||
|
|
||||||
|
bus.write(0x40, 0x01);
|
||||||
|
bus.write(0x41, 0x10);
|
||||||
|
|
||||||
|
bus.write(0x50, 0x02);
|
||||||
|
bus.write(0x51, 0x10);
|
||||||
|
|
||||||
|
bus.write(0x60, 0x03);
|
||||||
|
bus.write(0x61, 0x10);
|
||||||
|
|
||||||
|
bus.write(0x1000, 0x11);
|
||||||
|
bus.write(0x1001, 0x22);
|
||||||
|
bus.write(0x1002, 0x44);
|
||||||
|
bus.write(0x1003, 0x88);
|
||||||
|
|
||||||
|
bus.loadProgram(0x12, 0x30, // ORA ($30)
|
||||||
|
0x12, 0x40, // ORA ($40)
|
||||||
|
0x12, 0x50, // ORA ($50)
|
||||||
|
0x12, 0x60); // ORA ($60)
|
||||||
|
|
||||||
|
|
||||||
|
assertEquals(0x00, cpu.getAccumulator());
|
||||||
|
|
||||||
|
// 0x00 | 0x11 = 0x11
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x11, cpu.getAccumulator());
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
|
// 0x11 | 0x22 = 0x33
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x33, cpu.getAccumulator());
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
|
// 0x33 | 0x44 = 0x77
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x77, cpu.getAccumulator());
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
|
// 0x77 | 0x88 = 0xff
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xff, cpu.getAccumulator());
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
assertTrue(cpu.getNegativeFlag());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_ora_requiresCmosCpu() throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
|
||||||
|
// Set some initial values in zero page.
|
||||||
|
bus.write(0x30, 0x00);
|
||||||
|
bus.write(0x31, 0x10);
|
||||||
|
|
||||||
|
bus.write(0x40, 0x01);
|
||||||
|
bus.write(0x41, 0x10);
|
||||||
|
|
||||||
|
bus.write(0x50, 0x02);
|
||||||
|
bus.write(0x51, 0x10);
|
||||||
|
|
||||||
|
bus.write(0x60, 0x03);
|
||||||
|
bus.write(0x61, 0x10);
|
||||||
|
|
||||||
|
bus.write(0x1000, 0x11);
|
||||||
|
bus.write(0x1001, 0x22);
|
||||||
|
bus.write(0x1002, 0x44);
|
||||||
|
bus.write(0x1003, 0x88);
|
||||||
|
|
||||||
|
bus.loadProgram(0x12, 0x30, // ORA ($30)
|
||||||
|
0x12, 0x40, // ORA ($40)
|
||||||
|
0x12, 0x50, // ORA ($50)
|
||||||
|
0x12, 0x60); // ORA ($60)
|
||||||
|
|
||||||
|
|
||||||
|
assertEquals(0x00, cpu.getAccumulator());
|
||||||
|
|
||||||
|
boolean zState = cpu.getZeroFlag();
|
||||||
|
boolean nState = cpu.getNegativeFlag();
|
||||||
|
|
||||||
|
// 0x00 | 0x11 = 0x11, but not implemented in NMOS cpu
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00, cpu.getAccumulator());
|
||||||
|
assertEquals(zState, cpu.getZeroFlag()); // unchanged
|
||||||
|
assertEquals(nState, cpu.getNegativeFlag()); // unchanged
|
||||||
|
|
||||||
|
// 0x11 | 0x22 = 0x33, but not implemented in NMOS cpu
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00, cpu.getAccumulator());
|
||||||
|
assertEquals(zState, cpu.getZeroFlag()); // unchanged
|
||||||
|
assertEquals(nState, cpu.getNegativeFlag()); // unchanged
|
||||||
|
|
||||||
|
// 0x33 | 0x44 = 0x77, but not implemented in NMOS cpu
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00, cpu.getAccumulator());
|
||||||
|
assertEquals(zState, cpu.getZeroFlag()); // unchanged
|
||||||
|
assertEquals(nState, cpu.getNegativeFlag()); // unchanged
|
||||||
|
|
||||||
|
// 0x77 | 0x88 = 0xff, but not implemented in NMOS cpu
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00, cpu.getAccumulator());
|
||||||
|
assertEquals(zState, cpu.getZeroFlag()); // unchanged
|
||||||
|
assertEquals(nState, cpu.getNegativeFlag()); // unchanged
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_and() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
|
||||||
|
// Set some initial values in zero page.
|
||||||
|
bus.write(0x30, 0x00);
|
||||||
|
bus.write(0x31, 0x10);
|
||||||
|
|
||||||
|
bus.write(0x40, 0x01);
|
||||||
|
bus.write(0x41, 0x10);
|
||||||
|
|
||||||
|
bus.write(0x50, 0x02);
|
||||||
|
bus.write(0x51, 0x10);
|
||||||
|
|
||||||
|
bus.write(0x1000, 0x33);
|
||||||
|
bus.write(0x1001, 0x11);
|
||||||
|
bus.write(0x1002, 0x88);
|
||||||
|
|
||||||
|
bus.loadProgram(0x32, 0x30, // AND ($30)
|
||||||
|
0x32, 0x40, // AND ($40)
|
||||||
|
0x32, 0x50); // AND ($50)
|
||||||
|
|
||||||
|
cpu.setAccumulator(0xff);
|
||||||
|
|
||||||
|
// 0xFF & 0x33 == 0x33
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x33, cpu.getAccumulator());
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
|
// 0x33 & 0x11 == 0x11
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x11, cpu.getAccumulator());
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
|
// 0x11 & 0x80 == 0
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0, cpu.getAccumulator());
|
||||||
|
assertTrue(cpu.getZeroFlag());
|
||||||
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_and_requiresCmosCpu() throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
|
||||||
|
// Set some initial values in zero page.
|
||||||
|
bus.write(0x30, 0x00);
|
||||||
|
bus.write(0x31, 0x10);
|
||||||
|
|
||||||
|
bus.write(0x40, 0x01);
|
||||||
|
bus.write(0x41, 0x10);
|
||||||
|
|
||||||
|
bus.write(0x50, 0x02);
|
||||||
|
bus.write(0x51, 0x10);
|
||||||
|
|
||||||
|
bus.write(0x1000, 0x33);
|
||||||
|
bus.write(0x1001, 0x11);
|
||||||
|
bus.write(0x1002, 0x88);
|
||||||
|
|
||||||
|
bus.loadProgram(0x32, 0x30, // AND ($30)
|
||||||
|
0x32, 0x40, // AND ($40)
|
||||||
|
0x32, 0x50); // AND ($50)
|
||||||
|
|
||||||
|
|
||||||
|
cpu.setAccumulator(0xff);
|
||||||
|
|
||||||
|
boolean zState = cpu.getZeroFlag();
|
||||||
|
boolean nState = cpu.getNegativeFlag();
|
||||||
|
|
||||||
|
// 0xFF & 0x33 == 0x33, but not implemented in NMOS cpu
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xff, cpu.getAccumulator());
|
||||||
|
assertEquals(zState, cpu.getZeroFlag());
|
||||||
|
assertEquals(nState, cpu.getNegativeFlag());
|
||||||
|
|
||||||
|
// 0x33 & 0x11 == 0x11, but not implemented in NMOS cpu
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xff, cpu.getAccumulator());
|
||||||
|
assertEquals(zState, cpu.getZeroFlag());
|
||||||
|
assertEquals(nState, cpu.getNegativeFlag());
|
||||||
|
|
||||||
|
// 0x11 & 0x80 == 0, but not implemented in NMOS cpu
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xff, cpu.getAccumulator());
|
||||||
|
assertEquals(zState, cpu.getZeroFlag());
|
||||||
|
assertEquals(nState, cpu.getNegativeFlag());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_eor() throws Exception {
|
||||||
|
makeCmosCpu();
|
||||||
|
|
||||||
|
// Set some initial values in zero page.
|
||||||
|
bus.write(0x30, 0x00);
|
||||||
|
bus.write(0x31, 0x10);
|
||||||
|
|
||||||
|
bus.write(0x40, 0x01);
|
||||||
|
bus.write(0x41, 0x10);
|
||||||
|
|
||||||
|
bus.write(0x50, 0x02);
|
||||||
|
bus.write(0x51, 0x10);
|
||||||
|
|
||||||
|
bus.write(0x60, 0x03);
|
||||||
|
bus.write(0x61, 0x10);
|
||||||
|
|
||||||
|
bus.write(0x1000, 0x00);
|
||||||
|
bus.write(0x1001, 0xff);
|
||||||
|
bus.write(0x1002, 0x33);
|
||||||
|
bus.write(0x1003, 0x44);
|
||||||
|
|
||||||
|
bus.loadProgram(0x52, 0x30, // AND ($30)
|
||||||
|
0x52, 0x40, // AND ($40)
|
||||||
|
0x52, 0x50, // EOR ($50)
|
||||||
|
0x52, 0x60); // AND ($60)
|
||||||
|
|
||||||
|
|
||||||
|
cpu.setAccumulator(0x88);
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x88, cpu.getAccumulator());
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x77, cpu.getAccumulator());
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x44, cpu.getAccumulator());
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00, cpu.getAccumulator());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_eor_requiresCmosCpu() throws Exception {
|
||||||
|
makeNmosCpu();
|
||||||
|
|
||||||
|
// Set some initial values in zero page.
|
||||||
|
bus.write(0x30, 0x00);
|
||||||
|
bus.write(0x31, 0x10);
|
||||||
|
|
||||||
|
bus.write(0x40, 0x01);
|
||||||
|
bus.write(0x41, 0x10);
|
||||||
|
|
||||||
|
bus.write(0x50, 0x02);
|
||||||
|
bus.write(0x51, 0x10);
|
||||||
|
|
||||||
|
bus.write(0x60, 0x03);
|
||||||
|
bus.write(0x61, 0x10);
|
||||||
|
|
||||||
|
bus.write(0x1000, 0x00);
|
||||||
|
bus.write(0x1001, 0xff);
|
||||||
|
bus.write(0x1002, 0x33);
|
||||||
|
bus.write(0x1003, 0x44);
|
||||||
|
|
||||||
|
bus.loadProgram(0x52, 0x30, // AND ($30)
|
||||||
|
0x52, 0x40, // AND ($40)
|
||||||
|
0x52, 0x50, // EOR ($50)
|
||||||
|
0x52, 0x60); // AND ($60)
|
||||||
|
|
||||||
|
|
||||||
|
cpu.setAccumulator(0x88);
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x88, cpu.getAccumulator());
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x88, cpu.getAccumulator());
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x88, cpu.getAccumulator());
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x88, cpu.getAccumulator());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -119,31 +119,31 @@ public class CpuZeroPageModeTest extends TestCase {
|
|||||||
0x06, 0x04);
|
0x06, 0x04);
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x0000));
|
assertEquals(0x00, bus.read(0x0000, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x02, bus.read(0x0001));
|
assertEquals(0x02, bus.read(0x0001, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x04, bus.read(0x0002));
|
assertEquals(0x04, bus.read(0x0002, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x88, bus.read(0x0003));
|
assertEquals(0x88, bus.read(0x0003, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x0004));
|
assertEquals(0x00, bus.read(0x0004, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertTrue(cpu.getCarryFlag());
|
assertTrue(cpu.getCarryFlag());
|
||||||
@@ -274,61 +274,61 @@ public class CpuZeroPageModeTest extends TestCase {
|
|||||||
0x26, 0x01); // ROL $01 (m=%10000001, c=0)
|
0x26, 0x01); // ROL $01 (m=%10000001, c=0)
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x0000));
|
assertEquals(0x00, bus.read(0x0000, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x02, bus.read(0x0001));
|
assertEquals(0x02, bus.read(0x0001, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step(2);
|
cpu.step(2);
|
||||||
assertEquals(0x05, bus.read(0x0001));
|
assertEquals(0x05, bus.read(0x0001, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x0a, bus.read(0x0001));
|
assertEquals(0x0a, bus.read(0x0001, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x14, bus.read(0x0001));
|
assertEquals(0x14, bus.read(0x0001, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x28, bus.read(0x0001));
|
assertEquals(0x28, bus.read(0x0001, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x50, bus.read(0x0001));
|
assertEquals(0x50, bus.read(0x0001, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0xa0, bus.read(0x0001));
|
assertEquals(0xa0, bus.read(0x0001, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x40, bus.read(0x0001));
|
assertEquals(0x40, bus.read(0x0001, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertTrue(cpu.getCarryFlag());
|
assertTrue(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x81, bus.read(0x0001));
|
assertEquals(0x81, bus.read(0x0001, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
@@ -387,38 +387,38 @@ public class CpuZeroPageModeTest extends TestCase {
|
|||||||
0x46, 0x05); // LSR $05
|
0x46, 0x05); // LSR $05
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x0000));
|
assertEquals(0x00, bus.read(0x0000, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x0001));
|
assertEquals(0x00, bus.read(0x0001, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertTrue(cpu.getCarryFlag());
|
assertTrue(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x01, bus.read(0x0002));
|
assertEquals(0x01, bus.read(0x0002, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x22, bus.read(0x0003));
|
assertEquals(0x22, bus.read(0x0003, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x40, bus.read(0x0004));
|
assertEquals(0x40, bus.read(0x0004, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
// Setting Carry should not affect the result.
|
// Setting Carry should not affect the result.
|
||||||
cpu.step(2);
|
cpu.step(2);
|
||||||
assertEquals(0x01, bus.read(0x0005));
|
assertEquals(0x01, bus.read(0x0005, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
@@ -623,61 +623,61 @@ public class CpuZeroPageModeTest extends TestCase {
|
|||||||
0x66, 0x11); // ROR $01 (m=%00010000, c=0)
|
0x66, 0x11); // ROR $01 (m=%00010000, c=0)
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x10));
|
assertEquals(0x00, bus.read(0x10, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x08, bus.read(0x11));
|
assertEquals(0x08, bus.read(0x11, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x04, bus.read(0x11));
|
assertEquals(0x04, bus.read(0x11, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x02, bus.read(0x11));
|
assertEquals(0x02, bus.read(0x11, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x01, bus.read(0x11));
|
assertEquals(0x01, bus.read(0x11, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x11));
|
assertEquals(0x00, bus.read(0x11, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertTrue(cpu.getCarryFlag());
|
assertTrue(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x80, bus.read(0x11));
|
assertEquals(0x80, bus.read(0x11, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x40, bus.read(0x11));
|
assertEquals(0x40, bus.read(0x11, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x20, bus.read(0x11));
|
assertEquals(0x20, bus.read(0x11, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x10, bus.read(0x11));
|
assertEquals(0x10, bus.read(0x11, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
@@ -689,7 +689,7 @@ public class CpuZeroPageModeTest extends TestCase {
|
|||||||
cpu.setYRegister(0x00);
|
cpu.setYRegister(0x00);
|
||||||
bus.loadProgram(0x84, 0x10);
|
bus.loadProgram(0x84, 0x10);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x10));
|
assertEquals(0x00, bus.read(0x10, true));
|
||||||
// Should have no effect on flags.
|
// Should have no effect on flags.
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
@@ -699,7 +699,7 @@ public class CpuZeroPageModeTest extends TestCase {
|
|||||||
cpu.setYRegister(0x0f);
|
cpu.setYRegister(0x0f);
|
||||||
bus.loadProgram(0x84, 0x10);
|
bus.loadProgram(0x84, 0x10);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x0f, bus.read(0x10));
|
assertEquals(0x0f, bus.read(0x10, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
@@ -708,7 +708,7 @@ public class CpuZeroPageModeTest extends TestCase {
|
|||||||
cpu.setYRegister(0x80);
|
cpu.setYRegister(0x80);
|
||||||
bus.loadProgram(0x84, 0x10);
|
bus.loadProgram(0x84, 0x10);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x80, bus.read(0x10));
|
assertEquals(0x80, bus.read(0x10, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
@@ -719,7 +719,7 @@ public class CpuZeroPageModeTest extends TestCase {
|
|||||||
cpu.setAccumulator(0x00);
|
cpu.setAccumulator(0x00);
|
||||||
bus.loadProgram(0x85, 0x10);
|
bus.loadProgram(0x85, 0x10);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x10));
|
assertEquals(0x00, bus.read(0x10, true));
|
||||||
// Should have no effect on flags.
|
// Should have no effect on flags.
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
@@ -729,7 +729,7 @@ public class CpuZeroPageModeTest extends TestCase {
|
|||||||
cpu.setAccumulator(0x0f);
|
cpu.setAccumulator(0x0f);
|
||||||
bus.loadProgram(0x85, 0x10);
|
bus.loadProgram(0x85, 0x10);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x0f, bus.read(0x10));
|
assertEquals(0x0f, bus.read(0x10, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
@@ -738,7 +738,7 @@ public class CpuZeroPageModeTest extends TestCase {
|
|||||||
cpu.setAccumulator(0x80);
|
cpu.setAccumulator(0x80);
|
||||||
bus.loadProgram(0x85, 0x10);
|
bus.loadProgram(0x85, 0x10);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x80, bus.read(0x10));
|
assertEquals(0x80, bus.read(0x10, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
@@ -749,7 +749,7 @@ public class CpuZeroPageModeTest extends TestCase {
|
|||||||
cpu.setXRegister(0x00);
|
cpu.setXRegister(0x00);
|
||||||
bus.loadProgram(0x86, 0x10);
|
bus.loadProgram(0x86, 0x10);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x10));
|
assertEquals(0x00, bus.read(0x10, true));
|
||||||
// Should have no effect on flags.
|
// Should have no effect on flags.
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
@@ -759,7 +759,7 @@ public class CpuZeroPageModeTest extends TestCase {
|
|||||||
cpu.setXRegister(0x0f);
|
cpu.setXRegister(0x0f);
|
||||||
bus.loadProgram(0x86, 0x10);
|
bus.loadProgram(0x86, 0x10);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x0f, bus.read(0x10));
|
assertEquals(0x0f, bus.read(0x10, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
@@ -768,7 +768,7 @@ public class CpuZeroPageModeTest extends TestCase {
|
|||||||
cpu.setXRegister(0x80);
|
cpu.setXRegister(0x80);
|
||||||
bus.loadProgram(0x86, 0x10);
|
bus.loadProgram(0x86, 0x10);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x80, bus.read(0x10));
|
assertEquals(0x80, bus.read(0x10, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
@@ -926,22 +926,22 @@ public class CpuZeroPageModeTest extends TestCase {
|
|||||||
0xc6, 0x13); // DEC $13
|
0xc6, 0x13); // DEC $13
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0xff, bus.read(0x10));
|
assertEquals(0xff, bus.read(0x10, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x11));
|
assertEquals(0x00, bus.read(0x11, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x7f, bus.read(0x12));
|
assertEquals(0x7f, bus.read(0x12, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0xfe, bus.read(0x13));
|
assertEquals(0xfe, bus.read(0x13, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
@@ -1182,17 +1182,17 @@ public class CpuZeroPageModeTest extends TestCase {
|
|||||||
0xe6, 0x12); // INC $12
|
0xe6, 0x12); // INC $12
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x01, bus.read(0x10));
|
assertEquals(0x01, bus.read(0x10, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x80, bus.read(0x11));
|
assertEquals(0x80, bus.read(0x11, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x12));
|
assertEquals(0x00, bus.read(0x12, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,38 +131,38 @@ public class CpuZeroPageXModeTest extends TestCase {
|
|||||||
0x16, 0xd2); // ASL $d2,X
|
0x16, 0xd2); // ASL $d2,X
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x30));
|
assertEquals(0x00, bus.read(0x30, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x02, bus.read(0x31));
|
assertEquals(0x02, bus.read(0x31, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x04, bus.read(0x32));
|
assertEquals(0x04, bus.read(0x32, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x88, bus.read(0x33));
|
assertEquals(0x88, bus.read(0x33, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x34));
|
assertEquals(0x00, bus.read(0x34, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertTrue(cpu.getCarryFlag());
|
assertTrue(cpu.getCarryFlag());
|
||||||
|
|
||||||
// Should wrap around, d2 + 30 = 02
|
// Should wrap around, d2 + 30 = 02
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x02, bus.read(0x02));
|
assertEquals(0x02, bus.read(0x02, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
@@ -251,61 +251,61 @@ public class CpuZeroPageXModeTest extends TestCase {
|
|||||||
0x36, 0x01); // ROL $01,X (m=%10000001, c=0)
|
0x36, 0x01); // ROL $01,X (m=%10000001, c=0)
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x70));
|
assertEquals(0x00, bus.read(0x70, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x02, bus.read(0x71));
|
assertEquals(0x02, bus.read(0x71, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step(2);
|
cpu.step(2);
|
||||||
assertEquals(0x05, bus.read(0x71));
|
assertEquals(0x05, bus.read(0x71, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x0a, bus.read(0x71));
|
assertEquals(0x0a, bus.read(0x71, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x14, bus.read(0x71));
|
assertEquals(0x14, bus.read(0x71, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x28, bus.read(0x71));
|
assertEquals(0x28, bus.read(0x71, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x50, bus.read(0x71));
|
assertEquals(0x50, bus.read(0x71, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0xa0, bus.read(0x71));
|
assertEquals(0xa0, bus.read(0x71, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x40, bus.read(0x71));
|
assertEquals(0x40, bus.read(0x71, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertTrue(cpu.getCarryFlag());
|
assertTrue(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x81, bus.read(0x71));
|
assertEquals(0x81, bus.read(0x71, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
@@ -368,38 +368,38 @@ public class CpuZeroPageXModeTest extends TestCase {
|
|||||||
0x56, 0x05); // LSR $05,X
|
0x56, 0x05); // LSR $05,X
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x30));
|
assertEquals(0x00, bus.read(0x30, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x31));
|
assertEquals(0x00, bus.read(0x31, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertTrue(cpu.getCarryFlag());
|
assertTrue(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x01, bus.read(0x32));
|
assertEquals(0x01, bus.read(0x32, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x22, bus.read(0x33));
|
assertEquals(0x22, bus.read(0x33, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x40, bus.read(0x34));
|
assertEquals(0x40, bus.read(0x34, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
// Setting Carry should not affect the result.
|
// Setting Carry should not affect the result.
|
||||||
cpu.step(2);
|
cpu.step(2);
|
||||||
assertEquals(0x01, bus.read(0x35));
|
assertEquals(0x01, bus.read(0x35, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
@@ -641,61 +641,61 @@ public class CpuZeroPageXModeTest extends TestCase {
|
|||||||
cpu.setXRegister(0x30);
|
cpu.setXRegister(0x30);
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x40));
|
assertEquals(0x00, bus.read(0x40, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x08, bus.read(0x41));
|
assertEquals(0x08, bus.read(0x41, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x04, bus.read(0x41));
|
assertEquals(0x04, bus.read(0x41, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x02, bus.read(0x41));
|
assertEquals(0x02, bus.read(0x41, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x01, bus.read(0x41));
|
assertEquals(0x01, bus.read(0x41, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x41));
|
assertEquals(0x00, bus.read(0x41, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertTrue(cpu.getCarryFlag());
|
assertTrue(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x80, bus.read(0x41));
|
assertEquals(0x80, bus.read(0x41, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x40, bus.read(0x41));
|
assertEquals(0x40, bus.read(0x41, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x20, bus.read(0x41));
|
assertEquals(0x20, bus.read(0x41, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x10, bus.read(0x41));
|
assertEquals(0x10, bus.read(0x41, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
@@ -708,7 +708,7 @@ public class CpuZeroPageXModeTest extends TestCase {
|
|||||||
cpu.setYRegister(0x00);
|
cpu.setYRegister(0x00);
|
||||||
bus.loadProgram(0x94, 0x10); // STY $10,X
|
bus.loadProgram(0x94, 0x10); // STY $10,X
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x40));
|
assertEquals(0x00, bus.read(0x40, true));
|
||||||
// Should have no effect on flags.
|
// Should have no effect on flags.
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
@@ -719,7 +719,7 @@ public class CpuZeroPageXModeTest extends TestCase {
|
|||||||
cpu.setYRegister(0x0f);
|
cpu.setYRegister(0x0f);
|
||||||
bus.loadProgram(0x94, 0x10); // STY $10,X
|
bus.loadProgram(0x94, 0x10); // STY $10,X
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x0f, bus.read(0x40));
|
assertEquals(0x0f, bus.read(0x40, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
@@ -729,7 +729,7 @@ public class CpuZeroPageXModeTest extends TestCase {
|
|||||||
cpu.setYRegister(0x80);
|
cpu.setYRegister(0x80);
|
||||||
bus.loadProgram(0x94, 0x10); // STY $10,X
|
bus.loadProgram(0x94, 0x10); // STY $10,X
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x80, bus.read(0x40));
|
assertEquals(0x80, bus.read(0x40, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
@@ -742,7 +742,7 @@ public class CpuZeroPageXModeTest extends TestCase {
|
|||||||
cpu.setAccumulator(0x00);
|
cpu.setAccumulator(0x00);
|
||||||
bus.loadProgram(0x95, 0x10); // STA $10,X
|
bus.loadProgram(0x95, 0x10); // STA $10,X
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x40));
|
assertEquals(0x00, bus.read(0x40, true));
|
||||||
// Should have no effect on flags.
|
// Should have no effect on flags.
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
@@ -753,7 +753,7 @@ public class CpuZeroPageXModeTest extends TestCase {
|
|||||||
cpu.setAccumulator(0x0f);
|
cpu.setAccumulator(0x0f);
|
||||||
bus.loadProgram(0x95, 0x10); // STA $10,X
|
bus.loadProgram(0x95, 0x10); // STA $10,X
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x0f, bus.read(0x40));
|
assertEquals(0x0f, bus.read(0x40, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
@@ -763,7 +763,7 @@ public class CpuZeroPageXModeTest extends TestCase {
|
|||||||
cpu.setAccumulator(0x80);
|
cpu.setAccumulator(0x80);
|
||||||
bus.loadProgram(0x95, 0x10); // STA $10,X
|
bus.loadProgram(0x95, 0x10); // STA $10,X
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x80, bus.read(0x40));
|
assertEquals(0x80, bus.read(0x40, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
@@ -873,22 +873,22 @@ public class CpuZeroPageXModeTest extends TestCase {
|
|||||||
cpu.setXRegister(0x30);
|
cpu.setXRegister(0x30);
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0xff, bus.read(0x40));
|
assertEquals(0xff, bus.read(0x40, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x41));
|
assertEquals(0x00, bus.read(0x41, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x7f, bus.read(0x42));
|
assertEquals(0x7f, bus.read(0x42, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0xfe, bus.read(0x43));
|
assertEquals(0xfe, bus.read(0x43, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
@@ -1116,17 +1116,17 @@ public class CpuZeroPageXModeTest extends TestCase {
|
|||||||
0xf6, 0x12); // INC $12,X
|
0xf6, 0x12); // INC $12,X
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x01, bus.read(0x30));
|
assertEquals(0x01, bus.read(0x30, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x80, bus.read(0x31));
|
assertEquals(0x80, bus.read(0x31, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
|
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x32));
|
assertEquals(0x00, bus.read(0x32, true));
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class CpuZeroPageYModeTest extends TestCase {
|
|||||||
cpu.setXRegister(0x00);
|
cpu.setXRegister(0x00);
|
||||||
bus.loadProgram(0x96, 0x10); // STX $10,Y
|
bus.loadProgram(0x96, 0x10); // STX $10,Y
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x00, bus.read(0x40));
|
assertEquals(0x00, bus.read(0x40, true));
|
||||||
// Should have no effect on flags.
|
// Should have no effect on flags.
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
@@ -57,7 +57,7 @@ public class CpuZeroPageYModeTest extends TestCase {
|
|||||||
cpu.setXRegister(0x0f);
|
cpu.setXRegister(0x0f);
|
||||||
bus.loadProgram(0x96, 0x10); // STX $10,Y
|
bus.loadProgram(0x96, 0x10); // STX $10,Y
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x0f, bus.read(0x40));
|
assertEquals(0x0f, bus.read(0x40, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ public class CpuZeroPageYModeTest extends TestCase {
|
|||||||
cpu.setXRegister(0x80);
|
cpu.setXRegister(0x80);
|
||||||
bus.loadProgram(0x96, 0x10); // STX $10,Y
|
bus.loadProgram(0x96, 0x10); // STX $10,Y
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0x80, bus.read(0x40));
|
assertEquals(0x80, bus.read(0x40, true));
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -242,19 +242,19 @@ public class CrtcTest {
|
|||||||
crtc.write(0, 12); // High byte
|
crtc.write(0, 12); // High byte
|
||||||
|
|
||||||
crtc.write(1, 0x03);
|
crtc.write(1, 0x03);
|
||||||
assertEquals(0, crtc.read(1));
|
assertEquals(0, crtc.read(1, true));
|
||||||
|
|
||||||
crtc.write(1, 0x70);
|
crtc.write(1, 0x70);
|
||||||
assertEquals(0, crtc.read(1));
|
assertEquals(0, crtc.read(1, true));
|
||||||
|
|
||||||
|
|
||||||
crtc.write(0, 13); // Low byte
|
crtc.write(0, 13); // Low byte
|
||||||
|
|
||||||
crtc.write(1, 0xff);
|
crtc.write(1, 0xff);
|
||||||
assertEquals(0, crtc.read(1));
|
assertEquals(0, crtc.read(1, true));
|
||||||
|
|
||||||
crtc.write(1, 0x0e);
|
crtc.write(1, 0x0e);
|
||||||
assertEquals(0, crtc.read(1));
|
assertEquals(0, crtc.read(1, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -278,10 +278,10 @@ public class CrtcTest {
|
|||||||
crtc.write(0, 14);
|
crtc.write(0, 14);
|
||||||
|
|
||||||
crtc.write(1, 0x3f);
|
crtc.write(1, 0x3f);
|
||||||
assertEquals(0x3f, crtc.read(1));
|
assertEquals(0x3f, crtc.read(1, true));
|
||||||
|
|
||||||
crtc.write(1, 0x70);
|
crtc.write(1, 0x70);
|
||||||
assertEquals(0x70, crtc.read(1));
|
assertEquals(0x70, crtc.read(1, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -313,13 +313,13 @@ public class CrtcTest {
|
|||||||
crtc.write(0, 15);
|
crtc.write(0, 15);
|
||||||
|
|
||||||
crtc.write(1, 0x00);
|
crtc.write(1, 0x00);
|
||||||
assertEquals(0x00, crtc.read(1));
|
assertEquals(0x00, crtc.read(1, true));
|
||||||
|
|
||||||
crtc.write(1, 0x1f);
|
crtc.write(1, 0x1f);
|
||||||
assertEquals(0x1f, crtc.read(1));
|
assertEquals(0x1f, crtc.read(1, true));
|
||||||
|
|
||||||
crtc.write(1, 0xff);
|
crtc.write(1, 0xff);
|
||||||
assertEquals(0xff, crtc.read(1));
|
assertEquals(0xff, crtc.read(1, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,231 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011 Graham Edgecombe.
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.loomcom.symon.jterminal.vt100.AnsiControlSequenceParser;
|
||||||
|
import com.loomcom.symon.jterminal.vt100.AnsiControlSequence;
|
||||||
|
import com.loomcom.symon.jterminal.vt100.AnsiControlSequenceListener;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A test for the {@link AnsiControlSequenceParser} class.
|
||||||
|
* @author Graham Edgecombe
|
||||||
|
*/
|
||||||
|
public class TestAnsiControlSequenceParser implements AnsiControlSequenceListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current parser.
|
||||||
|
*/
|
||||||
|
private AnsiControlSequenceParser parser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of objects returned through the
|
||||||
|
* {@link AnsiControlSequenceListener} interface.
|
||||||
|
*/
|
||||||
|
private List<Object> objects = new ArrayList<Object>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up the parser and object list.
|
||||||
|
*/
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
objects.clear();
|
||||||
|
parser = new AnsiControlSequenceParser(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests a broken sequence with the single byte CSI.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testBrokenSingleSequence() {
|
||||||
|
parser.parse(new String(new char[] { 155 }));
|
||||||
|
parser.parse(new String(new char[] { 'u' }));
|
||||||
|
|
||||||
|
assertEquals(1, objects.size());
|
||||||
|
|
||||||
|
Object obj = objects.get(0);
|
||||||
|
assertEquals(AnsiControlSequence.class, obj.getClass());
|
||||||
|
|
||||||
|
AnsiControlSequence seq = (AnsiControlSequence) obj;
|
||||||
|
String[] params = seq.getParameters();
|
||||||
|
|
||||||
|
assertEquals('u', seq.getCommand());
|
||||||
|
assertEquals(0, params.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests a broken sequence with the double byte CSI.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testBrokenDoubleSequence() {
|
||||||
|
char[] ch1 = { 27 };
|
||||||
|
char[] ch2 = { '[' };
|
||||||
|
char[] ch3 = { '3', '0', ';' };
|
||||||
|
char[] ch4 = { '4', '0', 'm' };
|
||||||
|
|
||||||
|
parser.parse(new String(ch1));
|
||||||
|
parser.parse(new String(ch2));
|
||||||
|
parser.parse(new String(ch3));
|
||||||
|
parser.parse(new String(ch4));
|
||||||
|
|
||||||
|
assertEquals(1, objects.size());
|
||||||
|
Object obj = objects.get(0);
|
||||||
|
assertEquals(AnsiControlSequence.class, obj.getClass());
|
||||||
|
|
||||||
|
AnsiControlSequence seq = (AnsiControlSequence) obj;
|
||||||
|
String[] params = seq.getParameters();
|
||||||
|
|
||||||
|
assertEquals('m', seq.getCommand());
|
||||||
|
assertEquals(2, params.length);
|
||||||
|
assertEquals("30", params[0]);
|
||||||
|
assertEquals("40", params[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests an empty string.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testEmpty() {
|
||||||
|
parser.parse("");
|
||||||
|
assertEquals(0, objects.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests a sequence embedded within some text.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testTextAndSequence() {
|
||||||
|
char[] ch = { 'h', 'i', 155, 'u', 'b', 'y', 'e' };
|
||||||
|
parser.parse(new String(ch));
|
||||||
|
|
||||||
|
assertEquals(3, objects.size());
|
||||||
|
|
||||||
|
Object o1 = objects.get(0);
|
||||||
|
Object o2 = objects.get(1);
|
||||||
|
Object o3 = objects.get(2);
|
||||||
|
|
||||||
|
assertEquals(String.class, o1.getClass());
|
||||||
|
assertEquals(AnsiControlSequence.class, o2.getClass());
|
||||||
|
assertEquals(String.class, o3.getClass());
|
||||||
|
|
||||||
|
assertEquals("hi", o1);
|
||||||
|
assertEquals("bye", o3);
|
||||||
|
|
||||||
|
AnsiControlSequence seq = (AnsiControlSequence) o2;
|
||||||
|
String[] params = seq.getParameters();
|
||||||
|
|
||||||
|
assertEquals(0, params.length);
|
||||||
|
assertEquals('u', seq.getCommand());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests parameters within a sequence.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testParameters() {
|
||||||
|
char[] ch = { 155, '3', '0', ';', '4', '0', 'm' };
|
||||||
|
parser.parse(new String(ch));
|
||||||
|
|
||||||
|
assertEquals(1, objects.size());
|
||||||
|
Object obj = objects.get(0);
|
||||||
|
assertEquals(AnsiControlSequence.class, obj.getClass());
|
||||||
|
|
||||||
|
AnsiControlSequence seq = (AnsiControlSequence) obj;
|
||||||
|
String[] params = seq.getParameters();
|
||||||
|
|
||||||
|
assertEquals('m', seq.getCommand());
|
||||||
|
assertEquals(2, params.length);
|
||||||
|
assertEquals("30", params[0]);
|
||||||
|
assertEquals("40", params[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests with plain text.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testText() {
|
||||||
|
parser.parse("Hello, World!");
|
||||||
|
|
||||||
|
assertEquals(1, objects.size());
|
||||||
|
Object obj = objects.get(0);
|
||||||
|
assertEquals(String.class, obj.getClass());
|
||||||
|
assertEquals(obj, "Hello, World!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests with a single byte CSI.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSingleCsi() {
|
||||||
|
char[] ch = { 155, '6', 'n' };
|
||||||
|
parser.parse(new String(ch));
|
||||||
|
|
||||||
|
assertEquals(1, objects.size());
|
||||||
|
Object obj = objects.get(0);
|
||||||
|
assertEquals(AnsiControlSequence.class, obj.getClass());
|
||||||
|
|
||||||
|
AnsiControlSequence seq = (AnsiControlSequence) obj;
|
||||||
|
String[] params = seq.getParameters();
|
||||||
|
assertEquals('n', seq.getCommand());
|
||||||
|
assertEquals(1, params.length);
|
||||||
|
assertEquals("6", params[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests with a double byte CSI.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testDoubleCsi() {
|
||||||
|
char[] ch = { 27, '[', 's' };
|
||||||
|
parser.parse(new String(ch));
|
||||||
|
|
||||||
|
assertEquals(1, objects.size());
|
||||||
|
Object obj = objects.get(0);
|
||||||
|
assertEquals(AnsiControlSequence.class, obj.getClass());
|
||||||
|
|
||||||
|
AnsiControlSequence seq = (AnsiControlSequence) obj;
|
||||||
|
String[] params = seq.getParameters();
|
||||||
|
assertEquals('s', seq.getCommand());
|
||||||
|
assertEquals(0, params.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parsedControlSequence(AnsiControlSequence seq) {
|
||||||
|
objects.add(seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parsedString(String str) {
|
||||||
|
objects.add(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,233 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011 Graham Edgecombe.
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.loomcom.symon.jterminal.TerminalCell;
|
||||||
|
import com.loomcom.symon.jterminal.TerminalModel;
|
||||||
|
import com.loomcom.symon.jterminal.bell.BellStrategy;
|
||||||
|
import com.loomcom.symon.jterminal.vt100.Vt100TerminalModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A test for the {@link Vt100TerminalModel} class.
|
||||||
|
* @author Graham Edgecombe
|
||||||
|
*/
|
||||||
|
public class TestVt100TerminalModel {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The terminal model.
|
||||||
|
*/
|
||||||
|
private TerminalModel model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up the terminal model.
|
||||||
|
*/
|
||||||
|
@Before
|
||||||
|
public void setUp(){
|
||||||
|
model = new Vt100TerminalModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the word wrapping.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testWordWrapping() {
|
||||||
|
int width = model.getColumns();
|
||||||
|
for (int i = 0; i < (width + 1); i++) {
|
||||||
|
model.print("h");
|
||||||
|
}
|
||||||
|
assertEquals('h', model.getCell(0, 1).getCharacter());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests special ASCII characters.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSpecialCharacters() {
|
||||||
|
model.print("\u0000");
|
||||||
|
assertNull(model.getCell(0, 0));
|
||||||
|
|
||||||
|
model.print("a\rb\rc");
|
||||||
|
assertEquals('c', model.getCell(0, 0).getCharacter());
|
||||||
|
|
||||||
|
model.print("\na");
|
||||||
|
assertEquals('c', model.getCell(0, 0).getCharacter());
|
||||||
|
assertEquals('a', model.getCell(1, 1).getCharacter());
|
||||||
|
|
||||||
|
model.print("\u007F");
|
||||||
|
assertNull(model.getCell(0, 1));
|
||||||
|
|
||||||
|
model.print("A\tB");
|
||||||
|
assertEquals('B', model.getCell(8, 1).getCharacter());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that the terminal scrolls once the buffer is full.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testBuffer() {
|
||||||
|
model = new Vt100TerminalModel(model.getColumns(), 2, 2);
|
||||||
|
model.print("This is line one.\r\n");
|
||||||
|
model.print("This is line two. XXXXXX\r\n");
|
||||||
|
model.print("And this is line three!");
|
||||||
|
assertEquals('A', model.getCell(0, 1).getCharacter());
|
||||||
|
assertNull(model.getCell(23, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the erase functionality.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testErase() {
|
||||||
|
model.print("Hello");
|
||||||
|
model.print("\u009B2J");
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
assertNull(model.getCell(i, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests moving the cursor.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testMoveCursor() {
|
||||||
|
model.print("\u009B5B");
|
||||||
|
assertEquals(5, model.getCursorRow());
|
||||||
|
|
||||||
|
model.print("\u009B3A");
|
||||||
|
assertEquals(2, model.getCursorRow());
|
||||||
|
|
||||||
|
model.print("\u009B7C");
|
||||||
|
assertEquals(7, model.getCursorColumn());
|
||||||
|
|
||||||
|
model.print("\u009B4D");
|
||||||
|
assertEquals(3, model.getCursorColumn());
|
||||||
|
|
||||||
|
model.setCursorColumn(15);
|
||||||
|
model.setCursorRow(0);
|
||||||
|
|
||||||
|
model.print("\u009B3E");
|
||||||
|
assertEquals(0, model.getCursorColumn());
|
||||||
|
assertEquals(3, model.getCursorRow());
|
||||||
|
|
||||||
|
model.setCursorColumn(7);
|
||||||
|
|
||||||
|
model.print("\u009BF");
|
||||||
|
assertEquals(0, model.getCursorColumn());
|
||||||
|
assertEquals(2, model.getCursorRow());
|
||||||
|
|
||||||
|
model.print("\u009B4;8H");
|
||||||
|
assertEquals(3, model.getCursorRow());
|
||||||
|
assertEquals(7, model.getCursorColumn());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the SGR escape sequence.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSgr() {
|
||||||
|
model.print("\u009B2;33;41mX");
|
||||||
|
|
||||||
|
TerminalCell cell = model.getCell(0, 0);
|
||||||
|
assertNotNull(cell);
|
||||||
|
assertEquals('X', cell.getCharacter());
|
||||||
|
|
||||||
|
assertEquals(Color.RED, cell.getBackgroundColor());
|
||||||
|
assertEquals(Color.YELLOW, cell.getForegroundColor());
|
||||||
|
|
||||||
|
model.print("\u009B0m\rX");
|
||||||
|
|
||||||
|
cell = model.getCell(0, 0);
|
||||||
|
|
||||||
|
assertNotNull(cell);
|
||||||
|
assertEquals('X', cell.getCharacter());
|
||||||
|
|
||||||
|
assertEquals(model.getDefaultBackgroundColor(), cell.getBackgroundColor());
|
||||||
|
assertEquals(model.getDefaultForegroundColor(), cell.getForegroundColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests saving and restoring the cursor.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSaveAndRestoreCursor() {
|
||||||
|
model.setCursorColumn(3);
|
||||||
|
model.setCursorRow(17);
|
||||||
|
|
||||||
|
model.print("\u009Bs");
|
||||||
|
|
||||||
|
model.setCursorColumn(5);
|
||||||
|
model.setCursorRow(23);
|
||||||
|
|
||||||
|
model.print("\u009Bu");
|
||||||
|
|
||||||
|
assertEquals(3, model.getCursorColumn());
|
||||||
|
assertEquals(17, model.getCursorRow());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the printing of a simple message.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testPrint() {
|
||||||
|
model.print("Hi");
|
||||||
|
assertEquals('H', model.getCell(0, 0).getCharacter());
|
||||||
|
assertEquals('i', model.getCell(1, 0).getCharacter());
|
||||||
|
assertNull(model.getCell(2, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that the bell is sounded.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testBell() {
|
||||||
|
final int[] counter = new int[1];
|
||||||
|
|
||||||
|
BellStrategy strategy = new BellStrategy() {
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see com.loomcom.symon.jterminal.bell.BellStrategy#soundBell()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void soundBell() {
|
||||||
|
counter[0]++;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
model.setBellStrategy(strategy);
|
||||||
|
|
||||||
|
model.print("\u0007");
|
||||||
|
assertEquals(1, counter[0]);
|
||||||
|
|
||||||
|
model.print("Hello, \u0007World!\u0007\r\n");
|
||||||
|
assertEquals(3, counter[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Reference in new issue
Block a user