; ;************************************* ; ; ULD: UPLOAD PROGRAM DATA TO DUP BOARD ; ; ENTRY:STRADR SET BY SET ADDRESS ; :COMMAND ; ; EXIT:STATUS ($A0) HOLDS STATUS ; :0=OK 1=CHECKSUM ERROR ; :2=MEMORY OUT OF RANGE ERROR ; ;************************************** ; ULD PROC ; :STATUS = $A0 ;STATUS OF OPERATION :TEMP = $AF ;TEMP MEMORY LOCATION ; LDA #$00 STA :TEMP LDA STRADR+1 CMP #$60 ;TOP OF MEMORY EXCEDED? BCC :ULD01 ;YES WE HAVE MEM ERROR LDA #$FF STA :TEMP :ULD01 LDA #0 ;SAVE VALUE OF LENTH LDX STRADR ;LOW BYTE OF POINTER STX BPNT LDX STRADR+1 STX BPNT+1 JSR READ LDA :TEMP BNE :ULD02 INC STRADR+1 ;ADD ONE TO UPLOAD ADR BNE :ULDXT :ULD02 LDA #$02 STA :STATUS :ULDXT RTS EPROC ; ;************************************* ; ; DSKSTS: CHECK DISK STATUS ; ; ENTRY:NONE ; EXIT:$A0=0 IF OK ; :$A0=1 IF DOOR OPEN OR WRITE ; : PROTECT IS ON ; : SETS BIT 3 IN STAT ; ;************************************** ; DSKSTS PROC ; :STATUS = $A0 ; LDA #0 STA :STATUS LDA STREG STA TEMP BIT TEMP BPL :DSK01 ;DOOR IS NOT OPEN LDA :STATUS ORA #$01 STA :STATUS :DSK01 LDA STAT AND #$08 ;WRITE PROTECT NOT ON BEQ :DSK02 LDA :STATUS ORA #$01 STA :STATUS ; ;NOW SET GLOBAL STATUS BITS UP ; :DSK02 LDA TEMP EOR #$FF STA STAT+1 RTS ; ; ;************************************* ; ; DENSITY AND A HALF FORMAT ROUTINE ; ;************************************* ; DAHF PROC ; :STATUS = $A0 :TRYS = $AF ; ;IF WE GET HERE FORCE DENSITY AND 1/2 ; LDA #0 STA NTRK JSR SKTK ;GO TO TRACK ZERO ; LDA #26 STA CONFIG+3 LDA #128 STA CONFIG+7 LDA #0 STA CONFIG+5 STA CONFIG+6 LDA STAT AND #%01011111 ORA #%10000000 ;SET DUAL DENS STATUS STA STAT JSR DFLTS ;SET DEFAULT SECTOR SKEW LDA #0 ;START WITH TRACK 0 JSR DUTRK ;MAKE A HALF DENS TRACK LDA #$DF ;PUT FDC INTO DD MODE AND DRA STA DRA :LOOP JSR DFMT ;FORMAT TRACK LDA :STATUS BNE :DH001 ;ERROR IN FORMAT LDA #39 CMP TRACK BEQ :DH002 ;END OF FORMAT JSR INT JMP :LOOP ; :DH002 LDA #0 STA :STATUS JMP :EXIT ; :DH001 LDA #$01 ;HANDLE THE ERROR STA :STATUS ; :EXIT RTS EPROC ; ;************************************** ; ; DOUBLE DENSITY FORMAT ; ;************************************** ; DDFMT PROC ; :STATUS = $A0 ; LDA #$DF ;PUT IN DD MODE AND DRA STA DRA LDA #0 JSR DDTRK ;INIT TRACK 0 JSR DFMT ;FORMAT TRACK LDA :STATUS ;CHECK STATUS BNE :SFR01 ;ERROR LDA #1 JSR DDTRK ;INIT REGULAR TRACK JSR INT ;INCREMET TRACK NUMBER :LOOP1 JSR DFMT ;FORMAT TRACK LDA :STATUS BNE :SFR01 ;ERROR LDA #39 CMP TRACK BEQ :SFR02 ;DONE JSR INT ;INCREMENT TRACK NUMBER JMP :LOOP1 :SFR02 LDA #0 STA :STATUS JMP :EXIT ; ;HANDLE AN ERROR ; :SFR01 LDA #$01 STA :STATUS :EXIT RTS EPROC ; ;************************************* ;SINGLE DENSITY FD FORMAT ; ;************************************* ; SFRMAT PROC ; :STATUS = $A0 ;STATUS LOCATION ; LDA #$20 ;PUT INTO SD MODE ORA DRA STA DRA JSR ITRKS ;MAKE SINGLE D TRACK IMAGE :LOOP JSR FMT ;FORMAT TRACK LDA :STATUS BEQ TRKOK LDA #$01 STA :STATUS JMP :EXIT ; TRKOK LDA #39 CMP TRACK BEQ :SDF01 JSR INT ;INCREMENT TRACK NUMBER JMP :LOOP ; :SDF01 LDA #$00 STA :STATUS ; ;SET UP SKEW TABLE ; :EXIT RTS EPROC ; ;************************************** ; ;INCREMENT TRACK NUMBER ; ;************************************** ; INT PROC ; :EOTKP = $AD ; LDA CONFIG+3 ;SECTOR LENTH ASL A ;* 2 STA :EOTKP LDA #$FF JSR STEPT ;GO TO NEXT TRACK JSR FINT LDX #$00 LDA TRACK ;GET TRACK NUMBER LTRK STA (TNPNT,X) INX INX CPX :EOTKP ;ALL TRACK NUMBERS UPDATED? BNE LTRK RTS EPROC ; ;************************************** ; ; FMT: FORMAT SINGLE TRACK SD ; ;************************************** ; FMT PROC ; :STATUS = $A0 ;STATUS OF FORMAT :TRYS = $AF ;NUMBER OF RETRYS ; LDA #$05 STA :TRYS ;SET NUMBER OF RETRYS ; :FMT09 JSR DSKSTS ;CHECK STATUS OF DISK LDA :STATUS BEQ :FMT01 JMP :EXIT ;DEVICE NOT READY EXIT :FMT01 LDA #$00 STA BASE ;RESET LOW BYTE OF POINTER LDA #$20 STA BASE+1 ;RESET HIGH BYTE LDY #0 ;CLEAR INDEX STY DTAREG ;INIT DATA REG LDA #1 STA WT24E ; LDX #100 :FMT02 DEX ;HOLD YOUR HORSES A BIT BNE :FMT02 ;JUST HUMOR ME, OK! ; LDA #$F0 ;WRITE TRACK CMD STA CMDREG :FMT03 BIT DRA BPL :FMT03 STY DTAREG :FMT04 BIT DRA BPL :FMT04 STY DTAREG LDA WT64D LDA #$D1 STA WT24E ;RESET TIMER TO 208 MS ; :FMT05 BIT DRA BMI :FMT25 BVS :FMT05 BVC TRKERR ;RETRY TRACK WRITE BPL :FMT05 :FMT25 LDA (BASE),Y STA DTAREG ;NEXT DATA INC BASE ;INCREMENT BASE POINTER BNE :FMT15 INC BASE+1 :FMT15 LDA BASE CMP BPNT BNE :FMT05 LDA BPNT+1 CMP BASE+1 BNE :FMT05 LDA #$01 ;MASK FOR BUSY LDX #0 ;DATA BYTE :FMT06 AND STREG ;BUSY STATUS? BEQ :FMT07 ;CMD GONE BIT DRA BPL :FMT06 ;WAIT FOR DATA REQUEST STX DTAREG ;PADDING JMP :FMT06 :FMT07 LDA STREG AND #$04 ;LOST DATA? BEQ :FMTXT ;GOOD TRACK TRKERR LDA WT64D JSR FINT ;RETRY TRACK FORMAT DEC :TRYS BNE :FMT08 LDA #$01 STA :STATUS JMP :EXIT :FMT08 JMP :FMT09 :FMTXT LDA #$00 STA :STATUS :EXIT LDA RTDE ;CLEAR TIMING PULSE RTS EPROC ; ;************************************** ; ; DFMT: FORMAT SINGLE TRACK DD ; ;************************************** ; DFMT PROC ; :STATUS = $A0 ;STATUS OF FORMAT :TRYS = $AF ;NUMBER OF RETRYS ; LDA #$05 STA :TRYS ;SET NUMBER OF RETRYS ; :FMT09 JSR DSKSTS ;CHECK DISK STATUS LDA :STATUS BEQ :FMT01 JMP :EXIT ;DEVICE NOT READY EXIT :FMT01 LDA #$00 STA BASE ;RESET LOW BYTE OF POINTER LDA #$20 STA BASE+1 ;RESET HIGH BYTE LDY #$4E ;CLEAR INDEX STY DTAREG ;INIT DATA REG LDA #1 STA WT24E ; LDX #100 :FMT02 DEX ;HOLD YOUR HORSES A BIT BNE :FMT02 ;JUST HUMOR ME, OK! ; LDA #$F0 ;WRITE TRACK CMD STA CMDREG :FMT03 BIT DRA BPL :FMT03 STY DTAREG :FMT04 BIT DRA BPL :FMT04 STY DTAREG LDA WT64D LDA #$CC STA WT24E ;RESET TIMER TO 208 MS LDY #0 LDA (BASE),Y ; :FMT05 BIT DRA ;4 BVC :TRKER ;2+ ERROR TRY AGAIN BPL :FMT05 ;2+ STA DTAREG ;4 NEXT DATA INC BASE ;5 INCREMENT BASE POINTER BNE :FMT15 ;2 + INC BASE+1 ;5 :FMT15 LDA (BASE),Y ;5+ CMP #$B7 ;2 END OF TRACK MARK BNE :FMT05 ;3 LDA #$01 ;MASK FOR BUSY LDX #$4E ;DATA BYTE :FMT06 AND STREG ;BUSY STATUS? BEQ :FMT07 ;CMD GONE BIT DRA BPL :FMT06 ;WAIT FOR DATA REQUEST STX DTAREG ;PADDING JMP :FMT06 :FMT07 LDA STREG AND #$04 ;LOST DATA? BEQ :FMTXT ;GOOD TRACK :TRKER LDA WT64D JSR FINT ;RETRY TRACK FORMAT DEC :TRYS BNE :FMT08 LDA #$01 STA :STATUS JMP :EXIT :FMT08 JMP :FMT09 :FMTXT LDA #$00 STA :STATUS :EXIT LDA RTDE ;CLEAR TIMING PULSE RTS EPROC ; ; ;************************************** ; ; FORCE INTERRUPT ; ;************************************** ; FINT PHA TXA PHA LDA #$D0 STA CMDREG LDX #7 FINT1 DEX BNE FINT1 LDA #1 FINT2 BIT STREG BNE FINT2 PLA TAX PLA RTS ; ;************************************** ; ; VDSK: VERIFY DISK ; ; ENTRY:ACC=DATA TO COMMPARE ; EXIT:STATUS=0 VERIFY GOOD ; :STATUS=0 BAD DISK ; ;************************************** ; VDSK PROC ; :STATUS = $A0 :DATA = $A1 ; STA :DATA ;SAVE COMPARE DATA FOR LATER ; LDA #39 ;TRACK 39 STA NTRK LDA #0 STA BPNT1 ;BUFFER FOR BAD SECTOR MAP LDA #$20 STA BPNT1+1 LDA #$FF STA BUFF STA BUFF+1 :DH003 JSR SKTK LDA :DATA ;DATA TO COMPARE JSR VTRK LDA :STATUS BEQ :DH001 ;NO SECTOR ERROR JMP :VDXIT ;BAD SECTOR ERROR, EXIT :DH001 DEC NTRK BIT NTRK ;LESS THAN ZERO? BPL :DH003 LDA #0 STA :STATUS :VDXIT RTS EPROC ; ;************************************** ; ; VTRK : VERIFY THAT A TRACK IS WRITTEN ; CORRECTLY ; ; ENTRY: A = DATA TO COMPARE ; NTRK = TRACK # ; BPNT1 = PNTR TO SECTOR INFO ; EXIT: BPNT1 POINTS TO BAD SECR INFO ; ;************************************** ; VTRK PROC ; :STATUS = $A0 ; PHA ;SAVE DATA TO COMPARE LDA #0 STA :STATUS STA BPNT ;PNTR TO MODEL SECTOR LDA #$21 STA BPNT+1 PLA LDY #0 VT1 STA (BPNT),Y INY BNE VT1 LDA #0 ;SET INDEX TO SECTOR STA SECT VT2 LDX SECT LDA SKTAB,X ;GET SECTOR NUMBER JSR CTS ;CHECK TRACK SECTOR STATUS JSR VSEC BCC VT3 LDA #$01 STA :STATUS JMP :VTXIT ;BAD SECTOR ERROR, EXIT NOW VT3 INC SECT LDX CONFIG+3 ;END OF TRACK? CPX SECT BNE VT2 :VTXIT RTS EPROC ; ; ;************************************** ; ; MULT : 8 BIT MULTIPLY ; ; ENTRY : ACC = MULTIPLIER ; X-REG = MULTIPLICAND ; EXIT : PROD IN ACC AND X REG ; ;************************************** MULT PROC ; :MCAND = $82 :MLPLR = $84 :PROD = $86 ; STA :MLPLR STX :MCAND LDA #0 STA :PROD+1 LDX #8 SHIFT ASL A ROL :PROD+1 ASL :MCAND BCC CHCNT CLC ADC :MLPLR BCC CHCNT INC :PROD+1 CHCNT DEX BNE SHIFT LDX :PROD+1 ;LSB IN ACC, MSB IN X RTS EPROC ; ;************************************** ; ; STEP TRACK ; THIS ROUTINE WILL STEP ONE TRACK ; ; ENTRY:ACC=DIRECTION ; :$00 = STEP FORWARD ; :$FF = STEP BACKWARD ; ; EXIT:CARRY SET STEP ERROR ; ;CARRY CLEAR OK ;************************************** ; STEPT PHA ;SAVE COMMAND JSR TINC ;INC TRACK COUNTER BCS STEPTX ;EXIT IF ERROR PLA PHA JSR STEP PLA PHA JSR STEP CLC STEPTX PLA RTS ; ; ;************************************** ; ; STEPPER MOTOR ROUTINE ; THIS ROUTINE ONLY STEPS A HALF A ; A TRACK ; ; ENTRY:ACC=STEP DIRECTION ; :$00=STEP FORWARD ; ;$FF=STEP BACKWARD ; ; EXIT:NONE ; ;************************************** ; STEP PHA ;SAVE COMMAND LDA DRB ;GET CURRENT STEP POSITION ORA #$C3 ;STRIP OFF OTHER BITS LDX #$00 ;SET INDEX COUNT STEP21 CMP SDAT,X ;FIND ENTRY IN TABLE BEQ STEP22 INX ;NEXT ENTRY CPX #$05 ;ALL OUT OF ENTRIES BNE STEP21 PLA SEC ;SET ERROR FLAG BCS STPXIT ;EXIT FROM ROUTINE ; STEP22 PLA ;GET COMMAND BACK CMP #$00 ;COMPARE DIRECTION? BNE STEP01 ;BACKWARD STEP INX ;POINT TO NEXT ENTRY CPX #$05 ;IF XREG=5 THEN BNE STEP23 LDX #$01 ;XREG=1 STEP23 LDA DRB ;LOAD STEP DATA ORA #$3C ;SET ALL BITS HIGH AND SDAT,X ;SET ONE BIT LOW STA DRB ;SET PORT JSR SWAIT ;WAIT FOR 10mSEC CLC ;SET OK STATUS BCC STPXIT STEP01 DEX ;POINT TO NEXT ENTRY CPX #$00 ;IF XREG=0 THEN BNE STEP23 LDX #$04 ;XREG = 4 BNE STEP23 STPXIT RTS ;EXIT POINT STEP ; SDAT DB $FF,$FB,$F7,$EF,$DF ;STEP DATA ; ;************************************** ; ; TRACK INCREMENT ROUTINE ; ;************************************** ; TINC PHA CMP #0 BEQ TINC01 INC TRACK LDA TRACK CMP #40 ;FORTY TRACKS? BCC TINCXT LDA #39 STA TRACK SEC BCS TINCXT TINC01 DEC TRACK LDA TRACK CMP #$FF BNE TINC02 LDA #$00 STA TRACK SEC BCS TINCXT TINC02 CLC TINCXT PLA RTS ; ; ;************************************** ; ; READ DISK ADDRESS ; RETURNS ADDRESS IN SIX BYTE BLOCK ; ON PAGE ZERO ; ;************************************** ; RADR PROC ; :TRYS = $A1 ; PHA ;SAVE ACC TXA PHA LDA #$06 STA :TRYS ;SET NUMBER OF TRYS AT READ RADR10 LDX #$7A LDA #$D0 JSR STMO LDX #$00 ;INDEX OF BLOCK LDA #$C0 ;LOAD READ ADRESS COMMAND STA CMDREG ; RADR01 BIT DRA ;WATCH DATA READY FLAG BVC RADR04 BPL RADR01 LDA DTAREG ;READ DATA REGISTER STA TADRES,X LDA WT64D INX CPX #$06 ;SIX BYTES YET? BNE RADR01 LDA #$01 RADR03 BIT STREG BNE RADR03 LDA #$08 BIT STREG BEQ RDRXIT ;ALL SIX BYTES READ, EXIT DEC :TRYS BNE RADR10 RADR05 SEC ;SET CARRY TO IND. ERROR BCS RADRXT ; RADR04 LDA RTDE ;DISABLE INTERRUPTS DEC :TRYS ;DECREMENT # OF TRYS BEQ RADR05 ;ERROR, EXIT LDA #$D0 JSR STMO ;SET TIME OUT JMP RADR01 ; ;SIX BYTES READ, EXIT ; RDRXIT CLC ;NO ERROR ; RADRXT PLA TAX PLA RTS EPROC ; ;************************************** ; ; SWAIT:10 MSEC DELAY LOOP ; ; VARIABLE SRATE NOW CONTAINS TIME ; TO WASTE DOING NOTHING ; ; :PRESERVES ALL REGISTERS ; ;************************************** ; SWAIT PHA ;SAVE ACCUMULATOR TXA PHA ;SAVE X REGISTER ; ;9 CYCLES ; LDA #$00 STA TEMP ; ;5 CYCLES ; SWAIT1 LDX SRATE ;STEP TIME SWAIT0 DEX ;DECREMENT X REG DEX INX BNE SWAIT0 ; ;9 CYCLES * 111=999 ; INC TEMP LDA TEMP CMP #$0A BNE SWAIT1 ; PLA ;POP X REG TAX PLA ;POP ACCUMULATOR ; RTS ; ; ;************************************** ; ; SEEK TRACK ZERO ; PRESERVES ALL REGISTERS ; AND INITIALIZES DISK ADDRESS ; ;************************************** ; TRK0 PROC ; PHA ;SAVE ACCUM TXA ;PUSH X REG PHA TYA ;PUSH Y REG PHA JSR FINT ;FORCE INTERRUPT LDA #$55 STA TRKREG STA TRACK TRK001 LDA #$48 STA CMDREG ;STEP IN COMMAND LDA #$00 JSR STEP ;STEP DRIVE JSR SWAIT :LOOP LDA STREG;WAIT FOR STEP NOT BUSY AND #$01 BNE :LOOP LDA STREG AND #$04 ;CHECK FOR TRACK ZERO IND BNE TRK001 ;IF NOT TRK0 KEEP GOING ; ;OK, WE ARE WITHIN +/- 1/2 TRACK ;GIVE THE STEPPER THE COUP DE GRASS ; LDA DRB ORA #%00111100 AND SDAT + 4;STEPPER CAL POSITION STA DRB JSR SWAIT LDA #0 STA TRACK LDA DRB STA STPPOS CLC PLA TAY PLA TAX PLA RTS EPROC ; ; ;************************************** ; ; SEEK TRACK ; ; ENTRY:NTRK = TRACK NUMBER TO SEEK ; ; EXIT:CARRY SET IF TRACK NOT FOUND ; ; ;************************************** ; SKTK PROC ; :LOOP LDA NTRK CMP TRACK ;NEW TRACK? BEQ :SKT02 ;TRACK FOUND, EXIT OK BCS :SKT01 ;NEW TRACK IS LESS LDA #$00 ;STEP FORWARD JSR STEPT ;STEP A TRACK BCC :LOOP ;IF NO ERROR, LOOP BCS SKTXIT ;ERROR IN STEPING :SKT01 LDA #$FF ;STEP THE OTHER WAY JSR STEPT ;STEP A TRACK BCC :LOOP ;IF OK, KEEP LOOPING BCS SKTXIT ;ERROR IN STEPPING :SKT02 CLC SKTXIT RTS EPROC ; ;************************************** ; ; CALCULATE NEW TRACK/SECTOR NUMBER ; ; ENTRY:ATARI SECTOR NUMBER IN ; :CMDFRM+2 AND CMDFRM+3 ; EXIT:TRACK NUMBER IN ; :NTRK AND SECTOR NUMBER ; :IN NSEC CMDFRM+2 AND +3 ARE ; :DESTROYED ; ; SAVES NO REGISTERS ; ;************************************** ; NTS PROC ; SEC ;PREPARE TO SUBTRACT LDA CMDFRM+2 SBC #$01 STA CMDFRM+2 LDA CMDFRM+3 SBC #$00 STA CMDFRM+3 BCC NTSERR ;SECTOR NUMBER ERROR ; ;CALCULATE TRACK/SECTOR ; ACCL = CMDFRM+2 ACCH = CMDFRM+3 ; BIT STAT ;CHECK STATUS REGISTER BMI :NTS01 ;DUAL DENSITY LDA #18 ;NUMBER OF SECTORS PER TRACK JMP :NTS02 ; :NTS01 LDA #26 ;26 SECTORS PER TRACK :NTS02 STA TEMP LDY #8 ;NUMBER OF BITS TO DIVIDE BY ASL ACCL UDIV1 ROL ACCH ;SHIFT DIVIDEND BCS UDIV2 ;JMP IF 1 SHFTD OUT OF DVDND LDA ACCH ;SUBTRACT DIVISOR FROM ACCH SEC SBC TEMP BCC UDIV4 ;JMP TO SHIFT AND COUNT IF ;UNDEFLOW IS IMMENIENT,CARRY ;IS QUOTIENT BIT STA ACCH ;STORE DIFF IF NO UNDEFLOW ;FLAG IS QUOTIENT BIT BCS UDIV4 ; UDIV2 LDA ACCH ;SUBTRACT DVSR FRM ACCH; SBC TEMP BCS UDIV3 ;SKIP IF UNDERFLOW IMMENIENT STA ACCH SEC BCS UDIV4 UDIV3 CLC ;QUOTIENT BIT IS ZERO UDIV4 ROL ACCL ;SHIFT DIVIDENT LOW PART DEY ;COUNT INTERATIONS BNE UDIV1 ; LDA ACCL STA NTRK ;STORE NEW TRACK NUMBER LDA ACCH STA NSEC ;NEW SECTOR INC NSEC ;NSEC==+1 CLC BCC NTSXIT NTSERR SEC NTSXIT RTS EPROC ; LINK D2:DD15M4.ASM