Á}|Ø *Bå!ôÿ~#¶Ê) !øÿN#F>‘O>˜GÃ0 !øÿN#Fáywx#w!@—–>#žÒ? *D~þAúe *D>Z¾úe *D~O‡ŸG! MDÃm *D~O‡ŸGyþlÂv xþÂ? *D#"DÃ? *D~þaúÝ *D>z¾òï ÃÝ !øÿå!øÿN#FÅ! N#FÅÍÑ áå!öÿ~#foãÁ Á}|:@Ö2@:AÞ2A*D#"DÃÑ*D~þAú *D>Z¾ú !öÿå*D~þAú *D>Z¾ú *D~O‡ŸG! MDà *D~O‡ŸG!©ÿ Á}|!öÿå! Á – #žú˜ à *Då!òÿÁy–Ox#žGÃ= Í' !~#fo"D*D"B!#~·ò¡ !—–>#žú¡ !~#fo>•o>œg"@*Bå*B#"Bá6-ì !~#fo"@!~#¶ÂÄ !> w‡Ÿ#wÃé !#~·òé !å!~#fo>•o>œgÁ}|!:@–:A#žÚ! !N#FÅ*@å!N#FÅÍ *BåÍR ñññ*B "B*Bå*@å!N#FÅÍ4 á0 Á}*B>9¾òL *B~Æ'w*Bå!DÁy–Ox#žGÃ= Í' !~#fo"D>2@‡Ÿ2A!:@–:A#žÒÊ *Då*D~þAú® *D>Z¾ú® *D~O‡ŸG! MDö *D~O‡ŸGáyw*@#"@*D#"DÃw !~#foMDÃ= ÍÆ!,~#¶Ê ! :,½Âñ :-¼Ê *,ÍÌi`",ÃÚ *.ÍÌà Í' *,"D!~#fo",*DMDÃ= Á!þÿ9ëå*Då*Bå*@åi`é!úÿùá"@á"Bá"DÑÉáÕÕÅåø!9~‡w#~�w#~�w#~�w+MD!9 –_ #žÚZ { !94ÃZ åÅÕ! 9~·ò¤ —+–w>#žw! 9N#Fx·ò¸ —‘O>˜GÍP ÁññÒÈ —‘O>˜G! 9q#pÑÃéåÅÕ! 9~·òê —+–w>#žw! 9N#Fx·òþ —‘O>˜GÍP ñÁñÒ —‘O>˜G! 9q#pÑÃéåÅÕ! 9N#FÍP Áññ! 9q#pÑÃéåÅÕ! 9N#FÍP ñÁñ! 9q#pÑÃéåÅ!9~·ò_ /<à ÊéO!9~#fo) Âk ÃÅ åÅ!9~·òƒ /<Ã_ ÊéO!9~#fo|‡|g}o Â� ÃÅ åÅ!9~·ò® /<Ã_ ÊéO!9~#fo|·g}o º MD!9q#pÃéåÅ!å! 9~+¶Ê ~Òð ! 9N#Fá å! 9~‡w#~�w! 9~·w+~wÃ× Á!9q#pÃéÁá&Éå!Ûå!9ÍÌáÅO—GÉåÅ!9N#F!9~#fo ##– #ž +++ž #žÃÑ!9MD!9~#~#~#~— ø!9~‡w#~�w#~�w#~�w#~�w#~�w#~�w#~�w!9MD! 9 – #ž #ž #žÚx!9MD! 9 – #ž #ž #ž!94ÃxãÅÕë!ðÿ9ùëé!9ùÑÃé#~#~+++~#~É#~·òò—#–>#ž>+++ž>#žÉ~#~#~ #~É{æÊ$—–>#ž>#ž >#žÉÍÜ!9MD!9~#foÍ! 9MD!9~#foÍÍU!9N#F!9Í7ÃéÍÜ!9MD!9~#foÍ! 9MD!9~#foÍÍU!9N#F!9Í7ÃéÍÜ! 9MD!9~#fo#Íò!9MD!9~#fo#ÍòÍU!9N#Fkb9Í$ÃéÍÜÃÐåÅ!9~#foN#FÅ#N#FÅ! 9~#foN#FÅ#N#FÅ!åå!9~+¶+¶+¶Ê“~Òi!9MD!9 † #Ž #Ž #Ž!9~‡w#~�w#~�w#~�w!9~·w+~w+~w+~wÃ:!9N#F!9~#~á}|! 9ùÃéÁá&Éã}!Óå!9ÍÌÅÉ!9ëãéëùÑÉõ!9N#F###q#pÁ+++qÁáññÉ!9N#F#q#pÁáñÉMorrow Designs Inc.H–  Ã_ ÊéO!9~#fo|‡|g}o Â� ÃÅ åÅ!9~·ò® /<Ã_ ÊéO!9~#fo|·g}o º MD!9q#pÃéåÅ!å! 9~+¶Ê ~Òð ! 9N#Fá å! 9~‡w#~�w! 9~·w+~wÃ× Á!9q#pÃéÁá&Éå!Ûå!9ÍÌáÅO—GÉåÅ!9N#F!9~#fo ##– #ž +++ž #žÃÑ!9MD!9~#~#~#~— ø!9~‡w#~�w#~�w#~�w#~�w#~�w#~�w#~�w!9MD! 9 – #ž #ž #žÚx!9MD! 9 – #ž #ž #ž!94ÃxãÅÕë!ðÿ9ùëé!9ùÑÃé#~#~+++~#~É#~·òò—#–>#ž>+++ž>#žÉ~#~#~ #~É{æÊ$—–>#ž>#ž >#žÉÍÜ!9MD!9~#foÍ! 9MD!9~#foÍÍU!9N#F!9Í7ÃéÍÜ!9MD!9~#foÍ! 9MD!9~#foÍÍU!9N#F!9Í7ÃéÍÜ! 9MD!9~#fo#Íò!9MD!9~#fo#ÍòÍU!9N#Fkb9Í$ÃéÍÜÃÐåÅ!9~#foN#FÅ#N#FÅ! 9~#foN#FÅ#N#FÅ!åå!9~+¶+¶+¶Ê“~Òi!9MD!9 † #Ž #Ž #Ž!9~‡w#~�w#~�w#~�w!9~·w+~w+~w+~wÃ:!9N#F!9~#~á}|! 9ùÃéÁá&Éã}!Óå!9ÍÌÅÉ!9ëãéëùÑÉõ!9N#F###q#pÁ+++qÁáññÉ!9N#F#q#pÁáñÉMoåååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååå*ùÍKÍžÃ+ žé2,Ã'Ã+ÃFÃŽÃrÃÃû Í– þ8Ê{ æÄ‚w#w#wÑÁÉÍÆÃÞá^#V#å*~#foÉá^#å*~#foÉá^#V#å*nÉá^#å*nÉá^#V#åë ~#foÉá^#åë& ~#foÉ!È+É!È#É!Ø+É!Ø#É!ð+É!ø+ÉÈÉÈÉØÉØÉðÉøÉ}»À|ºÉëz¼À{½Éë|ºÀ}»Éë|ªòìz·ð7Éë|ªòó|·ð7ÉzõÍZëÍZëÍ)ñ·ð|/g}/o#É|µÈÕå͉ÑÍk|/g}/o#Ñɯ2qÍZëÍZÍk:qÐ|/g}/o#É|·ð/g}/o#:q<2qÉÅÍqÁÉDM!x±ÈxGyOÒƒë)ëÃv|µÈÅÍ”`iÁÉ|·ú )ÖëxõÍÝÚ·Õz/W{/_ѯzW{_ñ=ÈõyOxGæ¯2qÍZëÍZë͉ÃM|ºØÀ}»Éëȯ|g}oÃæëÈ)Ãô|/g}/o#Éz/W{/_É!9~#foÉ!à !à ! à ! à !à !à Ÿ!9Å~#ÂAÁÉá"s!`å*"³!è"µ!ÜY"—>Û2­>Ó2°>É2¯2²!Ì"�!"“!@"‘!"• ÍæÊžÍ!€ßF#x·Â±Ã~#±¯!ßb¯2r~#þ ÊÈ·Êþ"ÂÞ2rÃß+}|~#·ÊÅG:r·xÁÊþ"Âæ¯2r+w#þ Âæ+6#ÃÈÕ!×6#¯2w2x*sé!ÿÿÉ>õÍrÚ<o&åÍFáñ=þÂ-ÃÍ`Í ÍrÚ'~æÊhåÍÅÍëÍÁá6þÿ!À+ÉÍ`WÖØþ?ØÕ_!×~æ7ÑzÈ?ÉÍ`ÅÍ åþ:>ªÍÖ@w#ÍGþ.¶ÍƯww#Ã?Åþ*>?ÊéÍñÚçw#ÂÇÁÍñØÃÞ> w#ÂéÁÉÍþ.7Èþ:7Èþ7Èþ!ÉþaØþ{ÐÖ Éþ Ê þ Ê ÉÅÍ`·OÂE×!·æyÂ6ÁÉÕ$Ñ Â-7ÁÉÍrÚBÖo&))T])))ë!·yÁÉÕÅõå€ÍáñÁÑÉZ>½ÂE>¼ÊcÃi!�",Ãi!“",Ãi!¤",Ãi!´",!ÇåÍ�å*,åÍÑÑÑÍÁÉCan't create %s%sWrite error %s%sCan't find %s%sRead error on %s%s ...rebooting%+17=CFIORX[adjw}ÍÁ(C*v#ÍèaÃ(a¯Í¡(C:¹v_*·vͰL ÒaͲaÍÁ(C*v#ͲaÍÁ(C*"v#$%ò>aÍA>-Íc(Íèa:$vÍc(*è6|µÊja>+Í0(ÍÏ(*¿7ë*ì6ÍRe."ê6É:f5õ!»6¦ÌV(~·Ê�a>Í¡( C:pv·Ê�a>Í¡($Cñ·Ê›a>%Í¡("C:)þú±aõ>0Í¡((Cñö0Íc(ÉõÅÕå;aÃHÕÿÿüÚÅaã+|ã·òÅaèÑx±Êèaå`i;aáÕc(ÍiÑÃŽ :ç6·À:å6WÍ?)O*¿7:I=G:&·Âb:+·È:e5æ½Ã\b:1v·ÂWb:0v»Ê0bÒIbÕåÍrb{!g5¾zÒAbæ!e5Å!þÿ9ùDM! "(,!"$,!"&,!* åÍ¢ ÑÍ�ÍùÒà!G åÍ¢ Ñ!W åÍ¢ Ñà ! ^#Vr+së~#fo" ,! ^#Vr+së~#fo" ,Í�ÍÒ2! ^#Vr+së~#fo",!"",Ã8!"",!å* ,åÍeÑÑ",#|µÂ[* ,å!åÍÔ ÑÑ!å* ,åÍeÑÑ",#|µÂ~* ,å!åÍÔ ÑÑ!ÿÿ", ë"$$ë"(!å*$å*,åÍ©ÑÑÑ",#|µÂº* ,å!åÍÔ ÑÑ!å*(å*,åÍ©ÑÑÑ",#|µÂâ* ,å!åÍÔ ÑÑ`i¯w#wÍ�å*,å*,ÑÍúÒ *,Ãt random record DW RESDRV ;37: Reset drive DW JR ;38: Undefined - go back DW JR ;39: Undefined - go back DW ZERRND ;40: Fill random file w/ zeros ; ;********************************************************************** ; Print the permanent error message ; PERSUB: LXI H,PERMSG ;point to bad sector message CALL DOSERR ;print out with disk and return CPI CTRLC ;return with a char - is it ctrlc? JZ BOOTV ;if so go reboot RET ;otherwise just go back ; ;********************************************************************** ; Print the select error message then die ; SELSUB: LXI H,SELMSG ;'Select' msg JMP BOMB ;say too bad then abort ; ;********************************************************************** ; Print read only error message then die ; ROSUB: LXI H,ROMSG ;Send R/O msg JMP BOMB ; say too bad then abort ; ;********************************************************************** ; Print file read-only error message, die ; RONSUB: LXI H,ROEMSG ;'File R/O' msg ; ;********************************************************************** ; Print out the error message then reboot ; BOMB: CALL DOSERR ;Print BDOS err on [dsk #] JMP BOOTV ;Reboot system ; ;********************************************************************** ; Error messages ; DOSMSG: DB 'Bdos Err On ' DSKCH: DB ' : $' PERMSG: DB 'Bad Sector$' SELMSG: DB 'Select$' ROEMSG: DB 'File ' ROMSG: DB 'R/O$' ; ;********************************************************************** ; Print BDOS error msg with disk # ; DOSERR: PUSH H ;save the message pointer CALL CRLF ;Turn up a new line LDA CURDSK ;get the current disk ADI 'A' ;add in the ascii bias STA DSKCH ;Form drive ID char LXI B,DOSMSG ;Print the CALL PRINT ; 'Bdos Err on' msg POP B ;restore the message pointer CALL PRINT ;Print specific error message ; ;********************************************************************** ; Read next console character ; CONIN: LXI H,CHRRDY ;Point to the char ready flag MOV A,M ;move the ready byte into A MVI M,0 ;and zero out the flag ORA A ;was anyone home RNZ ;return if not JMP CONIF ;otherwise go get the thing ; ;********************************************************************** ; Read console character, echo print if it is ok ; CIECHO: CALL CONIN ;get a character CALL GRAFIC ;check the control characters RC ;return if the char is not printable PUSH PSW ;otherwise save it MOV C,A ;put a copy into C CALL WRTCON ;and print it out POP PSW ;restore it RET ;and return to sender ; ;********************************************************************** ;see if A is a good control char, ret with CY set if not ; GRAFIC: CPI CR ;test for carriage return RZ ;return if it was CPI LF ;how about line feed RZ ;that is ok CPI TAB ;as is tab RZ ;so back with it CPI BACKSP ;Backspace in 2.0 RZ ;is known CPI ' ' ;test all other control characters RET ;and go back with carry set for no echo ; ;********************************************************************** ; Check for console break and abort ; CONBRK: LDA CHRRDY ;get the character ready byte ORA A ;and check for waiting char JNZ CB1 ;non zero says something is there CALL CONSF ;check the console if none there ANI 01H ;and in the status bit RZ ;return if it came up zero CALL CONIF ;otherwise go get the waiting char CPI CTRLS ;was it a control-s JNZ CB0 ;if not return with ready flag set CALL CONIF ;if it was wait for the next char CPI CTRLC ;is this one control c? JZ BOOTV ;if so we reboot XRA A ;or else zero a RET ;and simply return ; CB0: STA CHRRDY ;Save input char CB1: MVI A,TRUE ;and say true to the caller RET ;and go back ; ;********************************************************************** ; Output char in C to console, list also if LSTCPY = true ; CONOUT: LDA CTEMP1 ;get the first temp column counter ORA A ;is it zero? JNZ CONOU1 ;if nonzero jump over PUSH B ;otherwise save input character CALL CONBRK ;Check for abort POP B ;recover the char PUSH B ;save it again CALL CONOF ;and print the character on the console POP B ;recover once more PUSH B ;would you believe save it again LDA LSTCPY ;get the list flag byte ORA A ;to set flags CNZ LISTF ; and to list if LSTCPY=true POP B ;restore char one last time CONOU1: MOV A,C ;put the byte into A LXI H,COLUMN ;point to the buffer column counter CPI 7FH ;Rubout ? RZ ;return if so INR M ;Increment column CPI ' ' ;is the character a space? RNC ;return if less - must be control DCR M ;Decrement column MOV A,M ;and get the character there ORA A ;check for a null RZ ;return if it is MOV A,C ;move the char into C CPI BACKSP ;was it a backspace? JNZ CONOU2 ;if not jump over DCR M ;Decrement column RET ;and return ; CONOU2: CPI LF ;was it a linefeed? RNZ ;return if not again MVI M,0 ;Set column to 0 RET ;and return ; ;********************************************************************** ; Print char in C at console, convert Ctrl chars to ^[char] ; CTLOUT: MOV A,C ;move the char into A CALL GRAFIC ;see if it is printable JNC WRTCON ;jump past cause it is ok PUSH PSW ;otherwise save ctrl char on the stack MVI C,5EH ;get the "^" char CALL CONOUT ;and print it POP PSW ;get the char back ORI 40H ;add in the bias to make it print MOV C,A ;put it into C for the next ; ;********************************************************************** ; BDOS function 2: write to the system console char in C ; WRTCON: MOV A,C ;which puts it into A CPI TAB ;check for tab JNZ CONOUT ;if not jump and print TABOUT: MVI C,' ' ;Space gets printed to expand tabs CALL CONOUT ; to LDA COLUMN ; next ANI 07H ; tab JNZ TABOUT ; stop RET ;Return ; DELAST: CALL BACKUP ;back up one character MVI C,' ' ;then get a blank CALL CONOF ;and print it out BACKUP: MVI C,BACKSP ;get a backspace JMP CONOF ;and print it as well to move into spot ; ;********************************************************************** ; Print pound sign, CRLF, and fix columns ; LBCRLF: MVI C,'#' ;get a pound sign CALL CONOUT ;and print it CALL CRLF ;Turn up a new line LB1: LDA COLUMN ;get the column counter LXI H,CTEMP2 ;point to the temp counter CMP M ;are they equal? RNC ;not there yet MVI C,' ' ;so get a space CALL CONOUT ;and print it out JMP LB1 ;loop til the counts are the same ; ;********************************************************************** ; Print CR/LF at console ; CRLF: MVI C,CR ; get a cr CALL CONOUT ;and print it out MVI C,LF ;followed by a lf JMP CONOUT ;which goes out too ; ;********************************************************************** ; Print string at (BC) until '$' with TAB expansion ; PRINT: LDAX B ;get the byte at (BC) CPI '$' ;is it the end mark? RZ ;if so we are done INX B ;otherwise bump the pointer PUSH B ;and save it in the stack MOV C,A ;get the character into C CALL WRTCON ;write it out expanding tabs POP B ;recover the pointer JMP PRINT ;and loop til we hit the stop ; ;********************************************************************** ; BDOS function 10: Read console buffer at ; enter with BC -> console buffer address ; REDBUF: LDA COLUMN ;get the column counter into A STA CTEMP2 ;save it at CTEMP2 LHLD FCB ;get the information into HL MOV C,M ;get the buffer count byte INX H ;and bump the pointer to the next spot PUSH H ;save it for later MVI B,0 ;zero B RB0: PUSH B ;save BC for later PUSH H ;and HL as well RB1: CALL CONIN ;go get a char from the console ANI 7FH ;strip the parity bit POP H ;recover HL POP B ;and BC CPI CR ;is this character a CR? JZ RBEXIT ;if so jump over CPI LF ;how about a LF JZ RBEXIT ;jump with that as well CPI BACKSP ;do we have a backspace? JNZ CHKRUB ;if not over we go MOV A,B ;put B into A ORA A ;is it still zero? JZ RB0 ;and save this address at scratch 1 INX H ;move over INX H ; two more SHLD SCRT2 ;saving the result at scratch 2 INX H ;two more INX H ; for good measure XCHG ;swap DE and HL - DE has DIRBUF pointer SHLD TRANS ;save the original disp parm header LXI H,DTEMP ;point to the temp DMA area MVI C,8 ;Bytes to move CALL MOVE ;Move C bytes DIRBUF to DTEMP (dont know why) LHLD DPB ;get the disk parm block address XCHG ;and put it into DE LXI H,DPBLK ;now set HL to point to storage area MVI C,15 ;Bytes to move CALL MOVE ;Move disk data into storage area LHLD DSIZE ;get the size of this disk MOV A,H ;high byte zero says 1024 byte blocks LXI H,BSIZE ;point to block size byte MVI M,0FFH ;put in an FF ORA A ;set flags JZ JRFF ;Return FF if blocks are 1024 bytes MVI M,0 ;otherwise set in a ZERO JRFF: MVI A,0FFH ;and get an FF into A ORA A ;set flags RET ;and return ; ;********************************************************************** ;routine to home the selected disk and reset data words ; HOMDSK: CALL HOMF ;home the selected drive XRA A ;get a zero LHLD SCRT1 ;point to the current track storage MOV M,A ;put in the zero INX H ;point to the low half MOV M,A ;and zero this as well LHLD SCRT2 ;point to starting sector count for this track MOV M,A ;zero it INX H ;bump pointer MOV M,A ;both halves of this word RET ;and return ; ;********************************************************************** ;routine reads indicated sector and checks status ; RDSEC: CALL DRDF ;Read sector JMP PERCHK ;jump to check error and return ; ;********************************************************************** ;routine to write indicated sector and check result ; WRSEC: CALL DWRF ;Write sector ; PERCHK: ORA A ;set flags RZ ;return if all is well LXI H,PERERR ;HL=Permanent err sub addr JMP HLGO ;Go to routine ; ;********************************************************************** ;routine to get the next directory sector location for reading ; GETDS: LHLD COUNT ;get the directory count MVI C,02H ;ready to slide it over 2 bits right CALL SPINHL ;spin hl into position - sector number SHLD GROUP ;save a copy at group SHLD LDIRPNT ;and another at directory pointer GETD1: LXI H,GROUP ;point to directory sector number MOV C,M ;pull it INX H ; into MOV B,M ; BC LHLD SCRT2 ;pull current sector address MOV E,M ;pull (scratch2) 16 bits wide INX H ; into MOV D,M ; DE LHLD SCRT1 ;pull current track address MOV A,M ;pull (scratch1) into A INX H ; into MOV H,M ; HL MOV L,A ; 16 bits at (scratch1) into HL ; ;next two blocks set the track and starting sector number for the track ; so the directory disk access will be right ; GETD2: MOV A,C ;subtract SUB E ; track start sector MOV A,B ; from SBB D ; desired sector number JNC GETD3 ;if too far jump PUSH H ;save current track on stack LHLD DPBLK ;get sectors per track out MOV A,E ;subtract SUB L ; value MOV E,A ; from MOV A,D ; track start sector SBB H ; and leave MOV D,A ; result in DE POP H ;restore track count DCX H ;decrement count JMP GETD2 ;and loop until start is less than desired ; ; BC has the sector we want, DE the track start sector number, HL the track ; GETD3: PUSH H ;save the track count LHLD DPBLK ;get the sectors per track DAD D ;compute the next track start sector number JC GETD4 ;if this exceeds the desired number jump MOV A,C ;otherwise SUB L ; subtract MOV A,B ; new track start number SBB H ; from the desired sector JC GETD4 ;if ok then jump over XCHG ;otherwise swap DE and HL POP H ;recover track number INX H ;bump it by 1 JMP GETD3 ;and loop until done ; ;point the disk to the right spot for access now that the computing is done ; GETD4: POP H ;recover track number PUSH B ;save desired sector number PUSH D ;and the track starting sector number PUSH H ;and the track number again XCHG ;swap DE and HL LHLD TOFS ;get track offset into HL DAD D ;add in the desired track number MOV B,H ;and move it MOV C,L ; into BC CALL TRKF ;Select track POP D ;recover entry track into DE LHLD SCRT1 ;get pointer to current track storage MOV M,E ;and put INX H ; the new track MOV M,D ; back into scratch POP D ;recover current sector number LHLD SCRT2 ;get storage address MOV M,E ;and save INX H ; the new current sector number MOV M,D ; there POP B ;recover new track sector start number MOV A,C ;subtract SUB E ; track sector start number MOV C,A ; from MOV A,B ; the desired number SBB D ; and MOV B,A ; leave result in BC LHLD TRANS ;point to translation routine XCHG ;put address into DE CALL SECTRN ;go do the translation MOV C,L ;put the result MOV B,H ; into BC JMP SECF ;finish setting up the disk pointers ; ;********************************************************************** ;routine gets extent sector count from storage and figures block number ; COMBLK: LXI H,BLSHFT ;point to block shift factor MOV C,M ;pull it into C LDA ESCNT2 ; pull in the extent low byte COMBL1: ORA A ;set flags - clear carry RAR ;rotate right through carry DCR C ;decrement count JNZ COMBL1 ;loop until done MOV B,A ;then save the byte into B MVI A,08H ;get bit 3 set SUB M ;subtract block shift from this value MOV C,A ;and save it into C LDA ESCNT1 ;get the extent high byte COMBL2: DCR C ;decrement count again JZ COMBL3 ;if done jump ORA A ;otherwise set flags - clear carry RAL ;rotate left through carry JMP COMBL2 ;loop until done ; COMBL3: ADD B ;add in the offset RET ;and return ; ;********************************************************************** ;routine points into the FCB block and returns with group pointer. ;If BSIZE=0 blocks are>1024 and 16 bits come back ; GETGRP: LHLD FCB ;get the FCB address LXI D,16 ;and a 16 DAD D ;add in the offset DAD B ;add in BC as well LDA BSIZE ;get the block size byte ORA A ;set flags JZ HLPBC ;if zero add HL and BC MOV L,M ;pull in this byte MVI H,0 ;set upper byte 0 RET ;return with HL set ; ; routine sets HL = (HL+BC) ; HLPBC: DAD B ;add HL and BC MOV E,M ;move this address byte into E INX H ;point to next MOV D,M ;pull this one into D XCHG ;swap DE and HL RET ;and go back ; ;********************************************************************** ;routine takes sector count for directory area and gets the group pointer out ; SECGRP: CALL COMBLK ;get the block number MOV C,A ;and put it into C MVI B,0 ;zero out B CALL GETGRP ;now go get the right group SHLD GROUP ;save it at group storage RET ;and go back ; ;********************************************************************** ; routine checks group and sets flags if zero - no group 0 should be there ; TSTGRP: LHLD GROUP ;get the group pointer out MOV A,L ;move low into A ORA H ;or with H to set flags RET ;and go back ; ;********************************************************************** ; routine appears to figure actual sector number from group pointer ; COMSEC: LDA BLSHFT ;get the block shift factor LHLD GROUP ;and the group pointer into HL COMS1: DAD H ;slide it right DCR A ;and decrement count JNZ COMS1 ;looping until it has shifted right amount SHLD DIRPNT ;then save it in the directory pointer LDA BLKMSK ;now get the block mask out MOV C,A ;save it in C LDA ESCNT2 ;get the low extent counter ANA C ;and it with the block mask ORA L ;or in the directory pointer low byte MOV L,A ;slide this back into L SHLD GROUP ;and save this address at group RET ;then back to sender ; ;********************************************************************** ;routine to point to information + 12 - the extent byte of the FCB ; GETEX: LHLD FCB ;get the FCB pointer LXI D,12 ;and d only if not RET ;and return ; CHK1: MOV M,A ;put A into (HL) RET ;and return ; ;********************************************************************** ;routine to write directory sector out ; WRTDS: CALL CHKSUM ;check the directory check sum CALL SETEMP ;if ok set DMA address up MVI C,01H ;get the code into C CALL WRSEC ;write the sector JMP SETDMA ;reset the DMA address and return ; ;********************************************************************** ;routine to read the next sector from the disk ; GETNXT: CALL SETEMP ;set the DMA address to (DTEMP) CALL RDSEC ;and read the next sector ; ;********************************************************************** ;tell BIOS the correct DMA address ; SETDMA: LXI H,DMAADR ;point to the DMA address word JMP SET2 ;and tell BIOS about it ; ;********************************************************************** ; set the dma address to DTEMP ; SETEMP: LXI H,DTEMP ;get the DMA address from DTEMP ; SET2: MOV C,M ;move the low byte into C INX H ;point to the next MOV B,M ;and pull high into B JMP DMAF ;Set DMA buffer addr & return ; ;********************************************************************** ;routine to move the data stored at (DTEMP) to (DMAADR) ; MOVSEC: LHLD DTEMP ;point to the DMA buffer XCHG ;put it into DE LHLD DMAADR ;get the DMA address for the load MVI C,128 ;Bytes to move JMP MOVE ;Move C bytes DE to HL ; ;********************************************************************** ;routine checks count - returns 1 if it is zero ;and the first byte at count if it is nonzero ; CHKCNT: LXI H,COUNT ;get count MOV A,M ;check to INX H ; see CMP M ; if it is zero RNZ ; return if it is not INR A ;bump up to 1 if it is RET ;and then return ; ;********************************************************************** ;routine sets counter to -1 for starting loop ; SETCNT: LXI H,-1 ;start off with a 16 bit -1 SHLD COUNT ;and save it at count RET ;return to sender ; ;********************************************************************** ;routine moves to next directory entry - COUNT says the last one looked at ; NXTDIR: LHLD DIRMAX ;get the number of directory entries XCHG ;save it in DE LHLD COUNT ;now get the directory counter INX H ;add one to it SHLD COUNT ;and save it back for later CALL SUBHD ;looking too far? JNC GOTDIR ;if no carry still entries left JMP SETCNT ;otherwise return with a 16 bit -1 ; ;********************************************************************** ;routine to get the next directory sector off of the disk ; GOTDIR: LDA COUNT ;get the directory count low byte ANI 03H ;strip off all but low two (4 entries per sec) MVI B,5 ;set to spin low 3 over 5 SPINAB: ADD A ;move over 1 bit DCR B ;decrement count JNZ SPINAB ;loop until done STA DIROFF ;save this for later ORA A ;set flags RNZ ;return if not zero PUSH B ;otherwise save BC CALL GETDS ;looks like we set for getting the next dir CALL GETNXT ;and read the next sector POP B ;recover the BC pair JMP CHKCNG ;see if the disk changed and return ; ;********************************************************************** ;routine gets an allocation bit set into position ; and sets pointer to allocation byte for marking blocks ; BC has the group pointer - Exit with BC -> allocat