Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8e2ca81489 | |||
| cad8d5eaa3 | |||
| 6fcf1547d1 | |||
| ff43a99e0c | |||
| b7e161ef0b | |||
| 258e4dc59b | |||
| a5042383c9 |
@@ -1,5 +0,0 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/mos6502.iml" filepath="$PROJECT_DIR$/.idea/mos6502.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="EMPTY_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/cli/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/core/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/macroquad/src" isTestSource="false" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -1 +1,3 @@
|
||||
/target
|
||||
*produced.asm
|
||||
*produced.bin
|
||||
|
||||
@@ -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 ]
|
||||
Generated
+241
-30
@@ -31,7 +31,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"once_cell 1.21.3",
|
||||
"version_check",
|
||||
"zerocopy",
|
||||
]
|
||||
@@ -119,6 +119,15 @@ dependencies = [
|
||||
"lewton",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78"
|
||||
dependencies = [
|
||||
"autocfg 1.5.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.0"
|
||||
@@ -229,9 +238,9 @@ checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.40"
|
||||
version = "4.5.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f"
|
||||
checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@@ -239,9 +248,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.40"
|
||||
version = "4.5.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e"
|
||||
checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -251,9 +260,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.40"
|
||||
version = "4.5.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce"
|
||||
checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
@@ -287,6 +296,15 @@ dependencies = [
|
||||
"error-code",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cloudabi"
|
||||
version = "0.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "color_quant"
|
||||
version = "1.1.0"
|
||||
@@ -327,14 +345,15 @@ name = "core"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"rand",
|
||||
"once_cell 0.1.8",
|
||||
"rand 0.9.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.4.2"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
|
||||
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
@@ -466,7 +485,7 @@ dependencies = [
|
||||
"emath",
|
||||
"epaint_default_fonts",
|
||||
"nohash-hasher",
|
||||
"parking_lot",
|
||||
"parking_lot 0.12.4",
|
||||
"profiling",
|
||||
]
|
||||
|
||||
@@ -539,6 +558,12 @@ dependencies = [
|
||||
"ttf-parser 0.21.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-cprng"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||
|
||||
[[package]]
|
||||
name = "gethostname"
|
||||
version = "0.4.3"
|
||||
@@ -649,7 +674,7 @@ version = "0.3.77"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"once_cell 1.21.3",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
@@ -692,14 +717,23 @@ version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
|
||||
dependencies = [
|
||||
"scopeguard 0.3.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
"autocfg 1.5.0",
|
||||
"scopeguard 1.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -761,9 +795,9 @@ checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
||||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
version = "0.9.5"
|
||||
version = "0.9.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f"
|
||||
checksum = "483758ad303d734cec05e5c12b41d7e93e6a6390c5e9dae6bdeb7c1259012d28"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
@@ -808,7 +842,7 @@ version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"autocfg 1.5.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -928,6 +962,15 @@ dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "532c29a261168a45ce28948f9537ddd7a5dd272cc513b3017b1e82a88f962c37"
|
||||
dependencies = [
|
||||
"parking_lot 0.7.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.3"
|
||||
@@ -949,14 +992,37 @@ dependencies = [
|
||||
"ttf-parser 0.25.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337"
|
||||
dependencies = [
|
||||
"lock_api 0.1.5",
|
||||
"parking_lot_core 0.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
"lock_api 0.4.13",
|
||||
"parking_lot_core 0.9.11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand 0.6.5",
|
||||
"rustc_version",
|
||||
"smallvec 0.6.14",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1007,7 +1073,7 @@ dependencies = [
|
||||
"concurrent-queue",
|
||||
"hermit-abi",
|
||||
"pin-project-lite",
|
||||
"rustix 1.0.7",
|
||||
"rustix 1.0.8",
|
||||
"tracing",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
@@ -1108,14 +1174,43 @@ version = "5.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
|
||||
dependencies = [
|
||||
"autocfg 0.1.8",
|
||||
"libc",
|
||||
"rand_chacha 0.1.1",
|
||||
"rand_core 0.4.2",
|
||||
"rand_hc",
|
||||
"rand_isaac",
|
||||
"rand_jitter",
|
||||
"rand_os",
|
||||
"rand_pcg",
|
||||
"rand_xorshift",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
|
||||
dependencies = [
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_chacha 0.9.0",
|
||||
"rand_core 0.9.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
|
||||
dependencies = [
|
||||
"autocfg 0.1.8",
|
||||
"rand_core 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1125,9 +1220,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
"rand_core 0.9.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
||||
dependencies = [
|
||||
"rand_core 0.4.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.9.3"
|
||||
@@ -1137,6 +1247,77 @@ dependencies = [
|
||||
"getrandom 0.3.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_isaac"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_jitter"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_core 0.4.2",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_os"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
|
||||
dependencies = [
|
||||
"cloudabi",
|
||||
"fuchsia-cprng",
|
||||
"libc",
|
||||
"rand_core 0.4.2",
|
||||
"rdrand",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_pcg"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
|
||||
dependencies = [
|
||||
"autocfg 0.1.8",
|
||||
"rand_core 0.4.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_xorshift"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rdrand"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.13"
|
||||
@@ -1175,6 +1356,15 @@ version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.44"
|
||||
@@ -1190,15 +1380,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.0.7"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
|
||||
checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
|
||||
dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.9.4",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1213,12 +1403,33 @@ version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
dependencies = [
|
||||
"semver-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
@@ -1313,8 +1524,8 @@ checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1"
|
||||
dependencies = [
|
||||
"fastrand",
|
||||
"getrandom 0.3.3",
|
||||
"once_cell",
|
||||
"rustix 1.0.7",
|
||||
"once_cell 1.21.3",
|
||||
"rustix 1.0.8",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
@@ -1425,7 +1636,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"once_cell 1.21.3",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
@@ -1567,7 +1778,7 @@ checksum = "dbcebb399c77d5aa9fa5db874806ee7b4eba4e73650948e8f93963f128896615"
|
||||
dependencies = [
|
||||
"dlib",
|
||||
"log",
|
||||
"once_cell",
|
||||
"once_cell 1.21.3",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -21,24 +21,34 @@ fn main() {
|
||||
// Fill with 0xea -> NOP
|
||||
let mut vec: [u8; SIZE_32KB] = [ISA_OP_NOP; SIZE_32KB];
|
||||
|
||||
// Load to A
|
||||
vec[0] = ISA_OP_LDA_I; // LDA #$ab
|
||||
vec[1] = 0b1010_1011; // 1010 1011
|
||||
// Jump to rotate cycle
|
||||
vec[2] = 0x02; // --
|
||||
vec[3] = 0x03; // --
|
||||
|
||||
// Jump to Main
|
||||
vec[0x2210] = ISA_OP_JMP_ABS;
|
||||
vec[0x2211] = 0x00;
|
||||
vec[0x2212] = 0x40;
|
||||
|
||||
// load to a
|
||||
vec[0x4000] = ISA_OP_LDA_I;
|
||||
vec[0x4001] = 0b0101_0100;
|
||||
// jump to top of load to a
|
||||
vec[0x4002] = ISA_OP_JMP_ABS;
|
||||
vec[0x4003] = 0x00;
|
||||
vec[0x4004] = 0x40;
|
||||
vec[0x4005] = ISA_OP_NOP;
|
||||
|
||||
vec[0x7ffa] = 0x22; // NMI Vector
|
||||
vec[0x7ffb] = 0x11;
|
||||
vec[0x7ffc] = 0x12; // Reset Vector
|
||||
vec[0x7ffd] = 0x34;
|
||||
vec[0x7ffe] = 0x43; // Interrupt Vector
|
||||
vec[0x7fff] = 0x21;
|
||||
|
||||
|
||||
vec = le_swap(&vec);
|
||||
|
||||
// write the rom to disk
|
||||
|
||||
@@ -8,6 +8,10 @@ fn main() {
|
||||
|
||||
let mut backplane = Backplane::new();
|
||||
|
||||
for i in 0..12 {
|
||||
backplane.tick();
|
||||
}
|
||||
|
||||
//backplane.load_rom();
|
||||
println!("Backplane is live.");
|
||||
|
||||
@@ -16,7 +20,7 @@ fn main() {
|
||||
new_program[(OFFSET_RESET_VECTOR + 1 - SIZE_32KB as u16) as usize] = 0x60;
|
||||
println!("Set offset in rom...");
|
||||
println!(
|
||||
"VALUE AT OFFSET_RESET_VECTOR = 0x{:02x} ",
|
||||
"VALUE AT OFFSET_RESET_VECTOR = 0x{:04x} ",
|
||||
new_program[(OFFSET_RESET_VECTOR - SIZE_32KB as u16) as usize]
|
||||
);
|
||||
// println!("{:?}", new_program);
|
||||
|
||||
@@ -19,7 +19,7 @@ pub struct Backplane {
|
||||
// pub for dev
|
||||
pub cpu: Mos6502Cpu,
|
||||
pub via: VIA6522,
|
||||
pub memory: Box<[u8; SIZE_32KB]>,
|
||||
pub memory: Box<[u8]>,
|
||||
pub rom: At28C256,
|
||||
data_bus: u8,
|
||||
address_bus: u16
|
||||
@@ -38,7 +38,7 @@ impl Backplane {
|
||||
}
|
||||
|
||||
pub fn load_rom(&mut self, to_load: &[u8; SIZE_32KB]) {
|
||||
self.rom.program(to_load);
|
||||
self.rom.program((*to_load).into());
|
||||
}
|
||||
|
||||
pub fn tick(&mut self) {
|
||||
|
||||
@@ -7,7 +7,7 @@ pub struct CpuDisplay {}
|
||||
impl CpuDisplay {
|
||||
pub fn render(cpu: &Mos6502Cpu, x_offset: f32, y_offset: f32) {
|
||||
// get the data to display...
|
||||
let (pc, a, x, y, address_bus, data_bus, microsteps_remaining, reset_vector, interrupt_vector) = cpu.dump_data();
|
||||
let (pc, a, x, y, address_bus, data_bus, microsteps_remaining, reset_vector, interrupt_vector, nmi_vector) = cpu.dump_data();
|
||||
|
||||
// ...build the interface
|
||||
Self::draw_square(x_offset, y_offset, x_offset + 300.0, y_offset + 85.0, BLACK);
|
||||
|
||||
@@ -201,6 +201,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_write_data() {
|
||||
let mut lcd = HD44780::new();
|
||||
lcd.set_data_bus(0x41); // 'A'
|
||||
|
||||
@@ -162,6 +162,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_timer1_write_and_tick() {
|
||||
let mut via = VIA6522::new();
|
||||
|
||||
@@ -180,6 +181,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_timer2_write_and_tick() {
|
||||
let mut via = VIA6522::new();
|
||||
via.t2_enabled = true;
|
||||
@@ -194,6 +196,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_interrupt_enable_disable() {
|
||||
let mut via = VIA6522::new();
|
||||
|
||||
@@ -205,6 +208,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_clear_interrupt_flags() {
|
||||
let mut via = VIA6522::new();
|
||||
via.ifr = 0xFF;
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
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;
|
||||
use std::path::PathBuf;
|
||||
use std::thread::current;
|
||||
use core::constants::constants_system::*;
|
||||
use core::constants::constants_isa_op::*;
|
||||
use clap::{Parser, Subcommand};
|
||||
use core::instruction_table::INSTRUCTION_TABLE;
|
||||
use std::io::Write;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(version, about, long_about = None)]
|
||||
struct CliOptions {
|
||||
/// File to Decompile
|
||||
input: PathBuf,
|
||||
/// File to write
|
||||
output: PathBuf,
|
||||
/// Verbose output
|
||||
#[arg(short, action = clap::ArgAction::Count)]
|
||||
verbose: u8
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DecompiledLine {
|
||||
offset: u16,
|
||||
text: String,
|
||||
label: Option<String>,
|
||||
bytes: Vec<u8>
|
||||
}
|
||||
|
||||
impl DecompiledLine {
|
||||
/// is_jump
|
||||
///
|
||||
/// Check if the current line is a type of a jump
|
||||
pub fn is_jump(&self) -> bool {
|
||||
self.bytes[0] == ISA_OP_JMP_ABS || self.bytes[0] == ISA_OP_JMP_IND
|
||||
}
|
||||
|
||||
/// is_branch
|
||||
///
|
||||
/// Check if the current line is a branch
|
||||
pub fn is_branch(&self) -> bool {
|
||||
self.bytes[0] == ISA_OP_BCC || self.bytes[0] == ISA_OP_BCS ||
|
||||
self.bytes[0] == ISA_OP_BEQ || self.bytes[0] == ISA_OP_BMI ||
|
||||
self.bytes[0] == ISA_OP_BNE || self.bytes[0] == ISA_OP_BPL ||
|
||||
self.bytes[0] == ISA_OP_BVS || self.bytes[0] == ISA_OP_BVC
|
||||
}
|
||||
}
|
||||
|
||||
/// WorkingProgram
|
||||
///
|
||||
/// Where we keep the program being decompiled
|
||||
struct WorkingProgram {
|
||||
data: [u8; SIZE_64KB],
|
||||
lines: Vec<DecompiledLine>
|
||||
}
|
||||
|
||||
impl WorkingProgram {
|
||||
|
||||
}
|
||||
|
||||
fn parse_to_decompiled_lines(data: &[u8]) -> HashMap<u16, DecompiledLine> {
|
||||
println!("PARSE GOT {}b", data.len());
|
||||
let mut current_data_position = 0;
|
||||
let mut lines: HashMap<u16, DecompiledLine> = 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 {
|
||||
// println!("Instruction {:?}/{:?} needs {:?} bytes.", top.operation, top.mode, top.length);
|
||||
|
||||
let num_bytes_to_load = top.length - 1;
|
||||
// println!("Need {num_bytes_to_load} more bytes.");
|
||||
let mut formatted_asm = String::from(top.format_prefix);
|
||||
let mut param = None;
|
||||
if num_bytes_to_load == 1 {
|
||||
bytes.push(data[current_data_position as usize + 1]);
|
||||
formatted_asm = format!("{}{:02x}{}", formatted_asm, bytes[1], top.format_postfix);
|
||||
};
|
||||
|
||||
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.
|
||||
param = Some(((bytes[2] as u16) << 8) | bytes[1] as u16);
|
||||
formatted_asm = format!("{}{:04x}{}", formatted_asm, param.unwrap(), top.format_postfix);
|
||||
};
|
||||
|
||||
// figure out how long the instruction is and read that much more data
|
||||
lines.insert(current_data_position, DecompiledLine {
|
||||
offset: current_data_position,
|
||||
text: String::from(formatted_asm),
|
||||
label: None,
|
||||
bytes,
|
||||
});
|
||||
|
||||
current_data_position = current_data_position + top.length as u16;
|
||||
} else {
|
||||
// invalid instruction
|
||||
println!("Byte sequence 0x{} invalid.", next_byte);
|
||||
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());
|
||||
|
||||
//let targets = vec![];
|
||||
|
||||
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<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.
|
||||
// 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
|
||||
|
||||
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() {
|
||||
let opts = CliOptions::parse();
|
||||
println!("Taxation is theft.");
|
||||
|
||||
// Load program to an array...
|
||||
let data = vec![
|
||||
0xa9, 0xab, 0x4c, 0x00, 0x40, 0xa9, 0x54, 0x4c, 0x00, 0x40,
|
||||
ISA_OP_TYA, ISA_OP_TXA, ISA_OP_TSX
|
||||
];
|
||||
|
||||
let loaded_data = fs::read(opts.input).unwrap();
|
||||
println!("Loaded {}b", loaded_data.len());
|
||||
// ...load the array to the WorkingProgram structure...
|
||||
let result = decompile(&loaded_data);
|
||||
let mut output_file = File::create(opts.output).unwrap();
|
||||
|
||||
// ...reap the decompiled code.
|
||||
for (_, line) in &result {
|
||||
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);
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
fn main() {
|
||||
println!("Taxation is theft.");
|
||||
println!("TODO:");
|
||||
println!(" Load specified binary and parse it out to ASM");
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
use std::fs;
|
||||
|
||||
fn main() {
|
||||
println!("Taxation is Theft");
|
||||
|
||||
// let opts = CliOptions::parse();
|
||||
let path = "/home/tmerritt/Projects/mos6502/resources/test/periph/at28c256/checksum.bin";
|
||||
let bytes = match fs::read(path) {
|
||||
Ok(bytes) => {
|
||||
println!("Read {} bytes.", bytes.len());
|
||||
bytes
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("FAIL to read rom.");
|
||||
panic!("No rom no run.");
|
||||
vec![]
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
+34
-5
@@ -1,5 +1,7 @@
|
||||
use std::fs;
|
||||
use clap::Parser;
|
||||
use core::computers::rom_only::backplane::Backplane;
|
||||
use core::computers::rom_only::backplane::RomOnlyComputer;
|
||||
use core::periph::backplane::Backplane;
|
||||
|
||||
#[derive(Parser)]
|
||||
struct CliOptions {
|
||||
@@ -11,8 +13,35 @@ struct CliOptions {
|
||||
fn main() {
|
||||
println!("Taxation is theft");
|
||||
|
||||
let opts = CliOptions::parse();
|
||||
// let opts = CliOptions::parse();
|
||||
let path = "/home/tmerritt/Projects/mos6502/resources/test/periph/at28c256/checksum.bin";
|
||||
let bytes = match fs::read(path) {
|
||||
Ok(bytes) => {
|
||||
println!("Read {} bytes.", bytes.len());
|
||||
bytes
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("FAIL to read rom.");
|
||||
panic!("No rom no run.");
|
||||
vec![]
|
||||
}
|
||||
};
|
||||
|
||||
let mut rom_only = Backplane::new();
|
||||
rom_only.tick()
|
||||
}
|
||||
let mut rom_only = RomOnlyComputer::program((&bytes[..]).to_vec());
|
||||
|
||||
rom_only.set_read_mode(true);
|
||||
rom_only.set_address_bus(0x05);
|
||||
rom_only.tick();
|
||||
|
||||
println!("COMPUTER: Read {:02x} from ROM", rom_only.data_bus()) ;
|
||||
println!("COMPUTER: Read {:04x} from Address Bus", rom_only.address_bus());
|
||||
|
||||
println!("----");
|
||||
rom_only.set_read_mode(true);
|
||||
rom_only.set_address_bus(0x07);
|
||||
rom_only.tick();
|
||||
|
||||
println!("COMPUTER: Read {:02x} from ROM", rom_only.data_bus()) ;
|
||||
println!("COMPUTER: Read {:04x} from Address Bus", rom_only.address_bus());
|
||||
println!("----");
|
||||
}
|
||||
|
||||
@@ -5,3 +5,4 @@ edition = "2024"
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
rand = "0.9.0"
|
||||
once_cell = "0.1"
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
use crate::mos6502cpu::cpu::Mos6502Cpu;
|
||||
use crate::periph::ram_chip::RamChip;
|
||||
|
||||
/// BackplaneBuilder
|
||||
///
|
||||
/// Builds a Backplane for a 6502 Emulated PC
|
||||
struct BackplaneBuilder {
|
||||
cpu: Mos6502Cpu,
|
||||
// ram_modules: Vec<dyn RamChip>
|
||||
}
|
||||
|
||||
impl BackplaneBuilder {
|
||||
pub fn add_cpu(mut self, new_cpu: Mos6502Cpu) -> Self {
|
||||
self.cpu = new_cpu;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_ram(mut self, new_ram: impl RamChip) -> Self {
|
||||
// self.ram_modules.push(new_ram);
|
||||
self
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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,4 @@
|
||||
pub mod beneater;
|
||||
pub mod rom_only;
|
||||
pub mod kim1;
|
||||
pub mod ram_rom;
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
use crate::periph::at28c256::At28C256;
|
||||
use crate::periph::backplane::Backplane;
|
||||
use crate::periph::hm62256::Hm62256;
|
||||
|
||||
pub struct RamRomComputer {
|
||||
rom: At28C256,
|
||||
ram: Hm62256,
|
||||
data_bus: u8,
|
||||
address_bus: u16,
|
||||
read_mode: bool,
|
||||
}
|
||||
|
||||
impl Backplane for RamRomComputer {
|
||||
fn data_bus(&self) -> u8 {
|
||||
self.data_bus
|
||||
}
|
||||
|
||||
fn address_bus(&self) -> u16 {
|
||||
self.address_bus
|
||||
}
|
||||
|
||||
fn read_mode(&self) -> bool {
|
||||
self.read_mode
|
||||
}
|
||||
|
||||
fn tick(&mut self) {
|
||||
todo!()
|
||||
}
|
||||
fn set_read_mode(&mut self, new_mode: bool) {
|
||||
self.read_mode = new_mode;
|
||||
}
|
||||
|
||||
fn set_address_bus(&mut self, new_value: u16) {
|
||||
self.address_bus = new_value;
|
||||
}
|
||||
|
||||
fn set_data_bus(&mut self, new_value: u8) {
|
||||
self.data_bus = new_value;
|
||||
}
|
||||
}
|
||||
|
||||
impl RamRomComputer {
|
||||
pub fn new() -> RamRomComputer {
|
||||
RamRomComputer {
|
||||
rom: At28C256::default(),
|
||||
ram: Hm62256::default(),
|
||||
data_bus: 0x00,
|
||||
address_bus: 0x0000,
|
||||
/// is the CPU reading from the 'other' device?
|
||||
read_mode: true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod backplane;
|
||||
@@ -1,29 +1,59 @@
|
||||
use crate::constants::constants_system::{SIZE_32KB, SIZE_64KB};
|
||||
use crate::periph::hm62256::Hm62256;
|
||||
use crate::periph::at28c256::At28C256;
|
||||
use crate::periph::backplane::Backplane;
|
||||
use crate::periph::rom_chip::RomChip;
|
||||
|
||||
pub struct Backplane {
|
||||
rom: Hm62256,
|
||||
pub struct RomOnlyComputer {
|
||||
rom: At28C256,
|
||||
data_bus: u8,
|
||||
address_bus: u16
|
||||
address_bus: u16,
|
||||
read_mode: bool,
|
||||
}
|
||||
|
||||
impl Backplane {
|
||||
pub fn new() -> Backplane {
|
||||
Backplane::program(&[0x00; SIZE_32KB])
|
||||
impl Backplane for RomOnlyComputer {
|
||||
fn data_bus(&self) -> u8 { self.data_bus }
|
||||
fn address_bus(&self) -> u16 { self.address_bus }
|
||||
fn read_mode(&self) -> bool { self.read_mode }
|
||||
|
||||
fn set_read_mode(&mut self, new_mode: bool) {
|
||||
self.read_mode = new_mode
|
||||
}
|
||||
|
||||
pub fn program(rom: &[u8; SIZE_32KB]) -> Backplane {
|
||||
Backplane {
|
||||
rom: *Hm62256::program(rom),
|
||||
|
||||
fn set_data_bus(&mut self, new_value: u8) {
|
||||
self.data_bus = new_value
|
||||
}
|
||||
|
||||
fn set_address_bus(&mut self, new_value: u16) {
|
||||
self.address_bus = new_value
|
||||
}
|
||||
|
||||
fn tick(&mut self) {
|
||||
println!("COMPUTER: Preparing to tick.");
|
||||
|
||||
// do are we being addressed?
|
||||
println!("COMPUTER: BUSSES PRE: 0x{:04x} 0x{:02x} {}", self.address_bus, self.data_bus, self.read_mode);
|
||||
let (new_addr, new_data) = self.rom.tick(self.address_bus, self.data_bus, self.read_mode);
|
||||
self.set_address_bus(new_addr);
|
||||
self.set_data_bus(new_data);
|
||||
println!("COMPUTER: BUSSES POST: 0x{:04x} 0x{:02x} {}", self.address_bus, self.data_bus, self.read_mode);
|
||||
println!("COMPUTER: Done ticking.");
|
||||
}
|
||||
}
|
||||
|
||||
impl RomOnlyComputer {
|
||||
pub fn new() -> RomOnlyComputer {
|
||||
let mut working = vec![0x00u8; SIZE_32KB];
|
||||
for index in 0..SIZE_32KB {
|
||||
working[index] = index as u8;
|
||||
}
|
||||
RomOnlyComputer::program(working)
|
||||
}
|
||||
|
||||
pub fn program(rom: Vec<u8>) -> RomOnlyComputer {
|
||||
RomOnlyComputer {
|
||||
rom: At28C256::new(0x000, 0x3fff, rom),
|
||||
address_bus: 0x0000,
|
||||
data_bus: 0x00
|
||||
data_bus: 0x00,
|
||||
read_mode: true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tick(&mut self) {
|
||||
println!("Preparing to tick.");
|
||||
|
||||
println!("Done ticking.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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_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;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
use std::borrow::ToOwned;
|
||||
use once_cell::unsync::Lazy;
|
||||
|
||||
pub const TEST_RESOURCES_ROOT: &str = "/home/tmerritt/Projects/resources/test";
|
||||
pub const TEST_PERIPH_ROOT: &str = "/home/tmerritt/Projects/resources/test/periph";
|
||||
pub const TEST_PERIPH_AT28C256_ROOT: &str = "/home/tmerritt/Projects/mos6502/resources/test/periph/at28c256";
|
||||
|
||||
@@ -2,3 +2,5 @@ pub mod constants_isa_op;
|
||||
pub mod constants_isa_stub;
|
||||
pub mod constants_system;
|
||||
pub mod constants_via6522;
|
||||
pub mod constants_mos6530;
|
||||
pub mod constants_test;
|
||||
|
||||
@@ -19,7 +19,7 @@ impl Instruction {
|
||||
pub fn opinfo(bytes: &[u8]) -> Option<OpInfo> {
|
||||
trace!("DECODING : {bytes:?}");
|
||||
let opcode = bytes.get(0).copied()?;
|
||||
Some(INSTRUCTION_TABLE[opcode as usize])?
|
||||
Some(INSTRUCTION_TABLE[opcode as usize].clone())?
|
||||
}
|
||||
|
||||
pub fn decode(bytes: &[u8]) -> Option<Instruction> {
|
||||
@@ -245,7 +245,7 @@ mod test {
|
||||
vec![0x10, 0xab],
|
||||
Instruction {
|
||||
op: BPL,
|
||||
mode: Implied,
|
||||
mode: Immediate,
|
||||
operand: Operand::Byte(0xab),
|
||||
},
|
||||
),
|
||||
@@ -253,7 +253,7 @@ mod test {
|
||||
vec![0x30, 0xab],
|
||||
Instruction {
|
||||
op: BMI,
|
||||
mode: Implied,
|
||||
mode: Immediate,
|
||||
operand: Operand::Byte(0xab),
|
||||
},
|
||||
),
|
||||
@@ -261,7 +261,7 @@ mod test {
|
||||
vec![0x50, 0xab],
|
||||
Instruction {
|
||||
op: BVC,
|
||||
mode: Implied,
|
||||
mode: Immediate,
|
||||
operand: Operand::Byte(0xab),
|
||||
},
|
||||
),
|
||||
@@ -269,7 +269,7 @@ mod test {
|
||||
vec![0x70, 0xab],
|
||||
Instruction {
|
||||
op: BVS,
|
||||
mode: Implied,
|
||||
mode: Immediate,
|
||||
operand: Operand::Byte(0xab),
|
||||
},
|
||||
),
|
||||
@@ -277,7 +277,7 @@ mod test {
|
||||
vec![0x90, 0xab],
|
||||
Instruction {
|
||||
op: BCC,
|
||||
mode: Implied,
|
||||
mode: Immediate,
|
||||
operand: Operand::Byte(0xab),
|
||||
},
|
||||
),
|
||||
@@ -285,7 +285,7 @@ mod test {
|
||||
vec![0xb0, 0xab],
|
||||
Instruction {
|
||||
op: BCS,
|
||||
mode: Implied,
|
||||
mode: Immediate,
|
||||
operand: Operand::Byte(0xab),
|
||||
},
|
||||
),
|
||||
@@ -293,7 +293,7 @@ mod test {
|
||||
vec![0xd0, 0xab],
|
||||
Instruction {
|
||||
op: BNE,
|
||||
mode: Implied,
|
||||
mode: Immediate,
|
||||
operand: Operand::Byte(0xab),
|
||||
},
|
||||
),
|
||||
@@ -301,7 +301,7 @@ mod test {
|
||||
vec![0xf0, 0xab],
|
||||
Instruction {
|
||||
op: BEQ,
|
||||
mode: Implied,
|
||||
mode: Immediate,
|
||||
operand: Operand::Byte(0xab),
|
||||
},
|
||||
),
|
||||
|
||||
+341
-11
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,5 @@
|
||||
#![feature(slice_as_array)]
|
||||
|
||||
pub mod computers;
|
||||
pub mod address_mode;
|
||||
pub mod constants;
|
||||
@@ -9,3 +11,4 @@ pub mod op_info;
|
||||
pub mod operand;
|
||||
pub mod operation;
|
||||
pub mod periph;
|
||||
mod backplane;
|
||||
|
||||
@@ -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 {
|
||||
@@ -67,14 +71,16 @@ impl Default for Mos6502Cpu {
|
||||
mode: AddressMode::Implied,
|
||||
operand: Operand::None,
|
||||
},
|
||||
oi: INSTRUCTION_TABLE[ISA_OP_NOP as usize].unwrap(),
|
||||
oi: INSTRUCTION_TABLE[ISA_OP_NOP as usize].clone().unwrap(),
|
||||
has_reset: false,
|
||||
iv: 0xfffe,
|
||||
cycle_carry: 0x0000,
|
||||
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;
|
||||
@@ -478,7 +526,7 @@ impl Mos6502Cpu {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
@@ -489,6 +537,12 @@ mod test {
|
||||
fn clc() {
|
||||
// setup the CPU for our test
|
||||
let mut cpu = Mos6502Cpu::default();
|
||||
|
||||
// tick through the reset cycle
|
||||
while !cpu.has_reset {
|
||||
cpu.tick();
|
||||
}
|
||||
println!("DONE RESET TICKS");
|
||||
cpu.flags.set_flag(Carry);
|
||||
// Load our 'test program'
|
||||
cpu.memory[0x6000] = ISA_OP_CLC;
|
||||
@@ -715,3 +769,4 @@ mod test {
|
||||
assert_eq!(cpu.memory[0xab], 0b1010_1010);;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -13,14 +13,12 @@ impl Mos6502Cpu {
|
||||
working
|
||||
}
|
||||
|
||||
|
||||
pub(crate) fn reset_cpu(&mut self) {
|
||||
self.microcode_step = 7 + 4;
|
||||
self.microcode_step = 7 + 6;
|
||||
// self = &mut Mos6502Cpu::default();
|
||||
println!("Should tick 7 times, then 4 cycles to read the reset and int vectors.");
|
||||
println!("Should tick 7 times, then 6 cycles to read the reset and int vectors.");
|
||||
// read the value at 0xfffa 0xfffb for our NMI vector.
|
||||
// read the value at 0xfffc 0xfffd for our reset vector.
|
||||
// read the value at 0xfffe 0xffff for our int vector
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
+5
-2
@@ -1,7 +1,7 @@
|
||||
use crate::address_mode::AddressMode;
|
||||
use crate::operation::Operation;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OpInfo {
|
||||
/// What is the operation
|
||||
pub operation: Operation,
|
||||
@@ -11,4 +11,7 @@ pub struct OpInfo {
|
||||
pub length: u8,
|
||||
/// CPU Cycles to complete the instruction
|
||||
pub cycles: u8,
|
||||
}
|
||||
/// Format string for disassembly
|
||||
pub format_prefix: &'static str,
|
||||
pub format_postfix: &'static str
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
use crate::constants::constants_system::SIZE_32KB;
|
||||
use crate::periph::at28c256::At28C256;
|
||||
use crate::constants::constants_test::*;
|
||||
|
||||
impl At28C256 {
|
||||
/// checksum
|
||||
///
|
||||
/// calculates and returns the checksum for the loaded binary.
|
||||
/// files with all zero will calculate to zero
|
||||
pub fn checksum(&self) -> u8 {
|
||||
At28C256::checksum_static(&self.data[..])
|
||||
}
|
||||
|
||||
pub fn checksum_static(data: &[u8]) -> u8 {
|
||||
data.iter().fold(0u8, |acc, &b| acc.wrapping_add(b))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use crate::constants::constants_system::SIZE_1KB;
|
||||
use crate::periph::rom_chip::RomChip;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn smoke() { assert!(true); }
|
||||
|
||||
#[test]
|
||||
fn programmed_data_reads_back_same() {
|
||||
let mut data = At28C256::default();
|
||||
for i in 0..SIZE_32KB {
|
||||
data.data[i] = 0xeau8;
|
||||
}
|
||||
for offset in 0..SIZE_32KB {
|
||||
if offset.is_multiple_of(SIZE_1KB) {};
|
||||
assert_eq!(0xea, data.read(&(offset as u16)));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn checksums_calculate_correctly_for_zero() {
|
||||
let data1 = [0x00u8; SIZE_32KB];
|
||||
assert_eq!(0x00, At28C256::checksum_static(&data1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn checksums_calculate_for_1_byte() {
|
||||
let data = [0xff; 1];
|
||||
assert_eq!(0xff, At28C256::checksum_static(&data));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn checksums_calculate_for_2_bytes() {
|
||||
let data = [0xff; 2];
|
||||
// 0xff + 0xff = 0x1fe
|
||||
assert_eq!(0xfe, At28C256::checksum_static(&data));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn checksums_calculate_for_first_80_bytes() {
|
||||
println!("STARTING TEST");
|
||||
let mut checksum = 0x00;
|
||||
|
||||
let path = format!("{}{}", TEST_PERIPH_AT28C256_ROOT, "/checksum.bin");
|
||||
println!("READING [{path}]");
|
||||
let data = fs::read(path);
|
||||
match data {
|
||||
Ok(bytes) => {
|
||||
println!("Read {} bytes", bytes.len());
|
||||
checksum = At28C256::checksum_static(&bytes);
|
||||
println!("Checksum: 0x{:02x}", checksum);
|
||||
}
|
||||
Err(e) => eprintln!("Failed to read file: {}", e),
|
||||
}
|
||||
assert_eq!(0x58, checksum);
|
||||
println!("TEST COMPLETE");
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,13 @@ 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,
|
||||
max_offset: 0x3fff,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,8 @@ pub mod rom_chip;
|
||||
pub mod tick;
|
||||
mod new;
|
||||
mod program;
|
||||
mod dump;
|
||||
mod checksum;
|
||||
|
||||
use crate::constants::constants_system::SIZE_32KB;
|
||||
use crate::periph::rom_chip::RomChip;
|
||||
@@ -10,33 +12,15 @@ use std::io::Read;
|
||||
|
||||
/// At28C256
|
||||
///
|
||||
/// Represents a single At28C256 Chip
|
||||
/// Represents a single At28C256 EEPROM Chip
|
||||
///
|
||||
/// 256kbit storage
|
||||
/// 32kbyte storage
|
||||
pub struct At28C256 {
|
||||
data: Box<[u8; SIZE_32KB]>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::constants::constants_system::SIZE_1KB;
|
||||
|
||||
#[test]
|
||||
fn smoke() {
|
||||
assert!(true)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn programmed_data_reads_back_same() {
|
||||
let mut data = At28C256::default();
|
||||
for i in 0..SIZE_32KB {
|
||||
data.data[i] = 0xea;
|
||||
}
|
||||
for offset in 0..SIZE_32KB {
|
||||
if offset.is_multiple_of(SIZE_1KB) {};
|
||||
assert_eq!(0xea, data.read(&(offset as u16)));
|
||||
}
|
||||
}
|
||||
data_bus: u8,
|
||||
address_bus: u16,
|
||||
data: Box<[u8]>,
|
||||
// where in the computer memory map do we live?
|
||||
offset: u16,
|
||||
max_offset: u16
|
||||
}
|
||||
|
||||
@@ -2,9 +2,15 @@ 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, max_offset: u16, data: Vec<u8>) -> Self {
|
||||
println!("NEW At28C256 with checksum ${:02x}", At28C256::checksum_static(&data[..]));
|
||||
|
||||
At28C256 {
|
||||
data: (*data).into()
|
||||
data: data.into_boxed_slice(),
|
||||
address_bus: 0x0000,
|
||||
data_bus: 0x00,
|
||||
offset,
|
||||
max_offset
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,29 @@ use crate::constants::constants_system::SIZE_32KB;
|
||||
use crate::periph::at28c256::At28C256;
|
||||
|
||||
impl At28C256 {
|
||||
pub fn program(&mut self, new_program: &[u8; SIZE_32KB]) {
|
||||
pub fn program(&mut self, new_program: Box<[u8]>) {
|
||||
// panic!("FAIL. Cant program the chip.");
|
||||
// println!("PROGRAMMING {:?}", new_program);
|
||||
self.data = Box::new(*new_program);
|
||||
self.data = new_program;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::periph::rom_chip::RomChip;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn smoke() { assert!(true) }
|
||||
|
||||
#[test]
|
||||
fn programming_chip_changes_contents() {
|
||||
let mut chip = At28C256::new(0x0000, 0x3fff, vec![]);
|
||||
|
||||
assert_eq!(0x00, chip.read(&0x0000));
|
||||
|
||||
let new_data: Vec<u8> = vec![0xff, 0xff, 0xff, 0xff];
|
||||
chip.program(new_data.into());
|
||||
assert_eq!(0xff, chip.read(&0x0000));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,30 @@ use crate::periph::at28c256::At28C256;
|
||||
use crate::periph::rom_chip::RomChip;
|
||||
|
||||
impl RomChip for At28C256 {
|
||||
/// read
|
||||
///
|
||||
/// Reads a byte from memory.
|
||||
/// Returns a 0x00 if there is no data at that location but is still in ROM address range
|
||||
fn read(&self, offset: &u16) -> u8 {
|
||||
self.data[*offset as usize]
|
||||
println!("STARTING READ FROM At28C256 ${:04x} | ${:04x} | ${:04x}", self.offset, offset, self.max_offset);
|
||||
if offset < &self.offset || offset > &self.max_offset {
|
||||
println!("Unable to read from ${offset:04x} as it it out of range.");
|
||||
return 0x00;
|
||||
} else {
|
||||
println!("OK READ FROM GOOD AREA total len = {}", self.data.len());
|
||||
}
|
||||
|
||||
if *offset >= self.data.len() as u16 {
|
||||
0x00
|
||||
} else {
|
||||
self.data[*offset as usize]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// program
|
||||
///
|
||||
/// Writes new data to the memory chip
|
||||
fn program(new_data: &[u8; SIZE_32KB]) -> Box<At28C256> {
|
||||
println!("Writing new chip.");
|
||||
let mut working = At28C256::default();
|
||||
|
||||
@@ -1,33 +1,68 @@
|
||||
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.
|
||||
fn talking_to_me(&self, address: u16) -> bool {
|
||||
address >= self.offset && address < self.max_offset
|
||||
}
|
||||
|
||||
pub fn tick(&mut self, address_bus: u16, data_bus: u8, read_mode: bool) -> (u16, u8) {
|
||||
println!("At28C256: Tick starting for A${address_bus:04x} D${data_bus:02x} R{read_mode}");
|
||||
|
||||
// we aren't being addressed
|
||||
// OR
|
||||
// we arent reading from the ROM...
|
||||
if !self.talking_to_me(address_bus) ||
|
||||
!read_mode {
|
||||
// ...go away.
|
||||
return (address_bus, data_bus)
|
||||
}
|
||||
(address_bus, self.data[address_bus as usize])
|
||||
|
||||
let effective = address_bus - self.offset;
|
||||
if effective < self.max_offset {
|
||||
if effective < self.data.len() as u16 {
|
||||
self.data_bus = self.data[effective as usize];
|
||||
} else {
|
||||
self.data_bus = 0x00;
|
||||
}
|
||||
} else {
|
||||
println!("At28C256: OUTSIDE RANGE. :(");
|
||||
return (address_bus, data_bus)
|
||||
}
|
||||
|
||||
println!("At28C256: Read... {:02x}", self.data_bus);
|
||||
println!("At28C256: Done with ticking the AtC256");
|
||||
(address_bus, self.data_bus)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::fs;
|
||||
use crate::periph::rom_chip::RomChip;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn smoke() { assert!(true); }
|
||||
|
||||
#[test]
|
||||
fn write_to_memory_read_back_works_at_0() {
|
||||
let mut rom = At28C256::default();
|
||||
fn checksum_binary_loads() {
|
||||
let path = "/home/tmerritt/Projects/mos6502/resources/test/periph/at28c256/checksum.bin";
|
||||
let bytes = match fs::read(path) {
|
||||
Ok(bytes) => {
|
||||
println!("Read {} bytes.", bytes.len());
|
||||
bytes
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("FAIL to read rom.");
|
||||
panic!("No rom no run.");
|
||||
vec![]
|
||||
}
|
||||
};
|
||||
|
||||
rom.tick(0x0000, 0xab, false);
|
||||
let (_, new_data) = rom.tick(0x0000, 0x00, true);
|
||||
let mut rom = At28C256::new(0x0000, 0x3fff, bytes);
|
||||
|
||||
assert_eq!(new_data, 0xab);
|
||||
assert_eq!(rom.checksum(), 0x58);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
pub trait Backplane {
|
||||
fn data_bus(&self) -> u8;
|
||||
fn address_bus(&self) -> u16;
|
||||
fn read_mode(&self) -> bool;
|
||||
fn set_read_mode(&mut self, new_mode: bool);
|
||||
fn set_data_bus(&mut self, new_value: u8);
|
||||
fn set_address_bus(&mut self, new_value: u16);
|
||||
fn tick(&mut self);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
pub trait BusDevice {
|
||||
fn talking_to_me(&self, address: u16) -> bool;
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 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)]
|
||||
|
||||
@@ -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;
|
||||
|
||||
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) {
|
||||
println!("HM62256RAM TICK START -> 0x{address_bus:04x} 0x{data_bus:02x} {read_mode} {cs}");
|
||||
if !(address_bus >= self.offset && address_bus < self.max_address()) {
|
||||
return (address_bus, data_bus);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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,9 @@
|
||||
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;
|
||||
pub mod backplane;
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
pub mod mos6522;
|
||||
mod registers;
|
||||
mod registers;
|
||||
mod new;
|
||||
mod tick;
|
||||
@@ -5,104 +5,49 @@ 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 max_offset(&self) -> u16 {
|
||||
self.offset + 0x10
|
||||
}
|
||||
|
||||
pub fn start_clocks(&mut self) {
|
||||
@@ -115,7 +60,6 @@ impl Mos6522 {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
@@ -126,40 +70,40 @@ mod test {
|
||||
#[test]
|
||||
fn registers() {
|
||||
let mut x = Mos6522::new();
|
||||
x.tick(0b0000_0000, VIA6522_DDRA, true);
|
||||
x.tick(VIA6522_DDRA as u16, 0b0000_0000, false, true);
|
||||
assert_eq!(x.dda, 0b0000_0000);
|
||||
x.tick(0b1111_1111, VIA6522_DDRA, true);
|
||||
x.tick(VIA6522_DDRA as u16, 0b1111_1111, false, true);
|
||||
assert_eq!(x.dda, 0b1111_1111);
|
||||
|
||||
x.tick(0b0000_0000, VIA6522_DDRB, true);
|
||||
x.tick(VIA6522_DDRB as u16, 0b0000_0000, false, true);
|
||||
assert_eq!(x.ddb, 0b0000_0000);
|
||||
x.tick(0b1111_1111, VIA6522_DDRB, true);
|
||||
x.tick(VIA6522_DDRB as u16, 0b1111_1111, false, true);
|
||||
assert_eq!(x.ddb, 0b1111_1111);
|
||||
|
||||
x.tick(0b0000_0000, VIA6522_ORA, true);
|
||||
assert_eq!(x.porta, 0b0000_0000);
|
||||
x.tick(0b1111_1111, VIA6522_ORA, true);
|
||||
assert_eq!(x.porta, 0b1111_1111);
|
||||
x.tick(VIA6522_ORA as u16, 0b0000_0000, false, true);
|
||||
assert_eq!(x.ora, 0b0000_0000);
|
||||
x.tick(VIA6522_ORA as u16, 0b1111_1111, false, true);
|
||||
assert_eq!(x.ora, 0b1111_1111);
|
||||
|
||||
x.tick(0b0000_0000, VIA6522_ORB, true);
|
||||
assert_eq!(x.portb, 0b0000_0000);
|
||||
x.tick(0b1111_1111, VIA6522_ORB, true);
|
||||
assert_eq!(x.portb, 0b1111_1111);
|
||||
x.tick(VIA6522_ORB as u16, 0b0000_0000, false, true);
|
||||
assert_eq!(x.orb, 0b0000_0000);
|
||||
x.tick(VIA6522_ORB as u16, 0b1111_1111, false, true);
|
||||
assert_eq!(x.orb, 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(VIA6522_DDRA as u16, 0b1010_1010, false, true);
|
||||
x.tick(VIA6522_ORA as u16,0b1111_1111, 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(VIA6522_DDRB as u16, 0b0101_0101, false, true);
|
||||
x.tick(VIA6522_ORB as u16, 0b1111_1111, false, true);
|
||||
assert_eq!(x.portb, 0b0101_0101);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
use crate::periph::mos6522::mos6522::Mos6522;
|
||||
|
||||
impl Mos6522 {
|
||||
pub fn new() -> Self {
|
||||
Mos6522::default()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
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 >= 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} / 0b{local_address:08b})");
|
||||
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 => {
|
||||
println!("Setting DDA to 0x{data_bus:02x}");
|
||||
// setting the Data Direction for Port A
|
||||
self.dda = data_bus;
|
||||
},
|
||||
VIA6522_ORB => {
|
||||
// writing data to ORB
|
||||
let masked_data = data_bus & self.ddb;
|
||||
println!("Setting ORB to 0x{data_bus:02x} / masked at 0x{masked_data:02x}");
|
||||
self.orb = data_bus;
|
||||
self.portb = masked_data;
|
||||
},
|
||||
VIA6522_DDRB => {
|
||||
println!("Setting DDB to 0x{data_bus:02x}");
|
||||
// setting the data direction for port b
|
||||
self.ddb = data_bus;
|
||||
},
|
||||
|
||||
VIA6522_ORA => {
|
||||
// writing data to ORA
|
||||
let masked_data = data_bus & self.dda;
|
||||
println!("Setting ORA to 0x{data_bus:02x} / masked at 0x{masked_data:02x}");
|
||||
self.ora = data_bus;
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
pub mod mos6530;
|
||||
pub mod tick;
|
||||
mod new;
|
||||
mod dump;
|
||||
@@ -0,0 +1,31 @@
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
use core::periph::backplane::Backplane;
|
||||
use core::computers::rom_only::backplane::RomOnlyComputer;
|
||||
use egui_macroquad::egui::TextBuffer;
|
||||
use macroquad::prelude::*;
|
||||
|
||||
struct UIState {
|
||||
address: u16,
|
||||
data: u8,
|
||||
new_address_input: String,
|
||||
new_data_input: String,
|
||||
}
|
||||
|
||||
#[macroquad::main("Tick Interface")]
|
||||
async fn main() {
|
||||
let mut ui = UIState {
|
||||
address: 0x1234,
|
||||
data: 0xAB,
|
||||
new_address_input: String::new(),
|
||||
new_data_input: String::new(),
|
||||
};
|
||||
|
||||
let rom_program = vec![0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07];
|
||||
|
||||
let mut rom_only_pc = RomOnlyComputer::program(rom_program);
|
||||
|
||||
loop {
|
||||
clear_background(BLACK);
|
||||
|
||||
// Labels
|
||||
draw_text("Address:", 20.0, 40.0, 30.0, WHITE);
|
||||
draw_text(&format!("0x{:04X}", ui.address), 150.0, 40.0, 30.0, YELLOW);
|
||||
|
||||
draw_text("Data:", 20.0, 80.0, 30.0, WHITE);
|
||||
draw_text(&format!("0x{:02X}", ui.data), 150.0, 80.0, 30.0, YELLOW);
|
||||
|
||||
// Input: New Address
|
||||
draw_text("New Address:", 20.0, 140.0, 25.0, WHITE);
|
||||
ui.new_address_input = draw_textbox(&ui.new_address_input, 200.0, 120.0, 150.0);
|
||||
|
||||
// Input: New Data
|
||||
draw_text("New Data:", 20.0, 190.0, 25.0, WHITE);
|
||||
ui.new_data_input = draw_textbox(&ui.new_data_input, 200.0, 170.0, 150.0);
|
||||
|
||||
// Tick Button
|
||||
if is_mouse_button_pressed(MouseButton::Left) {
|
||||
let (mx, my) = mouse_position();
|
||||
if mx >= 20.0 && mx <= 120.0 && my >= 220.0 && my <= 260.0 {
|
||||
if let Ok(addr) = u16::from_str_radix(&ui.new_address_input.trim_start_matches("0x"), 16) {
|
||||
rom_only_pc.set_address_bus(addr);
|
||||
}
|
||||
if let Ok(dat) = u8::from_str_radix(&ui.new_data_input.trim_start_matches("0x"), 16) {
|
||||
rom_only_pc.set_data_bus(dat);
|
||||
}
|
||||
println!("Tick: addr=0x{:04X} data=0x{:02X}", ui.address, ui.data);
|
||||
rom_only_pc.tick();
|
||||
}
|
||||
}
|
||||
|
||||
// Draw button
|
||||
draw_rectangle(20.0, 220.0, 100.0, 40.0, DARKGRAY);
|
||||
draw_text("Tick", 40.0, 250.0, 30.0, WHITE);
|
||||
|
||||
ui.address = rom_only_pc.address_bus();
|
||||
ui.data = rom_only_pc.data_bus();
|
||||
|
||||
next_frame().await;
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_textbox(input: &str, x: f32, y: f32, width: f32) -> String {
|
||||
let mut new_input = input.to_string();
|
||||
|
||||
draw_rectangle_lines(x - 5.0, y - 5.0, width + 10.0, 40.0, 2.0, WHITE);
|
||||
draw_text(input, x, y + 25.0, 30.0, WHITE);
|
||||
|
||||
if is_mouse_button_pressed(MouseButton::Left) {
|
||||
let (mx, my) = mouse_position();
|
||||
if mx >= x && mx <= x + width && my >= y && my <= y + 40.0 {
|
||||
new_input = String::new(); // reset input on click
|
||||
}
|
||||
}
|
||||
|
||||
for c in get_char_pressed() {
|
||||
if c == '\u{8}' {
|
||||
new_input.pop(); // backspace
|
||||
} else if c.is_ascii_hexdigit() {
|
||||
new_input.push(c.to_ascii_uppercase());
|
||||
}
|
||||
}
|
||||
|
||||
new_input
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
To Build
|
||||
|
||||
64tass -a -b -o <your_bin> <your_asm>
|
||||
@@ -0,0 +1,26 @@
|
||||
* = $A000
|
||||
.fill Reset - *, $ea
|
||||
Reset:
|
||||
SEI
|
||||
CLD
|
||||
LDX #$FF
|
||||
TXS
|
||||
; Drop to the start of our main loop
|
||||
MainLoop:
|
||||
LDA #$AA
|
||||
ROR
|
||||
JMP MainLoop
|
||||
|
||||
; What to do when we get a NMI
|
||||
NMI:
|
||||
RTI
|
||||
|
||||
; What do we get when we get an interrupt
|
||||
IRQ:
|
||||
RTI
|
||||
|
||||
; setup the requirements for the CPU
|
||||
* = $FFF8
|
||||
.word NMI
|
||||
.word Reset
|
||||
.word IRQ
|
||||
@@ -0,0 +1,22 @@
|
||||
* = $0000
|
||||
.fill Reset - *, $ea
|
||||
|
||||
Reset:
|
||||
SEI
|
||||
CLD
|
||||
LDX #$FF
|
||||
TXS
|
||||
|
||||
MainLoop:
|
||||
NOP
|
||||
JMP MainLoop
|
||||
|
||||
NMI:
|
||||
RTI
|
||||
IRQ:
|
||||
RTI
|
||||
|
||||
* = $FFF8
|
||||
.word NMI
|
||||
.word RESET
|
||||
.word IRQ
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,189 @@
|
||||
; Test of instructions for the decompiler
|
||||
;
|
||||
; This file is intended to be assembled and then
|
||||
; used as an input to a test that decompiles the
|
||||
; binary back to the text version of the instructions
|
||||
ADC #$ab ; ADC Immediate
|
||||
ADC $ab ; ADC ZeroPage
|
||||
ADC $ab,X ; ADC ZeroPageX
|
||||
ADC $abcd ; ADC Absolute
|
||||
ADC $abcd,X; ADC AbsoluteX
|
||||
ADC $abcd,Y; ADC AbsoluteY
|
||||
ADC ($ab,X); ADC IndirectX
|
||||
ADC ($ab),Y; ADC IndirectY
|
||||
|
||||
AND #$ab ; AND Immediate
|
||||
AND $ab ; AND ZeroPage
|
||||
AND $ab,X ; AND ZeroPageX
|
||||
AND $abcd ; AND Absolute
|
||||
AND $abcd,X; AND AbsoluteX
|
||||
AND $abcd,Y; AND AbsoluteY
|
||||
AND ($ab,X); AND IndirectX
|
||||
AND ($ab),Y; AND IndirectY
|
||||
|
||||
ASL ; ASL Accumulator
|
||||
ASL $ab ; ASL ZeroPage
|
||||
ASL $ab,X ; ASL ZeroPageX
|
||||
ASL $abcd ; ASL Absolute
|
||||
ASL $abcd,X; ASL AbsoluteX
|
||||
|
||||
BCC $71 ; BCC Immediate
|
||||
BCS $71 ; BCS Immediate
|
||||
BEQ $71 ; BEQ Immediate
|
||||
|
||||
BIT $ab ; BIT ZeroPage
|
||||
BIT $abcd ; BIT Absolute
|
||||
|
||||
BMI $7b ; BMI Immediate
|
||||
BNE $7b ; BNI Immediate
|
||||
BPL $7b ; BPL Immediate
|
||||
|
||||
BRK ; BRK
|
||||
|
||||
BVC $ab ; BVC Immediate
|
||||
BVS $ab ; BVS Immediate
|
||||
|
||||
CLC ; CLC
|
||||
CLD ; CLD
|
||||
CLI ; CLI
|
||||
CLV ; CLV
|
||||
|
||||
CMP #$ab ; CMP Immediate
|
||||
CMP $ab ; CMP ZeroPage
|
||||
CMP $ab,X ; CMP ZeroPageX
|
||||
CMP $abcd ; CMP Absolute
|
||||
CMP $abcd,X; CMP AbsoluteX
|
||||
CMP $abcd,Y; CMP AbsoluteY
|
||||
CMP ($ab,X); CMP IndirectX
|
||||
CMP ($ab),Y; CMP IndirectY
|
||||
|
||||
CPX #$ab ; CPX Immediate
|
||||
CPX $ab ; CPX ZeroPage
|
||||
CPX $abcd ; CPX Absolute
|
||||
|
||||
CPY #$ab ; CPY Immediate
|
||||
CPY $ab ; CPY ZeroPage
|
||||
CPY $abcd ; CPY Absolute
|
||||
|
||||
DEC $ab ; DEC ZeroPage
|
||||
DEC $ab,X ; DEC ZeroPageX
|
||||
DEC $abcd ; DEC Absolute
|
||||
DEC $abcd,X; DEC AbsoluteX
|
||||
|
||||
DEX ; DEX
|
||||
DEY ; DEY
|
||||
|
||||
EOR #$ab ; EOR Immediate
|
||||
EOR $ab ; EOR ZeroPage
|
||||
EOR $ab,X ; EOR ZeroPageX
|
||||
EOR $abcd ; EOR Absolute
|
||||
EOR $abcd,X; EOR AbsoluteX
|
||||
EOR $abcd,Y; EOR AbsoluteY
|
||||
EOR ($ab,X); EOR IndirectX
|
||||
EOR ($ab),Y; EOR IndirectY
|
||||
|
||||
INC $ab ; INC ZeroPage
|
||||
INC $ab,X ; INC ZeroPage,X
|
||||
INC $abcd ; INC Absolute
|
||||
INC $abcd,X; INC AbsoluteX
|
||||
|
||||
INX ; INX
|
||||
INY ; INY
|
||||
|
||||
JMP $abcd ; JMP Absolute
|
||||
JMP ($abcd); JMP Indirect
|
||||
|
||||
JSR $abcd ; JSR Absolute
|
||||
|
||||
LDA #$ab ; LDA Immediate
|
||||
LDA $ab ; LDA ZeroPage
|
||||
LDA $ab,X ; LDA ZeroPageX
|
||||
LDA $abcd ; LDA Absolute
|
||||
LDA $abcd,X; LDA AbsoluteX
|
||||
LDA $abcd,Y; LDA AbsoluteY
|
||||
LDA ($ab,X); LDA IndirectX
|
||||
LDA ($ab),Y; LDA IndirectY
|
||||
|
||||
LDX #$ab ; LDX Immediate
|
||||
LDX $ab ; LDX ZeroPage
|
||||
LDX $ab,Y ; LDX ZeroPageY
|
||||
LDX $abcd ; LDX Absolute
|
||||
LDX $abcd,Y; LDX AbsoluteY
|
||||
|
||||
LDY #$ab ; LDY Immediate
|
||||
LDY $ab ; LDY ZeroPage
|
||||
LDY $ab,X ; LDY ZeroPageX
|
||||
LDY $abcd ; LDY Absolute
|
||||
LDY $abcd,X; LDY AbsoluteX
|
||||
|
||||
LSR ; LSR Accumulator
|
||||
LSR $ab ; LSR ZeroPage
|
||||
LSR $ab,X ; LSR ZeroPageX
|
||||
LSR $abcd ; LSR Absolute
|
||||
LSR $abcd,X; LSR AbsoluteX
|
||||
|
||||
NOP ; The great and powerful NOP
|
||||
|
||||
ORA #$ab ; ORA Immediate
|
||||
ORA $ab ; ORA ZeroPage
|
||||
ORA $ab,X ; ORA ZeroPageX
|
||||
ORA $abcd ; ORA Absolute
|
||||
ORA $abcd,X; ORA AbsoluteX
|
||||
ORA $abcd,Y; ORA AbsoluteY
|
||||
ORA ($ab,X); ORA IndirectX
|
||||
ORA ($ab),Y; ORA IndirectY
|
||||
|
||||
PHA ; PHA
|
||||
PHP ; PHP
|
||||
PLA ; PLA
|
||||
PLP ; PLP
|
||||
|
||||
ROL ; ROL Accumulator
|
||||
ROL $ab ; ROL ZeroPage
|
||||
ROL $ab,X ; ROL ZeroPageX
|
||||
ROL $abcd ; ROL Absolute
|
||||
ROL $abcd,X; ROL AbsoluteX
|
||||
|
||||
ROR ; ROR Accumulator
|
||||
ROR $ab ; ROR ZeroPage
|
||||
ROR $ab,X ; ROR ZeroPageX
|
||||
ROR $abcd ; ROR Absolute
|
||||
ROR $abcd,X; ROR AbsoluteX
|
||||
|
||||
RTI ; Interrupt 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
|
||||
@@ -0,0 +1,8 @@
|
||||
* = $4000
|
||||
.fill start - *, $00
|
||||
start:
|
||||
LDA #$ab
|
||||
ROR
|
||||
LDX #$ba
|
||||
TXA
|
||||
JMP start
|
||||
Binary file not shown.
Reference in New Issue
Block a user