Merge pull request #1 from felipecsl/nes-emulation

Initial commit for INES file/cartridge parser
This commit is contained in:
Felipe Lima 2017-03-08 01:04:55 -08:00 committed by GitHub
commit 4a9bc14659
11 changed files with 404 additions and 217 deletions

33
.travis.yml Normal file
View File

@ -0,0 +1,33 @@
language: android
android:
components:
- tools
- platform-tools
- build-tools-25.0.2
- extra-android-m2repository
- android-25
licenses:
- 'android-sdk-license-.+'
jdk:
- oraclejdk8
branches:
except:
- gh-pages
notifications:
email: false
sudo: false
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
cache:
directories:
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/
- $HOME/.android/build-cache

View File

@ -31,8 +31,6 @@ dependencies {
compile 'com.google.guava:guava:20.0'
testCompile 'junit:junit:4.12'
testCompile 'com.google.truth:truth:0.32'
testCompile 'org.mockito:mockito-core:1.10.19'
testCompile 'org.hamcrest:hamcrest-integration:1.3'
testCompile 'org.hamcrest:hamcrest-core:1.3'
testCompile 'org.hamcrest:hamcrest-library:1.3'
}

View File

@ -0,0 +1,41 @@
package android.emu6502.nes
import java.util.*
data class Cartridge(
// @formatter:off
val pgr: ByteArray, // PRG-ROM banks
val chr: ByteArray, // CHR-ROM banks
val mapper: Byte, // mapper type
val mirror: Byte, // mirroring mode
val battery: Byte // battery present
// @formatter:on
) {
private val sram: ByteArray = ByteArray(0x2000) // Save RAM
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
other as Cartridge
if (!Arrays.equals(pgr, other.pgr)) return false
if (!Arrays.equals(chr, other.chr)) return false
if (!Arrays.equals(sram, other.sram)) return false
if (mapper != other.mapper) return false
if (mirror != other.mirror) return false
if (battery != other.battery) return false
return true
}
override fun hashCode(): Int {
var result = Arrays.hashCode(pgr)
result = 31 * result + Arrays.hashCode(chr)
result = 31 * result + Arrays.hashCode(sram)
result = 31 * result + mapper
result = 31 * result + mirror
result = 31 * result + battery
return result
}
}

View File

@ -0,0 +1,51 @@
package android.emu6502.nes
import android.emu6502.nes.INESFileParser.Companion.INES_FILE_MAGIC
import android.emu6502.nes.INESFileParser.Companion.PADDING
import java.util.*
// http://wiki.nesdev.com/w/index.php/INES
// Sample header:
// 4e 45 53 1a 10 10 40 00 00 00 00 00 00 00 00 00
data class INESFileHeader(
// @formatter:off
val magic: ByteArray, // Constant $4E $45 $53 $1A ("NES" followed by MS-DOS end-of-file)
val numPRG: Byte, // Size of PRG ROM in 16 KB units
val numCHR: Byte, // Size of CHR ROM in 8 KB units (Value 0 means the board uses CHR RAM)
val control1: Byte, // Flags 6
val control2: Byte, // Flags 7
val numRAM: Byte, // Size of PRG RAM in 8 KB units
val padding: ByteArray // 7 bytes, unused
// @formatter:on
) {
fun isValid() =
Arrays.equals(magic, INES_FILE_MAGIC) && Arrays.equals(padding, PADDING)
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
other as INESFileHeader
if (!Arrays.equals(magic, other.magic)) return false
if (numPRG != other.numPRG) return false
if (numCHR != other.numCHR) return false
if (control1 != other.control1) return false
if (control2 != other.control2) return false
if (numRAM != other.numRAM) return false
if (!Arrays.equals(padding, other.padding)) return false
return true
}
override fun hashCode(): Int {
var result = Arrays.hashCode(magic)
result = 31 * result + numPRG
result = 31 * result + numCHR
result = 31 * result + control1
result = 31 * result + control2
result = 31 * result + numRAM
result = 31 * result + Arrays.hashCode(padding)
return result
}
}

View File

