Birdstrike (Hacking Tips #2)

By Mr. Spock

Originally published in EUG #71

Birdstrike - example of Firebird's custom tape loader. Disassembly of STRIKE1.

0E00 JMP &0E32 \continue execution at &E32

\Tape messages
\Offset Address Message
\ &03   &0E03   Searching
\ &0D   &0E0D   Loading
\ &15   &0E15   Data?
\ &1B   &0E1B   Block?
\ &22   &0E22   Reposition Tape

0E00 ** ** ** 53 65 61 72 63    Searc
0E08 68 69 6E 67 0D 4C 6F 61 hing.Loa
0E10 64 69 6E 67 0D 44 61 74 ding.Dat
0E18 61 3F 0D 42 6C 6F 63 6B a?.Block
0E20 3F 0D 52 65 70 6F 73 69 ?.Reposi
0E28 74 69 6F 6E 20 54 61 70 tion Tap
0E30 65 0D 20 2C 0F 20 01 0F e. ,. ..

0E32 JSR &0F2C \initialise
0E35 JSR &0F01 \print searching
0E38 LDA #&55  \decrypt byte
0E3A STA &5A
0E3C JSR &0ED6 \get bytes to match #&55
0E3F JSR &0F06 \print Loading
0E42 LDY #&00  \get bytes and store in &5A-&5F
0E44 JSR &0F53 \get byte from tape
0E47 JSR &0F74 \get one page
0E4A JSR &0ECB \get checksum
0E4D CMP &63
0E4F BEQ &0EA6 \ok - continue
0E51 JSR &0F0B \problem - print Data?
0E54 JMP &0E38 \try again

0E57 LDA #0
0E59 STA &65
0E5B CLI     \reenable interrupts
0E5C INC &5B   \increment block count
0E5E JSR &0ED6 \delay
0E61 JSR &0ECB \get byte
0E64 STA &5C   \number to print in &5A
0E66 JSR &0EBA \print digit
0E69 LDA &5C   \compare
0E6B CMP &5B   \with block count
0E6D BEQ &0E75 \ok - continue
0E6F JSR &0F16 \unexpected block no - print Block?
0E72 JMP &0E5E \jump back into loop to try a gain
0E75 JSR &0ECB \come here if match ok, get 
0E78 STA &5D   \address
0E7A JSR &0ECB \to store
0E7D STA &5E   \data at
0E7F LDY #0
0E81 STY &63
0E83 JSR &0ECB   \get byte
0E86 STA (&5D),Y \store in memory
0E88 EOR &63     \EOR with &63
0E8A STA &63     \check sum
0E8C INY 
0E8D BNE &0E83   \until done
0E8F JSR &0ECB   \get byte
0E92 TAX         \delay value
0E93 JSR &0ECB   \get byte
0E96 DEX         \short
0E97 BNE &0E93   \delay
0E99 JSR &0ECB   \get byte
0E9C CMP &63     \cf checksum
0E9E BEQ &0EA6   \ok so go to &EA6
0EA0 JSR &0F0B   \print Data?
0EA3 JMP &0E5E   \and try again
0EA6 SEI        \disable interrupts
0EA7 JSR &0ECB  \get address to 
0EAA STA &64    \jump to 
0EAC JSR &0ECB  \in
0EAF STA &65    \&64/&65
0EB1 JSR &0ECB  \get byte
0EB4 STA &F000  \dummy
0EB7 JMP (&0064) \jump to address in &64/&65

\print number in hex
0EBA LDA &5C  \get the number
0EBC AND #&0F \mask low nybble
0EBE ORA #&30 \+ASC"0"
0EC0 CMP #&3A \check for hex digit
0EC2 BCC &0EC7 
0EC4 CLC       \add
0EC5 ADC #&07  \extra 7 to get ASCII code
0EC7 JSR OSwrch \print it
0ECA RTS        \and return

0ECB LDA &FE00 \repeat get tape
0ECE AND #&10  \bits
0ED0 BEQ &0ECB \until one
0ED2 LDA &FE04 \byte received
0ED5 RTS 
0ED6 LDA #&10  \10 unit
0ED8 JSR &0EEE \Delay
0EDB JSR &0ECB \get byte from tape
0EDE CMP &5A   \cf value in &5A
0EE0 BNE &0ED6 \until match
0EE2 EOR #&FF  \reverse bits
0EE4 STA &64   \store
0EE6 JSR &0ECB \get tape byte
0EE9 CMP &64   \until match
0EEB BNE &0ED6 \
0EED RTS       \return

\delay routine
0EEE STA &64  \loop1
0EF0 STA &65  \loop2
0EF2 STA &66  \loop3
0EF4 DEC &66
0EF6 BNE &0EF4
0EF8 DEC &65
0EFA BNE &0EF2
0EFC DEC &64
0EFE BNE &0EEE
0F00 RTS 

0F01 LDX #&03  \Print
0F03 JMP &0F20 \Searching

0F06 LDX #&0D  \Print
0F08 JMP &0F20 \Loading

0F0B JSR OSnewl \new line
0F0E LDX #&15   \Print
0F10 JSR &0F20  \Data?
0F13 JMP &0F1E  \jump to print reposition tape

0F16 JSR OSnewl \new line
0F19 LDX #&1B   \Print Block?
0F1B JSR &0F20
0F1E LDX #&22    \Reposition tape
0F20 LDA &0E00,X \get char of message
0F23 JSR OSasci  \print it
0F26 INX         \until
0F27 CMP #&0D    \char is CR
0F29 BNE &0F20   \(&0D)
0F2B RTS 

\Initialisation routine called at &E32
0F2C LDA #50   \
0F2E JSR &0EEE \delay
0F31 SEI       \disable interrupts
0F32 LDA #0
0F34 STA &CA
0F36 STA &FE06 \cassette receive mode
0F39 LDA &0282 \ULA register 7
0F3C AND #&F9  \clear bits 1+2 for cassette receive
0F3E ORA #&40  \set bit 6 - cassette motor on
0F40 STA &0282 \RAM copy
0F43 STA &FE07 \SHEILA copy
0F46 LDA &025B
0F49 AND #&8F  \%10001111
0F4B STA &025B
0F4E STA &FE00
0F51 CLI       \reenable interrupts
0F52 RTS       \return from initialisation routine

0F53 JSR &0ECB   \get byte from tape
0F56 STA &005A,Y \store in zero page
0F59 INY         \until
0F5A CPY #&06    \filled &5A-&5F
0F5C BNE &0F53
0F5E PLA 
0F5F STA &64
0F61 PLA 
0F62 STA &60
0F64 PHA 
0F65 LDY #&00
0F67 STY &5B
0F69 STY &5C
0F6B STY &63
0F6D LDA &64
0F6F PHA 
0F70 JSR &0EBA
0F73 RTS 
0F74 JSR &0ECB  \get byte
0F77 PHA        \put original vale on stack
0F78 EOR &63    \EOR with ?&63
0F7A STA &63    \store at &63
0F7C PLA        \retrieve original value
0F7D EOR (&5F),Y \decode
0F7F STA (&5D),Y \and store in memory
0F81 INY         \until
0F82 BNE &0F74   \done 1 page
0F84 RTS 

\Apparently redundant data
0F80 ** ** ** ** 60 97 DD BC     `...
0F88 65 E2 24 23 FC 99 7B 32 e.$#..{2
0F90 70 87 04 10 A0 6C 92 B3 p....l..
0F98 C5 39 46 B1 DA 7D D0 A4 .9F..}..
0FA0 E5 AE C3 DB 35 04 96 D2 ....5...
0FA8 1D 0F 74 91 E7 C5 DC CA ..t.....
0FB0 EB 14 57 A7 EA 0F A9 4B ..W....K
0FB8 87 C6 AD 97 AD D4 10 41 .......A
0FC0 43 22 73 0A 30 27 56 33 C"s.0'V3
0FC8 39 13 A6 3A 18 22 69 4C 9..:."iL
0FD0 68 40 1D 18 E4 CB 7D A2 h@....}.
0FD8 7B A2 94 9F AF BF 72 36 {.....r6
0FE0 57 63 49 3A 6E 10 3C 43 WcI:n.<C
0FE8 D7 F3 6F 08 44 B6 B2 F6 ..o.D...
0FF0 E5 D8 4D 2B 41 87 84 46 ..M+A..F
0FF8 CF 76 9A D1 4A 5D D1 76 .v..J].v

Mr Spock 5 April 2004