mirror of
https://github.com/erkyrath/infocom-zcode-terps.git
synced 2026-02-27 09:09:14 +00:00
1091 lines
22 KiB
NASM
1091 lines
22 KiB
NASM
PAGE
|
||
STTL "--- BOOT CODE & RWTS: APPLE II ---"
|
||
|
||
|
||
; ---------
|
||
; BOOT CODE
|
||
; ---------
|
||
; LOADS ALL OF TRACK 0 INTO RAM AT $800 TO $1800,
|
||
; THEN JUMPS THROUGH [COLD]
|
||
|
||
ORG BORG ; (EZIP)
|
||
DB 01 ; MAGICAL MYSTERY BYTE
|
||
|
||
; BOOT BEGINS HERE
|
||
|
||
BOOT: ;THIS LABLE NEVER USED BUT MUST BE HERE
|
||
LDA BADDR+HI ; CHECK MSB OF BOOT ADDRESS
|
||
CMP #$09 ; 1ST ENTRY INTO BOOT?
|
||
BEQ BOOTS2 ; YES, DO STUFF (X)
|
||
CMP #$0A ; 3RD SECTOR GOES UP >(X)
|
||
BNE BOOTS0 ; NO, CONTINUE
|
||
|
||
; CALC ADDRESS OF ROM SECTOR READ ROUTINE
|
||
|
||
LDA #$D0
|
||
STA BADDR+HI
|
||
BNE BOOTS0 ; JMP (X)
|
||
|
||
BOOTS2: LDA $C08B ; SET TO R/W RAM, BANK 1
|
||
LDA $C08B ; MUST READ 2CE
|
||
LDA BSLOT ; GET SLOT ID * 16
|
||
STA DCBSLT ; MAKE IT THE DEFAULT TARGET
|
||
STA DCBPSL ; AND THE "OLD" SLOT
|
||
LSR A ; DIVIDE BY 16
|
||
LSR A
|
||
LSR A
|
||
LSR A
|
||
ORA #%11000000 ; MAKE IT $C0nn
|
||
STA I+HI ; USE AS MSB OF ADDRESS
|
||
LDA #$5C ; LSB IS ALWAYS $5C
|
||
STA I+LO
|
||
LDA #1
|
||
STA DCBSEC
|
||
|
||
BOOTS0: LDX DCBSEC
|
||
INC DCBSEC
|
||
CPX #$10
|
||
BCS BOOTS1
|
||
LDA ILEAVE,X
|
||
STA BSECT
|
||
LDX BSLOT
|
||
JMP (I)
|
||
BOOTS1: JSR INIT
|
||
JMP COLD ; LOAD REMAINDER OF ZIP
|
||
|
||
|
||
; ---------------------
|
||
; SECTOR INTERLEAVE MAP
|
||
; ---------------------
|
||
; USED BY "BOOT" (AND "RWTS" (NOT THIS W/ EZIP))
|
||
; MUST BE IN 1ST PAGE!
|
||
|
||
ILEAVE: DB $00,$04,$08,$0C,$01,$05,$09,$0D
|
||
DB $02,$06,$0A,$0E,$03,$07,$0B,$0F
|
||
|
||
|
||
; RAMDSK
|
||
; THIS CODE IS DESIGNED TO RESIDE
|
||
; IN MAIN 48K *ABOVE PAGE 2*
|
||
;
|
||
; ON ENTRY IT ASSUMES THAT MAIN
|
||
; BANK 1 IS ENABLED
|
||
; A = SECTOR - $00=<$4F
|
||
; Y = PAGE TO READ/WRITE
|
||
; TO/FROM
|
||
; X = ON ENTRY 1=WRITE
|
||
; 0=READ
|
||
; RMDBNK - 48K BANK TO READ TO
|
||
; AUX OR MAIN
|
||
; THE RAMDISK CAN ONLY WRITE FROM
|
||
; MAIN MEMORY (ACTUALLY FROM THE BANK THIS CODE IS IN)
|
||
; SECTOR MAP
|
||
; $00=<$0F IN MAIN BANK 2
|
||
; $10=<$1F IN AUX BANK 2
|
||
; $20=<$4F IN AUX BANK 1
|
||
|
||
|
||
RMDBNK: DB 00 ;REMEMBER WHAT BANK THIS IS IN WHEN YOU SET IT
|
||
|
||
RAMDSK: STY WRTBNK+MAIN ;WRITE TO MAIN 48K BANK (WHERE THIS CODE IS)
|
||
STY WRDADD+1+HI ;SAVE >ADDRESS FOR EITHER
|
||
STY RAMLOOP+1+HI ;READ OR WRITE
|
||
|
||
CMP #$10
|
||
BCS RAM1
|
||
LDY BNK2SET ;IN MAIN BANK 2
|
||
LDY BNK2SET ;ENABLE BANK 2 WITH TWO READS
|
||
ADC #$D0 ;C=0 , ALIGN SECTOR INTO RAM
|
||
BNE RAMDO
|
||
RAM1:
|
||
STA ALTZP+AUX ;IT IS IN AUX RAM
|
||
CMP #$20 ;BANK 1 OR 2 ???
|
||
BCS RAM2
|
||
LDY BNK2SET ;IN AUX BANK 2
|
||
LDY BNK2SET ;ENABLE BANK 2
|
||
ADC #$C0 ;ALIGN
|
||
BNE RAMDO
|
||
|
||
RAM2: ADC #$AF ;C=1 ; IN AUX BANK 1
|
||
|
||
RAMDO: DEX ; SEE IF X WAS A 1
|
||
BNE RAMREAD ;NO IT WAS A ZERO
|
||
STA WRDADD+1+HI ;WRITE
|
||
BEQ RAMDO1
|
||
|
||
RAMREAD: STA RAMLOOP+1+HI ;READ
|
||
LDY RMDBNK ;THIS MUST BE GOTTEN FROM A SAFE PLACE
|
||
STA WRTBNK,Y ;SET TO READ TO RMDBNK
|
||
RAMDO1: LDY #00
|
||
RAMLOOP: LDA $FF00,Y
|
||
WRDADD: STA $FF00,Y
|
||
INY
|
||
BNE RAMLOOP
|
||
|
||
; LEAVE WITH MAIN BANK1 ENABLED
|
||
; AND MAIN 48K SELECTED FOR WRITE
|
||
|
||
LDA BNK1SET
|
||
LDA BNK1SET
|
||
STA WRTBNK+MAIN
|
||
STA ALTZP+MAIN
|
||
RTS
|
||
|
||
|
||
; MONITOR CALLS ARE TO ROM SO MUST BE FROM MAIN 48K OF MEMORY
|
||
; ALL CALLS IN XZIP ARE UNCHANGED FROM EZIP BUT ARE DIVERTED NOW
|
||
; THROUGH THESE RTNS WHICH SWITCH IN ROM TO READ FROM, CALL THE
|
||
; MONITOR ROUTINE THEN SWITCH BACK TO RAM FOR EVERYTHING AND RETURN
|
||
|
||
; EACH CALL SHOULD BE SEPARATE SO AS TO PRESERVE REGISTERS ON CALL
|
||
|
||
BASCAL: PHA
|
||
LDA RDROM ; SET TO READ FROM ROM
|
||
LDA RDROM
|
||
PLA
|
||
JSR MBASCAL ; CALL MONITOR RTN
|
||
JMP MOUT
|
||
|
||
BELL: PHA
|
||
LDA RDROM
|
||
LDA RDROM
|
||
PLA
|
||
JSR MBELL
|
||
JMP MOUT
|
||
|
||
CLEOL: PHA
|
||
LDA RDROM
|
||
LDA RDROM
|
||
PLA
|
||
JSR MCLEOL
|
||
JMP MOUT
|
||
|
||
CLEOS: PHA
|
||
LDA RDROM
|
||
LDA RDROM
|
||
PLA
|
||
JSR MCLEOS
|
||
JMP MOUT
|
||
|
||
HOME: PHA
|
||
LDA RDROM
|
||
LDA RDROM
|
||
PLA
|
||
JSR MHOME
|
||
JMP MOUT
|
||
|
||
MCOUT: PHA
|
||
LDA RDROM
|
||
LDA RDROM
|
||
PLA
|
||
JSR MMCOUT
|
||
JMP MOUT
|
||
|
||
COUT1: PHA
|
||
LDA RDROM
|
||
LDA RDROM
|
||
PLA
|
||
JSR MCOUT1
|
||
JMP MOUT
|
||
|
||
RDKEY: PHA
|
||
LDA RDROM
|
||
LDA RDROM
|
||
PLA
|
||
JSR MRDKEY
|
||
JMP MOUT
|
||
|
||
GETLN1: PHA
|
||
LDA RDROM
|
||
LDA RDROM
|
||
PLA
|
||
JSR MGETLN1
|
||
JMP MOUT
|
||
|
||
MWAIT: PHA
|
||
LDA RDROM
|
||
LDA RDROM
|
||
PLA
|
||
JSR MMWAIT
|
||
; FALL THRU ON LAST ONE
|
||
|
||
|
||
MOUT: PHA ; SAVE [A] AS MAY HAVE INFORMATION
|
||
LDA BNK1SET ; RESET TO READ FROM RAM
|
||
LDA BNK1SET
|
||
PLA
|
||
RTS
|
||
|
||
|
||
; TO CHECK IF HAVE ENOUGH MEMORY, MUST HAVE 128K OF MEMORY (X)
|
||
|
||
CHKSIZ: LDA RDROM ; FLAGS IN ROM, MUST GET THEM
|
||
LDA RDROM
|
||
LDA $FBB3 ; CHECK ID BYTE
|
||
CMP #$06 ; IS IT A IIE OR IIC?
|
||
BEQ CHKS0 ; YES
|
||
|
||
LDA BNK1SET ; RESET TO RAM
|
||
LDA BNK1SET
|
||
SEC ; NO, IT'S NOT 128K (EZIP)
|
||
RTS
|
||
|
||
CHKS0: LDA $FBC0 ; IS IT A IIE OR! A IIC
|
||
LDX BNK1SET ; RESET TO RAM
|
||
LDX BNK1SET
|
||
STA SIG ; 0 = IIC
|
||
CLC ; SAY OK,
|
||
RTS ; FINISH UP IN COLD
|
||
|
||
CALL80: LDA RDROM ; SET TO READ ROM
|
||
LDA RDROM ; SO CAN TURN 80 COL DISPLAY ON
|
||
JSR $C300 ; THIS NEEDS ROM
|
||
LDA BNK1SET ; RESET TO RAM
|
||
LDA BNK1SET
|
||
RTS
|
||
|
||
; MARK END OF SECTOR
|
||
|
||
PAGE
|
||
|
||
; INFOCOM'S VERSION OF APPLE RWTS (READ/WRITE TRACK/SECTOR)
|
||
; HACKED BY ANDREW KALUZNIACKI
|
||
; FROM THE DOS RWTS ON APPLE DOS 3.3
|
||
|
||
ORG $D000
|
||
|
||
|
||
; -------------------------------
|
||
; MAIN ENTRY INTO INFO-DOS (IDOS)
|
||
; -------------------------------
|
||
; [DCBSEC] SECTOR (0-15), SET BY CALLER
|
||
; [DCBTRK] TRACK (0-34), SET BY CALLER
|
||
; [DCBDRV] DRIVE (1 OR 2), SET BY CALLER [BOOT DEFAULT]
|
||
; [DCBSLT] SLOT*16, SET BY CALLER [BOOT DEFAULT]
|
||
; [DCBPSL] SLOT*16 OF LAST USED SLOT, SET BY BOOT
|
||
; [DCBPDR] LAST DRIVE USED (1 OR 2), SET BY BOOT
|
||
; [DCBCMD] STORAGE FOR COMMAND SENT IN >A< AT CALL TO IDOS
|
||
; [DCBERR] IDOS ERROR CODE
|
||
; [DCBBFL] DISK BUFFER ADDRESS (LSB) [BOOT = IOBUFF]
|
||
; [DCBBFM] DISK BUFFER ADDRESS (MSB) [BOOT = IOBUFF]
|
||
; >A<=1 WRITES DISK BUFFER
|
||
; >A<=0 READS DISK BUFFER
|
||
; [IOBUFF] = 256-BYTE BUFFER FOR DISK I/O
|
||
; (OPTIONAL IF [DCBBFL/DCBBFM] ARE SET)
|
||
; [BUFFA] ONE PAGE BUFFER
|
||
; [BUFFB] $56 BYTE BUFFER
|
||
; CARRY CLEAR ON RETURN IF NO ERROR
|
||
; IF CARRY SET, ERROR CODE IS IN [DERR]:
|
||
; $10 = WRITE PROTECTED
|
||
; $40 = DRIVE ERROR
|
||
; $80 = READ ERROR
|
||
; *** WARNING ***
|
||
; IDOS MUST START ON A PAGE BOUNDARY.
|
||
; CHANGE ANY CODE BETWEEN [IDOS] AND [INIT] AT YOUR OWN RISK.
|
||
; YOU HAVE BEEN WARNED.
|
||
|
||
DOS: NOP
|
||
NOP
|
||
NOP ; DON'T ASK, AND DON'T CHANGE
|
||
PHP ; SAVE STATUS OF [I]
|
||
SEI ; DISABLE INTERUPTS
|
||
JSR DOSENT ; DO IT (GO TO MAIN ROUTINE)
|
||
BCS DSERR ; ERROR OCCURED IF C=1
|
||
PLP ; RESTORE [I]
|
||
CLC ; SET "NO ERROR"
|
||
RTS ; RETURN FROM CALL
|
||
|
||
DSERR: PLP ; RESTORE [I]
|
||
SEC ; INDICATE ERROR
|
||
RTS ; EXIT
|
||
|
||
; PRE-NIBBLIZE [IOBUFF] BEFORE WRITING
|
||
|
||
PRENIB: LDX #0
|
||
LDY #2
|
||
PRELP1: DEY
|
||
LDA (DCBBFL),Y
|
||
LSR A
|
||
ROL BUFFB,X
|
||
LSR A
|
||
ROL BUFFB,X
|
||
STA BUFFA,Y
|
||
INX
|
||
CPX #$56
|
||
BCC PRELP1
|
||
LDX #0
|
||
TYA
|
||
BNE PRELP1
|
||
LDX #$55 ; CLEAR BITS 7 AND 6
|
||
PRELP2: LDA BUFFB,X ; OF TOP NIBBLE BUFFER
|
||
AND #%00111111
|
||
STA BUFFB,X
|
||
DEX
|
||
BPL PRELP2
|
||
RTS
|
||
|
||
|
||
; ------------
|
||
; WRITE SECTOR
|
||
; ------------
|
||
; WRITES PRENIBBLIZED DATA AT [BUFFA/BUFFB] TO DISK
|
||
; ENTRY: SLOT*16 IN [X]
|
||
; EXIT: CARRY SET IF ERROR
|
||
|
||
WRTDTA: STX DTMP4 ; SAVE SLOT ID HERE
|
||
STX SLTMP2
|
||
SEC ; SET CARRY FOR POSSIBLE ERROR
|
||
LDA Q6H,X ; CHECK FOR WRITE-PROTECT
|
||
LDA Q7L,X
|
||
BMI WRTEXI ; EXIT W/CARRY SET IF PROTECTED
|
||
LDA BUFFB ; SAVE 1ST BYTE OF 2NDARY BUFFER
|
||
STA DTMP3 ; FOR LATER
|
||
LDA #$FF ; ESTABLISH AUTOSYNC BYTE
|
||
STA Q7H,X ; SET DRIVE TO WRITE MODE
|
||
ORA Q6L,X ; WAIT FOR HARDWARE TO SETTLE
|
||
PHA
|
||
PLA
|
||
NOP
|
||
LDY #4 ; WRITE 5 AUTOSYNC BYTES
|
||
WRTLP1: PHA
|
||
PLA
|
||
JSR WRBYT2 ; USING 40 uS DELAY
|
||
DEY
|
||
BNE WRTLP1
|
||
LDA #$D5 ; WRITE DATA FIELD PROLOGUE:
|
||
JSR WRBYT1 ; $D5-$AA-$AD
|
||
LDA #$AA
|
||
JSR WRBYT1
|
||
LDA #$AD
|
||
JSR WRBYT1
|
||
TYA ; A BRIEF DELAY
|
||
LDY #$56 ; INIT LOOP INDEX
|
||
BNE WRTSK1 ; BRANCH ALWAYS
|
||
|
||
; WRITE [BUFFB] TO DISK
|
||
|
||
WRTLP2: LDA BUFFB,Y ; GET A BYTE FROM [BUFFB]
|
||
WRTSK1: EOR BUFFB-1,Y
|
||
TAX ; USE IT AS AN INDEX
|
||
LDA WRTTBL,X ; INTO THE TRANSLATE TABLE
|
||
LDX DTMP4 ; RESTORE SLOT ID
|
||
STA Q6H,X ; AND WRITE THE TRANSLATED BYTE
|
||
LDA Q6L,X
|
||
DEY ; LOOP TILL
|
||
BNE WRTLP2 ; EMPTY
|
||
|
||
; WRITE [BUFFA] TO DISK
|
||
|
||
LDA DTMP3 ; RESTORE "LOST" [BUFFB] BYTE
|
||
NOP ; WAIT JUST A MOMENT ...
|
||
WRTLP3: EOR BUFFA,Y ; GET A BYTE FROM [BUFFA]
|
||
TAX ; USE IT AS AN INDEX
|
||
LDA WRTTBL,X ; INTO THE TRANSLATE TABLE
|
||
LDX SLTMP2 ; RESTORE SLOT ID
|
||
STA Q6H,X ; AND WRITE THE TRANSLATED BYTE
|
||
LDA Q6L,X
|
||
LDA BUFFA,Y ; GET NEXT BYTE FROM BUFFER
|
||
INY ; AND LOOP TILL
|
||
BNE WRTLP3 ; ALL OF [BUFFA] IS WRITTEN
|
||
TAX
|
||
LDA WRTTBL,X
|
||
LDX DTMP4 ; RESTORE SLOT ID
|
||
JSR WRBYT3 ; AND WRITE THE LAST [BUFFA] BYTE
|
||
LDA #$DE ; WRITE DATA FIELD EPILOGUE:
|
||
JSR WRBYT1 ; $DE-$AA-$EB
|
||
LDA #$AA
|
||
JSR WRBYT1
|
||
LDA #$EB
|
||
JSR WRBYT1
|
||
LDA #$FF ; WRITE GAP 3
|
||
JSR WRBYT1
|
||
LDA Q7L,X ; SET DRIVE TO READ MODE
|
||
WRTEXI: LDA Q6L,X
|
||
RTS
|
||
|
||
|
||
; ----------------------------
|
||
; WRITE A BYTE (TIME-CRITICAL)
|
||
; ----------------------------
|
||
; ENTRY: BYTE TO WRITE IN [A]
|
||
; SLOT*16 IN [X]
|
||
|
||
WRBYT1: CLC ; PROLOGUE, EPILOGUE AND GAP 3 TIMING
|
||
WRBYT2: PHA ; ENTRY FOR GAP 2 TIMING
|
||
PLA
|
||
WRBYT3: STA Q6H,X
|
||
ORA Q6L,X
|
||
RTS
|
||
|
||
; CONVERT RAW DATA TO BINARY IN [IOBUFF]
|
||
|
||
POSTNB: LDY #0
|
||
PSTSK1: LDX #$56
|
||
PSTLP1: DEX
|
||
BMI PSTSK1
|
||
LDA BUFFA,Y
|
||
LSR BUFFB,X
|
||
ROL A
|
||
LSR BUFFB,X
|
||
ROL A
|
||
STA (DCBBFL),Y
|
||
INY
|
||
CPY DTMP3
|
||
BNE PSTLP1
|
||
RTS
|
||
|
||
|
||
; -----------
|
||
; READ SECTOR
|
||
; -----------
|
||
; READ RAW SECTOR DATA TO [BUFFA/BUFFB]
|
||
; ENTRY: SLOT*16 IN [X]
|
||
; EXIT: CARRY SET IF ERROR, ELSE 342 RAW BYTES IN [BUFFA/BUFFB]
|
||
|
||
RDSECT: LDY #$20
|
||
RDLP1: DEY ; RETURN AN ERROR IF
|
||
BEQ RDBAD ; NO $D5 FOUND AFTER 32 TRIES
|
||
|
||
; FETCH & VALIDATE PROLOGUE ($D5-$AA-$AD)
|
||
|
||
RD1: LDA Q6L,X ; GET A BYTE
|
||
BPL RD1
|
||
RDSK1: EOR #$D5 ; WAS IT $D5?
|
||
BNE RDLP1 ; NO, KEEP LOOKING
|
||
NOP ; ELSE WAIT A MOMENT ...
|
||
RD2: LDA Q6L,X ; GET ANOTHER BYTE
|
||
BPL RD2
|
||
CMP #$AA ; WAS IT $AA?
|
||
BNE RDSK1 ; CHECK FOR $D5 AGAIN IF NOT
|
||
LDY #$56 ; ELSE INIT DATA-READ INDEX
|
||
RD3: LDA Q6L,X ; GET A BYTE
|
||
BPL RD3
|
||
CMP #$AD ; WAS IT $AD?
|
||
BNE RDSK1 ; CHECK FOR $D5 IF NOT
|
||
|
||
; READ RAW DATA INTO [BUFFB]
|
||
|
||
LDA #0 ; CLEAR [A], DELAY ...
|
||
RDLP2: DEY
|
||
STY DTMP3 ; SAVE INDEX HERE
|
||
RD4: LDY Q6L,X ; GET A DATA BYTE
|
||
BPL RD4
|
||
EOR RDTBL-$96,Y ; TRANSLATE IT
|
||
LDY DTMP3 ; RESTORE INDEX
|
||
STA BUFFB,Y ; STORE BYTE IN [BUFFB]
|
||
BNE RDLP2 ; CONTINUE TILL [BUFFB] FULL
|
||
|
||
; READ RAW DATA INTO [BUFFA]
|
||
|
||
RDLP3: STY DTMP3 ; RE-INIT INDEX TO ZERO
|
||
RD5: LDY Q6L,X ; GET A DATA BYTE
|
||
BPL RD5
|
||
EOR RDTBL-$96,Y ; TRANSLATE IT
|
||
LDY DTMP3 ; RESTORE INDEX
|
||
STA BUFFA,Y ; SAVE BYTE IN [BUFFA]
|
||
INY
|
||
BNE RDLP3 ; LOOP TILL [BUFFA] IS FULL
|
||
|
||
; FETCH & VALIDATE CHECKSUM
|
||
|
||
RD6: LDY Q6L,X ; GET THE NEXT BYTE
|
||
BPL RD6
|
||
CMP RDTBL-$96,Y ; TRANSLATE IT
|
||
BNE RDBAD ; ERROR IF CHECKSUM BAD
|
||
|
||
; FETCH & VALIDATE EPILOGUE ($DE-$AA-$EB)
|
||
|
||
RD7: LDA Q6L,X ; GET A BYTE
|
||
BPL RD7
|
||
CMP #$DE ; IS IT $DE?
|
||
BNE RDBAD ; ERROR IF NOT
|
||
NOP ; WAIT ...
|
||
RD8: LDA Q6L,X ; GET ANOTHER BYTE
|
||
BPL RD8
|
||
CMP #$AA ; IS IT $AA?
|
||
BEQ RDOK ; DATA OKAY IF SO
|
||
RDBAD: SEC ; ELSE SET CARRY FOR ERROR
|
||
RTS ; AND SCRAM
|
||
|
||
|
||
; ---------------------
|
||
; READ AN ADDRESS FIELD
|
||
; ---------------------
|
||
; ENTRY: SLOT*16 IN [X]
|
||
; EXIT: CARRY SET IF ERROR
|
||
|
||
RDADDR: LDY #$FC ; INIT TIMEOUT COUNTER
|
||
STY DTMP3
|
||
ADDLP1: INY
|
||
BNE ADD1
|
||
INC DTMP3 ; ERROR IF
|
||
BEQ RDBAD ; CAN'T FIND ADDRESS HEADER
|
||
|
||
; FETCH THE ADDRESS FIELD PROLOGUE ($D5-$AA-$96)
|
||
|
||
ADD1: LDA Q6L,X ; GRAB A BYTE
|
||
BPL ADD1
|
||
ADDLP2: CMP #$D5 ; WAS IT $D5?
|
||
BNE ADDLP1 ; NO, KEEP SEARCHING
|
||
NOP ; ELSE WAIT A FEW MICROSECONDS ...
|
||
ADD2: LDA Q6L,X ; GET ANOTHER BYTE
|
||
BPL ADD2
|
||
CMP #$AA ; WAS IT $AA?
|
||
BNE ADDLP2 ; NO, CHECK IF $D5
|
||
LDY #3 ; ELSE INIT DATA-FETCH INDEX
|
||
ADD3: LDA Q6L,X ; GET A BYTE
|
||
BPL ADD3
|
||
CMP #$96 ; WAS IT $96?
|
||
BNE ADDLP2 ; NO, CHECK FOR $D5
|
||
|
||
; FETCH THE 4 BYTES OF ADDRESS DATA
|
||
|
||
LDA #0 ; INIT CHECKSUM BYTE
|
||
ADDLP3: STA DTMP4 ; UPDATE CHECKSUM
|
||
ADD4: LDA Q6L,X ; GET A BYTE
|
||
BPL ADD4
|
||
ROL A ; SHIFT IT
|
||
STA DTMP3 ; AND SAVE 1ST PART HERE
|
||
ADD5: LDA Q6L,X ; GET ANOTHER BYTE
|
||
BPL ADD5
|
||
AND DTMP3 ; SUPER 1ST PART OF BYTE
|
||
STA HDRCHK,Y ; STORE IN RESULT TABLE
|
||
EOR DTMP4 ; COMPUTE CHECKSUM
|
||
DEY ; GOT 4 BYTES YET?
|
||
BPL ADDLP3 ; NO, LOOP BACK
|
||
TAY ; LOOK AT CHECKSUM BYTE
|
||
BNE RDBAD ; ERROR IF NON-ZERO
|
||
|
||
; FETCH & VALIDATE EPILOGUE ($DE-$AA, IGNORE $EB)
|
||
|
||
ADD6: LDA Q6L,X ; GET A BYTE
|
||
BPL ADD6
|
||
CMP #$DE ; WAS IT $DE?
|
||
BNE RDBAD ; ERROR IF NOT
|
||
NOP ; ELSE WAIT A MOMENT ...
|
||
ADD7: LDA Q6L,X ; GET ONE MORE BYTE
|
||
BPL ADD7
|
||
CMP #$AA ; WAS IT $AA
|
||
BNE RDBAD ; ERROR IF NOT
|
||
RDOK: CLC ; ELSE CLEAR CARRY FOR SUCCESS
|
||
RTS ; AND RETURN
|
||
|
||
|
||
; ---------------------
|
||
; MOVE ARM TO TRACK [A]
|
||
; ---------------------
|
||
; ENTRY: SLOT*16 IN [X]
|
||
; TARGET TRACK IN [A]
|
||
; CURRENT TRACK IN [CTRACK]
|
||
|
||
SEEK: STX SLTMP3 ; SAVE SLOT ID
|
||
STA TTRK ; AND TARGET TRACK
|
||
CMP CTRACK ; TARGET SAME AS CURRENT?
|
||
BEQ SEEEXI ; EXIT NOW IF SO
|
||
LDA #0 ; INIT
|
||
STA DTMP3 ; INDEX
|
||
SEESK1: LDA CTRACK ; GET CURRENT TRACK
|
||
STA DTMP4 ; SAVE IT HERE
|
||
SEC
|
||
SBC TTRK ; GET TRACK DIFFERENCE
|
||
BEQ SEESK6
|
||
BCS SEESK2
|
||
EOR #%11111111
|
||
INC CTRACK
|
||
BCC SEESK3
|
||
SEESK2: ADC #$FE
|
||
DEC CTRACK
|
||
SEESK3: CMP DTMP3
|
||
BCC SEESK4
|
||
LDA DTMP3
|
||
SEESK4: CMP #$0C
|
||
BCS SEESK5
|
||
TAY
|
||
SEESK5: SEC
|
||
JSR SEEK0
|
||
LDA DELTB1,Y
|
||
JSR ARMDEL
|
||
LDA DTMP4
|
||
CLC
|
||
JSR SEEK1
|
||
LDA DELTB2,Y
|
||
JSR ARMDEL
|
||
INC DTMP3
|
||
BNE SEESK1
|
||
SEESK6: JSR ARMDEL
|
||
CLC
|
||
SEEK0: LDA CTRACK
|
||
SEEK1: AND #%00000011
|
||
ROL A
|
||
ORA SLTMP3
|
||
TAX
|
||
LDA PH0OFF,X ; MOVE THE ARM
|
||
LDX SLTMP3
|
||
SEEEXI: RTS
|
||
|
||
|
||
; ------------------
|
||
; ARM MOVEMENT DELAY
|
||
; ------------------
|
||
; NOTE: THIS ROUTINE MUST BEGIN ON A PAGE BOUNDARY!
|
||
; ENTRY: 100uS DELAY INTERVAL IN [A]
|
||
; MOTOR TIME COUNT IN [MTIME]
|
||
|
||
ARMDEL: LDX #$11
|
||
ARMLP1: DEX
|
||
BNE ARMLP1
|
||
INC DCNT
|
||
BNE ARMLP2
|
||
INC DTMP2
|
||
ARMLP2: SEC
|
||
SBC #1
|
||
BNE ARMDEL
|
||
RTS
|
||
|
||
|
||
; -------------------------
|
||
; ARM MOVEMENT DELAY TABLES
|
||
; -------------------------
|
||
|
||
DELTB1: DB $01,$30,$28,$24,$20,$1E,$1D,$1C
|
||
DB $1C,$1C,$1C,$1C
|
||
DELTB2: DB $70,$2C,$26,$22,$1F,$1E,$1D,$1C
|
||
DB $1C,$1C,$1C,$1C
|
||
|
||
|
||
; ---------------------
|
||
; WRITE TRANSLATE TABLE
|
||
; ---------------------
|
||
|
||
WRTTBL: DB $96,$97,$9A,$9B,$9D,$9E,$9F,$A6
|
||
DB $A7,$AB,$AC,$AD,$AE,$AF,$B2,$B3
|
||
DB $B4,$B5,$B6,$B7,$B9,$BA,$BB,$BC
|
||
DB $BD,$BE,$BF,$CB,$CD,$CE,$CF,$D3
|
||
DB $D6,$D7,$D9,$DA,$DB,$DC,$DD,$DE
|
||
DB $DF,$E5,$E6,$E7,$E9,$EA,$EB,$EC
|
||
DB $ED,$EE,$EF,$F2,$F3,$F4,$F5,$F6
|
||
DB $F7,$F9,$FA,$FB,$FC,$FD,$FE,$FF
|
||
|
||
|
||
; --------------------
|
||
; READ TRANSLATE TABLE
|
||
; --------------------
|
||
|
||
RDTBL: DB $00,$01,$98,$99,$02,$03,$9C,$04
|
||
DB $05,$06,$A0,$A1,$A2,$A3,$A4,$A5
|
||
DB $07,$08,$A8,$A9,$AA,$09,$0A,$0B
|
||
DB $0C,$0D,$B0,$B1,$0E,$0F,$10,$11
|
||
DB $12,$13,$B8,$14,$15,$16,$17,$18
|
||
DB $19,$1A,$C0,$C1,$C2,$C3,$C4,$C5
|
||
DB $C6,$C7,$C8,$C9,$CA,$1B,$CC,$1C
|
||
DB $1D,$1E,$D0,$D1,$D2,$1F,$D4,$D5
|
||
DB $20,$21,$D8,$22,$23,$24,$25,$26
|
||
DB $27,$28,$E0,$E1,$E2,$E3,$E4,$29
|
||
DB $2A,$2B,$E8,$2C,$2D,$2E,$2F,$30
|
||
DB $31,$32,$F0,$F1,$33,$34,$35,$36
|
||
DB $37,$38,$F8,$39,$3A,$3B,$3C,$3D
|
||
DB $3E,$3F
|
||
|
||
|
||
; ---------------
|
||
; MAIN RWTS ENTRY
|
||
; ---------------
|
||
; ENTRY: [A]=0 FOR READ, [A]=1 FOR WRITE
|
||
; [SLOT] = TARGET SLOT
|
||
; [DRIVE] = TARGET DRIVE
|
||
; [TRACK] = TARGET TRACK
|
||
; [SECTOR] = TARGET SECTOR
|
||
; EXIT: CARRY CLEAR IF OKAY
|
||
; COMMENTS - LINDE
|
||
; ACTUAL VARIABLES ARE:
|
||
; [DCBSLT] = SLOT
|
||
; [DCBTRK] = TRACK
|
||
; [DCBSEC] = SECTOR
|
||
; [[DCBDRV] = DRIVE
|
||
; FOR TRK, SEC, DRV 1 = 1 (DRIVE 1, SET DCBDRV TO 1)
|
||
; FOR SLT - MULTIPLY SLOT BY 16 (SLOT 6, SET DCBSLT TO $60)
|
||
|
||
DOSENT: STA DCBCMD ; SAVE COMMAND
|
||
LDA #2 ; AL<2
|
||
STA NRECAL ; RECALS
|
||
ASL A ; AND 4
|
||
STA NSEEK ; SEEKS
|
||
LDX DCBSLT ; GET REQUESTED SLOT ID
|
||
CPX DCBPSL ; SAME AS LAST SLOT?
|
||
BEQ DOSS1 ; YES, CONTINUE
|
||
LDX DCBPSL
|
||
|
||
; WAIT FOR OLD DRIVE TO TURN OFF, UPDATE SLOT ID
|
||
|
||
LDA Q7L,X ; SET OLD SLOT TO READ MODE
|
||
DOSL1: LDY #8 ; INIT COUNTER
|
||
LDA Q6L,X
|
||
DOSL2: CMP Q6L,X
|
||
BNE DOSL1
|
||
DEY
|
||
BNE DOSL2
|
||
LDX DCBSLT ; GET NEW SLOT ID INTO [X]
|
||
STX DCBPSL ; MAKE IT THE "OLD" SLOT
|
||
|
||
; CURRENT SLOT ID IN [X]
|
||
|
||
DOSS1: LDA Q7L,X ; GET DRIVE INTO READ MODE
|
||
LDA Q6L,X ; READ WITH DELAYS
|
||
LDY #8 ; TO SEE IF DRIVE IS SPINNING
|
||
DOSL3: LDA Q6L,X
|
||
PHA
|
||
PLA
|
||
PHA
|
||
PLA
|
||
STX SLTMP1 ; SAVE SLOT HERE
|
||
CMP Q6L,X
|
||
BNE DOSS2
|
||
DEY
|
||
BNE DOSL3
|
||
DOSS2: PHP ; SAVE TEST RESULT ON STACK
|
||
LDA DRVON,X ; TURN ON MOTOR
|
||
LDA #$D8 ; REFRESH
|
||
STA DTMP2 ; MOTOR TIME CONSTANT
|
||
|
||
; CHECK DRIVE ID
|
||
|
||
LDA DCBDRV
|
||
CMP DCBPDR ; HAS DRIVE CHANGED?
|
||
BEQ DOSS3 ; NO, CONTINUE
|
||
STA DCBPDR ; ELSE MAKE NEW DRIVE "OLD"
|
||
PLP ; SET ZERO FLAG
|
||
LDY #0 ; OF TEST RESULT
|
||
PHP ; AND PUSH IT BACK ON STACK
|
||
DOSS3: ROR A ; CHECK DRIVE ID
|
||
BCC DOSS4 ; CARRY WILL BE CLEAR IF DRIVE = 2
|
||
LDA DRV0EN,X ; ELSE SELECT DRIVE #1
|
||
BCS DOSS5 ; BRANCH ALWAYS
|
||
DOSS4: LDA DRV1EN,X ; SELECT DRIVE #2
|
||
DOSS5: ROR DRVFLG ; >BIT = 1 FOR DRIVE 1, 0 FOR 2
|
||
PLP ; CHECK TEST RESULTS
|
||
PHP
|
||
BNE DOSS6 ; BRANCH IF DRIVE WAS ON
|
||
LDY #7 ; WAIT FOR CAP DISCHARGE
|
||
DOSL4: JSR ARMDEL
|
||
DEY
|
||
BNE DOSL4
|
||
LDX SLTMP1 ; RESTORE SLOT ID
|
||
|
||
; SEEK THE TARGET TRACK
|
||
|
||
DOSS6: LDA DCBTRK ; GET TARGET TRACK
|
||
JSR MYSEEK
|
||
PLP ; WAS DRIVE ON?
|
||
BNE DOSS7 ; YES, CONTINUE
|
||
|
||
; WAIT FOR DRIVE TO COME UP TO SPEED
|
||
|
||
LDY DTMP2
|
||
BPL DOSS7
|
||
DOSL5: LDY #$12 ; WAIT FOR DRIVE TO
|
||
DOSL6: DEY ; COME UP TO SPEED
|
||
BNE DOSL6
|
||
INC DCNT
|
||
BNE DOSL5
|
||
INC DTMP2
|
||
BNE DOSL5
|
||
|
||
; DECODE DISK COMMAND
|
||
|
||
DOSS7: LDA DCBCMD ; GET COMMAND
|
||
ROR A ; CARRY = 0 IF "READ"
|
||
PHP ; SAVE READ/WRITE STATUS
|
||
|
||
; AND MAINTAIN STACK
|
||
|
||
BCC GETADR ; BRANCH IF "READ"
|
||
JSR PRENIB
|
||
|
||
; FETCH AN ADDRESS FIELD
|
||
|
||
GETADR: LDA #48
|
||
STA DTMP1 ; INIT RETRY COUNT
|
||
GTA0: LDX SLTMP1 ; RESTORE SLOT ID
|
||
LDA DCBCMD
|
||
BPL DOSS8
|
||
STA DTMP6 ; TELL RDFADD TO GET HEADER ONLY
|
||
JSR RDFSEC ; #$84 = READ FUNNY FORMAT
|
||
BCC RRGHT ; READ IT
|
||
BCS GTA1 ; OOPS
|
||
DOSS8: JSR RDADDR ; GET AN ADDRESS FIELD
|
||
BCC RRGHT ; CONTINUE IF SUCCESSFUL
|
||
GTA1: DEC DTMP1 ; ELSE UPDATE RETRY COUNT
|
||
BPL GTA0 ; AND TRY AGAIN
|
||
|
||
; RECALIBRATE THE ARM
|
||
|
||
GTA2: LDA CTRACK ; SAVE THE
|
||
PHA ; CURRENT TRACK ID
|
||
LDA #$60
|
||
JSR SETTRK
|
||
DEC NRECAL ; UPDATE RECAL COUNT
|
||
BEQ DOSERR ; ERROR IF EMPTY
|
||
LDA #4 ; RESET
|
||
STA NSEEK ; SEEK COUNT
|
||
LDA #0 ; CALIBRATE THE ARM
|
||
JSR MYSEEK ; TO TRACK #0
|
||
PLA ; RESTORE CURRENT TRACK
|
||
GTA3: JSR MYSEEK ; GO TO IT
|
||
JMP GETADR ; AND TRY AGAIN
|
||
|
||
; ADDRESS FIELD FOUND
|
||
|
||
RRGHT: LDY HDRTRK
|
||
CPY CTRACK ; ON THE RIGHT TRACK?
|
||
BEQ RTTRAK ; YES, CONTINUE
|
||
LDA CTRACK
|
||
PHA
|
||
TYA
|
||
JSR SETTRK
|
||
PLA
|
||
DEC NSEEK
|
||
BNE GTA3
|
||
BEQ GTA2 ; ELSE RECALIBRATE
|
||
|
||
; HANDLE A DRIVE ERROR
|
||
|
||
DOSERR PLA ; CLEAN UP STACK
|
||
LDA #$40 ; $40 = DRIVE ERROR
|
||
PLP ; CLEAN UP STATUS REGISTER
|
||
JMP DOSERR2
|
||
|
||
; CHECK FOR PROPER SECTOR (VOLUME CHECK OMITTED)
|
||
|
||
RTTRAK: LDA DCBCMD
|
||
BMI DOSS9 ; NO INTERLEAVE
|
||
LDY DCBSEC
|
||
LDA INTLVE,Y ; GET INTERLEAVE BYTE
|
||
CMP HDRSEC ; MATCHED FOUND SECTOR?
|
||
BNE GTA1 ; NO, TRY AGAIN
|
||
|
||
; SECTOR FOUND!
|
||
|
||
DOSS9: PLP ; WILL THIS BE READ OR WRITE?
|
||
BCS DOSWRT ; DO "WRITE" IF CARRY SET
|
||
|
||
; READ A SECTOR
|
||
|
||
LDA DCBCMD
|
||
BPL DOSS10
|
||
LDY DCBSEC ; FUNNY FORMAT
|
||
STY DTMP6
|
||
JSR RDFSEC
|
||
BCC DOSS11
|
||
SEC
|
||
BCS DOSS11
|
||
DOSS10: JSR RDSECT ; DO THE READ
|
||
DOSS11: BCC GTA3A ; OK
|
||
CLC ; RESET FOR NEXT TIME THRU
|
||
PHP ; PUSH FOR NEXT TIME THRU
|
||
BCC GTA1 ; JMP, ERROR OCCURRED
|
||
GTA3A: LDX #$00
|
||
STX DTMP3
|
||
JSR POSTNB
|
||
LDX SLTMP1 ; RESTORE SLOT ID
|
||
DOSFIN: LDA #0 ; 0 = NO ERRORS
|
||
CLC ; CARRY CLEAR FOR SUCCESS
|
||
BCC DOSEXI
|
||
|
||
; ERROR EXIT
|
||
|
||
DOSERR2: SEC ; CARRY SET FOR ERROR
|
||
|
||
; GENERAL EXIT
|
||
|
||
DOSEXI: STA DCBERR ; SAVE ERROR CODE HERE
|
||
LDA DRVOFF,X ; STOP THE DRIVE
|
||
RTS ; BYE!
|
||
|
||
; WRITE A SECTOR
|
||
|
||
DOSWRT: JSR WRTDTA
|
||
BCC DOSFIN ; ALL'S WELL IF CARRY CLEAR
|
||
LDA #$10 ; ELSE GET ERROR CODE INTO [A]
|
||
BNE DOSERR2 ; AND DO AN ERROR EXIT
|
||
|
||
|
||
; ---------------------
|
||
; SET UP FOR TRACK SEEK
|
||
; ---------------------
|
||
|
||
MYSEEK: ASL A ; TRACK*2 (PHASE OF DISK CARE)
|
||
JSR DOSEEK
|
||
LSR CTRACK ; CURRENT TRACK/2
|
||
RTS
|
||
|
||
|
||
; --------------
|
||
; EXECUTE A SEEK
|
||
; --------------
|
||
; PAGE BOUNDARY SHOULD BEGIN HERE!
|
||
|
||
DOSEEK: STA TTRK
|
||
JSR XTOY
|
||
LDA DR1TBL,Y
|
||
BIT DRVFLG
|
||
BMI EEK1
|
||
LDA DR2TBL,Y
|
||
EEK1: STA CTRACK
|
||
LDA TTRK
|
||
BIT DRVFLG
|
||
BMI EEK2
|
||
STA DR2TBL,Y
|
||
BPL EEK3
|
||
EEK2: STA DR1TBL,Y
|
||
EEK3: JMP SEEK
|
||
|
||
|
||
; --------------------
|
||
; GET SLOT ID INTO [Y]
|
||
; --------------------
|
||
|
||
XTOY: TXA
|
||
LSR A
|
||
LSR A
|
||
LSR A
|
||
LSR A
|
||
TAY
|
||
RTS
|
||
|
||
|
||
; ------------
|
||
; SET TRACK ID
|
||
; ------------
|
||
|
||
SETTRK: PHA
|
||
LDA DCBDRV
|
||
ROR A
|
||
ROR DRVFLG
|
||
JSR XTOY
|
||
PLA
|
||
ASL A
|
||
BIT DRVFLG
|
||
BMI SETT1
|
||
STA DR2TBL,Y
|
||
BPL SETT2
|
||
SETT1: STA DR1TBL,Y
|
||
SETT2: RTS
|
||
|
||
|
||
; -----------
|
||
; IDOS TABLES
|
||
; -----------
|
||
|
||
DR1TBL: DB 00,00,00,00 ; (8 BYTES)
|
||
DB 00,00,00,00
|
||
CTRACK EQU DR1TBL ; CURRENT TRACK
|
||
DR2TBL: DB 00,00,00,00 ; (8 BYTES)
|
||
DB 00,00,00,00
|
||
NSEEK: DB 00 ; SEEK COUNT
|
||
DTMP1: DB 00 ; RETRY COUNT
|
||
SLTMP1: DB 00 ; SLOT ID
|
||
SLTMP2: DB 00
|
||
NRECAL: DB 00 ; RECALIBRATE COUNT
|
||
|
||
;DUPLICATE INTERLEAVE TBL FOR USE AFTER BOOT
|
||
|
||
INTLVE: DB $00,$04,$08,$0C,$01,$05,$09,$0D
|
||
DB $02,$06,$0A,$0E,$03,$07,$0B,$0F
|
||
|
||
|
||
; ------------------
|
||
; READ SECTOR FROM BIG TRACK
|
||
; ------------------
|
||
; READ ADDRESS FIELD TO CHECK TRACK
|
||
; FIND HEADER $D5:$AA:$AD
|
||
|
||
RDFSEC: LDA #$20
|
||
STA HTEMP
|
||
TAY
|
||
RDFL1: LDA #$84 ; IN CASE ERROR OCCURS
|
||
DEC HTEMP
|
||
BEQ RDFBAD2
|
||
RDFL2: DEY
|
||
BEQ RDFL2
|
||
NOP
|
||
NOP
|
||
LDA Q6L,X
|
||
BPL RDFL2
|
||
CMP #$D5
|
||
BNE RDFL2
|
||
RDF1: LDA Q6L,X
|
||
BPL RDF1
|
||
CMP #$AA
|
||
BNE RDFL1
|
||
RDF2: LDA Q6L,X
|
||
BPL RDF2
|
||
CMP #$AD
|
||
BNE RDFL1
|
||
|
||
; HEADER FOUND - GET TRACK ID 4+4
|
||
|
||
SEC
|
||
RDF3: LDA Q6L,X
|
||
BPL RDF3
|
||
ROL A
|
||
STA TEMP
|
||
RDF4: LDA Q6L,X
|
||
BPL RDF4
|
||
AND TEMP
|
||
STA HDRTRK
|
||
LDA DTMP6
|
||
BMI RDFOK ; ONLY LOOKING FOR TRACK NUMBER AND ?
|
||
RDFNEXT: LDY #$56 ; SET INDEX (AND TIMING)
|
||
|
||
; SKIP UNUSED SECTORS
|
||
|
||
LDA #$00 ; ZERO >A<
|
||
RDFL3: DEY ; NEXT
|
||
STY DTMP3 ; SAVE INDEX
|
||
RDF5: LDY Q6L,X ; GET A BYTE
|
||
BPL RDF5 ; WAIT VALID
|
||
EOR RDTBL-$96,Y ; CHECK SUM AND DECODE
|
||
LDY DTMP3 ; GET INDEX
|
||
STA BUFFB,Y ; SAVE DATRA
|
||
BNE RDFL3 ; LOOP TILL DONE
|
||
RDFL4: STY DTMP3 ; SAVE INDEX
|
||
RDF6: LDY Q6L,X ; GET A BYTE
|
||
BPL RDF6 ; WAIT VALID
|
||
EOR RDTBL-$96,Y ; DECODE AND CHECK SUM
|
||
LDY DTMP3 ; GET INDEX
|
||
STA BUFFA,Y ; SAVE DATA
|
||
INY ; NEXT
|
||
BNE RDFL4 ; LOOP TIL DONE
|
||
RDF7: LDY Q6L,X ; GET A BYTE
|
||
BPL RDF7 ; WAIT VALID
|
||
DEC DTMP6
|
||
BPL RDFNEXT
|
||
CMP RDTBL-$96,Y ; CHECK SUM VALID?
|
||
BNE RDFBAD ; NO, EXIT ERROR
|
||
RDFOK: CLC
|
||
RTS
|
||
|
||
RDFBAD: LDA #$85
|
||
RDFBAD2: STA DCBERR
|
||
SEC
|
||
RTS
|
||
|
||
|
||
; ----------------------
|
||
; MACHINE INITIALIZATION
|
||
; ----------------------
|
||
|
||
INIT: LDA TXTSET ; SET TEXT MODE
|
||
LDA MIXCLR ; SET NO MIX
|
||
LDA LOWSCR ; SET PAGE 1
|
||
LDA #>IOBUFF ; POINT [DCBBFL/M] TO [IOBUFF]
|
||
STA DCBBFM
|
||
LDA #<IOBUFF
|
||
STA DCBBFL
|
||
LDA #1
|
||
STA DCBDRV ; SET DRIVE = 1
|
||
STA DCBPDR
|
||
RTS
|
||
|
||
END
|
||
|