@ -0,0 +1,49 @@
package android.emu6502.nes
import java.io.DataInputStream
import java.io.File
import java.io.InputStream
internal class INESFileParser {
companion object {
internal val INES_FILE_MAGIC = byteArrayOf(0x4e, 0x45, 0x53, 0x1a)/*0x4e45531a*/
internal val PADDING = byteArrayOf(0, 0, 0, 0, 0, 0, 0)
internal fun parseFileHeader(stream: InputStream): INESFileHeader {
val dataStream = DataInputStream(stream.buffered())
return INESFileHeader(
(0..3).map { dataStream.readByte() }.toByteArray(),
dataStream.readByte(),
dataStream.readByte(),
dataStream.readByte(),
dataStream.readByte(),
dataStream.readByte(),
(0..6).map { dataStream.readByte() }.toByteArray())
}
internal fun parseCartridge(file: File): Cartridge {
val stream = file.inputStream()
stream.use {
val inesFileHeader = parseFileHeader(stream)
// mapper type
val control1 = inesFileHeader.control1.toInt()
val mapper1 = control1.shr(4)
val mapper2 = inesFileHeader.control2.toInt().shr(4)
val mapper = if (mapper1 != 0) mapper1 else mapper2
// mirroring type
val mirror1 = control1.and(1)
val mirror2 = control1.shr(3).and(1)
val mirror = if (mirror1 != 0) mirror1 else mirror2.shl(1)
// battery-backed RAM
val battery = control1.shr(1).and(1).toByte()
// read prg-rom bank(s)
val pgr = ByteArray(inesFileHeader.numPRG.toInt() * 16384)
stream.read(pgr)
// read chr-rom bank(s)
val chr = ByteArray(inesFileHeader.numCHR.toInt() * 8192)
stream.read(chr)
return Cartridge(pgr, chr, mapper.toByte(), mirror.toByte(), battery)
}
}
}
}

View File

@ -1,22 +0,0 @@
package android.emu6502;
import android.emu6502.instructions.Symbols;
import org.junit.Test;
import java.util.Collections;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
public class LabelsTest {
private final Symbols symbols = new Symbols();
private final Assembler assembler = new Assembler(new Memory(mock(Display.class)), symbols);
private final Labels labels = new Labels(assembler, symbols);
@Test public void testAddLabel() {
labels.indexLines(Collections.singletonList("test:"));
assertThat(labels.get("test"), equalTo(assembler.getDefaultCodePC()));
}
}

View File

