diff --git a/sim65/sim65.iml b/sim65/sim65.iml
index 9c96a55d9..f439d557d 100644
--- a/sim65/sim65.iml
+++ b/sim65/sim65.iml
@@ -15,10 +15,12 @@
+
+
\ No newline at end of file
diff --git a/sim65/src/Sim65Main.kt b/sim65/src/Sim65Main.kt
index 7c2db9a0c..3ae2efa92 100644
--- a/sim65/src/Sim65Main.kt
+++ b/sim65/src/Sim65Main.kt
@@ -65,8 +65,8 @@ private fun startSimulator(args: Array) {
bus.reset()
- ram.load("sim65/ram.bin", 0x8000)
- ram.load("sim65/bcdtest.bin", 0x1000)
+ ram.load("sim65/test/testfiles/ram.bin", 0x8000)
+ ram.load("sim65/test/testfiles/bcdtest.bin", 0x1000)
//ram.dump(0x8000, 0x802f)
//cpu.disassemble(ram, 0x8000, 0x802f)
diff --git a/sim65/src/components/Cpu6502.kt b/sim65/src/components/Cpu6502.kt
index ee5bbce38..121fd1beb 100644
--- a/sim65/src/components/Cpu6502.kt
+++ b/sim65/src/components/Cpu6502.kt
@@ -4,7 +4,7 @@ package sim65.components
class InstructionError(msg: String) : RuntimeException(msg)
interface ICpu {
- fun disassemble(memory: Array, baseAddress: Address, from: Address, to: Address)
+ fun disassemble(memory: Array, baseAddress: Address, from: Address, to: Address): List
fun disassemble(component: MemMappedComponent, from: Address, to: Address) =
disassemble(component.cloneMem(), component.startAddress, from, to)
@@ -30,10 +30,13 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu
const val RESET_vector = 0xfffc
const val IRQ_vector = 0xfffe
- fun hexW(number: Address): String {
+ fun hexW(number: Address, allowSingleByte: Boolean = false): String {
val msb = number ushr 8
val lsb = number and 255
- return hexB(msb) + hexB(lsb)
+ return if(msb==0 && allowSingleByte)
+ hexB(lsb)
+ else
+ hexB(msb) + hexB(lsb)
}
private const val hexdigits = "0123456789abcdef"
@@ -130,38 +133,43 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu
AddrMode.IzY to ::amIzy
)
- override fun disassemble(memory: Array, baseAddress: Address, from: Address, to: Address) {
+ override fun disassemble(memory: Array, baseAddress: Address, from: Address, to: Address): List {
var address = from - baseAddress
val spacing1 = " "
val spacing2 = " "
val spacing3 = " "
+ val result = mutableListOf()
+
while (address <= (to - baseAddress)) {
val byte = memory[address]
- print("\$${hexW(address)} ${hexB(byte)} ")
+ var line = "\$${hexW(address)} ${hexB(byte)} "
address++
val opcode = opcodes[byte.toInt()]
if (!opcode.official && !illegalInstrsAllowed) {
- println("$spacing1 ???")
+ line += "$spacing1 ???"
} else {
when (opcode.mode) {
- AddrMode.Imp, AddrMode.Acc -> {
- println("$spacing1 ${opcode.mnemonic}")
+ AddrMode.Acc -> {
+ line += "$spacing1 ${opcode.mnemonic} a"
+ }
+ AddrMode.Imp -> {
+ line += "$spacing1 ${opcode.mnemonic}"
}
AddrMode.Imm -> {
val value = memory[address++]
- println("${hexB(value)} $spacing2 ${opcode.mnemonic} #\$${hexB(value)}")
+ line += "${hexB(value)} $spacing2 ${opcode.mnemonic} #\$${hexB(value)}"
}
AddrMode.Zp -> {
val zpAddr = memory[address++]
- println("${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} \$${hexB(zpAddr)}")
+ line += "${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} \$${hexB(zpAddr)}"
}
AddrMode.ZpX -> {
val zpAddr = memory[address++]
- println("${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} \$${hexB(zpAddr)},x")
+ line += "${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} \$${hexB(zpAddr)},x"
}
AddrMode.ZpY -> {
val zpAddr = memory[address++]
- println("${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} \$${hexB(zpAddr)},y")
+ line += "${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} \$${hexB(zpAddr)},y"
}
AddrMode.Rel -> {
val rel = memory[address++]
@@ -170,43 +178,46 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu
address + rel
else
address - (256 - rel)
- println("${hexB(rel)} $spacing2 ${opcode.mnemonic} \$${hexW(target)}")
+ line += "${hexB(rel)} $spacing2 ${opcode.mnemonic} \$${hexW(target, true)}"
}
AddrMode.Abs -> {
val lo = memory[address++]
val hi = memory[address++]
val absAddr = lo.toInt() or (hi.toInt() shl 8)
- println("${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} \$${hexW(absAddr)}")
+ line += "${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} \$${hexW(absAddr)}"
}
AddrMode.AbsX -> {
val lo = memory[address++]
val hi = memory[address++]
val absAddr = lo.toInt() or (hi.toInt() shl 8)
- println("${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} \$${hexW(absAddr)},x")
+ line += "${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} \$${hexW(absAddr)},x"
}
AddrMode.AbsY -> {
val lo = memory[address++]
val hi = memory[address++]
val absAddr = lo.toInt() or (hi.toInt() shl 8)
- println("${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} \$${hexW(absAddr)},y")
+ line += "${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} \$${hexW(absAddr)},y"
}
AddrMode.Ind -> {
val lo = memory[address++]
val hi = memory[address++]
val indirectAddr = lo.toInt() or (hi.toInt() shl 8)
- println("${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} (\$${hexW(indirectAddr)})")
+ line += "${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} (\$${hexW(indirectAddr)})"
}
AddrMode.IzX -> {
val zpAddr = memory[address++]
- println("${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} (\$${hexB(zpAddr)},x)")
+ line += "${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} (\$${hexB(zpAddr)},x)"
}
AddrMode.IzY -> {
val zpAddr = memory[address++]
- println("${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} (\$${hexB(zpAddr)}),y")
+ line += "${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} (\$${hexB(zpAddr)}),y"
}
}
}
+ result.add(line)
}
+
+ return result
}
override fun reset() {
diff --git a/sim65/test/DisassemTest.kt b/sim65/test/DisassemTest.kt
new file mode 100644
index 000000000..21ae406f1
--- /dev/null
+++ b/sim65/test/DisassemTest.kt
@@ -0,0 +1,29 @@
+import org.junit.jupiter.api.Test
+import sim65.components.*
+import java.io.File
+import kotlin.test.*
+
+
+class TestDisassembler {
+
+ @Test
+ fun testDisassembleAllOpcodes() {
+ val cpu = Cpu6502(true)
+ val memory = Ram(0, 0xffff)
+ memory.load("test/testfiles/disassem_instr_test.prg", 0x1000-2)
+ val result = cpu.disassemble(memory, 0x1000, 0x1221)
+ assertEquals(256, result.size)
+ assertEquals("\$1000 69 01 adc #\$01", result[0])
+
+ val reference = File("test/testfiles/disassem_ref_output.txt").readLines()
+ assertEquals(256, reference.size)
+ for(line in result.zip(reference)) {
+ if(line.first!=line.second) {
+ fail("disassembled instruction mismatch: '${line.first}', expected '${line.second}'")
+ }
+ }
+ }
+
+}
+
+
diff --git a/sim65/test/testfiles/disassem_ref_output.txt b/sim65/test/testfiles/disassem_ref_output.txt
new file mode 100644
index 000000000..826e46b2b
--- /dev/null
+++ b/sim65/test/testfiles/disassem_ref_output.txt
@@ -0,0 +1,256 @@
+$1000 69 01 adc #$01
+$1002 65 02 adc $02
+$1004 75 03 adc $03,x
+$1006 6d 05 04 adc $0405
+$1009 7d 07 06 adc $0607,x
+$100c 79 09 08 adc $0809,y
+$100f 61 0a adc ($0a,x)
+$1011 71 0b adc ($0b),y
+$1013 29 0c and #$0c
+$1015 25 0d and $0d
+$1017 35 0e and $0e,x
+$1019 2d 10 0f and $0f10
+$101c 3d 12 11 and $1112,x
+$101f 39 14 13 and $1314,y
+$1022 21 15 and ($15,x)
+$1024 31 16 and ($16),y
+$1026 0a asl a
+$1027 06 17 asl $17
+$1029 16 18 asl $18,x
+$102b 0e 1a 19 asl $191a
+$102e 1e 1c 1b asl $1b1c,x
+$1031 90 1d bcc $1050
+$1033 b0 1e bcs $1053
+$1035 f0 1f beq $1056
+$1037 24 20 bit $20
+$1039 2c 22 21 bit $2122
+$103c 30 23 bmi $1061
+$103e d0 24 bne $1064
+$1040 10 25 bpl $1067
+$1042 00 brk
+$1043 50 26 bvc $106b
+$1045 70 27 bvs $106e
+$1047 18 clc
+$1048 d8 cld
+$1049 58 cli
+$104a b8 clv
+$104b c9 28 cmp #$28
+$104d c5 29 cmp $29
+$104f d5 2a cmp $2a,x
+$1051 cd 2c 2b cmp $2b2c
+$1054 dd 2e 2d cmp $2d2e,x
+$1057 d9 30 2f cmp $2f30,y
+$105a c1 31 cmp ($31,x)
+$105c d1 32 cmp ($32),y
+$105e e0 33 cpx #$33
+$1060 e4 34 cpx $34
+$1062 ec 36 35 cpx $3536
+$1065 c0 37 cpy #$37
+$1067 c4 38 cpy $38
+$1069 cc 3a 39 cpy $393a
+$106c c6 3b dec $3b
+$106e d6 3c dec $3c,x
+$1070 ce 3e 3d dec $3d3e
+$1073 de 40 3f dec $3f40,x
+$1076 ca dex
+$1077 88 dey
+$1078 49 41 eor #$41
+$107a 45 42 eor $42
+$107c 55 43 eor $43,x
+$107e 4d 45 44 eor $4445
+$1081 5d 47 46 eor $4647,x
+$1084 59 49 48 eor $4849,y
+$1087 41 4a eor ($4a,x)
+$1089 51 4b eor ($4b),y
+$108b e6 4c inc $4c
+$108d f6 4d inc $4d,x
+$108f ee 4f 4e inc $4e4f
+$1092 fe 51 50 inc $5051,x
+$1095 e8 inx
+$1096 c8 iny
+$1097 4c 53 52 jmp $5253
+$109a 6c 55 54 jmp ($5455)
+$109d 20 57 56 jsr $5657
+$10a0 a9 58 lda #$58
+$10a2 a5 59 lda $59
+$10a4 b5 5a lda $5a,x
+$10a6 ad 5c 5b lda $5b5c
+$10a9 bd 5e 5d lda $5d5e,x
+$10ac b9 60 5f lda $5f60,y
+$10af a1 61 lda ($61,x)
+$10b1 b1 62 lda ($62),y
+$10b3 a2 63 ldx #$63
+$10b5 a6 64 ldx $64
+$10b7 b6 65 ldx $65,y
+$10b9 ae 67 66 ldx $6667
+$10bc be 69 68 ldx $6869,y
+$10bf a0 6a ldy #$6a
+$10c1 a4 6b ldy $6b
+$10c3 b4 6c ldy $6c,x
+$10c5 ac 6e 6d ldy $6d6e
+$10c8 bc 70 6f ldy $6f70,x
+$10cb 4a lsr a
+$10cc 46 71 lsr $71
+$10ce 56 72 lsr $72,x
+$10d0 4e 74 73 lsr $7374
+$10d3 5e 76 75 lsr $7576,x
+$10d6 ea nop
+$10d7 09 77 ora #$77
+$10d9 05 78 ora $78
+$10db 15 79 ora $79,x
+$10dd 0d 7b 7a ora $7a7b
+$10e0 1d 7d 7c ora $7c7d,x
+$10e3 19 7f 7e ora $7e7f,y
+$10e6 01 80 ora ($80,x)
+$10e8 11 81 ora ($81),y
+$10ea 48 pha
+$10eb 08 php
+$10ec 68 pla
+$10ed 28 plp
+$10ee 2a rol a
+$10ef 26 82 rol $82
+$10f1 36 83 rol $83,x
+$10f3 2e 85 84 rol $8485
+$10f6 3e 87 86 rol $8687,x
+$10f9 6a ror a
+$10fa 66 88 ror $88
+$10fc 76 89 ror $89,x
+$10fe 6e 8b 8a ror $8a8b
+$1101 7e 8d 8c ror $8c8d,x
+$1104 40 rti
+$1105 60 rts
+$1106 e9 8e sbc #$8e
+$1108 e5 8f sbc $8f
+$110a f5 90 sbc $90,x
+$110c ed 92 91 sbc $9192
+$110f fd 94 93 sbc $9394,x
+$1112 f9 96 95 sbc $9596,y
+$1115 e1 97 sbc ($97,x)
+$1117 f1 98 sbc ($98),y
+$1119 38 sec
+$111a f8 sed
+$111b 78 sei
+$111c 85 99 sta $99
+$111e 95 9a sta $9a,x
+$1120 8d 9c 9b sta $9b9c
+$1123 9d 9e 9d sta $9d9e,x
+$1126 99 a0 9f sta $9fa0,y
+$1129 81 a1 sta ($a1,x)
+$112b 91 a2 sta ($a2),y
+$112d 86 a3 stx $a3
+$112f 96 a4 stx $a4,y
+$1131 8e a6 a5 stx $a5a6
+$1134 84 a7 sty $a7
+$1136 94 a8 sty $a8,x
+$1138 8c aa a9 sty $a9aa
+$113b aa tax
+$113c a8 tay
+$113d ba tsx
+$113e 8a txa
+$113f 9a txs
+$1140 98 tya
+$1141 02 ???
+$1142 12 ???
+$1143 22 ???
+$1144 32 ???
+$1145 42 ???
+$1146 52 ???
+$1147 62 ???
+$1148 72 ???
+$1149 92 ???
+$114a b2 ???
+$114b d2 ???
+$114c f2 ???
+$114d 7a nop
+$114e 5a nop
+$114f 1a nop
+$1150 3a nop
+$1151 da nop
+$1152 fa nop
+$1153 80 00 nop #$00
+$1155 82 00 nop #$00
+$1157 89 00 nop #$00
+$1159 c2 00 nop #$00
+$115b e2 00 nop #$00
+$115d 04 00 nop $00
+$115f 64 00 nop $00
+$1161 44 00 nop $00
+$1163 0c 00 00 nop $0000
+$1166 14 00 nop $00,x
+$1168 34 00 nop $00,x
+$116a 54 00 nop $00,x
+$116c 74 00 nop $00,x
+$116e d4 00 nop $00,x
+$1170 f4 00 nop $00,x
+$1172 1c 00 00 nop $0000,x
+$1175 3c 00 00 nop $0000,x
+$1178 5c 00 00 nop $0000,x
+$117b 7c 00 00 nop $0000,x
+$117e dc 00 00 nop $0000,x
+$1181 fc 00 00 nop $0000,x
+$1184 ab 00 lax #$00
+$1186 a7 00 lax $00
+$1188 b7 00 lax $00,y
+$118a af 00 00 lax $0000
+$118d bf 00 00 lax $0000,y
+$1190 a3 00 lax ($00,x)
+$1192 b3 00 lax ($00),y
+$1194 87 00 sax $00
+$1196 97 00 sax $00,y
+$1198 8f 00 00 sax $0000
+$119b 83 00 sax ($00,x)
+$119d eb 00 sbc #$00
+$119f c7 00 dcp $00
+$11a1 d7 00 dcp $00,x
+$11a3 cf 00 00 dcp $0000
+$11a6 df 00 00 dcp $0000,x
+$11a9 db 00 00 dcp $0000,y
+$11ac c3 00 dcp ($00,x)
+$11ae d3 00 dcp ($00),y
+$11b0 e7 00 isc $00
+$11b2 f7 00 isc $00,x
+$11b4 ef 00 00 isc $0000
+$11b7 ff 00 00 isc $0000,x
+$11ba fb 00 00 isc $0000,y
+$11bd e3 00 isc ($00,x)
+$11bf f3 00 isc ($00),y
+$11c1 27 00 rla $00
+$11c3 37 00 rla $00,x
+$11c5 2f 00 00 rla $0000
+$11c8 3f 00 00 rla $0000,x
+$11cb 3b 00 00 rla $0000,y
+$11ce 23 00 rla ($00,x)
+$11d0 33 00 rla ($00),y
+$11d2 67 00 rra $00
+$11d4 77 00 rra $00,x
+$11d6 6f 00 00 rra $0000
+$11d9 7f 00 00 rra $0000,x
+$11dc 7b 00 00 rra $0000,y
+$11df 63 00 rra ($00,x)
+$11e1 73 00 rra ($00),y
+$11e3 07 00 slo $00
+$11e5 17 00 slo $00,x
+$11e7 0f 00 00 slo $0000
+$11ea 1f 00 00 slo $0000,x
+$11ed 1b 00 00 slo $0000,y
+$11f0 03 00 slo ($00,x)
+$11f2 13 00 slo ($00),y
+$11f4 47 00 sre $00
+$11f6 57 00 sre $00,x
+$11f8 4f 00 00 sre $0000
+$11fb 5f 00 00 sre $0000,x
+$11fe 5b 00 00 sre $0000,y
+$1201 43 00 sre ($00,x)
+$1203 53 00 sre ($00),y
+$1205 0b 00 anc #$00
+$1207 2b 00 anc #$00
+$1209 4b 00 alr #$00
+$120b 6b 00 arr #$00
+$120d 8b 00 xaa #$00
+$120f 93 00 ahx ($00),y
+$1211 9f 00 00 ahx $0000,y
+$1214 9b 00 00 tas $0000,y
+$1217 9e 00 00 shx $0000,y
+$121a 9c 00 00 shy $0000,x
+$121d bb 00 00 las $0000,y
+$1220 cb 00 axs #$00