Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
process_command:
; Read decoder index 0x11: HIFSTS (host interface status)
2d50: ae 11 ldx $0x11
2d52: bf 04 stx 0x4
2d54: cd 40 f2 jsr 0x40f2 ; read_from_decoder
; Update value in *0xb5
2d57: b7 b5 sta 0xb5
; Test the 3 host IRQ bits. If they're not 0, return.
;
; We refuse to process a new command if the host hasn't ack'd pending IRQs
2d59: a4 07 and $0x7
2d5b: 26 f2 bne 0x2d4f
; Read decoder index 0x13: HSTCMD (host command)
2d5d: ae 13 ldx $0x13
2d5f: bf 04 stx 0x4
2d61: cd 40 f2 jsr 0x40f2 ; read_from_decoder
; Store command to *0x1e0
2d64: c7 01 e0 sta 0x1e0
; if command == 0 (Sync?) { f_3a1e }
2d67: 27 36 beq 0x2d9f
; if command == 0x1c (Reset) { f_3bc6; reset }
2d69: a1 1c cmp $0x1c
2d6b: 26 06 bne 0x2d73
2d6d: cd 3b c6 jsr 0x3bc6
2d70: cc 10 00 jmp 0x1000 ; reset
; if command == 0x17 (SetClock ?) { f_3a1e }
2d73: a1 17 cmp $0x17
2d75: 27 28 beq 0x2d9f
; if command == 0x18 (GetClock ?) { f_3a1e }
2d77: a1 18 cmp $0x18
2d79: 27 24 beq 0x2d9f
; if command >= 0x1f { f_3a1e }
2d7b: a1 1f cmp $0x1f
2d7d: 24 20 bcc 0x2d9f
; *0x8b = 0
; This is the counter for the number of parameters received
2d7f: a6 00 lda $0x0
2d81: b7 8b sta 0x8b
_param_read_loop:
; Read decoder index 0x11: HIFSTS (host interface status)
2d83: ae 11 ldx $0x11
2d85: bf 04 stx 0x4
2d87: cd 40 f2 jsr 0x40f2 ; read_from_decoder
; Update value in *0xb5
2d8a: b7 b5 sta 0xb5
; if decoder parameter FIFO empty { goto _no_param }
2d8c: 09 b5 13 brclr.4 0xb5,0x2da2
2d8f: ae 12 ldx $0x12
2d91: bf 04 stx 0x4
2d93: cd 40 f2 jsr 0x40f2 ; read_from_decoder
2d96: be 8b ldx 0x8b
2d98: d7 01 e1 sta %X,0x1e1
2d9b: 3c 8b inc 0x8b
2d9d: 20 e4 bra 0x2d83 ; _param_read_loop
2d9f: cc 3a 1e jmp 0x3a1e ; bad command?
_no_param:
; *0x88 = *0x8b
2da2: b6 8b lda 0x8b
2da4: b7 88 sta 0x88
; Reload command in X and decrement it
2da6: ce 01 e0 ldx 0x1e0
2da9: 5a decx
; Reload command in A
2daa: c6 01 e0 lda 0x1e0
; If command == 0x19 (test) { goto skip_param_check }
2dad: a1 19 cmp $0x19
2daf: 27 0b beq 0x2dbc
; If command == 0x3 (Play) { goto handle_play }
;
; Play has an optional parameter, so we don't validate the param count
2db1: a1 03 cmp $0x3
2db3: 27 1f beq 0x2dd4
; Compare the expected param count for this command with the number of
; parameters received (in *0x88). If it's different, goto _bad_param_count
2db5: d6 2e 01 lda %X,0x2e01
2db8: b1 88 cmp 0x88
2dba: 26 1e bne 0x2dda
_skip_param_check:
; Read mystery_command_table entry for this command and store it in *0x20c
2dbc: d6 2d e3 lda %X,0x2de3
2dbf: c7 02 0c sta 0x20c
; A = (command * 3) - 3 (offset in command handler tables)
2dc2: c6 01 e0 lda 0x1e0
2dc5: 48 asla
2dc6: cb 01 e0 add 0x1e0
2dc9: a0 03 sub $0x3
; Jump to the command_pre_handler_table entry for this command
2dcb: 97 tax
2dcc: dd 2e 1f jsr %X,0x2e1f
; If the pre-handler returned an error { goto _pre_handler_failed }
2dcf: 25 0d bcs 0x2dde ; _pre_handler_failed
; Everything okay, jump to the main command handler
2dd1: dc 2e 79 jmp %X,0x2e79
_handle_play:
2dd4: b6 88 lda 0x88
2dd6: a1 02 cmp $0x2
2dd8: 25 e2 bcs 0x2dbc
_bad_param_count:
2dda: a6 05 lda $0x5
2ddc: 20 02 bra 0x2de0
_pre_handler_failed
2dde: a6 07 lda $0x7
2de0: cc 3c 0c jmp 0x3c0c
mystery_command_table:
2de3:
.byte 00 ; 0x01 Getstat
.byte 00 ; 0x02 Setloc
.byte 00 ; 0x03 not used (should be Play)
.byte 00 ; 0x04 Forward
.byte 00 ; 0x05 Backward
.byte 00 ; 0x06 ReadN
.byte 01 ; 0x07 MotorOn
.byte 02 ; 0x08 Stop
.byte 01 ; 0x09 Pause
.byte 01 ; 0x0a Init
.byte 00 ; 0x0b Mute
.byte 00 ; 0x0c Demute
.byte 02 ; 0x0d Setfiler
.byte 01 ; 0x0e Setmode
.byte 00 ; 0x0f GetParam
.byte 00 ; 0x10 GetlocL
.byte 00 ; 0x11 GetlocP
.byte 03 ; 0x12 SetSession
.byte 00 ; 0x13 GetTN
.byte 01 ; 0x14 GetTD
.byte 04 ; 0x15 SeekL
.byte 05 ; 0x16 SeekP
.byte 00 ; 0x17 not used
.byte 00 ; 0x18 not used
.byte 00 ; 0x19 Test
.byte 00 ; 0x1a GetID
.byte 00 ; 0x1b ReadS
.byte 07 ; 0x1c not used (should be Reset)
.byte 01 ; 0x1d GetQ
; ReadTOC is missing from this table so it's read from the first entry of
; command_param_count instead. Clever optimization or lucky bug, you decide.
;; Table of the number of parameters expected for each command. Indexed by
;; `command - 1`
command_param_count:
2e01:
.byte 00 ; 0x01 Getstat
.byte 03 ; 0x02 Setloc
.byte 00 ; 0x03 not used (should be Play)
.byte 00 ; 0x04 Forward
.byte 00 ; 0x05 Backward
.byte 00 ; 0x06 ReadN
.byte 00 ; 0x07 MotorOn
.byte 00 ; 0x08 Stop
.byte 00 ; 0x09 Pause
.byte 00 ; 0x0a Init
.byte 00 ; 0x0b Mute
.byte 00 ; 0x0c Demute
.byte 02 ; 0x0d Setfiler
.byte 01 ; 0x0e Setmode
.byte 00 ; 0x0f GetParam
.byte 00 ; 0x10 GetlocL
.byte 00 ; 0x11 GetlocP
.byte 01 ; 0x12 SetSession
.byte 00 ; 0x13 GetTN
.byte 01 ; 0x14 GetTD
.byte 00 ; 0x15 SeekL
.byte 00 ; 0x16 SeekP
.byte 07 ; 0x17 not used
.byte 00 ; 0x18 not used
.byte 00 ; 0x19 not used (should be Test)
.byte 00 ; 0x1a GetID
.byte 00 ; 0x1b ReadS
.byte 00 ; 0x1c not used (should be Reset)
.byte 02 ; 0x1d GetQ
.byte 00 ; 0x1e ReadTOC
.byte 00 ; ??? Maybe they really messed up above for ReadTOC and offset the
; table by 1
;; Pre-command handler that does some basic sanity check and prevents the main
;; handler from running if something is wrong. Should preserve A.
command_pre_handler_table:
2e1f: cc 2f 12 jmp 0x2f12 ; always_ok
2e22: cc 2e eb jmp 0x2eeb
2e25: cc 2e eb jmp 0x2eeb
2e28: cc 2e d3 jmp 0x2ed3
2e2b: cc 2e d3 jmp 0x2ed3
2e2e: cc 2e eb jmp 0x2eeb
2e31: cc 2f 0f jmp 0x2f0f
2e34: cc 2f 0f jmp 0x2f0f
2e37: cc 2f 0f jmp 0x2f0f
2e3a: cc 2f 12 jmp 0x2f12
2e3d: cc 2e eb jmp 0x2eeb
2e40: cc 2e eb jmp 0x2eeb
2e43: cc 2f 0f jmp 0x2f0f
2e46: cc 2f 12 jmp 0x2f12
2e49: cc 2f 12 jmp 0x2f12
2e4c: cc 2e dd jmp 0x2edd
2e4f: cc 2e d3 jmp 0x2ed3
2e52: cc 2e fd jmp 0x2efd
2e55: cc 2f 0f jmp 0x2f0f
2e58: cc 2f 0f jmp 0x2f0f
2e5b: cc 2e eb jmp 0x2eeb
2e5e: cc 2e eb jmp 0x2eeb
2e61: cc 2f 0d jmp 0x2f0d
2e64: cc 2f 0d jmp 0x2f0d
2e67: cc 2f 12 jmp 0x2f12
2e6a: cc 2f 12 jmp 0x2f12
2e6d: cc 2e eb jmp 0x2eeb
2e70: cc 2f 12 jmp 0x2f12
2e73: cc 2e d3 jmp 0x2ed3
2e76: cc 2f 12 jmp 0x2f12
command_handler_table:
2e79: cc 2f 14 jmp 0x2f14 ; handle_get_stat
2e7c: cc 2f 1d jmp 0x2f1d
2e7f: cc 2f 6c jmp 0x2f6c
2e82: cc 2f f3 jmp 0x2ff3
2e85: cc 30 17 jmp 0x3017
2e88: cc 30 3b jmp 0x303b
2e8b: cc 30 9c jmp 0x309c
2e8e: cc 30 bd jmp 0x30bd
2e91: cc 30 ea jmp 0x30ea
2e94: cc 31 14 jmp 0x3114
2e97: cc 31 5f jmp 0x315f
2e9a: cc 31 76 jmp 0x3176
2e9d: cc 31 86 jmp 0x3186
2ea0: cc 31 9c jmp 0x319c
2ea3: cc 31 a4 jmp 0x31a4
2ea6: cc 32 36 jmp 0x3236
2ea9: cc 32 01 jmp 0x3201
2eac: cc 32 61 jmp 0x3261
2eaf: cc 32 96 jmp 0x3296
2eb2: cc 32 cf jmp 0x32cf
2eb5: cc 33 50 jmp 0x3350
2eb8: cc 33 25 jmp 0x3325
2ebb: cc 33 81 jmp 0x3381
2ebe: cc 33 81 jmp 0x3381
2ec1: cc 33 82 jmp 0x3382
2ec4: cc 39 79 jmp 0x3979
2ec7: cc 30 48 jmp 0x3048
2eca: cc 39 99 jmp 0x3999
2ecd: cc 39 9f jmp 0x399f
2ed0: cc 39 bc jmp 0x39bc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment