;HDFMT2/ASM - Hard format module - 10/31/83 IF LDI ;*=*=* ; Begin the actual format - Check for "one" drive ;*=*=* XOR A ;Init the count EXX LD B,A EXX LD C,(IY+1) ;P/u the driver vector LD B,(IY+2) ; & ck for # parts LD HL,DCT$ TSTDCT PUSH HL LD A,(HL) ;Is this disabled? CP 0C9H JR Z,NOTRES INC HL LD E,(HL) ;P/u the driver vector INC HL LD D,(HL) XOR A EX DE,HL SBC HL,BC EX DE,HL JR NZ,NOTRES ;Go if not this driver INC HL INC HL INC HL ;Point to DCT+5 LD A,(HL) CP (IY+5) ;Is this the same drive? JR NZ,NOTRES EXX INC B ;Bump the drive count EXX NOTRES POP HL LD DE,10 ;Advance to next one ADD HL,DE LD A,8*10+DCT$&0FFH CP L ;Done with DCTs? JR NZ,TSTDCT EXX ;Check how many drives! DEC B ;Is there only one? EXX JR NZ,HRDRV1 ;Only FORMAT if one!!! ;***** ; Hard drive format - most work done by controller ;***** HRDRV BIT 3,(IY+3) ;Check for floppy JR Z,AFLOP ;Go if a floppy LD HL,LAST$ ;Give one last chance to CALL GETARG ;Abort before wiping disk AND 5FH ;Make U/c CP 'Y' ;Must be yes to continue JP NZ,FMTABT AFLOP LD A,(SYSPRM+1) ;Bypass the formatting OR A ; if system info only JR NZ,HRDRV1 LD HL,FMTG$ ;"formatting - be patient LD DE,0 ;Set up for no interleave BIT 3,(IY+3) ;Hard drive? JR NZ,GOFMT LD E,5 ;Set interleave for 5" BIT 5,(IY+3) ;5" floppy? JR Z,GOFMT LD E,5 ;Same, but patchable! GOFMT CALL FMTHD ;Format hard drive JP NZ,IOERR ENDIF ; ;*=*=* ; Clear out the BOOT space ;*=*=* HRDRV1 LD HL,BOOT1 ;CLear the BOOT space PATLP LD (HL),6DH ;Using 6DB6 pattern INC L LD (HL),0B6H INC L LD A,L CP 208 JR NZ,PATLP ;*=*=* ; Calculate sectors/track & sectors/cylinder ;*=*=* LD A,(IY+7) ;# of sectors/track LD D,A ;-> reg E AND 1FH ;Strip # of heads LD E,A INC E ;Bump for 0 offset LD (SECTRK),A ;Stuff # sectors/track XOR D RLCA ;Get # of heads RLCA ; into reg D RLCA INC A ;Adjust for zero offset CALL MULTEA@ BIT 5,(IY+4) ;Double tracking? JR Z,$+3 ADD A,A ;Twice the number LD (SECCYL),A ;*=*=* ; Test if SYSTEM information only ;*=*=* SYSPRM LD HL,0 ;P/u system info only LD A,H ;Don't format if system OR L ; info only is req JP NZ,DONTFMT ; IF LSI!MTI!ARM!TRS!PDC ;*=*=* ; Begin the formatting ;*=*=* LD HL,FMTCYL$ ;"formatting clinder... CALL @DSPLY BGNFMT LD D,0 ;Init to cyl 0 BFMT1 LD A,D ;P/u cylinder position CALL CVDEC ;Cvrt to decimal PUSH DE ;Don't alter reg D CALL DSPCYL ;Display cyl # POP DE ENDIF ; IF MTI!TRS!PDC LD HL,SKEWDAT ;Point to skew table ENDIF ; IF LSI!MTI!ARM!TRS!PDC CALL WRCYL ;Cylinder write JP NZ,IOERR BFMT5 LD A,D ;Was this the last INC D ; cylinder to format? CP (IY+6) JR NZ,BFMT1 ENDIF DONTFMT EQU $ ; IF LSI ;*=*=* ; Lockout the alternate cylinder ;*=*=* LD HL,ALTLO$ ;"Inhibiting... CALL @DSPLY LD HL,GATBUF+77 LD (HL),0FFH ENDIF ; ;**** Lock out CYL #1 on TRS or PERCOM for diagnostics. IF TRS!PDC LD HL,DIAG$ CALL @DSPLY LD HL,GATBUF+1 LD (HL),0FFH ENDIF ; VERPRM LD DE,-1 ;P/u verify parm LD A,D ;If 0, don't verify OR E JP Z,DONTVER ;***** ; Begin the verification process ;***** LD HL,VERCYL$ ;"Verifying cylinder... CALL @DSPLY LD D,0 ;Init cylinder ctr BVER1 LD L,D ;Pt to GAT byte for this LD H,GATBUF<-8 ; track & bypass verify LD A,(HL) ; if track not formatted INC A JR Z,BVER8 LD A,D ;If this is the DIR cyl, ; IF MTI!LSI!ARM!TRS!PDC CP (IY+9) ; use VERSYS, else VERSEC LD HL,WRSEC ;Init for reg sector JR NZ,$+5 LD HL,WRSYS ;Init for system sector LD (BVER2W+1),HL ;Stuff vector LD HL,VERSEC JR NZ,$+5 LD HL,VERSYS LD (BVER2V+1),HL ENDIF ; CALL CVDEC ;Cvrt to decimal PUSH DE CALL DSPCYL ;Display cylinder # POP DE XOR A ;Initialize starting LD (BVER5+1),A ; sector LD E,A BVER2 LD HL,BOOT1 ;Point to buffer ; IF LDI BIT 3,(IY+3) ;Only WRSEC a hard disk * CALL NZ,WRSEC ;Write first then... CALL Z,VERSEC ;SECtor or SYStem verify ENDIF ; IF MTI!LSI!ARM!TRS!PDC BVER2W CALL WRSEC ;Write first then... BVER2V CALL Z,VERSEC ;SECtor or SYStem verify ENDIF ; JR NZ,BVER9 ;Go on error BVER5 LD A,0 ;P/u sector # INC A ;Bump it up BVER6 LD (BVER5+1),A ; and save new # LD E,A ;Xfer to sector register LD A,(SECCYL) ;Is this = a cyl? CP E JR NZ,BVER2 ;Go if cyl not done ;*=*=* ; Readjust for end of cylinder ;*=*=* BVER8 LD A,D ;P/u current cyl position INC D ;Bump to next cyl CP (IY+6) ;Cp to highest # cyl JR NZ,BVER1 ;Go if more to verify ; IF LDI ;*=*=* ; If a floppy, then do the lockout table ;*=*=* BIT 3,(IY+3) ;If floppy, make a JR NZ,CALCDIR ; lockout, else skip * LD HL,GATBUF ;Allocation table LD DE,GATBUF+60H ;Lockout table LD B,0 ;High order length LD C,(IY+6) ;# of cyls INC C ;Adj for zero offset LDIR ENDIF ; JR CALCDIR ;Go start system info ;*=*=* ; Got verify error ;*=*=* BVER9 EQU $ ; IF LDI BIT 3,(IY+3) ;If floppy, only l/o JR NZ,BVER9A ; error 4 & 5 CP 5 ;Data rec not found? JR Z,BVER10 CP 4 ;Parity error? JP NZ,IOERR JR BVER10 BVER9A EQU $ ENDIF ; CP 8 ;Hard, l/o all except JP Z,IOERR ; device not avail... CP 16 ; & all > 15 JP NC,IOERR ;*=*=* ; Lockout granule (hard) or cylinder (floppy) ;*=*=* BVER10 PUSH DE LD HL,STAR$ ;Show the * lockout CALL @DSPLY POP DE LD L,D LD H,GATBUF<-8 BIT 3,(IY+3) ;If hard drive, then JR NZ,BVER11 ; only lockout gran LD (HL),0FFH ;Lockout this cylinder JR BVER8 ; its a floppy... ;*=*=* ; Bad sector on hard drive - Lockout the Granule ;*=*=* BVER11 LD A,(IY+8) ;Get # of sectors/gran PUSH DE ;Save this reg AND 1FH INC A ;Adj for zero offset CALL DIVEA@ ;Calc which granule PUSH AF ;Save gran # LD E,(HL) ;P/u current GAT byte CALL SETBIT ;Show gran allocated LD (HL),E ;Restuff into GAT LD A,(IY+8) ;Now point to next sector AND 1FH INC A LD E,A ;Xfer SPG to reg E POP AF ;Rcvr # of bad gran INC A ;Bump to start on next * CALL MULTEA@ ;Calc 1st sector of POP DE ; next gran & continue JR BVER6 ; DONTVER EQU $ ;***** ; Perform expanding binary search to find ; a cylinder available for the directory ; but start with suggested cylinder ;***** CALCDIR LD A,CR ;Close the display line CALL @DSP ; IF LSI ;Laredo must use this cyl LD L,(IY+9) ;P/u recommended dir cyl ENDIF ; IF .NOT.LSI LD L,(IY+6) ;P/u highest # cyl INC L ;Bump for 0 offset SRL L ;Find midpoint ENDIF ; LD C,0 ;Point to GAT byte for LD H,GATBUF<-8 ; this cylinder CALC1 LD A,0 ;P/u default GAT byte CP (HL) ;Is this cylinder locked? JR Z,GENSYS ;Bypass if available INC C ;Bump C LD A,C RRCA ;Test if odd or even LD A,L ;Get current test pos JR NC,CALC2 ;Jump if C was even ADD A,C ;Add to previous pos LD L,A CP (IY+6) ;Go over the top? JR NZ,CALC1 ;Loop if not JR CALC3 ;Else abort CALC2 SUB C ;Try a lower cylinder # LD L,A JR NZ,CALC1 ;At cylinder 0? CALC3 LD HL,NOCYL$ ;"No dir space avail... JP FMTABT ;*=*=* ; Generate the system initialization ;*=*=* GENSYS LD (IY+9),L ;Stuff the dir cyl LD A,L CALL CVDEC ;Cvrt reg A to 3 dec digs LD (DIRASC$),BC ;Stuff into the message LD (DIRASC$+2),A LD HL,DIRCYL$ ;"Dir will be placed... CALL @DSPLY LD HL,IPLSYS$ ;"Initializing... CALL @DSPLY LD HL,GATBUF LD A,(HL) ;P/u GAT byte for 1st OR 1 ;Cylinder & show 1st LD (HL),A ;Gran in use for BOOTs LD A,(IY+9) ;Dir cyl # into DIR/SYS LD (DIRDIR+16H),A LD L,A ;Show entire directory LD (HL),0FFH ;Cylinder locked out ;*=*=* ; Update BOOT for DIR ;*=*=* LD DE,0 ;Init for cyl 0, sect 0 CALL VERSEC ;Test if formatted JP NZ,NOTFMT ;Error if not LD HL,BOOT1 ;Pt to R/S E/I BOOT rtn LD C,0 CALL RDSECT@ ;Read BOOT1 from Drive 0 JP NZ,IOERR LD A,(IY+9) ;Dir cyl into BOOT LD (BOOT1+2),A CALL WRSEC ;Write R/S BOOT sector JP NZ,IOERR CALL VERSEC ;Verify after write JP NZ,IOERR CALL DOT ;Show "." LD DE,1 ;Pt to cyl 0, sector 1 LD C,0 ;Refer to drive 0 CALL RDSECT@ ;Read the real BOOT JP NZ,IOERR LD A,(IY+9) ;Dir cyl into BOOT LD (BOOT1+2),A CALL WRSEC ;Write 0/1 JP NZ,IOERR CALL VERSEC ;Verify after write JP NZ,IOERR CALL DOT ;*=*=* ; Complete GAT construction ;*=*=* LD A,(IY+6) ;P/u highest # cylinder SUB 22H ;Adj offset from 34 LD (GATBUF+0CCH),A ;Stuff GAT cyl excess LD A,(IY+4) ;P/u sec siz & # of sides AND 80H+20H LD B,A LD A,(IY+3) ;P/u density AND 40H OR B LD B,A LD A,(IY+8) ;P/u # of grans/cyl RLCA RLCA RLCA AND 7 LD (CYLGRN+1),A OR B ;Merge the two IF RAM OR 88H ;Set DATA disk bit ENDIF LD (GATBUF+0CDH),A ;Stuff into GAT ; LD DE,GATBUF+255-10;6.2 Media Data Block LD HL,LSIID ;Point to header LD BC,04 ;Set length LDIR ; move it PUSH IY POP HL ;This drive's DCT INC HL INC HL INC HL ;Bypass the JP addr LD C,7 ; bytes to move LDIR ; move it in JR WRGAT1 ;Skip around string LSIID DB 03,'LSI' ; ;*=*=* ; Write copy of GAT into 0/3 ;*=*=* WRGAT1 LD HL,GATBUF ;Pt to GAT buffer LD D,0 ;Write it out to LD E,3 ;Cyl 0, sector 3 CALL WRSEC ;Write 0/3 JP NZ,IOERR CALL VERSEC ;Verify after write JP NZ,IOERR CALL DOT ;*=*=* ; Write the config sector 0/2 ;*=*=* LD HL,HITBUF ;Zero out buffer GSYS1 LD (HL),0 INC L JR NZ,GSYS1 LD HL,HITBUF ;Set first byte to xx LD (HL),RLS ;For release number LD DE,2 ;Pt to cyl 0, sector 2 CALL WRSEC ;Write 0/2 JP NZ,IOERR CALL VERSEC ;Verify after write JP NZ,IOERR CALL DOT ;*=*=* ; Write the Granule Allocation Table ;*=*=* LD HL,GATBUF ;Pt to GAT sector buffer LD D,(IY+9) ;P/u the dir cyl LD E,0 ;Denote sector 0 CALL WRSYS ;Write the GAT JP NZ,IOERR CALL VERSYS ;Verify the GAT JP NZ,IOERR CALL DOT ;*=*=* ; Construct the HIT ;*=*=* LD HL,HITBUF ;Point to the HIT buffer LD (HL),0A2H ;Stuff BOOT/SYS hash code INC HL LD (HL),0C4H ;Stuff DIR/SYS hash code DEC HL LD D,(IY+9) ;P/u dir cyl # LD E,1 ;Pt to sector 1 CALL WRSYS ;Write the HIT JP NZ,IOERR CALL VERSYS ;Verify after write JP NZ,IOERR CALL DOT LD DE,HITBUF ;Establish buffer for LD HL,BOOTDIR ;Dir records LD BC,32 ;Move BOOT/SYS dir record LDIR ; into 1st slot LD D,(IY+9) ;P/u dir cyl LD E,2 ;This will be sector 2 LD HL,HITBUF ;Pt to buffer start CALL WRSYS ;Write the sector JP NZ,IOERR CALL VERSYS ;Verify after write JP NZ,IOERR CALL DOT LD A,(SECCYL) ;P/u # of records OR A ;If 256 SPC, then JR Z,USE34 ; the CP won't work CP 35 JR C,STUFSPC USE34 LD A,34 ;Max # of sectors LD (SECCYL),A STUFSPC LD (DIRDIR+14H),A ;& stuff into DIR/SYS CYLGRN LD A,0 ;P/u # grans/cyl BIT 5,(IY+4) ;Test 2-sided JR Z,$+4 ADD A,A ;Double count on 2-sided INC A ;Plus 1 for 0 offset adj LD (DIRDIR+23),A ;Stuff in DIR/SYS LD A,(IY+9) ;P/u the dir cyl # & LD (DIRDIR+16H),A ; stuff into the DIR rec LD HL,DIRDIR ;Pt to start of DIR data LD DE,HITBUF ;Pt to start of dir buf LD BC,32 ;Move DIR/SYS into buf LDIR LD D,(IY+9) ;P/u dir cyl # LD E,3 ;Write as sector 3 LD HL,HITBUF ;Pt to start of buffer CALL WRSYS ;Write the sector JP NZ,IOERR CALL VERSYS ;Verify after write JP NZ,IOERR CALL DOT LD HL,HITBUF ;Zero the 1st 32 bytes LD B,32 ;Of the buffer to clear GSYS2 LD (HL),0 ;Where we stuffed the INC HL ;BOOT & DIR dir records DJNZ GSYS2 LD D,(IY+9) ;P/u dir cyl # LD E,4 ;Cont writing at sect 4 GSYS3 LD HL,HITBUF ;Pt to start of buffer CALL WRSYS ;Write the sector JP NZ,IOERR CALL VERSYS ;Verify the sector JP NZ,IOERR ;*=*=* ; Write the remaining directory ;*=*=* PUSH DE ;Save cyl/sect CALL DOT ;Display a dot for each POP DE ;Directory sector INC E ;Bump the sector pointer LD A,(SECCYL) ;P/u highest # sector CP E ;Are we finished yet? JR NZ,GSYS3 ;Loop if not LD IX,(DCTPTR) ;Real DCT for drive LD A,(IY+9) ;DIR posn LD (IX+9),A ;Update for system ;*=*=* ; exit procedures ;*=*=* LD HL,FMTCAO$ ;"Formatting complete... CALL @LOGOT JP @EXIT ;***** ; disk I/O requests ;***** WRCYL PUSH BC LD B,15 ;Write track IF TRS!PDC CALL FMTDVR ;WRCYL code in formatter POP BC RET ELSE JR DISKIO ENDIF ; IF LDI FMTHD PUSH BC LD B,12 ;Format hard disk JR DISKIO ENDIF ; WRSEC PUSH BC LD B,13 ;Write data sector JR DISKIO WRSYS PUSH BC LD B,14 ;Write system sector JR DISKIO RDSEC PUSH BC LD B,9 ;Read data sector JR DISKIO VERSEC PUSH BC LD B,10 ;Verify a sector JR DISKIO ;***** ; Perform a verification to ensure system sector ;***** VERSYS CALL VERSEC ;Sector verify JR Z,VERS1 ;Bypass if not system SUB 6 ;Test read system retcod RET Z ;Go if that's what it was ADD A,6 ;Restore orig retcod RET VERS1 OR 1 ;S/b system, found data LD A,0 RET ; DISKIO LD C,-1 ;P/u drive # LD A,32 ;Init to illegal drive OR A CALL GOIO ;Go after DCT vector POP BC RET GOIO JP (IY) ;Vector to DCT ; ;***** ; routine to convert reg A to 3 decimal digits ; in registers C B A ;***** CVDEC LD C,'0' ;Init to count 100's CVD1 SUB 100 ;How many hundreds? JR C,CVD2 ;Go if no more INC C ;Else bump & loop JR CVD1 CVD2 ADD A,100 ;Adjust for underflow LD B,30H CVD3 SUB 10 ;How many 10s JR C,CVD4 ;Go if underflow INC B ;Bump 10s JR CVD3 ;Loop for more CVD4 ADD A,3AH ;Adjust units place RET ;*=*=* ; display cyl # DSPCYL PUSH AF ;Save units place PUSH BC ;Save tens/hundreds LD B,3 LD A,8 BKUP CALL @DSP ;Backspace 3 DJNZ BKUP POP BC LD A,C CALL @DSP ;Display hundreds LD A,B CALL @DSP ;Display tens POP AF ;Get back units CALL @DSP ;Display units RET ;***** ; Hash a diskette password ;***** CKMPW CALL CKMPW0 RET NZ CALL HASHMPW ; IF RAM JP NZ,IOERR ENDIF ; XOR A RET ; HASHMPW LD A,0E4H RST 28H ; CKMPW0 LD B,8 PUSH DE POP HL LD A,(HL) ;P/u 1st char JR CKMPW2 ; & check CKMPW1 INC HL LD A,(HL) CP ' ' JR Z,CKMPW7 CP '0' JR C,INVMPW CP '9'+1 JR C,CKMPW3 CKMPW2 CP 'A' JR C,INVMPW CP 'Z'+1 JR NC,INVMPW CKMPW3 DJNZ CKMPW1 XOR A ;All OK RET CKMPW5 INC HL CP (HL) ;No imbedded spaces JR NZ,INVMPW CKMPW7 DJNZ CKMPW5 XOR A ;All OK RET INVMPW LD HL,BADMPW$ LD A,63 ;Indicate extended error OR A ;Set NZ RET ;***** ; Routines to convert input strings to uc ;***** GETARG LD B,1 ;1 char input GETARGX CALL @DSPLY ;B chars input LD C,0 LD HL,HITBUF ;Buffer area INPT CALL @KEYIN ;Enter them JP C,FMTABT ;Break pressed! LD A,B OR A RET Z ;No input ; convert input line to U/C PUSH BC PUSH HL GETUC LD A,(HL) CP 'a' JR C,UC2 AND 5FH ;Make U/C LD (HL),A UC2 INC HL DJNZ GETUC ;Do entire input POP HL POP BC LD A,(HL) ;P/u one char OR A ;Make NZ RET ; INPMPW LD B,8 ;Max chars CALL GETARGX ;Input U/C into HITBUF RET Z ;If no input LD DE,MPWBUF ;Then move to MPWBUF PUSH DE LD A,9 ;An extra char means we don't SUB B ;Have to check for zero here LD C,B LD B,0 ;Xfer length LDIR ;Move input LD B,A ;Chars needed LD A,' ' ;Load a blank FILLBLK LD (DE),A ;Padd response INC DE DJNZ FILLBLK POP HL ;=>string RET ; ;*=*=* ; Routine to set a bit ;*=*=* SETBIT RLCA ;Shift to "b" field RLCA RLCA OR 0C3H ;Establish as SET b,E LD (SBIT1+1),A ;Alter the OP code SBIT1 SET 0,E ;Turn on the bit RET ;*=*=* ; print one "." ;*=*=* DOT LD A,'.' JP @DSP ;***** ; Temporary storage space for format drive DCT ;***** TMPDCT DS 10 ;***** ; Parm error exit ;***** BADNAM LD HL,BADNAM$ DB 0DDH DIFDVR LD HL,DIFDVR$ ;Driver mismatch... DB 0DDH NOTFMT LD HL,NOTFMT$ DB 0DDH NOTZER LD HL,NOTZER$ ;Can't format drive 0 DB 0DDH ILLEG LD HL,ILLEG$ ;Drive is disabled DB 0DDH BADMPW LD HL,BADMPW$ ;Wrong MPW entered DB 0DDH FMTABT LD HL,FMTABT$ DB 0DDH NOTHARD LD HL,HARD$ DB 0DDH PRMERR LD HL,PRMERR$ CALL @LOGOT JP @ABORT ;*=*=* ; abort if JCL running IF RAM SFLAG$ EQU 0 ;Stuffed by init code ENDIF ABTJCL1 NOP ;Patchable w/RET ABTJCL PUSH AF LD A,(SFLAG$) SFLAG EQU $-2 ;RAM version sets address BIT 5,A JR NZ,FMTABT ;Log out POP AF RET ; IOERR PUSH AF ;Save error code LD A,CR CALL @DSP ;Do a CR first POP AF LD L,A LD H,0 OR 0C0H ;Mask LD C,A CALL @ERROR IF .NOT.RAM JP @ABORT ENDIF ;*=*=* ; 6.x exit routine follows.... ; provide compatible I/O routines for 6.x LDOS ; accomodate EDAS's insistance on resolving labels ;With MACRO expansion inside of FALSE conditionals ;By not using SVCMAC here IF RAM MOD1 EQU 0 ;Keep EDAS happy when MOD3 EQU 0 ;Evaluating .NOT.RAM option ;*=*=* ; system routines for RAM version of HD formatters ;*=*=* QUIT LD SP,$-$ SPSAV EQU $-2 LD A,106 RST 40 RET @ABORT LD HL,-1 DB 0DDH ;Make next inst IX @EXIT LD HL,0 JR QUIT ; @DSP LD C,A LD A,2 RST 28H RET Z JR IOERR @DSPLY LD A,10 RST 28H RET Z JR IOERR ; DECHEX LD A,96 RST 28H RET HEXDEC LD A,97 RST 28H RET @KEYIN LD A,9 RST 28H RET @PARAM LD A,17 RST 28H RET @LOGOT LD A,12 RST 28H RET MULTEA@ LD C,A LD A,90 RST 28H RET DIVEA@ LD C,A LD A,93 RST 28H RET GETDCT@ LD A,81 RST 28H RET @DATE LD A,18 RST 28H RET RDSECT@ LD A,49 RST 28H RET @ERROR LD A,26 RST 28H RET ; ;*=*=* ; entry point if 6.x ;*=*=* ; BEGIN LD A,106 RST 40 JR Z,BEGINA ;Continue if no break LD HL,-1 RET ; else abort ; BEGINA LD (SPSAV),SP ;Save callers stack PUSH HL LD A,101 ;@@FLAGS RST 28H ;Find SFLAG$ LD DE,'S'-'A' ;Offset ADD IY,DE ;Calc byte address LD (SFLAG),IY ;Save for JCL test POP HL JP USER ;To pgm start ENDIF ; ;*=*=* IF .NOT.RAM ;Get version equates... ;Get correct EQU file *GET VERSION *LIST OFF IF MOD1 *GET MOD1/EQU *LIST OFF ENDIF IF MOD3 *GET MOD3/EQU ENDIF *LIST ON ; ;*=*=* ; Routine to convert ascii =>HL to number in BC ;*=*=* DECHEX LD DE,0 ;Clear to start CXDEC LD A,(HL) ;P/u char SUB 30H ;To BCD CP 10 ;Must be less JR NC,DONECON ;End if not digit PUSH HL ;Save ascii ptr LD H,D LD L,E ;Merge digit ADD HL,HL ADD HL,HL ADD HL,DE ADD HL,HL EX DE,HL ADD A,E LD E,A LD A,0 ADC A,D LD D,A POP HL INC HL ;Next char JR CXDEC DONECON PUSH DE POP BC ;Put answer in BC RET ; HEXDEC LD A,' ' ;Blank PUSH HL LD HL,TENTBL HDC1 LD C,(HL) INC HL LD B,(HL) INC HL EX (SP),HL PUSH DE LD D,A XOR A HDC2 INC A ADD HL,BC JR C,HDC2 SBC HL,BC LD B,D POP DE DEC A JR NZ,HDC3 INC C JR Z,HDC5 DEC C LD A,B LD (DE),A JR HDC4 HDC5 DEC C HDC3 ADD A,'0' LD (DE),A LD A,'0' HDC4 INC DE INC C EX (SP),HL JR NZ,HDC1 POP HL RET TENTBL DW -10000,-1000,-100,-10,-1 ; ENDIF