[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
MLB Crack: The RWTS
On Thursday, October 18, 2012 6:56:07 PM UTC-5, Hot Rod wrote:
> Hi,
>
> I'm going to be adding a series of posts here describing my most recent retro computing project - a crack of the Micro League Baseball Box Score/Stat Compiler disk.
>
>
>
> ]HR
The RWTS (well, RTS at least)
Having gone through the basic boot, program load and start, and the disk format, I needed to understand the RWTS in order to use it for converting the sectors to regular format, but I now also knew I needed to use it to get a sector mapping of the disk; the load table only provided the starting sector and buffer, but not a length.
So next I studied the RWTS. It wasn’t very large, and I soon realized it really only handled reading (so more accurately, it’s an RTS routine I suppose). I created an annotated listing of it, which I’ll just plop in here and leave it at that.
0900- 20 B0 0A JSR $0AB0 ;check if reached T/S limits
0903- B0 45 BCS $094A ;if either limit reached, then branch to err_display
0905- A4 22 LDY $22 ;drive num
0907- B9 23 00 LDA $0023,Y ;get track of drive
090A- 8D F8 0B STA $0BF8 ;store into current track
090D- A9 EF LDA #$EF ;odd - $B6A repeats this as first ops anyway
090F- 85 29 STA $29
0911- A9 D8 LDA #$D8
0913- 85 2A STA $2A
0915- 20 6A 0B JSR $0B6A ;seek to desired track
0918- A4 22 LDY $22 ;drive num
091A- A5 2C LDA $2C ;get desired track
091C- 99 23 00 STA $0023,Y ;store as current track (seek worked, so there now)
091F- A9 04 LDA #$04 ;retry count
0921- 8D BC 09 STA $09BC ;store retry count
0924- 20 BE 09 JSR $09BE ;read
0927- 90 08 BCC $0931 ;no err, continue
0929- CE BC 09 DEC $09BC ;decrement retry count
092C- D0 F6 BNE $0924 ;if not exhausted, retry
092E- 4C 4A 09 JMP $094A ;all retries exhausted, fail
0931- C6 3A DEC $3A ;how many bytes there were in sector to read
0933- 38 SEC
0934- A5 34 LDA $34 ;buff add_lo
0936- 65 3A ADC $3A ;add how many bytes read
0938- 85 34 STA $34 ;new buff add_lo
093A- 90 02 BCC $093E ;if didn't cross page, branch
093C- E6 35 INC $35 ;increment buff add_hi
093E- A5 30 LDA $30 ;next track (from nibble encoding)
0940- 85 2C STA $2C ;store track
0942- A5 32 LDA $32 ;next sector (from nibble encoding)
0944- 85 2E STA $2E ;store sector - if <#$80, then done
0946- 30 B8 BMI $0900 ;not done, continue
0948- 18 CLC ;clear carry, all good
0949- 60 RTS ;return
094A- A6 20 LDX $20 ;start of error message display routine
094C- BD 88 C0 LDA $C088,X ;turn off drive
094F- AD BD 09 LDA $09BD ;will be set to error code from failed routine (1, 2, 3 or 4)
0952- 20 8F 09 JSR $098F ;convert value in A-reg to two-char ASCII
0955- 8D B3 09 STA $09B3 ;save hi-nibb char
0958- 8E B4 09 STX $09B4 ;save lo-nibb char
095B- A5 2C LDA $2C ;load track num (in half tracks)
095D- 20 8F 09 JSR $098F ;convert to ASCII
0960- 8D B6 09 STA $09B6 ;save hi-nibb
0963- 8E B7 09 STX $09B7 ;save lo-nibb
0966- A5 2E LDA $2E ;load sector num
0968- 20 8F 09 JSR $098F ;convert to ASCII
096B- 8D B9 09 STA $09B9 ;save hi-nibb
096E- 8E BA 09 STX $09BA ;save lo-nibb
0971- A9 AA LDA #$AA
0973- 85 34 STA $34 ;store address_lo of error text
0975- A9 09 LDA #$09
0977- 85 35 STA $35 ;store address_hi of error text ($9AA)
0979- A0 11 LDY #$11 ;length of error text
097B- B1 34 LDA ($34),Y ;load char of error text
097D- 99 8A 04 STA $048A,Y ;display on text screen
0980- 88 DEY
0981- 10 F8 BPL $097B ;repeat until whole error text stored
0983- AD 54 C0 LDA $C054 ;display page1
0986- AD 51 C0 LDA $C051 ;display text
0989- 20 4B 0B JSR $0B4B ;beep routine (sounds just like the reset beep)
098C- 4C 8C 09 JMP $098C ;hang (end of error message display)
098F- 48 PHA ;routine to convert A-reg to two-char ASCII
0990- 29 0F AND #$0F
0992- 20 9F 09 JSR $099F
0995- AA TAX
0996- 68 PLA
0997- 4A LSR
0998- 4A LSR
0999- 4A LSR
099A- 4A LSR
099B- 20 9F 09 JSR $099F
099E- 60 RTS
099F- C9 0A CMP #$0A
09A1- B0 03 BCS $09A6
09A3- 69 B0 ADC #$B0
09A5- 60 RTS
09A6- 18 CLC
09A7- 69 B7 ADC #$B7
09A9- 60 RTS ;end of convert routine
09AA- A0 C5 LDY #$C5 ;start of error text
09AC- D2 ???
09AD- D2 ???
09AE- CF ???
09AF- D2 ???
09B0- A0 A3 LDY #$A3
09B2- A0 00 LDY #$00
09B4- 00 BRK
09B5- AD 00 00 LDA $0000
09B8- AD 00 00 LDA $0000
09BB- A0 ;end of error text
09BC- 00 ;retry count
09BD- 00 BRK ;error code
09BE- 20 F5 0A JSR $0AF5 ;read address field and desired sector 4+4 encoded (ED AD F5 xx xx)
09C1- 90 03 BCC $09C6 ;success, branch
09C3- 4C AE 0A JMP $0AAE ;jump to set carry and return
09C6- EA NOP
09C7- 4C CA 09 JMP $09CA
09CA- BD 8C C0 LDA $C08C,X ;now look for data field (ED AD F5 again)
09CD- 10 FB BPL $09CA
09CF- C9 ED CMP #$ED
09D1- D0 F3 BNE $09C6 ;interesting possible infinite loop here if markers not found...
09D3- EA NOP
09D4- B5 00 LDA $00,X
09D6- B5 00 LDA $00,X
09D8- BD 8C C0 LDA $C08C,X
09DB- 10 FB BPL $09D8
09DD- C9 AD CMP #$AD
09DF- D0 EE BNE $09CF
09E1- B5 00 LDA $00,X
09E3- B5 00 LDA $00,X
09E5- EA NOP
09E6- BD 8C C0 LDA $C08C,X
09E9- 10 FB BPL $09E6
09EB- C9 F5 CMP #$F5
09ED- D0 E0 BNE $09CF
09EF- EA NOP ;have data field markers, now read TRACK, SECTOR, BYTE COUNT, CHECKSUM
09F0- B5 00 LDA $00,X
09F2- B5 00 LDA $00,X
09F4- A9 00 LDA #$00 ;init checksum
09F6- 85 3C STA $3C ;store checksum var
09F8- BD 8C C0 LDA $C08C,X
09FB- 10 FB BPL $09F8
09FD- 2A ROL ;decode 4+4 hi
09FE- 85 3E STA $3E ;save in scratch
0A00- BD 8C C0 LDA $C08C,X
0A03- 10 FB BPL $0A00
0A05- 25 3E AND $3E ;decode 4+4 lo
0A07- 85 30 STA $30 ;store TRACK num (this should be "next" track to read)
0A09- 45 3C EOR $3C ;update checksum
0A0B- 85 3C STA $3C ;store checksum update
0A0D- EA NOP
0A0E- C5 3C CMP $3C
0A10- 38 SEC
0A11- BD 8C C0 LDA $C08C,X
0A14- 10 FB BPL $0A11
0A16- 2A ROL ;decode 4+4 hi
0A17- 85 3E STA $3E ;save in scratch
0A19- BD 8C C0 LDA $C08C,X
0A1C- 10 FB BPL $0A19
0A1E- 25 3E AND $3E ;decode 4+4 lo
0A20- 85 32 STA $32 ;store SECTOR num (this should be "next" sector to read, or 0 if no next)
0A22- EA NOP
0A23- 45 3C EOR $3C ;update checksum
0A25- 85 3C STA $3C ;store checksum update
0A27- C5 3C CMP $3C
0A29- 38 SEC
0A2A- BD 8C C0 LDA $C08C,X
0A2D- 10 FB BPL $0A2A
0A2F- 2A ROL ;decode 4+4 hi
0A30- 85 3E STA $3E ;save in scratch
0A32- BD 8C C0 LDA $C08C,X
0A35- 10 FB BPL $0A32
0A37- 25 3E AND $3E ;decode 4+4 lo
0A39- 85 3A STA $3A ;store BYTE COUNT
0A3B- EA NOP
0A3C- 45 3C EOR $3C ;update checksum
0A3E- 85 3C STA $3C ;store checksum update
0A40- C5 3C CMP $3C
0A42- 38 SEC
0A43- BD 8C C0 LDA $C08C,X
0A46- 10 FB BPL $0A43
0A48- 2A ROL ;decode 4+4 hi
0A49- 85 3E STA $3E ;save in scratch
0A4B- BD 8C C0 LDA $C08C,X
0A4E- 10 FB BPL $0A4B
0A50- 25 3E AND $3E ;decode 4+4 lo
0A52- 45 3C EOR $3C ;update checksum
0A54- F0 0A BEQ $0A60 ;if checksum is correct, then will be zero and branch
0A56- 85 3C STA $3C ;checksum is not correct
0A58- A9 03 LDA #$03 ;error code 3
0A5A- 8D BD 09 STA $09BD ;store error code
0A5D- 4C AE 0A JMP $0AAE ;jump to error exit
0A60- EA NOP
0A61- A0 00 LDY #$00 ;now are going to read the data field, decode 4+4 and store in buffer
0A63- 84 3C STY $3C ;init data checksum
0A65- C5 3C CMP $3C
0A67- BD 8C C0 LDA $C08C,X
0A6A- 10 FB BPL $0A67
0A6C- 38 SEC
0A6D- 2A ROL
0A6E- 85 3E STA $3E
0A70- 85 3E STA $3E
0A72- EA NOP
0A73- BD 8C C0 LDA $C08C,X
0A76- 10 FB BPL $0A73
0A78- 25 3E AND $3E ;byte is now 4+4 decoded
0A7A- 91 34 STA ($34),Y ;store it in buffer
0A7C- 45 3C EOR $3C ;update checksum
0A7E- 85 3C STA $3C ;store checksum update
0A80- C8 INY ;increment bytes read
0A81- C4 3A CPY $3A ;compare to number of bytes in sector to read
0A83- D0 E0 BNE $0A65 ;more bytes to read so keep going
0A85- EA NOP ;have read all the bytes, so get checksum
0A86- 38 SEC
0A87- BD 8C C0 LDA $C08C,X
0A8A- 10 FB BPL $0A87
0A8C- 2A ROL
0A8D- 85 3E STA $3E
0A8F- BD 8C C0 LDA $C08C,X
0A92- 10 FB BPL $0A8F
0A94- 25 3E AND $3E
0A96- 45 3C EOR $3C ;update checksum
0A98- 85 3C STA $3C ;store checksum update
0A9A- 98 TYA ;transfer count of bytes read
0A9B- D0 06 BNE $0AA3 ;if not 256 bytes, then branch
0A9D- A5 3C LDA $3C ;load checksum
0A9F- D0 06 BNE $0AA7 ;should be zero if read 256 bytes
0AA1- 18 CLC ;checksum good, indicate success
0AA2- 60 RTS ;return (end of read data)
0AA3- C8 INY ;need to pad reads to 256
0AA4- 4C 87 0A JMP $0A87 ;loop until read 256 bytes, but don't store these in read buffer
0AA7- 85 3C STA $3C ;store checksum (shouldn't be needed; just read it from here)
0AA9- A9 04 LDA #$04 ;error code 4
0AAB- 8D BD 09 STA $09BD ;store error code
0AAE- 38 SEC ;indicate error
0AAF- 60 RTS ;return
0AB0- 38 SEC ;start routine to check sector and track limits
0AB1- A5 2E LDA $2E ;load sector number ($80-$89, hi-bit is set)
0AB3- 10 10 BPL $0AC5 ;err if hi-bit not set
0AB5- C9 8A CMP #$8A ;
0AB7- B0 0C BCS $0AC5 ;err if beyond tenth sector (only have ten with 4+4 encoding)
0AB9- 85 32 STA $32 ;store sector num
0ABB- A5 2C LDA $2C ;load track number (half tracks)
0ABD- C9 46 CMP #$46 ;compare to max half tracks
0ABF- B0 04 BCS $0AC5 ;err if beyond max half tracks ($22 tracks, $44 half tracks
0AC1- 85 30 STA $30 ;store half track num
0AC3- 18 CLC ;no err, so clear carry
0AC4- 60 RTS ;end of limit check
0AC5- A9 01 LDA #$01 ;err #1 indicates this routine check
0AC7- 8D BD 09 STA $09BD ;store in error code
0ACA- 60 RTS
0ACB- A6 20 LDX $20 ;begin enable drive read routine (get slot num)
0ACD- BD 8A C0 LDA $C08A,X ;engage drive 1
0AD0- A5 22 LDA $22 ;drive number
0AD2- C9 01 CMP #$01 ;drive 1?
0AD4- F0 03 BEQ $0AD9 ;if yes, skip drive 2
0AD6- BD 8B C0 LDA $C08B,X ;engage drive 2
0AD9- BD 89 C0 LDA $C089,X ;turn on drive
0ADC- BD 8E C0 LDA $C08E,X ;prepare latch for input
0ADF- A9 C8 LDA #$C8 ;spin-up delay
0AE1- 20 E5 0A JSR $0AE5 ;delay
0AE4- 60 RTS ;return (end enable drive read routine)
0AE5- A0 00 LDY #$00 ;begin delay
0AE7- 38 SEC
0AE8- D0 00 BNE $0AEA
0AEA- 20 F4 0A JSR $0AF4
0AED- 88 DEY
0AEE- D0 F8 BNE $0AE8
0AF0- E9 01 SBC #$01
0AF2- D0 F4 BNE $0AE8
0AF4- 60 RTS ;end of delay
0AF5- A6 20 LDX $20 ;begin read address field (get slot num)
0AF7- A0 00 LDY #$00
0AF9- 84 3C STY $3C
0AFB- C8 INY
0AFC- D0 04 BNE $0B02
0AFE- E6 3C INC $3C
0B00- F0 42 BEQ $0B44 ;pretty generous retry count- 255*255
0B02- BD 8C C0 LDA $C08C,X ;looking for address marker of ED AD F5
0B05- 10 FB BPL $0B02 ;otherwise fairly staightforward
0B07- C9 ED CMP #$ED
0B09- D0 F0 BNE $0AFB
0B0B- EA NOP
0B0C- B5 00 LDA $00,X
0B0E- B5 00 LDA $00,X
0B10- BD 8C C0 LDA $C08C,X
0B13- 10 FB BPL $0B10
0B15- C9 AD CMP #$AD
0B17- D0 EE BNE $0B07
0B19- B5 00 LDA $00,X
0B1B- B5 00 LDA $00,X
0B1D- A0 03 LDY #$03 ;while it loads Y like it will be reading a Vol/T/S/Chksum, it only looks for sector
0B1F- BD 8C C0 LDA $C08C,X
0B22- 10 FB BPL $0B1F
0B24- C9 F5 CMP #$F5
0B26- D0 DF BNE $0B07
0B28- EA NOP
0B29- 85 3E STA $3E
0B2B- B5 00 LDA $00,X
0B2D- B5 00 LDA $00,X
0B2F- BD 8C C0 LDA $C08C,X
0B32- 10 FB BPL $0B2F
0B34- 2A ROL ;rotate nibble left (first part of 4+4 decode)
0B35- 85 3E STA $3E ;and store where building byte
0B37- BD 8C C0 LDA $C08C,X
0B3A- 10 FB BPL $0B37
0B3C- 25 3E AND $3E ;build 8-bit byte (second part of 4+4 decode)
0B3E- C5 2E CMP $2E ;compare to desired sector
0B40- D0 B9 BNE $0AFB ;get the right one? Branch back if no
0B42- 18 CLC ;matches, indicate no error
0B43- 60 RTS ;return (end read address field)
0B44- A9 02 LDA #$02 ;error code 2
0B46- 8D BD 09 STA $09BD ;store error code
0B49- 38 SEC ;indicate error
0B4A- 60 RTS ;return (end read address field - error)
0B4B- A9 40 LDA #$40 ;beep routine (sounds like the reset beep)
0B4D- 20 5E 0B JSR $0B5E
0B50- A0 C0 LDY #$C0
0B52- A9 0C LDA #$0C
0B54- 20 5E 0B JSR $0B5E
0B57- AD 30 C0 LDA $C030
0B5A- 88 DEY
0B5B- D0 F5 BNE $0B52
0B5D- 60 RTS ;end beep routine
0B5E- 38 SEC ;delay routine
0B5F- 48 PHA
0B60- E9 01 SBC #$01
0B62- D0 FC BNE $0B60
0B64- 68 PLA
0B65- E9 01 SBC #$01
0B67- D0 F6 BNE $0B5F
0B69- 60 RTS ;end delay routine
0B6A- A9 EF LDA #$EF ;seekabs routine
0B6C- 85 29 STA $29
0B6E- A9 D8 LDA #$D8
0B70- 85 2A STA $2A
0B72- A6 20 LDX $20 ;slot
0B74- A5 2C LDA $2C ;desired track
0B76- CD F8 0B CMP $0BF8 ;current track
0B79- F0 53 BEQ $0BCE ;already there, exit
0B7B- A9 00 LDA #$00
0B7D- 85 3E STA $3E
0B7F- AD F8 0B LDA $0BF8
0B82- 85 27 STA $27 ;$27 will be prior track
0B84- 38 SEC
0B85- E5 2C SBC $2C ;$2C will be final (as will $BF8)
0B87- F0 33 BEQ $0BBC
0B89- B0 07 BCS $0B92
0B8B- 49 FF EOR #$FF
0B8D- EE F8 0B INC $0BF8
0B90- 90 05 BCC $0B97
0B92- 69 FE ADC #$FE
0B94- CE F8 0B DEC $0BF8
0B97- C5 3E CMP $3E
0B99- 90 02 BCC $0B9D
0B9B- A5 3E LDA $3E
0B9D- C9 0C CMP #$0C
0B9F- B0 01 BCS $0BA2
0BA1- A8 TAY
0BA2- 38 SEC
0BA3- 20 C0 0B JSR $0BC0
0BA6- B9 E0 0B LDA $0BE0,Y
0BA9- 20 CF 0B JSR $0BCF
0BAC- A5 27 LDA $27
0BAE- 18 CLC
0BAF- 20 C3 0B JSR $0BC3
0BB2- B9 EC 0B LDA $0BEC,Y
0BB5- 20 CF 0B JSR $0BCF
0BB8- E6 3E INC $3E
0BBA- D0 C3 BNE $0B7F
0BBC- 20 CF 0B JSR $0BCF
0BBF- 18 CLC
0BC0- AD F8 0B LDA $0BF8
0BC3- 29 03 AND #$03
0BC5- 2A ROL
0BC6- 05 20 ORA $20
0BC8- AA TAX
0BC9- BD 80 C0 LDA $C080,X
0BCC- A6 20 LDX $20
0BCE- 60 RTS ;end seekabs ($BF8 is final track)
0BCF- A2 11 LDX #$11 ;arm move delay subroutine
0BD1- CA DEX
0BD2- D0 FD BNE $0BD1
0BD4- E6 29 INC $29
0BD6- D0 02 BNE $0BDA
0BD8- E6 2A INC $2A
0BDA- 38 SEC
0BDB- E9 01 SBC #$01
0BDD- D0 F0 BNE $0BCF
0BDF- 60 RTS ;end arm move delay
0BE0- 01 30 ORA ($30,X) ;arm move delay table start
0BE2- 28 PLP
0BE3- 24 20 BIT $20
0BE5- 1E 1D 1C ASL $1C1D,X
0BE8- 1C ???
0BE9- 1C ???
0BEA- 1C ???
0BEB- 1C ???
0BEC- 70 2C BVS $0C1A
0BEE- 26 22 ROL $22
0BF0- 1F ???
0BF1- 1E 1D 1C ASL $1C1D,X
0BF4- 1C ???
0BF5- 1C ???
0BF6- 1C ???
0BF7- 1C ??? ;arm move delay table end
0BF8- 0C ??? ;current track
0BF9- F0 05 BEQ $0C00 ;unused (to $BFF)?
0BFB- BA TSX
0BFC- 22 ???
0BFD- 54
0BFE- 48
0BFF- 45
]HR