@ -1,46 +1,39 @@
package android.emu6502;
package android.emu6502
import com.google.common.collect.ImmutableList;
import android.emu6502.instructions.Symbols
import com.google.common.collect.ImmutableList
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.mockito.Mockito.mock
import android.emu6502.instructions.Symbols;
class AssemblerTest {
private val assembler = Assembler(Memory(mock(Display::class.java)), Symbols())
import org.junit.Test;
import java.util.List;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.text.IsEqualIgnoringCase.equalToIgnoringCase;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
public class AssemblerTest {
private final Assembler assembler = new Assembler(new Memory(mock(Display.class)), new Symbols());
@Test public void testSimple() {
List<String> lines = ImmutableList.of(
@Test fun testSimple() {
val lines = ImmutableList.of(
"LDA #$01",
"STA $0200",
"LDA #$05",
"STA $0201",
"LDA #$08",
"STA $0202");
assembler.assembleCode(lines);
assertThat(assembler.hexdump(), equalTo("0600: A9 01 8D 00 02 A9 05 8D 01 02 A9 08 8D 02 02"));
"STA $0202")
assembler.assembleCode(lines)
assertThat(assembler.hexdump()).isEqualTo("0600: A9 01 8D 00 02 A9 05 8D 01 02 A9 08 8D 02 02")
}
@Test public void testWithComments() {
List<String> lines = ImmutableList.of(
"LDA #$c0 ;Load the hex value $c0 into the A register",
@Test fun testWithComments() {
val lines = ImmutableList.of(
"LDA #\$c0 ;Load the hex value \$c0 into the A register",
"TAX ;Transfer the value in the A register to X",
"INX ;Increment the value in the X register",
"ADC #$c4 ;Add the hex value $c4 to the A register",
"BRK ;Break - we're done");
assembler.assembleCode(lines);
assertThat(assembler.hexdump(), equalTo("0600: A9 C0 AA E8 69 C4 00"));
"ADC #\$c4 ;Add the hex value \$c4 to the A register",
"BRK ;Break - we're done")
assembler.assembleCode(lines)
assertThat(assembler.hexdump()).isEqualTo("0600: A9 C0 AA E8 69 C4 00")
}
@Test public void testBranchAndLabel() {
List<String> lines = ImmutableList.of(
@Test fun testBranchAndLabel() {
val lines = ImmutableList.of(
"LDX #$08",
"decrement:",
"DEX",
@ -48,38 +41,38 @@ public class AssemblerTest {
"CPX #$03",
"BNE decrement",
"STX $0201",
"BRK");
assembler.assembleCode(lines);
assertThat(assembler.hexdump(), equalTo("0600: A2 08 CA 8E 00 02 E0 03 D0 F8 8E 01 02 00"));
"BRK")
assembler.assembleCode(lines)
assertThat(assembler.hexdump()).isEqualTo("0600: A2 08 CA 8E 00 02 E0 03 D0 F8 8E 01 02 00")
}
@Test public void testRelative() {
List<String> lines = ImmutableList.of(
@Test fun testRelative() {
val lines = ImmutableList.of(
"LDA #$01",
"CMP #$02",
"BNE notequal",
"STA $22",
"notequal:",
"BRK");
"BRK")
assembler.assembleCode(lines);
assertThat(assembler.hexdump(), equalTo("0600: A9 01 C9 02 D0 02 85 22 00"));
assembler.assembleCode(lines)
assertThat(assembler.hexdump()).isEqualTo("0600: A9 01 C9 02 D0 02 85 22 00")
}
@Test public void testIndirect() {
List<String> lines = ImmutableList.of(
@Test fun testIndirect() {
val lines = ImmutableList.of(
"LDA #$01",
"STA $f0",
"LDA #$cc",
"STA $f1",
"JMP ($00f0) ;dereferences to $cc01");
"STA \$f0",
"LDA #\$cc",
"STA \$f1",
"JMP ($00f0) ;dereferences to \$cc01")
assembler.assembleCode(lines);
assertThat(assembler.hexdump(), equalTo("0600: A9 01 85 F0 A9 CC 85 F1 6C F0 00"));
assembler.assembleCode(lines)
assertThat(assembler.hexdump()).isEqualTo("0600: A9 01 85 F0 A9 CC 85 F1 6C F0 00")
}
@Test public void testIndirectX() {
List<String> lines = ImmutableList.of(
@Test fun testIndirectX() {
val lines = ImmutableList.of(
"LDX #$01",
"LDA #$05",
"STA $01",
@ -87,15 +80,15 @@ public class AssemblerTest {
"STA $02",
"LDY #$0a",
"STY $0605",
"LDA ($00,X)");
"LDA ($00,X)")
assembler.assembleCode(lines);
assertThat(assembler.hexdump(),
equalTo("0600: A2 01 A9 05 85 01 A9 06 85 02 A0 0A 8C 05 06 A1 \n0610: 00"));
assembler.assembleCode(lines)
assertThat(assembler.hexdump())
.isEqualTo("0600: A2 01 A9 05 85 01 A9 06 85 02 A0 0A 8C 05 06 A1 \n0610: 00")
}
@Test public void testIndirectY() {
List<String> lines = ImmutableList.of(
@Test fun testIndirectY() {
val lines = ImmutableList.of(
"LDY #$01",
"LDA #$03",
"STA $01",
@ -103,39 +96,39 @@ public class AssemblerTest {
"STA $02",
"LDX #$0a",
"STX $0704",
"LDA ($01),Y");
"LDA ($01),Y")
assembler.assembleCode(lines);
assertThat(assembler.hexdump(),
equalTo("0600: A0 01 A9 03 85 01 A9 07 85 02 A2 0A 8E 04 07 B1 \n0610: 01"));
assembler.assembleCode(lines)
assertThat(assembler.hexdump())
.isEqualTo("0600: A0 01 A9 03 85 01 A9 07 85 02 A2 0A 8E 04 07 B1 \n0610: 01")
}
@Test public void testJump() {
List<String> lines = ImmutableList.of(
@Test fun testJump() {
val lines = ImmutableList.of(
"LDA #$03",
"JMP there",
"BRK",
"BRK",
"BRK",
"there:",
"STA $0200");
"STA $0200")
assembler.assembleCode(lines);
assertThat(assembler.hexdump(), equalTo("0600: A9 03 4C 08 06 00 00 00 8D 00 02"));
assembler.assembleCode(lines)
assertThat(assembler.hexdump()).isEqualTo("0600: A9 03 4C 08 06 00 00 00 8D 00 02")
}
@Test public void testSymbols() {
List<String> lines = ImmutableList.of(
"define sysRandom $fe ; an adress",
@Test fun testSymbols() {
val lines = ImmutableList.of(
"define sysRandom \$fe ; an adress",
"define a_dozen $0c ; a constant",
"LDA sysRandom ; equivalent to \"LDA $fe\"",
"LDX #a_dozen ; equivalent to \"LDX #$0c\"");
assembler.assembleCode(lines);
assertThat(assembler.hexdump(), equalTo("0600: A5 FE A2 0C"));
"LDA sysRandom ; equivalent to \"LDA \$fe\"",
"LDX #a_dozen ; equivalent to \"LDX #$0c\"")
assembler.assembleCode(lines)
assertThat(assembler.hexdump()).isEqualTo("0600: A5 FE A2 0C")
}
@Test public void testSnake() {
List<String> lines = ImmutableList.of(
@Test fun testSnake() {
val lines = ImmutableList.of(
"define appleL $00 ; screen location of apple, low byte",
"define appleH $01 ; screen location of apple, high byte",
"define snakeHeadL $10 ; screen location of snake head, low byte",
@ -154,8 +147,8 @@ public class AssemblerTest {
"define ASCII_s $73",
"define ASCII_d $64",
"; System variables",
"define sysRandom $fe",
"define sysLastKey $ff",
"define sysRandom \$fe",
"define sysLastKey \$ff",
" jsr init",
" jsr loop",
"init:",
@ -361,28 +354,28 @@ public class AssemblerTest {
" dex",
" bne spinloop",
" rts",
"gameOver:", "\n");
assembler.assembleCode(lines);
assertThat(assembler.hexdump(), equalToIgnoringCase(
"gameOver:", "\n")
assembler.assembleCode(lines)
assertThat(assembler.hexdump().toLowerCase()).isEqualTo(
"0600: 20 06 06 20 38 06 20 0d 06 20 2a 06 60 a9 02 85 \n" +
"0610: 02 a9 04 85 03 a9 11 85 10 a9 10 85 12 a9 0f 85 \n" +
"0620: 14 a9 04 85 11 85 13 85 15 60 a5 fe 85 00 a5 fe \n" +
"0630: 29 03 18 69 02 85 01 60 20 4d 06 20 8d 06 20 c3 \n" +
"0640: 06 20 19 07 20 20 07 20 2d 07 4c 38 06 a5 ff c9 \n" +
"0650: 77 f0 0d c9 64 f0 14 c9 73 f0 1b c9 61 f0 22 60 \n" +
"0660: a9 04 24 02 d0 26 a9 01 85 02 60 a9 08 24 02 d0 \n" +
"0670: 1b a9 02 85 02 60 a9 01 24 02 d0 10 a9 04 85 02 \n" +
"0680: 60 a9 02 24 02 d0 05 a9 08 85 02 60 60 20 94 06 \n" +
"0690: 20 a8 06 60 a5 00 c5 10 d0 0d a5 01 c5 11 d0 07 \n" +
"06a0: e6 03 e6 03 20 2a 06 60 a2 02 b5 10 c5 10 d0 06 \n" +
"06b0: b5 11 c5 11 f0 09 e8 e8 e4 03 f0 06 4c aa 06 4c \n" +
"06c0: 35 07 60 a6 03 ca 8a b5 10 95 12 ca 10 f9 a5 02 \n" +
"06d0: 4a b0 09 4a b0 19 4a b0 1f 4a b0 2f a5 10 38 e9 \n" +
"06e0: 20 85 10 90 01 60 c6 11 a9 01 c5 11 f0 28 60 e6 \n" +
"06f0: 10 a9 1f 24 10 f0 1f 60 a5 10 18 69 20 85 10 b0 \n" +
"0700: 01 60 e6 11 a9 06 c5 11 f0 0c 60 c6 10 a5 10 29 \n" +
"0710: 1f c9 1f f0 01 60 4c 35 07 a0 00 a5 fe 91 00 60 \n" +
"0720: a2 00 a9 01 81 10 a6 03 a9 00 81 10 60 a2 00 ea \n" +
"0730: ea ca d0 fb 60"));
"0610: 02 a9 04 85 03 a9 11 85 10 a9 10 85 12 a9 0f 85 \n" +
"0620: 14 a9 04 85 11 85 13 85 15 60 a5 fe 85 00 a5 fe \n" +
"0630: 29 03 18 69 02 85 01 60 20 4d 06 20 8d 06 20 c3 \n" +
"0640: 06 20 19 07 20 20 07 20 2d 07 4c 38 06 a5 ff c9 \n" +
"0650: 77 f0 0d c9 64 f0 14 c9 73 f0 1b c9 61 f0 22 60 \n" +
"0660: a9 04 24 02 d0 26 a9 01 85 02 60 a9 08 24 02 d0 \n" +
"0670: 1b a9 02 85 02 60 a9 01 24 02 d0 10 a9 04 85 02 \n" +
"0680: 60 a9 02 24 02 d0 05 a9 08 85 02 60 60 20 94 06 \n" +
"0690: 20 a8 06 60 a5 00 c5 10 d0 0d a5 01 c5 11 d0 07 \n" +
"06a0: e6 03 e6 03 20 2a 06 60 a2 02 b5 10 c5 10 d0 06 \n" +
"06b0: b5 11 c5 11 f0 09 e8 e8 e4 03 f0 06 4c aa 06 4c \n" +
"06c0: 35 07 60 a6 03 ca 8a b5 10 95 12 ca 10 f9 a5 02 \n" +
"06d0: 4a b0 09 4a b0 19 4a b0 1f 4a b0 2f a5 10 38 e9 \n" +
"06e0: 20 85 10 90 01 60 c6 11 a9 01 c5 11 f0 28 60 e6 \n" +
"06f0: 10 a9 1f 24 10 f0 1f 60 a5 10 18 69 20 85 10 b0 \n" +
"0700: 01 60 e6 11 a9 06 c5 11 f0 0c 60 c6 10 a5 10 29 \n" +
"0710: 1f c9 1f f0 01 60 4c 35 07 a0 00 a5 fe 91 00 60 \n" +
"0720: a2 00 a9 01 81 10 a6 03 a9 00 81 10 60 a2 00 ea \n" +
"0730: ea ca d0 fb 60")
}
}

View File

@ -1,59 +1,54 @@
package android.emu6502;
package android.emu6502
import com.google.common.collect.ImmutableList;
import android.emu6502.instructions.Symbols
import com.google.common.collect.ImmutableList
import org.hamcrest.CoreMatchers.equalTo
import org.junit.Assert.assertThat
import org.junit.Test
import org.mockito.Mockito.mock
import android.emu6502.instructions.Symbols;
class CPUTest {
private val memory = Memory(mock(Display::class.java))
private val assembler = Assembler(memory, Symbols())
private val cpu = CPU(memory)
import org.junit.Test;
import java.util.List;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
public class CPUTest {
private final Memory memory = new Memory(mock(Display.class));
private final Assembler assembler = new Assembler(memory, new Symbols());
private final CPU cpu = new CPU(memory);
@Test public void testSimple() {
List<String> lines = ImmutableList.of(
@Test fun testSimple() {
val lines = ImmutableList.of(
"LDA #$01",
"STA $0200",
"LDA #$05",
"STA $0201",
"LDA #$08",
"STA $0202");
assembler.assembleCode(lines);
cpu.testRun();
assertThat(cpu.getA(), equalTo(0x08));
assertThat(cpu.getX(), equalTo(0x00));
assertThat(cpu.getY(), equalTo(0x00));
assertThat(cpu.getSP(), equalTo(0xFF));
assertThat(cpu.getPC(), equalTo(0x0610));
assertThat(cpu.flags(), equalTo("00110000"));
"STA $0202")
assembler.assembleCode(lines)
cpu.testRun()
assertThat(cpu.A, equalTo(0x08))
assertThat(cpu.X, equalTo(0x00))
assertThat(cpu.Y, equalTo(0x00))
assertThat(cpu.SP, equalTo(0xFF))
assertThat(cpu.PC, equalTo(0x0610))
assertThat(cpu.flags(), equalTo("00110000"))
}
@Test public void testWithComments() {
List<String> lines = ImmutableList.of(
"LDA #$c0 ;Load the hex value $c0 into the A register",
@Test fun testWithComments() {
val lines = ImmutableList.of(
"LDA #\$c0 ;Load the hex value \$c0 into the A register",
"TAX ;Transfer the value in the A register to X",
"INX ;Increment the value in the X register",
"ADC #$c4 ;Add the hex value $c4 to the A register",
"BRK ;Break - we're done");
assembler.assembleCode(lines);
cpu.testRun();
assertThat(cpu.getA(), equalTo(0x84));
assertThat(cpu.getX(), equalTo(0xC1));
assertThat(cpu.getY(), equalTo(0x00));
assertThat(cpu.getSP(), equalTo(0xFF));
assertThat(cpu.getPC(), equalTo(0x0607));
assertThat(cpu.flags(), equalTo("10110001"));
"ADC #\$c4 ;Add the hex value \$c4 to the A register",
"BRK ;Break - we're done")
assembler.assembleCode(lines)
cpu.testRun()
assertThat(cpu.A, equalTo(0x84))
assertThat(cpu.X, equalTo(0xC1))
assertThat(cpu.Y, equalTo(0x00))
assertThat(cpu.SP, equalTo(0xFF))
assertThat(cpu.PC, equalTo(0x0607))
assertThat(cpu.flags(), equalTo("10110001"))
}
@Test public void testBranchAndLabel() {
List<String> lines = ImmutableList.of(
@Test fun testBranchAndLabel() {
val lines = ImmutableList.of(
"LDX #$08",
"decrement:",
@ -62,19 +57,19 @@ public class CPUTest {
"CPX #$03",
"BNE decrement",
"STX $0201",
"BRK");
assembler.assembleCode(lines);
cpu.testRun();
assertThat(cpu.getA(), equalTo(0x00));
assertThat(cpu.getX(), equalTo(0x03));
assertThat(cpu.getY(), equalTo(0x00));
assertThat(cpu.getSP(), equalTo(0xFF));
assertThat(cpu.getPC(), equalTo(0x060e));
assertThat(cpu.flags(), equalTo("00110011"));
"BRK")
assembler.assembleCode(lines)
cpu.testRun()
assertThat(cpu.A, equalTo(0x00))
assertThat(cpu.X, equalTo(0x03))
assertThat(cpu.Y, equalTo(0x00))
assertThat(cpu.SP, equalTo(0xFF))
assertThat(cpu.PC, equalTo(0x060e))
assertThat(cpu.flags(), equalTo("00110011"))
}
@Test public void testJump() {
List<String> lines = ImmutableList.of(
@Test fun testJump() {
val lines = ImmutableList.of(
"LDA #$03",
"JMP there",
"BRK",
@ -82,19 +77,19 @@ public class CPUTest {
"BRK",
"there:",
"STA $0200");
assembler.assembleCode(lines);
cpu.testRun();
assertThat(cpu.getA(), equalTo(0x03));
assertThat(cpu.getX(), equalTo(0x00));
assertThat(cpu.getY(), equalTo(0x00));
assertThat(cpu.getSP(), equalTo(0xFF));
assertThat(cpu.getPC(), equalTo(0x060c));
assertThat(cpu.flags(), equalTo("00110000"));
"STA $0200")
assembler.assembleCode(lines)
cpu.testRun()
assertThat(cpu.A, equalTo(0x03))
assertThat(cpu.X, equalTo(0x00))
assertThat(cpu.Y, equalTo(0x00))
assertThat(cpu.SP, equalTo(0xFF))
assertThat(cpu.PC, equalTo(0x060c))
assertThat(cpu.flags(), equalTo("00110000"))
}
@Test public void testJumpToSubroutines() {
List<String> lines = ImmutableList.of(
@Test fun testJumpToSubroutines() {
val lines = ImmutableList.of(
"JSR init",
"JSR loop",
"JSR end",
@ -110,33 +105,33 @@ public class CPUTest {
"RTS",
"end:",
"BRK");
assembler.assembleCode(lines);
cpu.testRun();
assertThat(cpu.getA(), equalTo(0x00));
assertThat(cpu.getX(), equalTo(0x05));
assertThat(cpu.getY(), equalTo(0x00));
assertThat(cpu.getSP(), equalTo(0xFD));
assertThat(cpu.getPC(), equalTo(0x0613));
assertThat(cpu.flags(), equalTo("00110011"));
"BRK")
assembler.assembleCode(lines)
cpu.testRun()
assertThat(cpu.A, equalTo(0x00))
assertThat(cpu.X, equalTo(0x05))
assertThat(cpu.Y, equalTo(0x00))
assertThat(cpu.SP, equalTo(0xFD))
assertThat(cpu.PC, equalTo(0x0613))
assertThat(cpu.flags(), equalTo("00110011"))
}
@Test public void testSymbols() {
List<String> lines = ImmutableList.of(
@Test fun testSymbols() {
val lines = ImmutableList.of(
"define a_dozen $0c ; a constant",
"LDX #a_dozen ; equivalent to \"LDX #$0c\"");
assembler.assembleCode(lines);
cpu.testRun();
assertThat(cpu.getA(), equalTo(0x00));
assertThat(cpu.getX(), equalTo(0x0C));
assertThat(cpu.getY(), equalTo(0x00));
assertThat(cpu.getSP(), equalTo(0xFF));
assertThat(cpu.getPC(), equalTo(0x0603));
assertThat(cpu.flags(), equalTo("00110000"));
"LDX #a_dozen ; equivalent to \"LDX #$0c\"")
assembler.assembleCode(lines)
cpu.testRun()
assertThat(cpu.A, equalTo(0x00))
assertThat(cpu.X, equalTo(0x0C))
assertThat(cpu.Y, equalTo(0x00))
assertThat(cpu.SP, equalTo(0xFF))
assertThat(cpu.PC, equalTo(0x0603))
assertThat(cpu.flags(), equalTo("00110000"))
}
@Test public void testSnake() {
List<String> lines = ImmutableList.of(
@Test fun testSnake() {
val lines = ImmutableList.of(
"define appleL $00 ; screen location of apple, low byte",
"define appleH $01 ; screen location of apple, high byte",
"define snakeHeadL $10 ; screen location of snake head, low byte",
@ -155,8 +150,8 @@ public class CPUTest {
"define ASCII_s $73",
"define ASCII_d $64",
"; System variables",
"define sysRandom $fe",
"define sysLastKey $ff",
"define sysRandom \$fe",
"define sysLastKey \$ff",
" jsr init",
" jsr loop",
"init:",
@ -362,14 +357,14 @@ public class CPUTest {
" dex",
" bne spinloop",
" rts",
"gameOver:", "\n");
assembler.assembleCode(lines);
cpu.testRun();
assertThat(cpu.getA(), equalTo(0x1f));
assertThat(cpu.getX(), equalTo(0xff));
assertThat(cpu.getY(), equalTo(0x00));
assertThat(cpu.getSP(), equalTo(0xfb));
assertThat(cpu.getPC(), equalTo(0x0736));
assertThat(cpu.flags(), equalTo("00110011"));
"gameOver:", "\n")
assembler.assembleCode(lines)
cpu.testRun()
assertThat(cpu.A, equalTo(0x1f))
assertThat(cpu.X, equalTo(0xff))
assertThat(cpu.Y, equalTo(0x00))
assertThat(cpu.SP, equalTo(0xfb))
assertThat(cpu.PC, equalTo(0x0736))
assertThat(cpu.flags(), equalTo("00110011"))
}
}

View File

@ -0,0 +1,18 @@
package android.emu6502
import android.emu6502.instructions.Symbols
import org.hamcrest.CoreMatchers.equalTo
import org.junit.Assert.assertThat
import org.junit.Test
import org.mockito.Mockito.mock
class LabelsTest {
private val symbols = Symbols()
private val assembler = Assembler(Memory(mock(Display::class.java)), symbols)
private val labels = Labels(assembler, symbols)
@Test fun testAddLabel() {
labels.indexLines(listOf("test:"))
assertThat(labels["test"], equalTo(assembler.defaultCodePC))
}
}

View File

@ -0,0 +1,31 @@
package android.emu6502.nes
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Test
import java.io.File
class INESFileParserTest {
val tempFile: File = File.createTempFile("foo", "bar")
@Before fun setUp() {
tempFile.writeBytes((0..40).map(Int::toByte).toByteArray())
}
@After fun tearDown() {
tempFile.delete()
}
@Test fun invalidHeader() {
assertThat(INESFileParser.parseFileHeader(tempFile.inputStream()).isValid()).isFalse()
}
@Test fun validHeader() {
val testRom = javaClass.classLoader.getResource("roms/testrom.nes").toURI()
val header = INESFileParser.parseFileHeader(File(testRom).inputStream())
assertThat(header).isEqualTo(INESFileHeader(
INESFileParser.INES_FILE_MAGIC, 0x10, 0x10, 0x40, 0x0, 0x0, INESFileParser.PADDING))
assertThat(header.isValid()).isTrue()
}
}

Binary file not shown.