boxswap
This commit is contained in:
parent
b7e161ef0b
commit
ff43a99e0c
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1,3 @@
|
|||||||
/target
|
/target
|
||||||
|
*produced.asm
|
||||||
|
*produced.bin
|
||||||
|
|||||||
479
6530.asm
Normal file
479
6530.asm
Normal file
@ -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 ]
|
||||||
@ -8,6 +8,7 @@ use core::mos6502cpu::cpu::Mos6502Cpu;
|
|||||||
use core::periph::at28c256::At28C256;
|
use core::periph::at28c256::At28C256;
|
||||||
use core::periph::hm62256::Hm62256;
|
use core::periph::hm62256::Hm62256;
|
||||||
use core::constants::constants_system::*;
|
use core::constants::constants_system::*;
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
/// BenEater computer represents the 'Ben Eater' 6502 breadboard computer.
|
/// BenEater computer represents the 'Ben Eater' 6502 breadboard computer.
|
||||||
/// This was built along watching the video series where Ben builds a
|
/// This was built along watching the video series where Ben builds a
|
||||||
@ -20,20 +21,19 @@ pub struct BenEater {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BenEater {
|
impl BenEater {
|
||||||
pub fn new(rom: &[u8; SIZE_32KB]) -> BenEater {
|
// pub fn new(rom: &[u8; SIZE_32KB]) -> BenEater {
|
||||||
|
//
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[macroquad::main("Ben Eaters PC")]
|
#[macroquad::main("Ben Eaters PC")]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
println!("Taxation is Theft");
|
println!("Taxation is Theft");
|
||||||
|
|
||||||
let rom_to_run = fs::read("resources/beneater/roms/ror.bin");
|
// let rom_to_run = fs::read("resources/beneater/roms/ror.bin");
|
||||||
let mut pc = BenEater::new(&rom_to_run);
|
// let mut pc = BenEater::new(&rom_to_run);
|
||||||
|
//
|
||||||
let mut backplane = Backplane::new();
|
// let mut backplane = Backplane::new();
|
||||||
// backplane.load_rom("resources/beneater/roms/ror.bin");
|
// backplane.load_rom("resources/beneater/roms/ror.bin");
|
||||||
|
|
||||||
// let mut dm = DisplayMatrix::new(200.0, 50.0);
|
// let mut dm = DisplayMatrix::new(200.0, 50.0);
|
||||||
|
|||||||
@ -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::collections::HashMap;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
@ -15,7 +20,10 @@ struct CliOptions {
|
|||||||
/// File to Decompile
|
/// File to Decompile
|
||||||
input: PathBuf,
|
input: PathBuf,
|
||||||
/// File to write
|
/// File to write
|
||||||
output: PathBuf
|
output: PathBuf,
|
||||||
|
/// Verbose output
|
||||||
|
#[arg(short, action = clap::ArgAction::Count)]
|
||||||
|
verbose: u8
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -57,15 +65,16 @@ impl WorkingProgram {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decompile(data: &[u8]) -> Vec<(u16, DecompiledLine)> {
|
fn parse_to_decompiled_lines(data: &[u8]) -> HashMap<u16, DecompiledLine> {
|
||||||
println!("Preparing to decompile {}b", data.len());
|
println!("PARSE GOT {}b", data.len());
|
||||||
let mut current_data_position: u16 = 0;
|
let mut current_data_position = 0;
|
||||||
let mut lines: HashMap<u16, DecompiledLine> = HashMap::new();
|
let mut lines: HashMap<u16, DecompiledLine> = HashMap::new();
|
||||||
|
|
||||||
while current_data_position < data.len() as u16 {
|
while current_data_position < data.len() as u16 {
|
||||||
// read the next byte.
|
// read the next byte.
|
||||||
let next_byte = data[current_data_position as usize];
|
let next_byte = data[current_data_position as usize];
|
||||||
let mut bytes = vec![next_byte];
|
let mut bytes = vec![next_byte];
|
||||||
|
println!("Bytes = {bytes:?}");
|
||||||
let target_op = INSTRUCTION_TABLE[next_byte as usize].clone();
|
let target_op = INSTRUCTION_TABLE[next_byte as usize].clone();
|
||||||
|
|
||||||
if let Some(top) = target_op {
|
if let Some(top) = target_op {
|
||||||
@ -103,25 +112,45 @@ fn decompile(data: &[u8]) -> Vec<(u16, DecompiledLine)> {
|
|||||||
current_data_position += 1;
|
current_data_position += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lines
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decompile(data: &Vec<u8>) -> Vec<(u16, DecompiledLine)> {
|
||||||
|
println!("Preparing to decompile {}b", data.len());
|
||||||
|
let mut current_data_position: u16 = 0;
|
||||||
|
let mut lines: HashMap<u16, DecompiledLine> = parse_to_decompiled_lines(data);
|
||||||
|
|
||||||
println!("Found {} instructions in pass 1. Adding labels for jumps.", lines.len());
|
println!("Found {} instructions in pass 1. Adding labels for jumps.", lines.len());
|
||||||
|
|
||||||
//let targets = vec![];
|
//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();
|
let mut items: Vec<_> = lines.into_iter().collect();
|
||||||
items.sort_by(|a, b| a.0.cmp(&b.0));
|
items.sort_by(|a, b| a.0.cmp(&b.0));
|
||||||
|
|
||||||
|
|
||||||
// loop through the lines for JSR and label the 'target' as SUB<index>
|
// loop through the lines for JSR and label the 'target' as SUB<index>
|
||||||
|
// 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
|
// -> main
|
||||||
// -> NMI
|
// -> NMI
|
||||||
// -> IRQ
|
// -> IRQ
|
||||||
@ -129,6 +158,37 @@ fn decompile(data: &[u8]) -> Vec<(u16, DecompiledLine)> {
|
|||||||
items
|
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<u8>) -> 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() {
|
fn main() {
|
||||||
let opts = CliOptions::parse();
|
let opts = CliOptions::parse();
|
||||||
println!("Taxation is theft.");
|
println!("Taxation is theft.");
|
||||||
@ -147,8 +207,17 @@ fn main() {
|
|||||||
|
|
||||||
// ...reap the decompiled code.
|
// ...reap the decompiled code.
|
||||||
for (_, line) in &result {
|
for (_, line) in &result {
|
||||||
let line =format!("{:width$}; {:?}", line.text,line.bytes, width=30 );
|
let formatted_bytes = format_bytes(&line.bytes);
|
||||||
println!("{}", line);
|
let output_line =format!("{:width$}; {}", line.text, formatted_bytes, width=30 );
|
||||||
writeln!(output_file, "{}", line).expect("cant write output file. you picked the red snapper.");
|
|
||||||
|
// 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);
|
||||||
}
|
}
|
||||||
|
|||||||
26
cli/src/bin/kim1.rs
Normal file
26
cli/src/bin/kim1.rs
Normal file
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use core::computers::rom_only::backplane::Backplane;
|
use core::computers::rom_only::backplane::RomOnlyComputer;
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
struct CliOptions {
|
struct CliOptions {
|
||||||
@ -13,6 +13,6 @@ fn main() {
|
|||||||
|
|
||||||
let opts = CliOptions::parse();
|
let opts = CliOptions::parse();
|
||||||
|
|
||||||
let mut rom_only = Backplane::new();
|
let mut rom_only = RomOnlyComputer::new();
|
||||||
rom_only.tick()
|
rom_only.tick()
|
||||||
}
|
}
|
||||||
28
core/src/computers/kim1/mod.rs
Normal file
28
core/src/computers/kim1/mod.rs
Normal file
@ -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
|
||||||
|
}
|
||||||
31
core/src/computers/kim1/new.rs
Normal file
31
core/src/computers/kim1/new.rs
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
core/src/computers/kim1/reset.rs
Normal file
18
core/src/computers/kim1/reset.rs
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
26
core/src/computers/kim1/tick.rs
Normal file
26
core/src/computers/kim1/tick.rs
Normal file
@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,2 +1,3 @@
|
|||||||
pub mod beneater;
|
pub mod beneater;
|
||||||
pub mod rom_only;
|
pub mod rom_only;
|
||||||
|
pub mod kim1;
|
||||||
|
|||||||
@ -1,21 +1,22 @@
|
|||||||
use crate::constants::constants_system::{SIZE_32KB, SIZE_64KB};
|
use crate::constants::constants_system::{SIZE_32KB, SIZE_64KB};
|
||||||
|
use crate::periph::at28c256::At28C256;
|
||||||
use crate::periph::hm62256::Hm62256;
|
use crate::periph::hm62256::Hm62256;
|
||||||
use crate::periph::rom_chip::RomChip;
|
use crate::periph::rom_chip::RomChip;
|
||||||
|
|
||||||
pub struct Backplane {
|
pub struct RomOnlyComputer {
|
||||||
rom: Hm62256,
|
rom: At28C256,
|
||||||
data_bus: u8,
|
data_bus: u8,
|
||||||
address_bus: u16
|
address_bus: u16
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Backplane {
|
impl RomOnlyComputer {
|
||||||
pub fn new() -> Backplane {
|
pub fn new() -> RomOnlyComputer {
|
||||||
Backplane::program(&[0x00; SIZE_32KB])
|
RomOnlyComputer::program(&[0x00; SIZE_32KB])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn program(rom: &[u8; SIZE_32KB]) -> Backplane {
|
pub fn program(rom: &[u8; SIZE_32KB]) -> RomOnlyComputer {
|
||||||
Backplane {
|
RomOnlyComputer {
|
||||||
rom: *Hm62256::program(rom),
|
rom: *At28C256::new(0x000, rom),
|
||||||
address_bus: 0x0000,
|
address_bus: 0x0000,
|
||||||
data_bus: 0x00
|
data_bus: 0x00
|
||||||
}
|
}
|
||||||
@ -24,6 +25,10 @@ impl Backplane {
|
|||||||
pub fn tick(&mut self) {
|
pub fn tick(&mut self) {
|
||||||
println!("Preparing to tick.");
|
println!("Preparing to tick.");
|
||||||
|
|
||||||
|
// do are we being addressed?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
println!("Done ticking.");
|
println!("Done ticking.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
23
core/src/constants/constants_mos6530.rs
Normal file
23
core/src/constants/constants_mos6530.rs
Normal file
@ -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
|
||||||
|
*/
|
||||||
@ -2,6 +2,10 @@ pub const SIZE_1KB: usize = 1024;
|
|||||||
pub const SIZE_32KB: usize = SIZE_1KB * 32;
|
pub const SIZE_32KB: usize = SIZE_1KB * 32;
|
||||||
pub const SIZE_64KB: usize = SIZE_1KB * 64;
|
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_VECTOR: u16 = 0xfffc;
|
||||||
|
pub const OFFSET_RESET_VECTORS: usize = 0xffff;
|
||||||
pub const OFFSET_INT_VECTOR: u16 = 0xfffe;
|
pub const OFFSET_INT_VECTOR: u16 = 0xfffe;
|
||||||
|
pub const OFFSET_INT_VECTORS: usize = 0xfffe;
|
||||||
|
|||||||
@ -2,3 +2,4 @@ pub mod constants_isa_op;
|
|||||||
pub mod constants_isa_stub;
|
pub mod constants_isa_stub;
|
||||||
pub mod constants_system;
|
pub mod constants_system;
|
||||||
pub mod constants_via6522;
|
pub mod constants_via6522;
|
||||||
|
pub mod constants_mos6530;
|
||||||
|
|||||||
@ -215,10 +215,10 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
|
|||||||
|
|
||||||
table[ISA_OP_BCC as usize] = Some(OpInfo {
|
table[ISA_OP_BCC as usize] = Some(OpInfo {
|
||||||
operation: BCC,
|
operation: BCC,
|
||||||
mode: AddressMode::Immediate,
|
mode: AddressMode::Implied,
|
||||||
length: 2,
|
length: 2,
|
||||||
cycles: 2,
|
cycles: 2,
|
||||||
format_prefix: "BCC #$",
|
format_prefix: "BCC $",
|
||||||
format_postfix: "",
|
format_postfix: "",
|
||||||
|
|
||||||
});
|
});
|
||||||
@ -229,7 +229,6 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
|
|||||||
cycles: 2,
|
cycles: 2,
|
||||||
format_prefix: "BCS $",
|
format_prefix: "BCS $",
|
||||||
format_postfix: "",
|
format_postfix: "",
|
||||||
|
|
||||||
});
|
});
|
||||||
table[ISA_OP_BEQ as usize] = Some(OpInfo {
|
table[ISA_OP_BEQ as usize] = Some(OpInfo {
|
||||||
operation: BEQ,
|
operation: BEQ,
|
||||||
@ -267,7 +266,6 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
|
|||||||
cycles: 2,
|
cycles: 2,
|
||||||
format_prefix: "BMI #$",
|
format_prefix: "BMI #$",
|
||||||
format_postfix: "",
|
format_postfix: "",
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
table[ISA_OP_BNE as usize] = Some(OpInfo {
|
table[ISA_OP_BNE as usize] = Some(OpInfo {
|
||||||
@ -850,8 +848,8 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
|
|||||||
mode: AddressMode::AbsoluteX,
|
mode: AddressMode::AbsoluteX,
|
||||||
length: 3,
|
length: 3,
|
||||||
cycles: 7,
|
cycles: 7,
|
||||||
format_prefix: "LSR $(",
|
format_prefix: "LSR $",
|
||||||
format_postfix: ",X)",
|
format_postfix: ",X",
|
||||||
});
|
});
|
||||||
|
|
||||||
table[ISA_OP_NOP as usize] = Some(OpInfo {
|
table[ISA_OP_NOP as usize] = Some(OpInfo {
|
||||||
@ -1221,15 +1219,15 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
|
|||||||
mode: AddressMode::ZeroPageY,
|
mode: AddressMode::ZeroPageY,
|
||||||
length: 2,
|
length: 2,
|
||||||
cycles: 4,
|
cycles: 4,
|
||||||
format_prefix: "STX",
|
format_prefix: "STX $",
|
||||||
format_postfix: "",
|
format_postfix: ",Y",
|
||||||
});
|
});
|
||||||
table[ISA_OP_STX_ABS as usize] = Some(OpInfo {
|
table[ISA_OP_STX_ABS as usize] = Some(OpInfo {
|
||||||
operation: Operation::STX,
|
operation: Operation::STX,
|
||||||
mode: AddressMode::Absolute,
|
mode: AddressMode::Absolute,
|
||||||
length: 3,
|
length: 3,
|
||||||
cycles: 4,
|
cycles: 4,
|
||||||
format_prefix: "STX",
|
format_prefix: "STX $",
|
||||||
format_postfix: "",
|
format_postfix: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
#![feature(slice_as_array)]
|
||||||
|
|
||||||
pub mod computers;
|
pub mod computers;
|
||||||
pub mod address_mode;
|
pub mod address_mode;
|
||||||
pub mod constants;
|
pub mod constants;
|
||||||
|
|||||||
@ -9,6 +9,8 @@ use crate::op_info::OpInfo;
|
|||||||
use crate::operand::Operand;
|
use crate::operand::Operand;
|
||||||
use crate::operation::Operation;
|
use crate::operation::Operation;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
use crate::mos6502cpu::tick_stages::Mos6502TickStates;
|
||||||
|
use crate::mos6502cpu::tick_stages::Mos6502TickStates::*;
|
||||||
|
|
||||||
pub struct Mos6502Cpu {
|
pub struct Mos6502Cpu {
|
||||||
pub(crate) memory: [u8; SIZE_64KB],
|
pub(crate) memory: [u8; SIZE_64KB],
|
||||||
@ -36,7 +38,9 @@ pub struct Mos6502Cpu {
|
|||||||
/// CPU Read signal
|
/// CPU Read signal
|
||||||
pub read_signal: bool,
|
pub read_signal: bool,
|
||||||
pub(crate) reset_vector: u16,
|
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 {
|
impl Mos6502Cpu {
|
||||||
@ -74,7 +78,9 @@ impl Default for Mos6502Cpu {
|
|||||||
ir_bytes: [0x00; 4],
|
ir_bytes: [0x00; 4],
|
||||||
read_signal: true,
|
read_signal: true,
|
||||||
reset_vector: 0x0000,
|
reset_vector: 0x0000,
|
||||||
int_vector: 0x0000
|
int_vector: 0x0000,
|
||||||
|
nmi_vector: 0x0000,
|
||||||
|
tick_stage: LoadingInstruction
|
||||||
};
|
};
|
||||||
working.reset_cpu();
|
working.reset_cpu();
|
||||||
working
|
working
|
||||||
@ -160,6 +166,48 @@ impl Mos6502Cpu {
|
|||||||
/// Ticks the CPU
|
/// Ticks the CPU
|
||||||
pub fn tick(&mut self) {
|
pub fn tick(&mut self) {
|
||||||
println!("PREPARiNG TO TICK CPU AT PC 0x{:04x}", self.pc);
|
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 {
|
if self.microcode_step == 0 {
|
||||||
println!("OUT OF MICROSTEPS. Decoding the next instruction");
|
println!("OUT OF MICROSTEPS. Decoding the next instruction");
|
||||||
let offset = self.pc as usize;
|
let offset = self.pc as usize;
|
||||||
|
|||||||
@ -5,7 +5,7 @@ impl Mos6502Cpu {
|
|||||||
///
|
///
|
||||||
/// returns
|
/// returns
|
||||||
/// PC, A, X, Y, Address_Bus, Data_Bus, Microcode_Step
|
/// 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.pc,
|
||||||
self.a,
|
self.a,
|
||||||
@ -15,13 +15,14 @@ impl Mos6502Cpu {
|
|||||||
self.data_bus,
|
self.data_bus,
|
||||||
self.microcode_step,
|
self.microcode_step,
|
||||||
self.reset_vector,
|
self.reset_vector,
|
||||||
self.int_vector
|
self.int_vector,
|
||||||
|
self.nmi_vector
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dump(&self) {
|
pub fn dump(&self) {
|
||||||
println!(
|
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.pc,
|
||||||
self.a,
|
self.a,
|
||||||
self.x,
|
self.x,
|
||||||
@ -29,7 +30,10 @@ impl Mos6502Cpu {
|
|||||||
self.address_bus,
|
self.address_bus,
|
||||||
self.data_bus,
|
self.data_bus,
|
||||||
self.microcode_step,
|
self.microcode_step,
|
||||||
self.flags.dump()
|
self.flags.dump(),
|
||||||
|
self.nmi_vector,
|
||||||
|
self.reset_vector,
|
||||||
|
self.int_vector
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,5 +2,5 @@ pub mod cpu;
|
|||||||
pub mod new;
|
pub mod new;
|
||||||
|
|
||||||
pub mod tick2;
|
pub mod tick2;
|
||||||
mod dbg;
|
pub mod dbg;
|
||||||
mod tick_stages;
|
pub mod tick_stages;
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
use crate::constants::constants_system::{OFFSET_INT_VECTOR, OFFSET_RESET_VECTOR};
|
use crate::constants::constants_system::{OFFSET_INT_VECTOR, OFFSET_RESET_VECTOR};
|
||||||
use crate::mos6502cpu::cpu::Mos6502Cpu;
|
use crate::mos6502cpu::cpu::Mos6502Cpu;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
impl Mos6502Cpu {
|
impl Mos6502Cpu {
|
||||||
/// AccurateTick
|
/// AccurateTick
|
||||||
///
|
///
|
||||||
@ -19,6 +21,8 @@ impl Mos6502Cpu {
|
|||||||
if self.read_signal {
|
if self.read_signal {
|
||||||
// we should see new data in the data_bus for us
|
// we should see new data in the data_bus for us
|
||||||
let read_data = data_bus;
|
let read_data = data_bus;
|
||||||
|
println!("READ 0x{read_data:02x} from data bus.");
|
||||||
|
self.data_bus = read_data;
|
||||||
} else {
|
} else {
|
||||||
// we are writing to the bus.
|
// we are writing to the bus.
|
||||||
}
|
}
|
||||||
@ -28,6 +32,12 @@ impl Mos6502Cpu {
|
|||||||
// reduce the number of remaining microsteps
|
// reduce the number of remaining microsteps
|
||||||
self.read_signal = true;
|
self.read_signal = true;
|
||||||
match self.microcode_step {
|
match self.microcode_step {
|
||||||
|
6 => {
|
||||||
|
// NMI High byte
|
||||||
|
}
|
||||||
|
5 => {
|
||||||
|
// NMI low byte
|
||||||
|
}
|
||||||
4 => {
|
4 => {
|
||||||
// read first byte of reset vector
|
// read first byte of reset vector
|
||||||
self.address_bus = OFFSET_RESET_VECTOR;
|
self.address_bus = OFFSET_RESET_VECTOR;
|
||||||
@ -35,6 +45,7 @@ impl Mos6502Cpu {
|
|||||||
3 => {
|
3 => {
|
||||||
// at this point data holds the upper byte of our reset vector
|
// at this point data holds the upper byte of our reset vector
|
||||||
self.reset_vector = (data_bus as u16) << 8;
|
self.reset_vector = (data_bus as u16) << 8;
|
||||||
|
println!("Loaded reset vector of 0x{:04x}", self.reset_vector);
|
||||||
// read secondd byte of reset vector
|
// read secondd byte of reset vector
|
||||||
self.address_bus = OFFSET_RESET_VECTOR + 1;
|
self.address_bus = OFFSET_RESET_VECTOR + 1;
|
||||||
}
|
}
|
||||||
@ -53,12 +64,19 @@ impl Mos6502Cpu {
|
|||||||
println!("Loaded interrupt vector of 0x{:04x}", self.int_vector);
|
println!("Loaded interrupt vector of 0x{:04x}", self.int_vector);
|
||||||
self.pc = self.reset_vector;
|
self.pc = self.reset_vector;
|
||||||
println!("Set PC to Reset Vector. Giddy-up!");
|
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;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if self.microcode_step > 0 {
|
||||||
self.microcode_step -= 1;
|
self.microcode_step -= 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
(self.address_bus, self.data_bus, self.read_signal)
|
(self.address_bus, self.data_bus, self.read_signal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
///
|
///
|
||||||
/// The set of what a tick can be doing
|
/// The set of what a tick can be doing
|
||||||
///
|
///
|
||||||
enum Mos6502TickStates {
|
pub enum Mos6502TickStates {
|
||||||
/// Loading the first byte into the IR
|
/// Loading the first byte into the IR
|
||||||
LoadingInstruction,
|
LoadingInstruction,
|
||||||
/// Loading an 8 bit parameter
|
/// Loading an 8 bit parameter
|
||||||
@ -14,6 +14,6 @@ enum Mos6502TickStates {
|
|||||||
Loading16BitParameter2,
|
Loading16BitParameter2,
|
||||||
/// Stalling for accurate emulation
|
/// Stalling for accurate emulation
|
||||||
Stall(u8),
|
Stall(u8),
|
||||||
/// Completed the instruction
|
/// Waiting for the next instruction
|
||||||
Complete
|
Waiting
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,11 @@ impl Default for At28C256 {
|
|||||||
let boxed_array: Box<[u8; SIZE_32KB]> = boxed_slice
|
let boxed_array: Box<[u8; SIZE_32KB]> = boxed_slice
|
||||||
.try_into()
|
.try_into()
|
||||||
.expect("Failed to convert Vec to boxed array");
|
.expect("Failed to convert Vec to boxed array");
|
||||||
At28C256 { data: boxed_array }
|
At28C256 { data: boxed_array,
|
||||||
|
address_bus: 0x0000,
|
||||||
|
data_bus: 0x00,
|
||||||
|
offset: 0x0000
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
13
core/src/periph/at28c256/dump.rs
Normal file
13
core/src/periph/at28c256/dump.rs
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,6 +3,7 @@ pub mod rom_chip;
|
|||||||
pub mod tick;
|
pub mod tick;
|
||||||
mod new;
|
mod new;
|
||||||
mod program;
|
mod program;
|
||||||
|
mod dump;
|
||||||
|
|
||||||
use crate::constants::constants_system::SIZE_32KB;
|
use crate::constants::constants_system::SIZE_32KB;
|
||||||
use crate::periph::rom_chip::RomChip;
|
use crate::periph::rom_chip::RomChip;
|
||||||
@ -15,7 +16,11 @@ use std::io::Read;
|
|||||||
/// 256kbit storage
|
/// 256kbit storage
|
||||||
/// 32kbyte storage
|
/// 32kbyte storage
|
||||||
pub struct At28C256 {
|
pub struct At28C256 {
|
||||||
|
data_bus: u8,
|
||||||
|
address_bus: u16,
|
||||||
data: Box<[u8; SIZE_32KB]>,
|
data: Box<[u8; SIZE_32KB]>,
|
||||||
|
// where in the computer memory map do we live?
|
||||||
|
offset: u16
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@ -2,9 +2,12 @@ use crate::constants::constants_system::SIZE_32KB;
|
|||||||
use crate::periph::at28c256::At28C256;
|
use crate::periph::at28c256::At28C256;
|
||||||
|
|
||||||
impl At28C256 {
|
impl At28C256 {
|
||||||
pub fn new(data: &[u8; SIZE_32KB]) -> Self {
|
pub fn new(offset: u16, data: &[u8; SIZE_32KB]) -> Self {
|
||||||
At28C256 {
|
At28C256 {
|
||||||
data: (*data).into()
|
data: (*data).into(),
|
||||||
|
address_bus: 0x0000,
|
||||||
|
data_bus: 0x00,
|
||||||
|
offset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,23 @@
|
|||||||
|
use crate::constants::constants_system::SIZE_32KB;
|
||||||
use crate::periph::at28c256::At28C256;
|
use crate::periph::at28c256::At28C256;
|
||||||
use crate::periph::hm62256::Hm62256;
|
use crate::periph::hm62256::Hm62256;
|
||||||
|
|
||||||
impl At28C256 {
|
impl At28C256 {
|
||||||
fn tick(&mut self, address_bus: u16, data_bus: u8, read_mode: bool) -> (u16, u8) {
|
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 {
|
if read_mode {
|
||||||
panic!("UNABLE TO WRITE TO ROM");
|
panic!("UNABLE TO WRITE TO ROM");
|
||||||
} else {
|
} else {
|
||||||
// has to be read mode. its a rom.
|
// has to be read mode. its a rom.
|
||||||
return (address_bus, data_bus)
|
return (address_bus, data_bus)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// not for us.
|
||||||
(address_bus, self.data[address_bus as usize])
|
(address_bus, self.data[address_bus as usize])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
3
core/src/periph/bus_device.rs
Normal file
3
core/src/periph/bus_device.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
pub trait BusDevice {
|
||||||
|
fn talking_to_me(&self, address: u16) -> bool;
|
||||||
|
}
|
||||||
17
core/src/periph/hm62256/default.rs
Normal file
17
core/src/periph/hm62256/default.rs
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
core/src/periph/hm62256/dump.rs
Normal file
17
core/src/periph/hm62256/dump.rs
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,27 +3,23 @@
|
|||||||
pub mod ramchip;
|
pub mod ramchip;
|
||||||
pub mod romchip;
|
pub mod romchip;
|
||||||
pub mod tick;
|
pub mod tick;
|
||||||
|
pub mod default;
|
||||||
|
pub mod new;
|
||||||
|
pub mod dump;
|
||||||
|
|
||||||
use crate::constants::constants_system::SIZE_32KB;
|
use crate::constants::constants_system::SIZE_32KB;
|
||||||
use crate::periph::ram_chip::RamChip;
|
use crate::periph::ram_chip::RamChip;
|
||||||
use crate::periph::rom_chip::RomChip;
|
use crate::periph::rom_chip::RomChip;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
pub struct Hm62256 {
|
|
||||||
pub(crate) base_offset: u16,
|
|
||||||
pub(crate) data: Box<[u8]>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Hm62256 {
|
/// Hitachi Semiconductor
|
||||||
fn default() -> Self {
|
/// 8 Bit High Speed Static Ram
|
||||||
let vec = vec![0x00; SIZE_32KB];
|
/// 32KByte
|
||||||
let boxed_slice: Box<[u8]> = vec.into_boxed_slice();
|
pub struct Hm62256 {
|
||||||
let boxed_array: Box<[u8; SIZE_32KB]> =
|
pub(crate) offset: u16,
|
||||||
boxed_slice.try_into().expect("Unable to box the ram");
|
pub(crate) data: Box<[u8]>,
|
||||||
Hm62256 {
|
pub(crate) address_bus: u16,
|
||||||
base_offset: 0x0000,
|
pub(crate) data_bus: u8
|
||||||
data: boxed_array,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
13
core/src/periph/hm62256/new.rs
Normal file
13
core/src/periph/hm62256/new.rs
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,16 +1,41 @@
|
|||||||
|
use crate::constants::constants_system::SIZE_32KB;
|
||||||
use crate::periph::hm62256::Hm62256;
|
use crate::periph::hm62256::Hm62256;
|
||||||
|
|
||||||
impl Hm62256 {
|
impl Hm62256 {
|
||||||
fn tick(&mut self, address_bus: u16, data_bus: u8, read_mode: bool) -> (u16, u8) {
|
fn max_address(&self) -> u16 {
|
||||||
let new_data_bus = if read_mode {
|
self.offset + SIZE_32KB as u16
|
||||||
// reading from ram
|
}
|
||||||
self.data[address_bus as usize]
|
|
||||||
|
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 {
|
} else {
|
||||||
// writing to ram
|
// writing to ram
|
||||||
self.data[address_bus as usize] = data_bus.into();
|
self.data[addr as usize] = data_bus.into();
|
||||||
data_bus
|
data_bus
|
||||||
};
|
};
|
||||||
(address_bus, new_data_bus)
|
(self.address_bus, self.data_bus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,9 +51,9 @@ mod test {
|
|||||||
let mut ram = Hm62256::default();
|
let mut ram = Hm62256::default();
|
||||||
|
|
||||||
// load the data to ram
|
// load the data to ram
|
||||||
ram.tick(0x0000, 0xab, false);
|
ram.tick(0x0000, 0xab, false, true);
|
||||||
// read the data back
|
// 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);
|
assert_eq!(new_data, 0xab);
|
||||||
}
|
}
|
||||||
|
|||||||
105
core/src/periph/kim1_keypad/mod.rs
Normal file
105
core/src/periph/kim1_keypad/mod.rs
Normal file
@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,8 @@
|
|||||||
pub mod rom_chip;
|
pub mod rom_chip;
|
||||||
|
|
||||||
pub mod at28c256;
|
pub mod at28c256;
|
||||||
pub mod hm62256;
|
pub mod hm62256;
|
||||||
pub mod ram_chip;
|
pub mod ram_chip;
|
||||||
pub mod mos6522;
|
pub mod mos6522;
|
||||||
|
pub mod mos6530;
|
||||||
|
pub mod kim1_keypad;
|
||||||
|
mod bus_device;
|
||||||
|
|||||||
@ -1,2 +1,4 @@
|
|||||||
pub mod mos6522;
|
pub mod mos6522;
|
||||||
mod registers;
|
mod registers;
|
||||||
|
mod new;
|
||||||
|
mod tick;
|
||||||
@ -5,106 +5,47 @@ use crate::constants::constants_via6522::*;
|
|||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Mos6522 {
|
pub struct Mos6522 {
|
||||||
/// data direction
|
/// data direction
|
||||||
dda: u8,
|
pub(crate) dda: u8,
|
||||||
ddb: u8,
|
pub(crate) ddb: u8,
|
||||||
|
|
||||||
/// bottom 4 address bits
|
/// bottom 4 address bits
|
||||||
rs0: u8,
|
pub(crate) rs0: u8,
|
||||||
rs1: u8,
|
pub(crate) rs1: u8,
|
||||||
rs2: u8,
|
pub(crate) rs2: u8,
|
||||||
rs3: u8,
|
pub(crate) rs3: u8,
|
||||||
|
|
||||||
/// external data bus
|
/// external data bus
|
||||||
data_bus: u8,
|
pub(crate) data_bus: u8,
|
||||||
|
|
||||||
cs1: bool,
|
pub(crate) cs1: bool,
|
||||||
cs2: bool,
|
pub(crate) cs2: bool,
|
||||||
rw: bool,
|
// when true CPU is reading
|
||||||
|
pub(crate) rw: bool,
|
||||||
|
|
||||||
/// reset circuit - true when reset inited
|
/// reset circuit - true when reset inited
|
||||||
reset: bool,
|
pub(crate) reset: bool,
|
||||||
|
|
||||||
/// IRQ - true when interrupt waiting
|
/// IRQ - true when interrupt waiting
|
||||||
irq: bool,
|
pub(crate) irq: bool,
|
||||||
|
|
||||||
ira: u8,
|
pub(crate) ira: u8,
|
||||||
ora: u8,
|
pub(crate) ora: u8,
|
||||||
porta: u8,
|
pub(crate) porta: u8,
|
||||||
irb: u8,
|
pub(crate) irb: u8,
|
||||||
orb: u8,
|
pub(crate) orb: u8,
|
||||||
portb: u8,
|
pub(crate) portb: u8,
|
||||||
|
|
||||||
ca1: bool,
|
pub(crate) ca1: bool,
|
||||||
ca2: bool,
|
pub(crate) ca2: bool,
|
||||||
cb1: bool,
|
pub(crate) cb1: bool,
|
||||||
cb2: 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 {
|
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) {
|
pub fn start_clocks(&mut self) {
|
||||||
loop {
|
loop {
|
||||||
let cycle_start = Instant::now();
|
let cycle_start = Instant::now();
|
||||||
@ -115,7 +56,6 @@ impl Mos6522 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -126,40 +66,40 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn registers() {
|
fn registers() {
|
||||||
let mut x = Mos6522::new();
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
assert_eq!(x.portb, 0b1111_1111);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn partial_output_porta() {
|
fn partial_output_porta() {
|
||||||
let mut x = Mos6522::new();
|
let mut x = Mos6522::new();
|
||||||
x.tick(0b1010_1010, VIA6522_DDRA, true);
|
x.tick(0b1010_1010, VIA6522_DDRA, false, true);
|
||||||
x.tick(0b1111_1111, VIA6522_ORA, true);
|
x.tick(0b1111_1111, VIA6522_ORA, false, true);
|
||||||
assert_eq!(x.porta, 0b1010_1010);
|
assert_eq!(x.porta, 0b1010_1010);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn partial_output_portb() {
|
fn partial_output_portb() {
|
||||||
let mut x = Mos6522::new();
|
let mut x = Mos6522::new();
|
||||||
x.tick(0b0101_0101, VIA6522_DDRB, true);
|
x.tick(0b0101_0101, VIA6522_DDRB, false, true);
|
||||||
x.tick(0b1111_1111, VIA6522_ORB, true);
|
x.tick(0b1111_1111, VIA6522_ORB, false, true);
|
||||||
assert_eq!(x.portb, 0b0101_0101);
|
assert_eq!(x.portb, 0b0101_0101);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
7
core/src/periph/mos6522/new.rs
Normal file
7
core/src/periph/mos6522/new.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
use crate::periph::mos6522::mos6522::Mos6522;
|
||||||
|
|
||||||
|
impl Mos6522 {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Mos6522::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
86
core/src/periph/mos6522/tick.rs
Normal file
86
core/src/periph/mos6522/tick.rs
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
11
core/src/periph/mos6530/dump.rs
Normal file
11
core/src/periph/mos6530/dump.rs
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
4
core/src/periph/mos6530/mod.rs
Normal file
4
core/src/periph/mos6530/mod.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
pub mod mos6530;
|
||||||
|
pub mod tick;
|
||||||
|
mod new;
|
||||||
|
mod dump;
|
||||||
32
core/src/periph/mos6530/mos6530.rs
Normal file
32
core/src/periph/mos6530/mos6530.rs
Normal file
@ -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
|
||||||
|
}
|
||||||
25
core/src/periph/mos6530/new.rs
Normal file
25
core/src/periph/mos6530/new.rs
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
core/src/periph/mos6530/tick.rs
Normal file
26
core/src/periph/mos6530/tick.rs
Normal file
@ -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}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
resources/kim1/6530-002_fillerbyte00-0x1c00.bin
Normal file
BIN
resources/kim1/6530-002_fillerbyte00-0x1c00.bin
Normal file
Binary file not shown.
BIN
resources/kim1/6530-003_fillerbyte00-0x1800.bin
Normal file
BIN
resources/kim1/6530-003_fillerbyte00-0x1800.bin
Normal file
Binary file not shown.
@ -27,16 +27,16 @@
|
|||||||
ASL $abcd ; ASL Absolute
|
ASL $abcd ; ASL Absolute
|
||||||
ASL $abcd,X; ASL AbsoluteX
|
ASL $abcd,X; ASL AbsoluteX
|
||||||
|
|
||||||
BCC $ab ; BCC Immediate
|
BCC $71 ; BCC Immediate
|
||||||
BCS $ab ; BCS Immediate
|
BCS $71 ; BCS Immediate
|
||||||
BEQ $ab ; BEQ Immediate
|
BEQ $71 ; BEQ Immediate
|
||||||
|
|
||||||
BIT $ab ; BIT ZeroPage
|
BIT $ab ; BIT ZeroPage
|
||||||
BIT $abcd ; BIT Absolute
|
BIT $abcd ; BIT Absolute
|
||||||
|
|
||||||
BMI $ab ; BMI Immediate
|
BMI $7b ; BMI Immediate
|
||||||
BNE $ab ; BNI Immediate
|
BNE $7b ; BNI Immediate
|
||||||
BPL $ab ; BPL Immediate
|
BPL $7b ; BPL Immediate
|
||||||
|
|
||||||
BRK ; BRK
|
BRK ; BRK
|
||||||
|
|
||||||
@ -152,3 +152,38 @@
|
|||||||
|
|
||||||
RTI ; Interrupt Return
|
RTI ; Interrupt Return
|
||||||
RTS ; Subroutine Return
|
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
|
||||||
|
|||||||
8
resources/test/labels.asm
Normal file
8
resources/test/labels.asm
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
* = $4000
|
||||||
|
.fill start - *, $00
|
||||||
|
start:
|
||||||
|
LDA #$ab
|
||||||
|
ROR
|
||||||
|
LDX #$ba
|
||||||
|
TXA
|
||||||
|
JMP start
|
||||||
Loading…
x
Reference in New Issue
Block a user