From ff43a99e0c90c9c3c0554f51632f5c1f554b7a14 Mon Sep 17 00:00:00 2001 From: Trevor Merritt Date: Tue, 15 Jul 2025 08:19:32 -0400 Subject: [PATCH] boxswap --- .gitignore | 2 + 6530.asm | 479 ++++++++++++++++++ beneater/src/bin/beneater.rs | 16 +- cli/src/bin/de6502.rs | 103 +++- cli/src/bin/kim1.rs | 26 + cli/src/bin/rom_only.rs | 4 +- core/src/computers/kim1/mod.rs | 28 + core/src/computers/kim1/new.rs | 31 ++ core/src/computers/kim1/reset.rs | 18 + core/src/computers/kim1/tick.rs | 26 + core/src/computers/mod.rs | 1 + core/src/computers/rom_only/backplane.rs | 21 +- core/src/constants/constants_mos6530.rs | 23 + core/src/constants/constants_system.rs | 6 +- core/src/constants/mod.rs | 1 + core/src/instruction_table.rs | 16 +- core/src/lib.rs | 2 + core/src/mos6502cpu/cpu.rs | 52 +- core/src/mos6502cpu/dbg.rs | 12 +- core/src/mos6502cpu/mod.rs | 4 +- core/src/mos6502cpu/tick2.rs | 20 +- core/src/mos6502cpu/tick_stages.rs | 6 +- core/src/periph/at28c256/default.rs | 6 +- core/src/periph/at28c256/dump.rs | 13 + core/src/periph/at28c256/mod.rs | 5 + core/src/periph/at28c256/new.rs | 7 +- core/src/periph/at28c256/tick.rs | 21 +- core/src/periph/bus_device.rs | 3 + core/src/periph/hm62256/default.rs | 17 + core/src/periph/hm62256/dump.rs | 17 + core/src/periph/hm62256/mod.rs | 26 +- core/src/periph/hm62256/new.rs | 13 + core/src/periph/hm62256/tick.rs | 41 +- core/src/periph/kim1_keypad/mod.rs | 105 ++++ core/src/periph/mod.rs | 4 +- core/src/periph/mos6522/mod.rs | 4 +- core/src/periph/mos6522/mos6522.rs | 138 ++--- core/src/periph/mos6522/new.rs | 7 + core/src/periph/mos6522/tick.rs | 86 ++++ core/src/periph/mos6530/dump.rs | 11 + core/src/periph/mos6530/mod.rs | 4 + core/src/periph/mos6530/mos6530.rs | 32 ++ core/src/periph/mos6530/new.rs | 25 + core/src/periph/mos6530/tick.rs | 26 + .../kim1/6530-002_fillerbyte00-0x1c00.bin | Bin 0 -> 1024 bytes .../kim1/6530-003_fillerbyte00-0x1800.bin | Bin 0 -> 1024 bytes resources/test/instructions.asm | 49 +- resources/test/labels.asm | 8 + 48 files changed, 1368 insertions(+), 197 deletions(-) create mode 100644 6530.asm create mode 100644 cli/src/bin/kim1.rs create mode 100644 core/src/computers/kim1/mod.rs create mode 100644 core/src/computers/kim1/new.rs create mode 100644 core/src/computers/kim1/reset.rs create mode 100644 core/src/computers/kim1/tick.rs create mode 100644 core/src/constants/constants_mos6530.rs create mode 100644 core/src/periph/at28c256/dump.rs create mode 100644 core/src/periph/bus_device.rs create mode 100644 core/src/periph/hm62256/default.rs create mode 100644 core/src/periph/hm62256/dump.rs create mode 100644 core/src/periph/hm62256/new.rs create mode 100644 core/src/periph/kim1_keypad/mod.rs create mode 100644 core/src/periph/mos6522/new.rs create mode 100644 core/src/periph/mos6522/tick.rs create mode 100644 core/src/periph/mos6530/dump.rs create mode 100644 core/src/periph/mos6530/mod.rs create mode 100644 core/src/periph/mos6530/mos6530.rs create mode 100644 core/src/periph/mos6530/new.rs create mode 100644 core/src/periph/mos6530/tick.rs create mode 100644 resources/kim1/6530-002_fillerbyte00-0x1c00.bin create mode 100644 resources/kim1/6530-003_fillerbyte00-0x1800.bin create mode 100644 resources/test/labels.asm diff --git a/.gitignore b/.gitignore index ea8c4bf..98965fe 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /target +*produced.asm +*produced.bin diff --git a/6530.asm b/6530.asm new file mode 100644 index 0000000..9c684f3 --- /dev/null +++ b/6530.asm @@ -0,0 +1,479 @@ +STA $f3 ; [ 0x85 0xf3 ] +PLA ; [ 0x68 ] +STA $f1 ; [ 0x85 0xf1 ] +PLA ; [ 0x68 ] +STA $ef ; [ 0x85 0xef ] +STA $fa ; [ 0x85 0xfa ] +PLA ; [ 0x68 ] +STA $f0 ; [ 0x85 0xf0 ] +STA $fb ; [ 0x85 0xfb ] +STY $f4 ; [ 0x84 0xf4 ] +STX $f5 ; [ 0x86 0xf5 ] +TSX ; [ 0xba ] +STX $f2 ; [ 0x86 0xf2 ] +JSR $1e88 ; [ 0x20 0x88 0x1e ] +JMP $1c4f ; [ 0x4c 0x4f 0x1c ] +JMP ($17fa) ; [ 0x6c 0xfa 0x17 ] +JMP ($17fe) ; [ 0x6c 0xfe 0x17 ] +LDX #$ff ; [ 0xa2 0xff ] +TXS ; [ 0x9a ] +STX $f2 ; [ 0x86 0xf2 ] +JSR $1e88 ; [ 0x20 0x88 0x1e ] +LDA #$ff ; [ 0xa9 0xff ] +STA $17f3 ; [ 0x8d 0xf3 0x17 ] +LDA #$01 ; [ 0xa9 0x01 ] +BIT $1740 ; [ 0x2c 0x40 0x17 ] +BNE #$19 ; [ 0xd0 0x19 ] +BMI #$f9 ; [ 0x30 0xf9 ] +LDA #$fc ; [ 0xa9 0xfc ] +CLC ; [ 0x18 ] +ADC #$01 ; [ 0x69 0x01 ] +BCC $03 ; [ 0x90 0x03 ] +INC $17f3 ; [ 0xee 0xf3 0x17 ] +LDY $1740 ; [ 0xac 0x40 0x17 ] +BPL #$f3 ; [ 0x10 0xf3 ] +STA $17f2 ; [ 0x8d 0xf2 0x17 ] +LDX #$08 ; [ 0xa2 0x08 ] +JSR $1e6a ; [ 0x20 0x6a 0x1e ] +JSR $1e8c ; [ 0x20 0x8c 0x1e ] +LDA #$01 ; [ 0xa9 0x01 ] +BIT $1740 ; [ 0x2c 0x40 0x17 ] +BNE #$1e ; [ 0xd0 0x1e ] +JSR $1e2f ; [ 0x20 0x2f 0x1e ] +LDX #$0a ; [ 0xa2 0x0a ] +JSR $1e31 ; [ 0x20 0x31 0x1e ] +JMP $1daf ; [ 0x4c 0xaf 0x1d ] +LDA #$00 ; [ 0xa9 0x00 ] +STA $f8 ; [ 0x85 0xf8 ] +STA $f9 ; [ 0x85 0xf9 ] +JSR $1e5a ; [ 0x20 0x5a 0x1e ] +CMP #$01 ; [ 0xc9 0x01 ] +BEQ $06 ; [ 0xf0 0x06 ] +JSR $1fac ; [ 0x20 0xac 0x1f ] +JMP $1ddb ; [ 0x4c 0xdb 0x1d ] +JSR $1f19 ; [ 0x20 0x19 0x1f ] +BNE #$d3 ; [ 0xd0 0xd3 ] +LDA #$01 ; [ 0xa9 0x01 ] +BIT $1740 ; [ 0x2c 0x40 0x17 ] +BEQ $cc ; [ 0xf0 0xcc ] +JSR $1f19 ; [ 0x20 0x19 0x1f ] +BEQ $f4 ; [ 0xf0 0xf4 ] +JSR $1f19 ; [ 0x20 0x19 0x1f ] +BEQ $ef ; [ 0xf0 0xef ] +JSR $1f6a ; [ 0x20 0x6a 0x1f ] +CMP #$15 ; [ 0xc9 0x15 ] +BPL #$bb ; [ 0x10 0xbb ] +CMP #$14 ; [ 0xc9 0x14 ] +BEQ $44 ; [ 0xf0 0x44 ] +CMP #$10 ; [ 0xc9 0x10 ] +BEQ $2c ; [ 0xf0 0x2c ] +CMP #$11 ; [ 0xc9 0x11 ] +BEQ $2c ; [ 0xf0 0x2c ] +CMP #$12 ; [ 0xc9 0x12 ] +BEQ $2f ; [ 0xf0 0x2f ] +CMP #$13 ; [ 0xc9 0x13 ] +BEQ $31 ; [ 0xf0 0x31 ] +ASL ; [ 0x0a ] +ASL ; [ 0x0a ] +ASL ; [ 0x0a ] +ASL ; [ 0x0a ] +STA $fc ; [ 0x85 0xfc ] +LDX #$04 ; [ 0xa2 0x04 ] +LDY $ff ; [ 0xa4 0xff ] +BNE #$0a ; [ 0xd0 0x0a ] +LDA ($fa),Y ; [ 0xb1 0xfa ] +ASL $fc ; [ 0x06 0xfc ] +ROL ; [ 0x2a ] +STA ($fa),Y ; [ 0x91 0xfa ] +JMP $1cc3 ; [ 0x4c 0xc3 0x1c ] +ASL ; [ 0x0a ] +ROL $fa ; [ 0x26 0xfa ] +ROL $fb ; [ 0x26 0xfb ] +DEX ; [ 0xca ] +BNE #$ea ; [ 0xd0 0xea ] +BEQ $08 ; [ 0xf0 0x08 ] +LDA #$01 ; [ 0xa9 0x01 ] +BNE #$02 ; [ 0xd0 0x02 ] +LDA #$00 ; [ 0xa9 0x00 ] +STA $ff ; [ 0x85 0xff ] +JMP $1c4f ; [ 0x4c 0x4f 0x1c ] +JSR $1f63 ; [ 0x20 0x63 0x1f ] +JMP $1c4f ; [ 0x4c 0x4f 0x1c ] +JMP $1dc8 ; [ 0x4c 0xc8 0x1d ] +LDA $ef ; [ 0xa5 0xef ] +STA $fa ; [ 0x85 0xfa ] +LDA $f0 ; [ 0xa5 0xf0 ] +STA $fb ; [ 0x85 0xfb ] +JMP $1c4f ; [ 0x4c 0x4f 0x1c ] +JSR $1e5a ; [ 0x20 0x5a 0x1e ] +CMP #$3b ; [ 0xc9 0x3b ] +BNE #$f9 ; [ 0xd0 0xf9 ] +LDA #$00 ; [ 0xa9 0x00 ] +STA $f7 ; [ 0x85 0xf7 ] +STA $f6 ; [ 0x85 0xf6 ] +JSR $1f9d ; [ 0x20 0x9d 0x1f ] +TAX ; [ 0xaa ] +JSR $1f91 ; [ 0x20 0x91 0x1f ] +JSR $1f9d ; [ 0x20 0x9d 0x1f ] +STA $fb ; [ 0x85 0xfb ] +JSR $1f91 ; [ 0x20 0x91 0x1f ] +JSR $1f9d ; [ 0x20 0x9d 0x1f ] +STA $fa ; [ 0x85 0xfa ] +JSR $1f91 ; [ 0x20 0x91 0x1f ] +TXA ; [ 0x8a ] +BEQ $0f ; [ 0xf0 0x0f ] +JSR $1f9d ; [ 0x20 0x9d 0x1f ] +STA ($fa),Y ; [ 0x91 0xfa ] +JSR $1f91 ; [ 0x20 0x91 0x1f ] +JSR $1f63 ; [ 0x20 0x63 0x1f ] +DEX ; [ 0xca ] +BNE #$f2 ; [ 0xd0 0xf2 ] +INX ; [ 0xe8 ] +JSR $1f9d ; [ 0x20 0x9d 0x1f ] +CMP $f6 ; [ 0xc5 0xf6 ] +BNE #$17 ; [ 0xd0 0x17 ] +JSR $1f9d ; [ 0x20 0x9d 0x1f ] +CMP $f7 ; [ 0xc5 0xf7 ] +BNE #$13 ; [ 0xd0 0x13 ] +TXA ; [ 0x8a ] +BNE #$b9 ; [ 0xd0 0xb9 ] +LDX #$0c ; [ 0xa2 0x0c ] +LDA #$27 ; [ 0xa9 0x27 ] +STA $1742 ; [ 0x8d 0x42 0x17 ] +JSR $1e31 ; [ 0x20 0x31 0x1e ] +JMP $1c4f ; [ 0x4c 0x4f 0x1c ] +JSR $1f9d ; [ 0x20 0x9d 0x1f ] +LDX #$11 ; [ 0xa2 0x11 ] +BNE #$ee ; [ 0xd0 0xee ] +LDA #$00 ; [ 0xa9 0x00 ] +STA $f8 ; [ 0x85 0xf8 ] +STA $f9 ; [ 0x85 0xf9 ] +LDA #$00 ; [ 0xa9 0x00 ] +STA $f6 ; [ 0x85 0xf6 ] +STA $f7 ; [ 0x85 0xf7 ] +JSR $1e2f ; [ 0x20 0x2f 0x1e ] +LDA #$3b ; [ 0xa9 0x3b ] +JSR $1ea0 ; [ 0x20 0xa0 0x1e ] +LDA $fa ; [ 0xa5 0xfa ] +CMP $17f7 ; [ 0xcd 0xf7 0x17 ] +LDA $fb ; [ 0xa5 0xfb ] +SBC $17f8 ; [ 0xed 0xf8 0x17 ] +BCC $18 ; [ 0x90 0x18 ] +LDA #$00 ; [ 0xa9 0x00 ] +JSR $1e3b ; [ 0x20 0x3b 0x1e ] +JSR $1fcc ; [ 0x20 0xcc 0x1f ] +JSR $1e1e ; [ 0x20 0x1e 0x1e ] +LDA $f6 ; [ 0xa5 0xf6 ] +JSR $1e3b ; [ 0x20 0x3b 0x1e ] +LDA $f7 ; [ 0xa5 0xf7 ] +JSR $1e3b ; [ 0x20 0x3b 0x1e ] +JMP $1c64 ; [ 0x4c 0x64 0x1c ] +LDA #$18 ; [ 0xa9 0x18 ] +TAX ; [ 0xaa ] +JSR $1e3b ; [ 0x20 0x3b 0x1e ] +JSR $1f91 ; [ 0x20 0x91 0x1f ] +JSR $1e1e ; [ 0x20 0x1e 0x1e ] +LDY #$00 ; [ 0xa0 0x00 ] +LDA ($fa),Y ; [ 0xb1 0xfa ] +JSR $1e3b ; [ 0x20 0x3b 0x1e ] +JSR $1f91 ; [ 0x20 0x91 0x1f ] +JSR $1f63 ; [ 0x20 0x63 0x1f ] +DEX ; [ 0xca ] +BNE #$f0 ; [ 0xd0 0xf0 ] +LDA $f6 ; [ 0xa5 0xf6 ] +JSR $1e3b ; [ 0x20 0x3b 0x1e ] +LDA $f7 ; [ 0xa5 0xf7 ] +JSR $1e3b ; [ 0x20 0x3b 0x1e ] +INC $f8 ; [ 0xe6 0xf8 ] +BNE #$02 ; [ 0xd0 0x02 ] +INC $f9 ; [ 0xe6 0xf9 ] +JMP $1d48 ; [ 0x4c 0x48 0x1d ] +JSR $1fcc ; [ 0x20 0xcc 0x1f ] +JSR $1e2f ; [ 0x20 0x2f 0x1e ] +JSR $1e1e ; [ 0x20 0x1e 0x1e ] +JSR $1e9e ; [ 0x20 0x9e 0x1e ] +LDY #$00 ; [ 0xa0 0x00 ] +LDA ($fa),Y ; [ 0xb1 0xfa ] +JSR $1e3b ; [ 0x20 0x3b 0x1e ] +JSR $1e9e ; [ 0x20 0x9e 0x1e ] +JMP $1c64 ; [ 0x4c 0x64 0x1c ] +JSR $1f63 ; [ 0x20 0x63 0x1f ] +JMP $1dac ; [ 0x4c 0xac 0x1d ] +LDX $f2 ; [ 0xa6 0xf2 ] +TXS ; [ 0x9a ] +LDA $fb ; [ 0xa5 0xfb ] +PHA ; [ 0x48 ] +LDA $fa ; [ 0xa5 0xfa ] +PHA ; [ 0x48 ] +LDA $f1 ; [ 0xa5 0xf1 ] +PHA ; [ 0x48 ] +LDX $f5 ; [ 0xa6 0xf5 ] +LDY $f4 ; [ 0xa4 0xf4 ] +LDA $f3 ; [ 0xa5 0xf3 ] +RTI ; [ 0x40 ] +CMP #$20 ; [ 0xc9 0x20 ] +BEQ $ca ; [ 0xf0 0xca ] +CMP #$7f ; [ 0xc9 0x7f ] +BEQ $1b ; [ 0xf0 0x1b ] +CMP #$0d ; [ 0xc9 0x0d ] +BEQ $db ; [ 0xf0 0xdb ] +CMP #$0a ; [ 0xc9 0x0a ] +BEQ $1c ; [ 0xf0 0x1c ] +CMP #$2e ; [ 0xc9 0x2e ] +BEQ $26 ; [ 0xf0 0x26 ] +CMP #$47 ; [ 0xc9 0x47 ] +BEQ $d5 ; [ 0xf0 0xd5 ] +CMP #$51 ; [ 0xc9 0x51 ] +BEQ $0a ; [ 0xf0 0x0a ] +CMP #$4c ; [ 0xc9 0x4c ] +BEQ $09 ; [ 0xf0 0x09 ] +JMP $1c6a ; [ 0x4c 0x6a 0x1c ] +JMP $1c4f ; [ 0x4c 0x4f 0x1c ] +JMP $1d42 ; [ 0x4c 0x42 0x1d ] +JMP $1ce7 ; [ 0x4c 0xe7 0x1c ] +SEC ; [ 0x38 ] +LDA $fa ; [ 0xa5 0xfa ] +SBC #$01 ; [ 0xe9 0x01 ] +STA $fa ; [ 0x85 0xfa ] +BCS $02 ; [ 0xb0 0x02 ] +DEC $fb ; [ 0xc6 0xfb ] +JMP $1dac ; [ 0x4c 0xac 0x1d ] +LDY #$00 ; [ 0xa0 0x00 ] +LDA $f8 ; [ 0xa5 0xf8 ] +STA ($fa),Y ; [ 0x91 0xfa ] +JMP $1dc2 ; [ 0x4c 0xc2 0x1d ] +LDA $fb ; [ 0xa5 0xfb ] +JSR $1e3b ; [ 0x20 0x3b 0x1e ] +JSR $1f91 ; [ 0x20 0x91 0x1f ] +LDA $fa ; [ 0xa5 0xfa ] +JSR $1e3b ; [ 0x20 0x3b 0x1e ] +JSR $1f91 ; [ 0x20 0x91 0x1f ] +RTS ; [ 0x60 ] +LDX #$07 ; [ 0xa2 0x07 ] +LDA $1fd5,X ; [ 0xbd 0xd5 0x1f ] +JSR $1ea0 ; [ 0x20 0xa0 0x1e ] +DEX ; [ 0xca ] +BPL #$f7 ; [ 0x10 0xf7 ] +RTS ; [ 0x60 ] +STA $fc ; [ 0x85 0xfc ] +LSR ; [ 0x4a ] +LSR ; [ 0x4a ] +LSR ; [ 0x4a ] +LSR ; [ 0x4a ] +JSR $1e4c ; [ 0x20 0x4c 0x1e ] +LDA $fc ; [ 0xa5 0xfc ] +JSR $1e4c ; [ 0x20 0x4c 0x1e ] +LDA $fc ; [ 0xa5 0xfc ] +RTS ; [ 0x60 ] +AND #$0f ; [ 0x29 0x0f ] +CMP #$0a ; [ 0xc9 0x0a ] +CLC ; [ 0x18 ] +BMI #$02 ; [ 0x30 0x02 ] +ADC #$07 ; [ 0x69 0x07 ] +ADC #$30 ; [ 0x69 0x30 ] +JMP $1ea0 ; [ 0x4c 0xa0 0x1e ] +STX $fd ; [ 0x86 0xfd ] +LDX #$08 ; [ 0xa2 0x08 ] +LDA #$01 ; [ 0xa9 0x01 ] +BIT $1740 ; [ 0x2c 0x40 0x17 ] +BNE #$22 ; [ 0xd0 0x22 ] +BMI #$f9 ; [ 0x30 0xf9 ] +JSR $1ed4 ; [ 0x20 0xd4 0x1e ] +JSR $1eeb ; [ 0x20 0xeb 0x1e ] +LDA $1740 ; [ 0xad 0x40 0x17 ] +AND #$80 ; [ 0x29 0x80 ] +LSR $fe ; [ 0x46 0xfe ] +ORA $fe ; [ 0x05 0xfe ] +STA $fe ; [ 0x85 0xfe ] +JSR $1ed4 ; [ 0x20 0xd4 0x1e ] +DEX ; [ 0xca ] +BNE #$ef ; [ 0xd0 0xef ] +JSR $1eeb ; [ 0x20 0xeb 0x1e ] +LDX $fd ; [ 0xa6 0xfd ] +LDA $fe ; [ 0xa5 0xfe ] +ROL ; [ 0x2a ] +LSR ; [ 0x4a ] +RTS ; [ 0x60 ] +LDX #$01 ; [ 0xa2 0x01 ] +STX $ff ; [ 0x86 0xff ] +LDX #$00 ; [ 0xa2 0x00 ] +STX $1741 ; [ 0x8e 0x41 0x17 ] +LDX #$3f ; [ 0xa2 0x3f ] +STX $1743 ; [ 0x8e 0x43 0x17 ] +LDX #$07 ; [ 0xa2 0x07 ] +STX $1742 ; [ 0x8e 0x42 0x17 ] +CLD ; [ 0xd8 ] +SEI ; [ 0x78 ] +RTS ; [ 0x60 ] +LDA #$20 ; [ 0xa9 0x20 ] +STA $fe ; [ 0x85 0xfe ] +STX $fd ; [ 0x86 0xfd ] +JSR $1ed4 ; [ 0x20 0xd4 0x1e ] +LDA $1742 ; [ 0xad 0x42 0x17 ] +AND #$fe ; [ 0x29 0xfe ] +STA $1742 ; [ 0x8d 0x42 0x17 ] +JSR $1ed4 ; [ 0x20 0xd4 0x1e ] +LDX #$08 ; [ 0xa2 0x08 ] +LDA $1742 ; [ 0xad 0x42 0x17 ] +AND #$fe ; [ 0x29 0xfe ] +LSR $fe ; [ 0x46 0xfe ] +ADC #$00 ; [ 0x69 0x00 ] +STA $1742 ; [ 0x8d 0x42 0x17 ] +JSR $1ed4 ; [ 0x20 0xd4 0x1e ] +DEX ; [ 0xca ] +BNE #$ee ; [ 0xd0 0xee ] +LDA $1742 ; [ 0xad 0x42 0x17 ] +ORA #$01 ; [ 0x09 0x01 ] +STA $1742 ; [ 0x8d 0x42 0x17 ] +JSR $1ed4 ; [ 0x20 0xd4 0x1e ] +LDX $fd ; [ 0xa6 0xfd ] +RTS ; [ 0x60 ] +LDA $17f3 ; [ 0xad 0xf3 0x17 ] +STA $17f4 ; [ 0x8d 0xf4 0x17 ] +LDA $17f2 ; [ 0xad 0xf2 0x17 ] +SEC ; [ 0x38 ] +SBC #$01 ; [ 0xe9 0x01 ] +BCS $03 ; [ 0xb0 0x03 ] +DEC $17f4 ; [ 0xce 0xf4 0x17 ] +LDY $17f4 ; [ 0xac 0xf4 0x17 ] +BPL #$f3 ; [ 0x10 0xf3 ] +RTS ; [ 0x60 ] +LDA $17f3 ; [ 0xad 0xf3 0x17 ] +STA $17f4 ; [ 0x8d 0xf4 0x17 ] +LDA $17f2 ; [ 0xad 0xf2 0x17 ] +LSR ; [ 0x4a ] +LSR $17f4 ; [ 0x4e 0xf4 0x17 ] +BCC $e3 ; [ 0x90 0xe3 ] +ORA #$80 ; [ 0x09 0x80 ] +BCS $e0 ; [ 0xb0 0xe0 ] +LDY #$03 ; [ 0xa0 0x03 ] +LDX #$01 ; [ 0xa2 0x01 ] +LDA #$ff ; [ 0xa9 0xff ] +STX $1742 ; [ 0x8e 0x42 0x17 ] +INX ; [ 0xe8 ] +INX ; [ 0xe8 ] +AND $1740 ; [ 0x2d 0x40 0x17 ] +DEY ; [ 0x88 ] +BNE #$f5 ; [ 0xd0 0xf5 ] +LDY #$07 ; [ 0xa0 0x07 ] +STY $1742 ; [ 0x8c 0x42 0x17 ] +ORA #$80 ; [ 0x09 0x80 ] +EOR #$ff ; [ 0x49 0xff ] +RTS ; [ 0x60 ] +LDY #$00 ; [ 0xa0 0x00 ] +LDA ($fa),Y ; [ 0xb1 0xfa ] +STA $f9 ; [ 0x85 0xf9 ] +LDA #$7f ; [ 0xa9 0x7f ] +STA $1741 ; [ 0x8d 0x41 0x17 ] +LDX #$09 ; [ 0xa2 0x09 ] +LDY #$03 ; [ 0xa0 0x03 ] +LDA $00f8,Y ; [ 0xb9 0xf8 0x00 ] +LSR ; [ 0x4a ] +LSR ; [ 0x4a ] +LSR ; [ 0x4a ] +LSR ; [ 0x4a ] +JSR $1f48 ; [ 0x20 0x48 0x1f ] +LDA $00f8,Y ; [ 0xb9 0xf8 0x00 ] +AND #$0f ; [ 0x29 0x0f ] +JSR $1f48 ; [ 0x20 0x48 0x1f ] +DEY ; [ 0x88 ] +BNE #$eb ; [ 0xd0 0xeb ] +STX $1742 ; [ 0x8e 0x42 0x17 ] +LDA #$00 ; [ 0xa9 0x00 ] +STA $1741 ; [ 0x8d 0x41 0x17 ] +JMP $1efe ; [ 0x4c 0xfe 0x1e ] +STY $fc ; [ 0x84 0xfc ] +TAY ; [ 0xa8 ] +LDA $1fe7,Y ; [ 0xb9 0xe7 0x1f ] +LDY #$00 ; [ 0xa0 0x00 ] +STY $1740 ; [ 0x8c 0x40 0x17 ] +STX $1742 ; [ 0x8e 0x42 0x17 ] +STA $1740 ; [ 0x8d 0x40 0x17 ] +LDY #$7f ; [ 0xa0 0x7f ] +DEY ; [ 0x88 ] +BNE #$fd ; [ 0xd0 0xfd ] +INX ; [ 0xe8 ] +INX ; [ 0xe8 ] +LDY $fc ; [ 0xa4 0xfc ] +RTS ; [ 0x60 ] +INC $fa ; [ 0xe6 0xfa ] +BNE #$02 ; [ 0xd0 0x02 ] +INC $fb ; [ 0xe6 0xfb ] +RTS ; [ 0x60 ] +LDX #$21 ; [ 0xa2 0x21 ] +LDY #$01 ; [ 0xa0 0x01 ] +JSR $1f02 ; [ 0x20 0x02 0x1f ] +BNE #$07 ; [ 0xd0 0x07 ] +CPX #$27 ; [ 0xe0 0x27 ] +BNE #$f5 ; [ 0xd0 0xf5 ] +LDA #$15 ; [ 0xa9 0x15 ] +RTS ; [ 0x60 ] +LDY #$ff ; [ 0xa0 0xff ] +ASL ; [ 0x0a ] +BCS $03 ; [ 0xb0 0x03 ] +INY ; [ 0xc8 ] +BPL #$fa ; [ 0x10 0xfa ] +TXA ; [ 0x8a ] +AND #$0f ; [ 0x29 0x0f ] +LSR ; [ 0x4a ] +TAX ; [ 0xaa ] +TYA ; [ 0x98 ] +BPL #$03 ; [ 0x10 0x03 ] +CLC ; [ 0x18 ] +ADC #$07 ; [ 0x69 0x07 ] +DEX ; [ 0xca ] +BNE #$fa ; [ 0xd0 0xfa ] +RTS ; [ 0x60 ] +CLC ; [ 0x18 ] +ADC $f7 ; [ 0x65 0xf7 ] +STA $f7 ; [ 0x85 0xf7 ] +LDA $f6 ; [ 0xa5 0xf6 ] +ADC #$00 ; [ 0x69 0x00 ] +STA $f6 ; [ 0x85 0xf6 ] +RTS ; [ 0x60 ] +JSR $1e5a ; [ 0x20 0x5a 0x1e ] +JSR $1fac ; [ 0x20 0xac 0x1f ] +JSR $1e5a ; [ 0x20 0x5a 0x1e ] +JSR $1fac ; [ 0x20 0xac 0x1f ] +LDA $f8 ; [ 0xa5 0xf8 ] +RTS ; [ 0x60 ] +CMP #$30 ; [ 0xc9 0x30 ] +BMI #$1b ; [ 0x30 0x1b ] +CMP #$47 ; [ 0xc9 0x47 ] +BPL #$17 ; [ 0x10 0x17 ] +CMP #$40 ; [ 0xc9 0x40 ] +BMI #$03 ; [ 0x30 0x03 ] +CLC ; [ 0x18 ] +ADC #$09 ; [ 0x69 0x09 ] +ROL ; [ 0x2a ] +ROL ; [ 0x2a ] +ROL ; [ 0x2a ] +ROL ; [ 0x2a ] +LDY #$04 ; [ 0xa0 0x04 ] +ROL ; [ 0x2a ] +ROL $f8 ; [ 0x26 0xf8 ] +ROL $f9 ; [ 0x26 0xf9 ] +DEY ; [ 0x88 ] +BNE #$f8 ; [ 0xd0 0xf8 ] +LDA #$00 ; [ 0xa9 0x00 ] +RTS ; [ 0x60 ] +LDA $f8 ; [ 0xa5 0xf8 ] +STA $fa ; [ 0x85 0xfa ] +LDA $f9 ; [ 0xa5 0xf9 ] +STA $fb ; [ 0x85 0xfb ] +RTS ; [ 0x60 ] +BRK ; [ 0x00 ] +BRK ; [ 0x00 ] +BRK ; [ 0x00 ] +BRK ; [ 0x00 ] +BRK ; [ 0x00 ] +BRK ; [ 0x00 ] +ASL ; [ 0x0a ] +ORA $494d ; [ 0x0d 0x4d 0x49 ] +JSR $5213 ; [ 0x20 0x13 0x52 ] +EOR $20 ; [ 0x45 0x20 ] +STX $db ; [ 0x86 0xdb ] +INC $ed ; [ 0xe6 0xed ] +SBC $ff87,X ; [ 0xfd 0x87 0xff ] +LDA $f9de,Y ; [ 0xb9 0xde 0xf9 ] +SBC ($ff),Y ; [ 0xf1 0xff ] diff --git a/beneater/src/bin/beneater.rs b/beneater/src/bin/beneater.rs index 1597b7b..6609d5d 100644 --- a/beneater/src/bin/beneater.rs +++ b/beneater/src/bin/beneater.rs @@ -8,6 +8,7 @@ use core::mos6502cpu::cpu::Mos6502Cpu; use core::periph::at28c256::At28C256; use core::periph::hm62256::Hm62256; use core::constants::constants_system::*; +use std::fs; /// BenEater computer represents the 'Ben Eater' 6502 breadboard computer. /// This was built along watching the video series where Ben builds a @@ -20,20 +21,19 @@ pub struct BenEater { } impl BenEater { - pub fn new(rom: &[u8; SIZE_32KB]) -> BenEater { - - } + // pub fn new(rom: &[u8; SIZE_32KB]) -> BenEater { + // + // } } - #[macroquad::main("Ben Eaters PC")] async fn main() { println!("Taxation is Theft"); - let rom_to_run = fs::read("resources/beneater/roms/ror.bin"); - let mut pc = BenEater::new(&rom_to_run); - - let mut backplane = Backplane::new(); + // let rom_to_run = fs::read("resources/beneater/roms/ror.bin"); + // let mut pc = BenEater::new(&rom_to_run); + // + // let mut backplane = Backplane::new(); // backplane.load_rom("resources/beneater/roms/ror.bin"); // let mut dm = DisplayMatrix::new(200.0, 50.0); diff --git a/cli/src/bin/de6502.rs b/cli/src/bin/de6502.rs index 2aad2f5..929684a 100644 --- a/cli/src/bin/de6502.rs +++ b/cli/src/bin/de6502.rs @@ -1,3 +1,8 @@ +/* +64tass -a -o instructions.bin -b instructions.asm && +cargo run --bin de6502 -- -v instructions.bin instructions_produced.asm && +64tass -a -b instructions_produced.asm -o instructions_produced.bin +*/ use std::collections::HashMap; use std::fs; use std::fs::File; @@ -15,7 +20,10 @@ struct CliOptions { /// File to Decompile input: PathBuf, /// File to write - output: PathBuf + output: PathBuf, + /// Verbose output + #[arg(short, action = clap::ArgAction::Count)] + verbose: u8 } #[derive(Debug)] @@ -57,15 +65,16 @@ impl WorkingProgram { } -fn decompile(data: &[u8]) -> Vec<(u16, DecompiledLine)> { - println!("Preparing to decompile {}b", data.len()); - let mut current_data_position: u16 = 0; +fn parse_to_decompiled_lines(data: &[u8]) -> HashMap { + println!("PARSE GOT {}b", data.len()); + let mut current_data_position = 0; let mut lines: HashMap = HashMap::new(); while current_data_position < data.len() as u16 { // read the next byte. let next_byte = data[current_data_position as usize]; let mut bytes = vec![next_byte]; + println!("Bytes = {bytes:?}"); let target_op = INSTRUCTION_TABLE[next_byte as usize].clone(); if let Some(top) = target_op { @@ -83,7 +92,7 @@ fn decompile(data: &[u8]) -> Vec<(u16, DecompiledLine)> { if num_bytes_to_load == 2 { bytes.push(data[current_data_position as usize + 1]); bytes.push(data[current_data_position as usize + 2]); - // 16 bit parameter. + // 16 bit parameter. param = Some(((bytes[2] as u16) << 8) | bytes[1] as u16); formatted_asm = format!("{}{:04x}{}", formatted_asm, param.unwrap(), top.format_postfix); }; @@ -103,25 +112,45 @@ fn decompile(data: &[u8]) -> Vec<(u16, DecompiledLine)> { current_data_position += 1; } } + lines +} + +fn decompile(data: &Vec) -> Vec<(u16, DecompiledLine)> { + println!("Preparing to decompile {}b", data.len()); + let mut current_data_position: u16 = 0; + let mut lines: HashMap = parse_to_decompiled_lines(data); println!("Found {} instructions in pass 1. Adding labels for jumps.", lines.len()); //let targets = vec![]; - for (index, line) in &lines { - - if line.bytes[0] == ISA_OP_JMP_ABS { - // println!("ABS JUMP FOUND"); - } - } - let mut items: Vec<_> = lines.into_iter().collect(); items.sort_by(|a, b| a.0.cmp(&b.0)); - // loop through the lines for JSR and label the 'target' as SUB + // let mut jump_targets = vec![]; + for (line_index, working_line) in &mut items { + if working_line.is_jump() { + println!("There are {}b in bytes", working_line.bytes.len()); + let target = read_word(&working_line.bytes[1..=2]); + println!("Found a jump at index {line_index} / 0x{line_index} with target of 0x{:04x}", target);; + // Derp -> this doesnt work. + // items[target as usize].1.label = Some("Label1".parse().unwrap()); + } + } - // check the vectors to label those entrypoints. + // // check the vectors to label those entrypoints. + // let (mut main, mut nmi, mut irq) = (0, 0, 0); + // match data.len() { + // SIZE_32KB | SIZE_64KB => { + // main = read_word(&data[OFFSET_RESET_VECTORS..=OFFSET_RESET_VECTORS + 1]); + // nmi = read_word(&data[OFFSET_NMI_VECTORS..=OFFSET_NMI_VECTORS + 1]); + // irq = read_word(&data[OFFSET_INT_VECTORS..=OFFSET_INT_VECTORS]); + // } + // _ => { + // // dont know where to look for our offsets. :( + // } + // } // -> main // -> NMI // -> IRQ @@ -129,6 +158,37 @@ fn decompile(data: &[u8]) -> Vec<(u16, DecompiledLine)> { items } +/// read_word +/// +/// Read a word from the provided data with first byte being +/// LSB +fn read_word(from: &[u8]) -> u16 { + (from[1] as u16) << 8 | from[0] as u16 +} + +/// read_word_swap +/// +/// Read a word from the provided data with first byte being +/// MSB +fn read_word_swap(from: &[u8]) -> u16 { + (from[0] as u16) << 8 | from[1] as u16 +} + +/// format_bytes +/// +/// formats data for stuff +fn format_bytes(from: &Vec) -> String { + let mut to_return = String::from("["); + + for index in 0..from.len() { + to_return = format!("{} 0x{:02x}", to_return, from[index]); + } + to_return = format!("{} ]", to_return); + + to_return +} + + fn main() { let opts = CliOptions::parse(); println!("Taxation is theft."); @@ -147,8 +207,17 @@ fn main() { // ...reap the decompiled code. for (_, line) in &result { - let line =format!("{:width$}; {:?}", line.text,line.bytes, width=30 ); - println!("{}", line); - writeln!(output_file, "{}", line).expect("cant write output file. you picked the red snapper."); + let formatted_bytes = format_bytes(&line.bytes); + let output_line =format!("{:width$}; {}", line.text, formatted_bytes, width=30 ); + + // do we need a label + if let Some(label) = &line.label { + println!("There is a label - {label}"); + } + if opts.verbose > 0 { + println!("{}", output_line); + } + writeln!(output_file, "{}", output_line).expect("cant write output file. you picked the red snapper."); } + println!("OPTS = {}", opts.verbose); } diff --git a/cli/src/bin/kim1.rs b/cli/src/bin/kim1.rs new file mode 100644 index 0000000..cdd797c --- /dev/null +++ b/cli/src/bin/kim1.rs @@ -0,0 +1,26 @@ +use core::computers::kim1::Kim1; + +fn main() { + println!("Taxation is theft."); + + let mut kim = Kim1::new(); + let mut num_ticks = 0; + + kim.running = true; + + while kim.running { + kim.tick(); + num_ticks += 1; + + if num_ticks == 11 { + println!("Got our 11 ticks. time to hotwire this pc."); + kim.running = true; + kim.dump(); + } + + if num_ticks == 15 { + kim.running = false; + kim.dump(); + } + } +} \ No newline at end of file diff --git a/cli/src/bin/rom_only.rs b/cli/src/bin/rom_only.rs index ae54068..6abd7cd 100644 --- a/cli/src/bin/rom_only.rs +++ b/cli/src/bin/rom_only.rs @@ -1,5 +1,5 @@ use clap::Parser; -use core::computers::rom_only::backplane::Backplane; +use core::computers::rom_only::backplane::RomOnlyComputer; #[derive(Parser)] struct CliOptions { @@ -13,6 +13,6 @@ fn main() { let opts = CliOptions::parse(); - let mut rom_only = Backplane::new(); + let mut rom_only = RomOnlyComputer::new(); rom_only.tick() } \ No newline at end of file diff --git a/core/src/computers/kim1/mod.rs b/core/src/computers/kim1/mod.rs new file mode 100644 index 0000000..db2be79 --- /dev/null +++ b/core/src/computers/kim1/mod.rs @@ -0,0 +1,28 @@ +pub mod new; +pub mod tick; +pub mod reset; + +use std::fs; +use std::path::Path; +use crate::constants::constants_system::SIZE_1KB; +use crate::mos6502cpu::cpu::Mos6502Cpu; +use crate::periph::at28c256::At28C256; +use crate::periph::hm62256::Hm62256; +use crate::periph::kim1_keypad::Kim1Keypad; +use crate::periph::mos6522::mos6522::Mos6522; +use crate::periph::mos6530::mos6530::Mos6530; + +/// Represents a KIM-1 +/// +/// +pub struct Kim1 { + pub running: bool, + pub cpu: Mos6502Cpu, + rriot1: Mos6530, + rriot2: Mos6530, + ram: Hm62256, + pub(crate) keypad: Kim1Keypad, + address_bus: u16, + data_bus: u8, + cpu_read: bool +} diff --git a/core/src/computers/kim1/new.rs b/core/src/computers/kim1/new.rs new file mode 100644 index 0000000..773f378 --- /dev/null +++ b/core/src/computers/kim1/new.rs @@ -0,0 +1,31 @@ +use crate::computers::kim1::Kim1; +use crate::periph::hm62256::Hm62256; +use crate::periph::kim1_keypad::Kim1Keypad; +use crate::periph::mos6530::mos6530::Mos6530; + +impl Kim1 { + pub fn dump(&self) { + println!("DUMPING KIM-1 PC STATE"); + self.cpu.dump(); + self.rriot1.dump(); + self.rriot2.dump(); + self.keypad.dump(); + } + + pub fn new() -> Self { + let rriot1_rom = include_bytes!("/home/tmerritt/Projects/mos6502/resources/kim1/6530-002_fillerbyte00-0x1c00.bin"); + let rriot2_rom = include_bytes!("/home/tmerritt/Projects/mos6502/resources/kim1/6530-003_fillerbyte00-0x1800.bin"); + + Self { + cpu: Default::default(), + rriot1: Mos6530::new(0x1700, 0x1780, 0x1800, &rriot1_rom), + rriot2: Mos6530::new(0x1740, 0x17C0, 0x1C00, &rriot2_rom), + ram: Hm62256::new(0x0000), + keypad: Kim1Keypad::new(), + address_bus: 0, + data_bus: 0, + cpu_read: false, + running: false + } + } +} \ No newline at end of file diff --git a/core/src/computers/kim1/reset.rs b/core/src/computers/kim1/reset.rs new file mode 100644 index 0000000..1d13e8f --- /dev/null +++ b/core/src/computers/kim1/reset.rs @@ -0,0 +1,18 @@ +use crate::computers::kim1::Kim1; +use crate::periph::hm62256::Hm62256; +use crate::periph::mos6530::mos6530::Mos6530; + +impl Kim1 { + pub fn reset(&mut self) { + let rriot1_rom = include_bytes!("/home/tmerritt/Projects/mos6502/resources/kim1/6530-002_fillerbyte00-0x1c00.bin"); + let rriot2_rom = include_bytes!("/home/tmerritt/Projects/mos6502/resources/kim1/6530-003_fillerbyte00-0x1800.bin"); + self.cpu = Default::default(); + self.rriot1 = Mos6530::new(0x1700, 0x1780, 0x1800, rriot1_rom.as_array().unwrap()); + self.rriot2 = Mos6530::new(0x1740, 0x17c0, 0x1c00, rriot2_rom.as_array().unwrap()); + self.ram = Hm62256::new(0x0000); + self.address_bus = 0x0000; + self.data_bus = 0x0000; + self.cpu_read = true; + self.cpu.pc = 0x0000; + } +} \ No newline at end of file diff --git a/core/src/computers/kim1/tick.rs b/core/src/computers/kim1/tick.rs new file mode 100644 index 0000000..87d4a95 --- /dev/null +++ b/core/src/computers/kim1/tick.rs @@ -0,0 +1,26 @@ +use crate::computers::kim1::Kim1; + +impl Kim1 { + pub fn tick(&mut self) { + println!("<- START KIM-1 Backplane Tick"); + let (address_bus, data, rw) = self.cpu.tick2(self.address_bus, self.data_bus); + self.address_bus = address_bus; + self.data_bus = data; + self.cpu_read = rw; + // now tick the various items connected + + self.rriot1.tick(self.address_bus, self.data_bus, false, self.cpu_read); + self.rriot2.tick(self.address_bus, self.data_bus, false, self.cpu_read); + self.ram.tick(self.address_bus, self.data_bus, self.cpu_read, true); + + + let (rr1_io, rr1_ram, rr1_rom) = self.rriot1.dump_data(); + let (rr2_io, rr2_ram, rr2_rom) = self.rriot2.dump_data(); + + println!(" 0x0000 -> RAM / {}", self.ram.dump_data()); + println!(" 0x1700 -> RRIOT 1 / 0x{rr1_io:04x}/0x{rr1_ram:04x}/0x{rr1_rom:04x}"); + println!(" 0x1740 -> RRIOT 2 / 0x{rr2_io:04x}/0x{rr2_ram:04x}/0x{rr2_rom:04x}"); + // display the memory map and device states + println!("-> FINISH KIM-1 Backplane Tick"); + } +} \ No newline at end of file diff --git a/core/src/computers/mod.rs b/core/src/computers/mod.rs index 8d9bc4d..ceab4c3 100644 --- a/core/src/computers/mod.rs +++ b/core/src/computers/mod.rs @@ -1,2 +1,3 @@ pub mod beneater; pub mod rom_only; +pub mod kim1; diff --git a/core/src/computers/rom_only/backplane.rs b/core/src/computers/rom_only/backplane.rs index d01b7c0..770f5f7 100644 --- a/core/src/computers/rom_only/backplane.rs +++ b/core/src/computers/rom_only/backplane.rs @@ -1,21 +1,22 @@ use crate::constants::constants_system::{SIZE_32KB, SIZE_64KB}; +use crate::periph::at28c256::At28C256; use crate::periph::hm62256::Hm62256; use crate::periph::rom_chip::RomChip; -pub struct Backplane { - rom: Hm62256, +pub struct RomOnlyComputer { + rom: At28C256, data_bus: u8, address_bus: u16 } -impl Backplane { - pub fn new() -> Backplane { - Backplane::program(&[0x00; SIZE_32KB]) +impl RomOnlyComputer { + pub fn new() -> RomOnlyComputer { + RomOnlyComputer::program(&[0x00; SIZE_32KB]) } - pub fn program(rom: &[u8; SIZE_32KB]) -> Backplane { - Backplane { - rom: *Hm62256::program(rom), + pub fn program(rom: &[u8; SIZE_32KB]) -> RomOnlyComputer { + RomOnlyComputer { + rom: *At28C256::new(0x000, rom), address_bus: 0x0000, data_bus: 0x00 } @@ -23,6 +24,10 @@ impl Backplane { pub fn tick(&mut self) { println!("Preparing to tick."); + + // do are we being addressed? + + println!("Done ticking."); } diff --git a/core/src/constants/constants_mos6530.rs b/core/src/constants/constants_mos6530.rs new file mode 100644 index 0000000..46255c5 --- /dev/null +++ b/core/src/constants/constants_mos6530.rs @@ -0,0 +1,23 @@ +pub const MOS6530_DRA: u8 = 0x00; +pub const MOS6530_DDRA: u8 = 0x01; +pub const MOS6530_DRB: u8 = 0x02; +pub const MOS6530_DDRB: u8 = 0x03; + +/* +0 X Data Register A +1 X Data Direction Register A +2 X Data Register B +3 X Data Direction Register B +4 0 Count down from value, divide by 1, disable IRQ 1 ??? +5 0 Count down from value, divide by 8, disable IRQ 1 ??? +6 0 Count down from value, divide by 64, disable IRQ 1 Read current counter value, disable IRQ +7 0 Count down from value, divide by 1024, disable IRQ 1 Read counter status, bit7 = 1 means counter past zero +8 X Data Register A (mirror ?) +9 X Data Direction Register A (mirror ?) +A X Data Register B (mirror ?) +B X Data Direction Register B (mirror ?) +C 0 Count down from value, divide by 1, enable IRQ 1 ??? +D 0 Count down from value, divide by 8, enable IRQ 1 ??? +E 0 Count down from value, divide by 64, enable IRQ 1 Read current counter value, enable IRQ +F 0 Count down from value, divide by 1024, enable IRQ 1 Read counter status, bit7 = 1 means counter past zero +*/ \ No newline at end of file diff --git a/core/src/constants/constants_system.rs b/core/src/constants/constants_system.rs index 6f01bc3..653057e 100644 --- a/core/src/constants/constants_system.rs +++ b/core/src/constants/constants_system.rs @@ -2,6 +2,10 @@ pub const SIZE_1KB: usize = 1024; pub const SIZE_32KB: usize = SIZE_1KB * 32; pub const SIZE_64KB: usize = SIZE_1KB * 64; +// S Suffixed constants are for indexing slices +pub const OFFSET_NMI_VECTOR: u16 = 0xfffa; +pub const OFFSET_NMI_VECTORS: usize = 0xfffa; pub const OFFSET_RESET_VECTOR: u16 = 0xfffc; +pub const OFFSET_RESET_VECTORS: usize = 0xffff; pub const OFFSET_INT_VECTOR: u16 = 0xfffe; - +pub const OFFSET_INT_VECTORS: usize = 0xfffe; diff --git a/core/src/constants/mod.rs b/core/src/constants/mod.rs index 9fffc48..3912184 100644 --- a/core/src/constants/mod.rs +++ b/core/src/constants/mod.rs @@ -2,3 +2,4 @@ pub mod constants_isa_op; pub mod constants_isa_stub; pub mod constants_system; pub mod constants_via6522; +pub mod constants_mos6530; diff --git a/core/src/instruction_table.rs b/core/src/instruction_table.rs index ec1e1ee..9f46684 100644 --- a/core/src/instruction_table.rs +++ b/core/src/instruction_table.rs @@ -215,10 +215,10 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { table[ISA_OP_BCC as usize] = Some(OpInfo { operation: BCC, - mode: AddressMode::Immediate, + mode: AddressMode::Implied, length: 2, cycles: 2, - format_prefix: "BCC #$", + format_prefix: "BCC $", format_postfix: "", }); @@ -229,7 +229,6 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { cycles: 2, format_prefix: "BCS $", format_postfix: "", - }); table[ISA_OP_BEQ as usize] = Some(OpInfo { operation: BEQ, @@ -267,7 +266,6 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { cycles: 2, format_prefix: "BMI #$", format_postfix: "", - }); table[ISA_OP_BNE as usize] = Some(OpInfo { @@ -850,8 +848,8 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::AbsoluteX, length: 3, cycles: 7, - format_prefix: "LSR $(", - format_postfix: ",X)", + format_prefix: "LSR $", + format_postfix: ",X", }); table[ISA_OP_NOP as usize] = Some(OpInfo { @@ -1221,15 +1219,15 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { mode: AddressMode::ZeroPageY, length: 2, cycles: 4, - format_prefix: "STX", - format_postfix: "", + format_prefix: "STX $", + format_postfix: ",Y", }); table[ISA_OP_STX_ABS as usize] = Some(OpInfo { operation: Operation::STX, mode: AddressMode::Absolute, length: 3, cycles: 4, - format_prefix: "STX", + format_prefix: "STX $", format_postfix: "", }); diff --git a/core/src/lib.rs b/core/src/lib.rs index 4e855e1..474bc38 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,3 +1,5 @@ +#![feature(slice_as_array)] + pub mod computers; pub mod address_mode; pub mod constants; diff --git a/core/src/mos6502cpu/cpu.rs b/core/src/mos6502cpu/cpu.rs index a2f84ad..b7f3ae4 100644 --- a/core/src/mos6502cpu/cpu.rs +++ b/core/src/mos6502cpu/cpu.rs @@ -9,6 +9,8 @@ use crate::op_info::OpInfo; use crate::operand::Operand; use crate::operation::Operation; use log::trace; +use crate::mos6502cpu::tick_stages::Mos6502TickStates; +use crate::mos6502cpu::tick_stages::Mos6502TickStates::*; pub struct Mos6502Cpu { pub(crate) memory: [u8; SIZE_64KB], @@ -36,7 +38,9 @@ pub struct Mos6502Cpu { /// CPU Read signal pub read_signal: bool, pub(crate) reset_vector: u16, - pub(crate) int_vector: u16 + pub(crate) int_vector: u16, + pub(crate) nmi_vector: u16, + pub tick_stage: Mos6502TickStates } impl Mos6502Cpu { @@ -74,7 +78,9 @@ impl Default for Mos6502Cpu { ir_bytes: [0x00; 4], read_signal: true, reset_vector: 0x0000, - int_vector: 0x0000 + int_vector: 0x0000, + nmi_vector: 0x0000, + tick_stage: LoadingInstruction }; working.reset_cpu(); working @@ -160,6 +166,48 @@ impl Mos6502Cpu { /// Ticks the CPU pub fn tick(&mut self) { println!("PREPARiNG TO TICK CPU AT PC 0x{:04x}", self.pc); + match self.tick_stage { + LoadingInstruction => { + println!("Loading instruction from data bus -> {}", self.data_bus); + + let instruction = INSTRUCTION_TABLE[self.data_bus as usize].clone(); + + if let Some(inst) = instruction { + println!("DECODED INSTRUCTION [{:?}]/[{:?}]", inst.operation, inst.mode); + match inst.mode { + AddressMode::Absolute | AddressMode::AbsoluteX | AddressMode::AbsoluteY => { + println!("NEED TO LOAD a 16bit VALUE FOR INSTRUCTION"); + self.tick_stage = Loading16BitParameter1; + } + AddressMode::Immediate => { + println!("LOADING A 8BIT VALUE FOR INSTRUCTION"); + self.tick_stage = Loading8BitParameter; + } + _ => {} + } + } else { + println!("INVALID DECODE OF [${:02x}", self.data_bus); + } + + } + Loading8BitParameter => { + println!("Loading parameter for 8bit "); + }, + Loading16BitParameter1 => { + println!("Loading high bits of parameter"); + }, + Loading16BitParameter2 => { + println!("Loading low bits of parameter"); + }, + Stall(length) => { + println!("PREPARING TO STALL FOR {} CYCLES", length); + }, + Waiting => { + println!("CPU IS WAITING."); + } + } + + if self.microcode_step == 0 { println!("OUT OF MICROSTEPS. Decoding the next instruction"); let offset = self.pc as usize; diff --git a/core/src/mos6502cpu/dbg.rs b/core/src/mos6502cpu/dbg.rs index 696b462..53c47ad 100644 --- a/core/src/mos6502cpu/dbg.rs +++ b/core/src/mos6502cpu/dbg.rs @@ -5,7 +5,7 @@ impl Mos6502Cpu { /// /// returns /// PC, A, X, Y, Address_Bus, Data_Bus, Microcode_Step - pub fn dump_data(&self) -> (u16, u8, u8, u8, u16, u8, u8, u16, u16) { + pub fn dump_data(&self) -> (u16, u8, u8, u8, u16, u8, u8, u16, u16, u16) { ( self.pc, self.a, @@ -15,13 +15,14 @@ impl Mos6502Cpu { self.data_bus, self.microcode_step, self.reset_vector, - self.int_vector + self.int_vector, + self.nmi_vector ) } pub fn dump(&self) { println!( - "CPU State: PC: {:04x} / A: {:02x} / X: {:02x} / Y: {:02x} / ADDRESS: {:04x} / DATA: {:02x} / MICROSTEPS: {:02x} / S: {}", + "CPU State: PC: ${:04x} / A: ${:02x} / X: ${:02x} / Y: ${:02x} / ADDRESS: ${:04x} / DATA: ${:02x} / MICROSTEPS: {:02} / S: {} / NMI: ${:04x} / RST: ${:04x} / INT: ${:04x}", self.pc, self.a, self.x, @@ -29,7 +30,10 @@ impl Mos6502Cpu { self.address_bus, self.data_bus, self.microcode_step, - self.flags.dump() + self.flags.dump(), + self.nmi_vector, + self.reset_vector, + self.int_vector ); } } diff --git a/core/src/mos6502cpu/mod.rs b/core/src/mos6502cpu/mod.rs index a2362c5..8204dac 100644 --- a/core/src/mos6502cpu/mod.rs +++ b/core/src/mos6502cpu/mod.rs @@ -2,5 +2,5 @@ pub mod cpu; pub mod new; pub mod tick2; -mod dbg; -mod tick_stages; +pub mod dbg; +pub mod tick_stages; diff --git a/core/src/mos6502cpu/tick2.rs b/core/src/mos6502cpu/tick2.rs index b0c2ae7..c4db76f 100644 --- a/core/src/mos6502cpu/tick2.rs +++ b/core/src/mos6502cpu/tick2.rs @@ -1,6 +1,8 @@ use crate::constants::constants_system::{OFFSET_INT_VECTOR, OFFSET_RESET_VECTOR}; use crate::mos6502cpu::cpu::Mos6502Cpu; + + impl Mos6502Cpu { /// AccurateTick /// @@ -19,6 +21,8 @@ impl Mos6502Cpu { if self.read_signal { // we should see new data in the data_bus for us let read_data = data_bus; + println!("READ 0x{read_data:02x} from data bus."); + self.data_bus = read_data; } else { // we are writing to the bus. } @@ -28,6 +32,12 @@ impl Mos6502Cpu { // reduce the number of remaining microsteps self.read_signal = true; match self.microcode_step { + 6 => { + // NMI High byte + } + 5 => { + // NMI low byte + } 4 => { // read first byte of reset vector self.address_bus = OFFSET_RESET_VECTOR; @@ -35,6 +45,7 @@ impl Mos6502Cpu { 3 => { // at this point data holds the upper byte of our reset vector self.reset_vector = (data_bus as u16) << 8; + println!("Loaded reset vector of 0x{:04x}", self.reset_vector); // read secondd byte of reset vector self.address_bus = OFFSET_RESET_VECTOR + 1; } @@ -53,11 +64,18 @@ impl Mos6502Cpu { println!("Loaded interrupt vector of 0x{:04x}", self.int_vector); self.pc = self.reset_vector; println!("Set PC to Reset Vector. Giddy-up!"); + println!("START HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK"); + // the KIM-1 uses 0x0000 for its initial PC + self.pc = 0x0000; + println!("END HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK"); + self.has_reset = true; } _ => { } } - self.microcode_step -= 1; + if self.microcode_step > 0 { + self.microcode_step -= 1; + } } (self.address_bus, self.data_bus, self.read_signal) } diff --git a/core/src/mos6502cpu/tick_stages.rs b/core/src/mos6502cpu/tick_stages.rs index 9c523d8..b4f58c5 100644 --- a/core/src/mos6502cpu/tick_stages.rs +++ b/core/src/mos6502cpu/tick_stages.rs @@ -3,7 +3,7 @@ /// /// The set of what a tick can be doing /// -enum Mos6502TickStates { +pub enum Mos6502TickStates { /// Loading the first byte into the IR LoadingInstruction, /// Loading an 8 bit parameter @@ -14,6 +14,6 @@ enum Mos6502TickStates { Loading16BitParameter2, /// Stalling for accurate emulation Stall(u8), - /// Completed the instruction - Complete + /// Waiting for the next instruction + Waiting } diff --git a/core/src/periph/at28c256/default.rs b/core/src/periph/at28c256/default.rs index 47dd1d9..c592394 100644 --- a/core/src/periph/at28c256/default.rs +++ b/core/src/periph/at28c256/default.rs @@ -9,7 +9,11 @@ impl Default for At28C256 { let boxed_array: Box<[u8; SIZE_32KB]> = boxed_slice .try_into() .expect("Failed to convert Vec to boxed array"); - At28C256 { data: boxed_array } + At28C256 { data: boxed_array, + address_bus: 0x0000, + data_bus: 0x00, + offset: 0x0000 + } } } diff --git a/core/src/periph/at28c256/dump.rs b/core/src/periph/at28c256/dump.rs new file mode 100644 index 0000000..6994e26 --- /dev/null +++ b/core/src/periph/at28c256/dump.rs @@ -0,0 +1,13 @@ +use crate::periph::at28c256::At28C256; + +pub struct At28C256State { + offset: u16 +} + +impl At28C256 { + pub fn dump(&self) -> At28C256State { + At28C256State { + offset: self.offset + } + } +} diff --git a/core/src/periph/at28c256/mod.rs b/core/src/periph/at28c256/mod.rs index bf6267d..f7d3fc8 100644 --- a/core/src/periph/at28c256/mod.rs +++ b/core/src/periph/at28c256/mod.rs @@ -3,6 +3,7 @@ pub mod rom_chip; pub mod tick; mod new; mod program; +mod dump; use crate::constants::constants_system::SIZE_32KB; use crate::periph::rom_chip::RomChip; @@ -15,7 +16,11 @@ use std::io::Read; /// 256kbit storage /// 32kbyte storage pub struct At28C256 { + data_bus: u8, + address_bus: u16, data: Box<[u8; SIZE_32KB]>, + // where in the computer memory map do we live? + offset: u16 } #[cfg(test)] diff --git a/core/src/periph/at28c256/new.rs b/core/src/periph/at28c256/new.rs index 4d6c6fb..7b644c4 100644 --- a/core/src/periph/at28c256/new.rs +++ b/core/src/periph/at28c256/new.rs @@ -2,9 +2,12 @@ use crate::constants::constants_system::SIZE_32KB; use crate::periph::at28c256::At28C256; impl At28C256 { - pub fn new(data: &[u8; SIZE_32KB]) -> Self { + pub fn new(offset: u16, data: &[u8; SIZE_32KB]) -> Self { At28C256 { - data: (*data).into() + data: (*data).into(), + address_bus: 0x0000, + data_bus: 0x00, + offset } } } diff --git a/core/src/periph/at28c256/tick.rs b/core/src/periph/at28c256/tick.rs index 150ed16..bcedb05 100644 --- a/core/src/periph/at28c256/tick.rs +++ b/core/src/periph/at28c256/tick.rs @@ -1,14 +1,23 @@ +use crate::constants::constants_system::SIZE_32KB; use crate::periph::at28c256::At28C256; use crate::periph::hm62256::Hm62256; impl At28C256 { - fn tick(&mut self, address_bus: u16, data_bus: u8, read_mode: bool) -> (u16, u8) { - if read_mode { - panic!("UNABLE TO WRITE TO ROM"); - } else { - // has to be read mode. its a rom. - return (address_bus, data_bus) + fn max_address(&self) -> u16 { + self.offset + SIZE_32KB as u16 + } + + + pub fn tick(&mut self, address_bus: u16, data_bus: u8, read_mode: bool) -> (u16, u8) { + if address_bus.gt(&self.offset) & address_bus.lt(&self.max_address()) { + if read_mode { + panic!("UNABLE TO WRITE TO ROM"); + } else { + // has to be read mode. its a rom. + return (address_bus, data_bus) + } } + // not for us. (address_bus, self.data[address_bus as usize]) } } diff --git a/core/src/periph/bus_device.rs b/core/src/periph/bus_device.rs new file mode 100644 index 0000000..5934f0c --- /dev/null +++ b/core/src/periph/bus_device.rs @@ -0,0 +1,3 @@ +pub trait BusDevice { + fn talking_to_me(&self, address: u16) -> bool; +} \ No newline at end of file diff --git a/core/src/periph/hm62256/default.rs b/core/src/periph/hm62256/default.rs new file mode 100644 index 0000000..c81b268 --- /dev/null +++ b/core/src/periph/hm62256/default.rs @@ -0,0 +1,17 @@ +use crate::constants::constants_system::SIZE_32KB; +use crate::periph::hm62256::Hm62256; + +impl Default for Hm62256 { + fn default() -> Self { + let vec = vec![0x00; SIZE_32KB]; + let boxed_slice: Box<[u8]> = vec.into_boxed_slice(); + let boxed_array: Box<[u8; SIZE_32KB]> = + boxed_slice.try_into().expect("Unable to box the ram"); + Hm62256 { + offset: 0x0000, + data: boxed_array, + address_bus: 0x0000, + data_bus: 0x00 + } + } +} diff --git a/core/src/periph/hm62256/dump.rs b/core/src/periph/hm62256/dump.rs new file mode 100644 index 0000000..f945948 --- /dev/null +++ b/core/src/periph/hm62256/dump.rs @@ -0,0 +1,17 @@ +use crate::periph::hm62256::Hm62256; + +pub struct Hm62256State { + pub offset: u16 +} + +impl Hm62256 { + pub fn dump(&self) -> Hm62256State { + Hm62256State { + offset: self.offset + } + } + + pub fn dump_data(&self) -> (u16) { + self.offset + } +} diff --git a/core/src/periph/hm62256/mod.rs b/core/src/periph/hm62256/mod.rs index aed7f4b..4e5391d 100644 --- a/core/src/periph/hm62256/mod.rs +++ b/core/src/periph/hm62256/mod.rs @@ -3,27 +3,23 @@ pub mod ramchip; pub mod romchip; pub mod tick; +pub mod default; +pub mod new; +pub mod dump; use crate::constants::constants_system::SIZE_32KB; use crate::periph::ram_chip::RamChip; use crate::periph::rom_chip::RomChip; use log::debug; -pub struct Hm62256 { - pub(crate) base_offset: u16, - pub(crate) data: Box<[u8]>, -} -impl Default for Hm62256 { - fn default() -> Self { - let vec = vec![0x00; SIZE_32KB]; - let boxed_slice: Box<[u8]> = vec.into_boxed_slice(); - let boxed_array: Box<[u8; SIZE_32KB]> = - boxed_slice.try_into().expect("Unable to box the ram"); - Hm62256 { - base_offset: 0x0000, - data: boxed_array, - } - } +/// Hitachi Semiconductor +/// 8 Bit High Speed Static Ram +/// 32KByte +pub struct Hm62256 { + pub(crate) offset: u16, + pub(crate) data: Box<[u8]>, + pub(crate) address_bus: u16, + pub(crate) data_bus: u8 } #[cfg(test)] diff --git a/core/src/periph/hm62256/new.rs b/core/src/periph/hm62256/new.rs new file mode 100644 index 0000000..ec70998 --- /dev/null +++ b/core/src/periph/hm62256/new.rs @@ -0,0 +1,13 @@ +use crate::constants::constants_system::SIZE_32KB; +use crate::periph::hm62256::Hm62256; + +impl Hm62256 { + pub fn new(base_offset: u16) -> Self { + Self { + offset: base_offset, + data: vec![0; SIZE_32KB].into_boxed_slice(), + address_bus: 0x0000, + data_bus: 0x00 + } + } +} \ No newline at end of file diff --git a/core/src/periph/hm62256/tick.rs b/core/src/periph/hm62256/tick.rs index bfcd38d..8e0c842 100644 --- a/core/src/periph/hm62256/tick.rs +++ b/core/src/periph/hm62256/tick.rs @@ -1,16 +1,41 @@ +use crate::constants::constants_system::SIZE_32KB; use crate::periph::hm62256::Hm62256; impl Hm62256 { - fn tick(&mut self, address_bus: u16, data_bus: u8, read_mode: bool) -> (u16, u8) { - let new_data_bus = if read_mode { - // reading from ram - self.data[address_bus as usize] + fn max_address(&self) -> u16 { + self.offset + SIZE_32KB as u16 + } + + pub fn tick(&mut self, address_bus: u16, data_bus: u8, read_mode: bool, cs: bool) -> (u16, u8) { + if !(address_bus.gt( &self.offset) && address_bus.le(&self.max_address())) { + return (address_bus, data_bus); + } + + println!("HM62256RAM TICK START -> 0x{address_bus:04x} 0x{data_bus:02x} {read_mode} {cs}"); + + self.address_bus = address_bus; + self.data_bus = data_bus; + let addr = address_bus.wrapping_sub(self.offset) + self.offset; + + // did we want to talk to the chip... + if !cs { + return (address_bus, data_bus); + } + + // ...or are we outside the range? + if (addr - self.offset) > SIZE_32KB as u16 { + return (address_bus, data_bus); + } + + // ok. lets see what we are dealing with + self.data_bus = if read_mode { + self.data[addr as usize] } else { // writing to ram - self.data[address_bus as usize] = data_bus.into(); + self.data[addr as usize] = data_bus.into(); data_bus }; - (address_bus, new_data_bus) + (self.address_bus, self.data_bus) } } @@ -26,9 +51,9 @@ mod test { let mut ram = Hm62256::default(); // load the data to ram - ram.tick(0x0000, 0xab, false); + ram.tick(0x0000, 0xab, false, true); // read the data back - let (_, new_data) = ram.tick(0x0000, 0x00, true); + let (_, new_data) = ram.tick(0x0000, 0x00, true, true); assert_eq!(new_data, 0xab); } diff --git a/core/src/periph/kim1_keypad/mod.rs b/core/src/periph/kim1_keypad/mod.rs new file mode 100644 index 0000000..d942e3c --- /dev/null +++ b/core/src/periph/kim1_keypad/mod.rs @@ -0,0 +1,105 @@ +/* + +---+---+---+---+---+---+ + | 0 | 1 | 2 | 3 | 4 | 5 | + +---+---+---+---+---+---+ + | 6 | 7 | 8 | 9 | A | B | + +---+---+---+---+---+---+ + | C | D | E | F | AD| DA| + +---+---+---+---+---+---+ + | + | PC| ST| RS| | | + +---+---+---+---+---+---+ + */ + +pub struct Kim1Keypad { + keys: [bool; 23], + stepping: bool +} + +impl Kim1Keypad { + pub fn dump(&self) { + println!("Dumping state of keypad"); + } +} + +impl Kim1Keypad { + fn keyid(from: u8) -> usize{ + (from % 23) as usize + } + pub fn new() -> Self { + Kim1Keypad { + keys: [false; 23], + stepping: false + } + } + + pub fn toggle_stepping(&mut self) { + self.stepping = !self.stepping;; + } + + pub fn set_stepping(&mut self, new_state: bool) { + self.stepping = new_state + } + + pub fn press_key(&mut self, key_to_press: u8) { + self.keys[Self::keyid(key_to_press)] = true; + } + + pub fn release_key(&mut self, key_to_release: u8) { + self.keys[Self::keyid(key_to_release)] = false; + } + + pub fn is_pressed(&self, key: u8) -> bool { + self.keys[Self::keyid(key)] + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn smoke() { assert!(true); } + + #[test] + fn keys_are_pressed() { + let mut kb = Kim1Keypad::new(); + + for index in 0..23 { + assert!(!kb.is_pressed(index)); + kb.press_key(index); + assert!(kb.is_pressed(index)); + + kb.release_key(index); + assert!(!kb.is_pressed(index)); + } + } + + #[test] + fn stepping_changes() { + let mut kb = Kim1Keypad::new(); + + kb.set_stepping(false); + + assert!(!kb.stepping); + + kb.toggle_stepping(); + + assert!(kb.stepping); + + kb.toggle_stepping(); + kb.toggle_stepping(); + kb.toggle_stepping(); + kb.toggle_stepping(); + kb.toggle_stepping(); + + assert!(!kb.stepping); + } + + #[test] + fn out_of_range() { + let mut kb = Kim1Keypad::new(); + + kb.press_key(24); + assert!(kb.is_pressed(1)); + } +} diff --git a/core/src/periph/mod.rs b/core/src/periph/mod.rs index 6761bad..d2c5c69 100644 --- a/core/src/periph/mod.rs +++ b/core/src/periph/mod.rs @@ -1,6 +1,8 @@ pub mod rom_chip; - pub mod at28c256; pub mod hm62256; pub mod ram_chip; pub mod mos6522; +pub mod mos6530; +pub mod kim1_keypad; +mod bus_device; diff --git a/core/src/periph/mos6522/mod.rs b/core/src/periph/mos6522/mod.rs index b576f29..205335f 100644 --- a/core/src/periph/mos6522/mod.rs +++ b/core/src/periph/mos6522/mod.rs @@ -1,2 +1,4 @@ pub mod mos6522; -mod registers; \ No newline at end of file +mod registers; +mod new; +mod tick; \ No newline at end of file diff --git a/core/src/periph/mos6522/mos6522.rs b/core/src/periph/mos6522/mos6522.rs index b201231..5a91cdb 100644 --- a/core/src/periph/mos6522/mos6522.rs +++ b/core/src/periph/mos6522/mos6522.rs @@ -5,106 +5,47 @@ use crate::constants::constants_via6522::*; #[derive(Default)] pub struct Mos6522 { /// data direction - dda: u8, - ddb: u8, + pub(crate) dda: u8, + pub(crate) ddb: u8, /// bottom 4 address bits - rs0: u8, - rs1: u8, - rs2: u8, - rs3: u8, + pub(crate) rs0: u8, + pub(crate) rs1: u8, + pub(crate) rs2: u8, + pub(crate) rs3: u8, /// external data bus - data_bus: u8, + pub(crate) data_bus: u8, - cs1: bool, - cs2: bool, - rw: bool, + pub(crate) cs1: bool, + pub(crate) cs2: bool, + // when true CPU is reading + pub(crate) rw: bool, /// reset circuit - true when reset inited - reset: bool, + pub(crate) reset: bool, /// IRQ - true when interrupt waiting - irq: bool, + pub(crate) irq: bool, - ira: u8, - ora: u8, - porta: u8, - irb: u8, - orb: u8, - portb: u8, + pub(crate) ira: u8, + pub(crate) ora: u8, + pub(crate) porta: u8, + pub(crate) irb: u8, + pub(crate) orb: u8, + pub(crate) portb: u8, - ca1: bool, - ca2: bool, - cb1: bool, - cb2: bool, + pub(crate) ca1: bool, + pub(crate) ca2: bool, + pub(crate) cb1: bool, + pub(crate) cb2: bool, + + // memory offset for where in the computers memory map this fits + pub(crate) offset: u16, + pub(crate) address_bus: u16, } impl Mos6522 { - pub fn new() -> Self { - Mos6522::default() - } - - /// tick - /// - /// data_bus -> 8 bits from the data bus - /// control -> 4 bits to identify which register to control - pub fn tick(&mut self, data_bus: u8, control: u8, rw: bool) -> (u8) { - println!("Mos6522 Tick Start -> 0x{data_bus:02x} / 0x{control:02x} / {rw}"); - if rw { - // RW true = CPU is writing - self.data_bus = data_bus; - match control { - VIA6522_DDRA => { - debug!("Setting DDA to 0x{data_bus:02x}"); - // setting the Data Direction for Port A - self.dda = data_bus; - }, - VIA6522_DDRB => { - debug!("Setting DDB to 0x{data_bus:02x}"); - // setting the data direction for port b - self.ddb = data_bus; - }, - VIA6522_ORB => { - // writing data to ORB - let masked_data = data_bus & self.ddb; - debug!("Setting ORB to 0x{data_bus:02x} / masked at 0x{masked_data:02x}"); - self.portb = masked_data; - }, - VIA6522_ORA => { - // writing data to ORA - let masked_data = data_bus & self.dda; - debug!("Setting ORA to 0x{data_bus:02x} / masked at 0x{masked_data:02x}"); - self.porta = masked_data; - }, - _ => {} - } - } else { - // RW false = CPU is reading - self.data_bus = match control { - VIA6522_DDRA => { - self.dda - } - VIA6522_DDRB => { - self.ddb - } - VIA6522_ORA => { - self.porta & self.dda - } - VIA6522_ORB => { - self.portb & self.ddb - } - _ => { - debug!("VIA got request for b{:08b} / 0x{:02x}", control, control); - // do nothing. bad address for VIA - self.data_bus - } - } - } - - (self.data_bus) - } - pub fn start_clocks(&mut self) { loop { let cycle_start = Instant::now(); @@ -115,7 +56,6 @@ impl Mos6522 { } } - #[cfg(test)] mod test { use super::*; @@ -126,40 +66,40 @@ mod test { #[test] fn registers() { let mut x = Mos6522::new(); - x.tick(0b0000_0000, VIA6522_DDRA, true); + x.tick(0b0000_0000, VIA6522_DDRA, false, true); assert_eq!(x.dda, 0b0000_0000); - x.tick(0b1111_1111, VIA6522_DDRA, true); + x.tick(0b1111_1111, VIA6522_DDRA, false, true); assert_eq!(x.dda, 0b1111_1111); - x.tick(0b0000_0000, VIA6522_DDRB, true); + x.tick(0b0000_0000, VIA6522_DDRB, false, true); assert_eq!(x.ddb, 0b0000_0000); - x.tick(0b1111_1111, VIA6522_DDRB, true); + x.tick(0b1111_1111, VIA6522_DDRB, false, true); assert_eq!(x.ddb, 0b1111_1111); - x.tick(0b0000_0000, VIA6522_ORA, true); + x.tick(0b0000_0000, VIA6522_ORA, false, true); assert_eq!(x.porta, 0b0000_0000); - x.tick(0b1111_1111, VIA6522_ORA, true); + x.tick(0b1111_1111, VIA6522_ORA, false, true); assert_eq!(x.porta, 0b1111_1111); - x.tick(0b0000_0000, VIA6522_ORB, true); + x.tick(0b0000_0000, VIA6522_ORB, false, true); assert_eq!(x.portb, 0b0000_0000); - x.tick(0b1111_1111, VIA6522_ORB, true); + x.tick(0b1111_1111, VIA6522_ORB, false, true); assert_eq!(x.portb, 0b1111_1111); } #[test] fn partial_output_porta() { let mut x = Mos6522::new(); - x.tick(0b1010_1010, VIA6522_DDRA, true); - x.tick(0b1111_1111, VIA6522_ORA, true); + x.tick(0b1010_1010, VIA6522_DDRA, false, true); + x.tick(0b1111_1111, VIA6522_ORA, false, true); assert_eq!(x.porta, 0b1010_1010); } #[test] fn partial_output_portb() { let mut x = Mos6522::new(); - x.tick(0b0101_0101, VIA6522_DDRB, true); - x.tick(0b1111_1111, VIA6522_ORB, true); + x.tick(0b0101_0101, VIA6522_DDRB, false, true); + x.tick(0b1111_1111, VIA6522_ORB, false, true); assert_eq!(x.portb, 0b0101_0101); } } diff --git a/core/src/periph/mos6522/new.rs b/core/src/periph/mos6522/new.rs new file mode 100644 index 0000000..73a9bf8 --- /dev/null +++ b/core/src/periph/mos6522/new.rs @@ -0,0 +1,7 @@ +use crate::periph::mos6522::mos6522::Mos6522; + +impl Mos6522 { + pub fn new() -> Self { + Mos6522::default() + } +} \ No newline at end of file diff --git a/core/src/periph/mos6522/tick.rs b/core/src/periph/mos6522/tick.rs new file mode 100644 index 0000000..9e6ba25 --- /dev/null +++ b/core/src/periph/mos6522/tick.rs @@ -0,0 +1,86 @@ +use log::debug; +use crate::constants::constants_system::SIZE_32KB; +use crate::constants::constants_via6522::{VIA6522_DDRA, VIA6522_DDRB, VIA6522_ORA, VIA6522_ORB}; +use crate::periph::mos6522::mos6522::Mos6522; + +impl Mos6522 { + fn max_address(&self) -> u16 { + self.offset + SIZE_32KB as u16 + } + /// tick + /// + /// data_bus -> 8 bits from the data bus + /// control -> 4 bits to identify which register to control + pub fn tick(&mut self, address_bus: u16, data_bus: u8,reset: bool, rw: bool) -> (u16, u8) { + if !(address_bus.gt( &self.offset) && address_bus.le(&self.max_address())) { + return (address_bus, data_bus); + } + + let local_address = address_bus - self.offset; + + println!("Mos6522 Tick Start -> D:0x{data_bus:02x} / A:0x{address_bus:02x} / {rw} (Actual 0x{local_address:02x}"); + if reset { + // reset process + println!("Resetting Mos6522"); + self.data_bus = data_bus; + self.dda = 0x00; + self.ddb = 0x00; + self.porta = 0x00; + self.portb = 0x00; + return (self.address_bus, self.data_bus) + } + + if rw { + // RW true = CPU is writing + self.data_bus = data_bus; + match local_address as u8 { + VIA6522_DDRA => { + debug!("Setting DDA to 0x{data_bus:02x}"); + // setting the Data Direction for Port A + self.dda = data_bus; + }, + VIA6522_DDRB => { + debug!("Setting DDB to 0x{data_bus:02x}"); + // setting the data direction for port b + self.ddb = data_bus; + }, + VIA6522_ORB => { + // writing data to ORB + let masked_data = data_bus & self.ddb; + debug!("Setting ORB to 0x{data_bus:02x} / masked at 0x{masked_data:02x}"); + self.portb = masked_data; + }, + VIA6522_ORA => { + // writing data to ORA + let masked_data = data_bus & self.dda; + debug!("Setting ORA to 0x{data_bus:02x} / masked at 0x{masked_data:02x}"); + self.porta = masked_data; + }, + _ => {} + } + } else { + // RW false = CPU is reading + self.data_bus = match local_address as u8 { + VIA6522_DDRA => { + self.dda + } + VIA6522_DDRB => { + self.ddb + } + VIA6522_ORA => { + self.porta & self.dda + } + VIA6522_ORB => { + self.portb & self.ddb + } + _ => { + debug!("VIA got request for b{:08b} / 0x{:02x}", address_bus, address_bus); + // do nothing. bad address for VIA + self.data_bus + } + } + } + + (self.address_bus, self.data_bus) + } +} \ No newline at end of file diff --git a/core/src/periph/mos6530/dump.rs b/core/src/periph/mos6530/dump.rs new file mode 100644 index 0000000..f68f8e4 --- /dev/null +++ b/core/src/periph/mos6530/dump.rs @@ -0,0 +1,11 @@ +use crate::periph::mos6530::mos6530::Mos6530; + +impl Mos6530 { + pub fn dump(&self) { + println!("Dumping state of Mos6530 RRIOT"); + } + + pub fn dump_data(&self) -> (u16, u16, u16) { + (self.io_offset, self.ram_offset, self.rom_offset) + } +} diff --git a/core/src/periph/mos6530/mod.rs b/core/src/periph/mos6530/mod.rs new file mode 100644 index 0000000..15b4b48 --- /dev/null +++ b/core/src/periph/mos6530/mod.rs @@ -0,0 +1,4 @@ +pub mod mos6530; +pub mod tick; +mod new; +mod dump; \ No newline at end of file diff --git a/core/src/periph/mos6530/mos6530.rs b/core/src/periph/mos6530/mos6530.rs new file mode 100644 index 0000000..ab33696 --- /dev/null +++ b/core/src/periph/mos6530/mos6530.rs @@ -0,0 +1,32 @@ +use crate::constants::constants_system::*; +use crate::periph::mos6522::mos6522::Mos6522; + +/// Mos6530 RRIOT +/// Ram/Rom/IO/Timer +/// +/// Represents a single Mos6530 RRIOT Chip +/// +/// Used in the TIM-1, KIM-1 +/// +/// 1kb Rom +/// 64 bytes RAM +/// IO Ports (A, B) +/// Timer +/// +/// SEE ALSO Mos6532 +pub struct Mos6530 { + pub(crate) data: [u8; SIZE_1KB], + pub(crate) ram: [u8; 64], + pub(crate) porta: u8, + pub(crate) portb: u8, + pub(crate) data_bus: u8, + pub(crate) address_bus: u16, + pub(crate) cs1: bool, + pub(crate) cs2: bool, + // when true, CPU is reading + pub(crate) rw: bool, + pub(crate) reset: bool, + pub(crate) io_offset: u16, + pub(crate) ram_offset: u16, + pub(crate) rom_offset: u16 +} diff --git a/core/src/periph/mos6530/new.rs b/core/src/periph/mos6530/new.rs new file mode 100644 index 0000000..3123cc6 --- /dev/null +++ b/core/src/periph/mos6530/new.rs @@ -0,0 +1,25 @@ +use crate::constants::constants_system::SIZE_1KB; +use crate::periph::mos6530::mos6530::Mos6530; + +impl Mos6530 { + pub fn new(io_offset: u16, + ram_offset: u16, + rom_offset: u16, + data: &[u8; SIZE_1KB]) -> Self { + Mos6530 { + data: *data, + ram: [0x00; 64], + porta: 0, + portb: 0, + data_bus: 0, + address_bus: 0, + cs1: false, + cs2: false, + rw: false, + reset: false, + io_offset, + ram_offset, + rom_offset + } + } +} \ No newline at end of file diff --git a/core/src/periph/mos6530/tick.rs b/core/src/periph/mos6530/tick.rs new file mode 100644 index 0000000..c601bd7 --- /dev/null +++ b/core/src/periph/mos6530/tick.rs @@ -0,0 +1,26 @@ +use log::debug; +use crate::periph::mos6530::mos6530::Mos6530; + +impl Mos6530 { + pub fn tick(&mut self, address_bus: u16, data_bus: u8, reset: bool, rw: bool) { + debug!("Starting tick of MOS6530 RRIOT with 0x{address_bus:04x} / 0b{data_bus:08b} / R:{reset} / RW:{rw} (OFFSETS: I{:04x}, RA{:04x}, RO{:04x})", self.io_offset, self.ram_offset, self.rom_offset); + let io_max = self.io_offset + 0x3f; + let ram_max = self.ram_offset + 0x3f; + let rom_max = self.rom_offset + 0x400; + + if address_bus.ge(&self.io_offset) && address_bus.le(&io_max) { + let effective = address_bus - self.io_offset; + println!("IO Activity at effective 0x{effective:02x}"); + } + + if address_bus.ge(&self.ram_offset) && address_bus.le(&ram_max) { + let effective = address_bus - self.ram_offset; + println!("RAM Activity at effective 0x{effective:02x}"); + } + + if address_bus.ge(&self.rom_offset) && address_bus.le(&rom_max) { + let effective = address_bus - self.rom_offset; + println!("Rom Activity at effective 0x{effective:02x}"); + } + } +} diff --git a/resources/kim1/6530-002_fillerbyte00-0x1c00.bin b/resources/kim1/6530-002_fillerbyte00-0x1c00.bin new file mode 100644 index 0000000000000000000000000000000000000000..0577ff3ca95015db0694318cf4ad245304b26e55 GIT binary patch literal 1024 zcmYLI-D}%c6qoF-j>SscW#zh5zPjs!i$k}#Z-qR}%eL0dw2k#~Pl9a_hyDS3OCEYX z6XKA(jY5kMxnT+kOCPf_1{)id>9z}NVGtOFLF%qFxv?GV!?v^|JFEwEK7RV?eB66P z+jI12jvmrrjtbhl-KidbS8b6R)<0Hn1?X0Ytmw`Vu%mh#+4AKQ;^&LL-OpC!)#O1N zZIw`_U2h?4jLc)Qj7Jnqrm&@uD_H+FXG_$hKKT?ovN%n)G<`2e&TIV7AyYgAUvy%1 zNai)?T;_Y{b@85)5tp5_@Vq9boC$G70ik{C)Oy5~`@!k{ky=q^o&!BiL$az<@&hmrNbfCM`g`w?fVqzBj<|5X6;i1*6Es<$V9%=+* z)&-Zjp!CmGJG&XbfMOV%(*58hh%1Yi#C?w^_I~qkt1NgX z(_km@YY&o{67%4Ef6B4ms4I5TonfVZc&x#Ijf`v1{wxU5G3yVNQ5biWY%x(uRf@Wa zs{;#eC0>_{MV~yv6hp~B*|@Rg8;05td^U>gG#PR<&ZT#YPgGr8+Y!)ePJ zc!hCN)@uAYd}vER&_jH?|IO}G&6Ji)2+(>7nF}>OXg1gT#(n@-*fXp*OqnD!o_cbL zAKT{)Gg5Yv4>G}0VSIM;>r66RNi}$2WWR8!%eocVCj+(?ewUGEp5YXW7o6)EzWcOiNJCN1e0bvnGI8_f`()zB>fRswF9u&lhi-rOZ~q7g Ks(Mk?)c*jWr^*BX literal 0 HcmV?d00001 diff --git a/resources/kim1/6530-003_fillerbyte00-0x1800.bin b/resources/kim1/6530-003_fillerbyte00-0x1800.bin new file mode 100644 index 0000000000000000000000000000000000000000..f2dfdbd3b324919625b21bf03f16b18e726f3586 GIT binary patch literal 1024 zcmeHFO=}ZT6dlr#w8hXaO3%DOE2d+vRswEPTyfvIzH z9qOID0{@O$963MOdpRhM)MnVg1Cq0OKLSEwML|NhJH@vC*NCJ z-?s+dt<#)ZY%(4(@1i}&l$^BmtZKG_gO+ zmmG2q8|FCk%4vb3Pw5dqV$D9%5(y0~N)A()mz3lllQAYv0nj_W zAE>ADD%5LQ&tGA7VhwY6SNMeq>-|aADE!SzVwkBUfuO-@=rM}GbImh^K?h=Go%HEzs1LUZ7HZ}PW!%A9 l{3}(Y)Q#ctGx6sa8xOH}Qtc?r)OwE{>%aZ;4cv3G>nF(D7s&ts literal 0 HcmV?d00001 diff --git a/resources/test/instructions.asm b/resources/test/instructions.asm index 365eb47..b122c92 100644 --- a/resources/test/instructions.asm +++ b/resources/test/instructions.asm @@ -27,16 +27,16 @@ ASL $abcd ; ASL Absolute ASL $abcd,X; ASL AbsoluteX - BCC $ab ; BCC Immediate - BCS $ab ; BCS Immediate - BEQ $ab ; BEQ Immediate + BCC $71 ; BCC Immediate + BCS $71 ; BCS Immediate + BEQ $71 ; BEQ Immediate BIT $ab ; BIT ZeroPage BIT $abcd ; BIT Absolute - BMI $ab ; BMI Immediate - BNE $ab ; BNI Immediate - BPL $ab ; BPL Immediate + BMI $7b ; BMI Immediate + BNE $7b ; BNI Immediate + BPL $7b ; BPL Immediate BRK ; BRK @@ -151,4 +151,39 @@ ROR $abcd,X; ROR AbsoluteX RTI ; Interrupt Return - RTS ; Subroutine Return \ No newline at end of file + RTS ; Subroutine Return + + SBC #$ab ; SBC Immediate + SBC $ab ; SBC ZeroPage + SBC $ab,X ; SBC ZeroPageX + SBC $abcd ; SBC Absolute + SBC $abcd,X; SBC AbsoluteX + SBC ($ab,X); SBC IndirectX + SBC ($ab),Y; SBC IndirectY + + SEC ; SEC + SED ; SED + SEI ; SEI + + STA $ab ; STA ZeroPage + STA $ab,X ; STA ZeroPageX + STA $abcd ; STA Absolute + STA $abcd,X; STA AbsoluteX + STA $abcd,Y; STA AbsoluteY + STA ($ab,X); STA IndirectX + STA ($ab),Y; STA IndirectY + + STX $ab ; STX ZeroPage + STX $ab,Y ; STX ZeroPageY + STX $abcd ; STX Absolute + + STY $ab ; STY ZeroPage + STY $ab,X ; STY ZeroPageX + STY $abcd ; STY Absolute + + TAX ; TAX + TAY ; TAY + TSX ; TSX + TXA ; TXA + TXS ; TXS + TYA ; TYA diff --git a/resources/test/labels.asm b/resources/test/labels.asm new file mode 100644 index 0000000..f51620f --- /dev/null +++ b/resources/test/labels.asm @@ -0,0 +1,8 @@ + * = $4000 + .fill start - *, $00 +start: + LDA #$ab + ROR + LDX #$ba + TXA + JMP start