[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