Explorations in Retrocomputing
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

bdos22.z80 132KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749
  1. ;**************************************************************
  2. ;*
  3. ;* C P / M version 2 . 2
  4. ;*
  5. ;* Reconstructed from memory image on February 27, 1981
  6. ;*
  7. ;* by Clark A. Calkins
  8. ;*
  9. ;**************************************************************
  10. ;
  11. ; Set memory limit here. This is the amount of contigeous
  12. ; ram starting from 0000. CP/M will reside at the end of this space.
  13. ;
  14. IOBYTE EQU 3 ;i/o definition byte.
  15. TDRIVE EQU 4 ;current drive name and user number.
  16. ENTRY EQU 5 ;entry point for the cp/m bdos.
  17. TFCB EQU 5CH ;default file control block.
  18. TBUFF EQU 80H ;i/o buffer and command line storage.
  19. TBASE EQU 100H ;transiant program storage area.
  20. ;
  21. ; Set control character equates.
  22. ;
  23. CNTRLC EQU 3 ;control-c
  24. CNTRLE EQU 05H ;control-e
  25. BS EQU 08H ;backspace
  26. TAB EQU 09H ;tab
  27. LF EQU 0AH ;line feed
  28. FF EQU 0CH ;form feed
  29. CR EQU 0DH ;carriage return
  30. CNTRLP EQU 10H ;control-p
  31. CNTRLR EQU 12H ;control-r
  32. CNTRLS EQU 13H ;control-s
  33. CNTRLU EQU 15H ;control-u
  34. CNTRLX EQU 18H ;control-x
  35. CNTRLZ EQU 1AH ;control-z (end-of-file mark)
  36. DEL EQU 7FH ;rubout
  37. ;
  38. ; Set origin for CP/M
  39. ;
  40. ORG 0E800H
  41. ;
  42. CBASE: JP COMMAND ;execute command processor (ccp).
  43. JP CLEARBUF ;entry to empty input buffer before starting ccp.
  44. ;
  45. ; Standard cp/m ccp input buffer. Format is (max length),
  46. ; (actual length), (char #1), (char #2), (char #3), etc.
  47. ;
  48. INBUFF: DB 127 ;length of input buffer.
  49. DB 0 ;current length of contents.
  50. DB "Copyright"
  51. DB " 1979 (c) by Digital Research "
  52. DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  53. DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  54. DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  55. DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  56. INPOINT: DW INBUFF+2 ;input line pointer
  57. NAMEPNT: DW 0 ;input line pointer used for error message. Points to
  58. ; ;start of name in error.
  59. ;
  60. ; Routine to print (A) on the console. All registers used.
  61. ;
  62. PRINT: LD E,A ;setup bdos call.
  63. LD C,2
  64. JP ENTRY
  65. ;
  66. ; Routine to print (A) on the console and to save (BC).
  67. ;
  68. PRINTB: PUSH BC
  69. CALL PRINT
  70. POP BC
  71. RET
  72. ;
  73. ; Routine to send a carriage return, line feed combination
  74. ; to the console.
  75. ;
  76. CRLF: LD A,CR
  77. CALL PRINTB
  78. LD A,LF
  79. JP PRINTB
  80. ;
  81. ; Routine to send one space to the console and save (BC).
  82. ;
  83. SPACE: LD A,' '
  84. JP PRINTB
  85. ;
  86. ; Routine to print character string pointed to be (BC) on the
  87. ; console. It must terminate with a null byte.
  88. ;
  89. PLINE: PUSH BC
  90. CALL CRLF
  91. POP HL
  92. PLINE2: LD A,(HL)
  93. OR A
  94. RET Z
  95. INC HL
  96. PUSH HL
  97. CALL PRINT
  98. POP HL
  99. JP PLINE2
  100. ;
  101. ; Routine to reset the disk system.
  102. ;
  103. RESDSK: LD C,13
  104. JP ENTRY
  105. ;
  106. ; Routine to select disk (A).
  107. ;
  108. DSKSEL: LD E,A
  109. LD C,14
  110. JP ENTRY
  111. ;
  112. ; Routine to call bdos and save the return code. The zero
  113. ; flag is set on a return of 0ffh.
  114. ;
  115. ENTRY1: CALL ENTRY
  116. LD (RTNCODE),A ;save return code.
  117. INC A ;set zero if 0ffh returned.
  118. RET
  119. ;
  120. ; Routine to open a file. (DE) must point to the FCB.
  121. ;
  122. OPEN: LD C,15
  123. JP ENTRY1
  124. ;
  125. ; Routine to open file at (FCB).
  126. ;
  127. OPENFCB:XOR A ;clear the record number byte at fcb+32
  128. LD (FCB+32),A
  129. LD DE,FCB
  130. JP OPEN
  131. ;
  132. ; Routine to close a file. (DE) points to FCB.
  133. ;
  134. CLOSE: LD C,16
  135. JP ENTRY1
  136. ;
  137. ; Routine to search for the first file with ambigueous name
  138. ; (DE).
  139. ;
  140. SRCHFST:LD C,17
  141. JP ENTRY1
  142. ;
  143. ; Search for the next ambigeous file name.
  144. ;
  145. SRCHNXT:LD C,18
  146. JP ENTRY1
  147. ;
  148. ; Search for file at (FCB).
  149. ;
  150. SRCHFCB:LD DE,FCB
  151. JP SRCHFST
  152. ;
  153. ; Routine to delete a file pointed to by (DE).
  154. ;
  155. DELETE: LD C,19
  156. JP ENTRY
  157. ;
  158. ; Routine to call the bdos and set the zero flag if a zero
  159. ; status is returned.
  160. ;
  161. ENTRY2: CALL ENTRY
  162. OR A ;set zero flag if appropriate.
  163. RET
  164. ;
  165. ; Routine to read the next record from a sequential file.
  166. ; (DE) points to the FCB.
  167. ;
  168. RDREC: LD C,20
  169. JP ENTRY2
  170. ;
  171. ; Routine to read file at (FCB).
  172. ;
  173. READFCB:LD DE,FCB
  174. JP RDREC
  175. ;
  176. ; Routine to write the next record of a sequential file.
  177. ; (DE) points to the FCB.
  178. ;
  179. WRTREC: LD C,21
  180. JP ENTRY2
  181. ;
  182. ; Routine to create the file pointed to by (DE).
  183. ;
  184. CREATE: LD C,22
  185. JP ENTRY1
  186. ;
  187. ; Routine to rename the file pointed to by (DE). Note that
  188. ; the new name starts at (DE+16).
  189. ;
  190. RENAM: LD C,23
  191. JP ENTRY
  192. ;
  193. ; Get the current user code.
  194. ;
  195. GETUSR: LD E,0FFH
  196. ;
  197. ; Routne to get or set the current user code.
  198. ; If (E) is FF then this is a GET, else it is a SET.
  199. ;
  200. GETSETUC: LD C,32
  201. JP ENTRY
  202. ;
  203. ; Routine to set the current drive byte at (TDRIVE).
  204. ;
  205. SETCDRV:CALL GETUSR ;get user number
  206. ADD A,A ;and shift into the upper 4 bits.
  207. ADD A,A
  208. ADD A,A
  209. ADD A,A
  210. LD HL,CDRIVE ;now add in the current drive number.
  211. OR (HL)
  212. LD (TDRIVE),A ;and save.
  213. RET
  214. ;
  215. ; Move currently active drive down to (TDRIVE).
  216. ;
  217. MOVECD: LD A,(CDRIVE)
  218. LD (TDRIVE),A
  219. RET
  220. ;
  221. ; Routine to convert (A) into upper case ascii. Only letters
  222. ; are affected.
  223. ;
  224. UPPER: CP 'a' ;check for letters in the range of 'a' to 'z'.
  225. RET C
  226. CP '{'
  227. RET NC
  228. AND 5FH ;convert it if found.
  229. RET
  230. ;
  231. ; Routine to get a line of input. We must check to see if the
  232. ; user is in (BATCH) mode. If so, then read the input from file
  233. ; ($$$.SUB). At the end, reset to console input.
  234. ;
  235. GETINP: LD A,(BATCH) ;if =0, then use console input.
  236. OR A
  237. JP Z,GETINP1
  238. ;
  239. ; Use the submit file ($$$.sub) which is prepared by a
  240. ; SUBMIT run. It must be on drive (A) and it will be deleted
  241. ; if and error occures (like eof).
  242. ;
  243. LD A,(CDRIVE) ;select drive 0 if need be.
  244. OR A
  245. LD A,0 ;always use drive A for submit.
  246. CALL NZ,DSKSEL ;select it if required.
  247. LD DE,BATCHFCB
  248. CALL OPEN ;look for it.
  249. JP Z,GETINP1 ;if not there, use normal input.
  250. LD A,(BATCHFCB+15) ;get last record number+1.
  251. DEC A
  252. LD (BATCHFCB+32),A
  253. LD DE,BATCHFCB
  254. CALL RDREC ;read last record.
  255. JP NZ,GETINP1 ;quit on end of file.
  256. ;
  257. ; Move this record into input buffer.
  258. ;
  259. LD DE,INBUFF+1
  260. LD HL,TBUFF ;data was read into buffer here.
  261. LD B,128 ;all 128 characters may be used.
  262. CALL HL2DE ;(HL) to (DE), (B) bytes.
  263. LD HL,BATCHFCB+14
  264. LD (HL),0 ;zero out the 's2' byte.
  265. INC HL ;and decrement the record count.
  266. DEC (HL)
  267. LD DE,BATCHFCB ;close the batch file now.
  268. CALL CLOSE
  269. JP Z,GETINP1 ;quit on an error.
  270. LD A,(CDRIVE) ;re-select previous drive if need be.
  271. OR A
  272. CALL NZ,DSKSEL ;don't do needless selects.
  273. ;
  274. ; Print line just read on console.
  275. ;
  276. LD HL,INBUFF+2
  277. CALL PLINE2
  278. CALL CHKCON ;check console, quit on a key.
  279. JP Z,GETINP2 ;jump if no key is pressed.
  280. ;
  281. ; Terminate the submit job on any keyboard input. Delete this
  282. ; file such that it is not re-started and jump to normal keyboard
  283. ; input section.
  284. ;
  285. CALL DELBATCH ;delete the batch file.
  286. JP CMMND1 ;and restart command input.
  287. ;
  288. ; Get here for normal keyboard input. Delete the submit file
  289. ; incase there was one.
  290. ;
  291. GETINP1:CALL DELBATCH ;delete file ($$$.sub).
  292. CALL SETCDRV ;reset active disk.
  293. LD C,10 ;get line from console device.
  294. LD DE,INBUFF
  295. CALL ENTRY
  296. CALL MOVECD ;reset current drive (again).
  297. ;
  298. ; Convert input line to upper case.
  299. ;
  300. GETINP2:LD HL,INBUFF+1
  301. LD B,(HL) ;(B)=character counter.
  302. GETINP3:INC HL
  303. LD A,B ;end of the line?
  304. OR A
  305. JP Z,GETINP4
  306. LD A,(HL) ;convert to upper case.
  307. CALL UPPER
  308. LD (HL),A
  309. DEC B ;adjust character count.
  310. JP GETINP3
  311. GETINP4:LD (HL),A ;add trailing null.
  312. LD HL,INBUFF+2
  313. LD (INPOINT),HL ;reset input line pointer.
  314. RET
  315. ;
  316. ; Routine to check the console for a key pressed. The zero
  317. ; flag is set is none, else the character is returned in (A).
  318. ;
  319. CHKCON: LD C,11 ;check console.
  320. CALL ENTRY
  321. OR A
  322. RET Z ;return if nothing.
  323. LD C,1 ;else get character.
  324. CALL ENTRY
  325. OR A ;clear zero flag and return.
  326. RET
  327. ;
  328. ; Routine to get the currently active drive number.
  329. ;
  330. GETDSK: LD C,25
  331. JP ENTRY
  332. ;
  333. ; Set the stabdard dma address.
  334. ;
  335. STDDMA: LD DE,TBUFF
  336. ;
  337. ; Routine to set the dma address to (DE).
  338. ;
  339. DMASET: LD C,26
  340. JP ENTRY
  341. ;
  342. ; Delete the batch file created by SUBMIT.
  343. ;
  344. DELBATCH: LD HL,BATCH ;is batch active?
  345. LD A,(HL)
  346. OR A
  347. RET Z
  348. LD (HL),0 ;yes, de-activate it.
  349. XOR A
  350. CALL DSKSEL ;select drive 0 for sure.
  351. LD DE,BATCHFCB ;and delete this file.
  352. CALL DELETE
  353. LD A,(CDRIVE) ;reset current drive.
  354. JP DSKSEL
  355. ;
  356. ; Check to two strings at (PATTRN1) and (PATTRN2). They must be
  357. ; the same or we halt....
  358. ;
  359. VERIFY: LD DE,PATTRN1 ;these are the serial number bytes.
  360. LD HL,PATTRN2 ;ditto, but how could they be different?
  361. LD B,6 ;6 bytes each.
  362. VERIFY1:LD A,(DE)
  363. CP (HL)
  364. JP NZ,HALT ;jump to halt routine.
  365. INC DE
  366. INC HL
  367. DEC B
  368. JP NZ,VERIFY1
  369. RET
  370. ;
  371. ; Print back file name with a '?' to indicate a syntax error.
  372. ;
  373. SYNERR: CALL CRLF ;end current line.
  374. LD HL,(NAMEPNT) ;this points to name in error.
  375. SYNERR1:LD A,(HL) ;print it until a space or null is found.
  376. CP ' '
  377. JP Z,SYNERR2
  378. OR A
  379. JP Z,SYNERR2
  380. PUSH HL
  381. CALL PRINT
  382. POP HL
  383. INC HL
  384. JP SYNERR1
  385. SYNERR2:LD A,'?' ;add trailing '?'.
  386. CALL PRINT
  387. CALL CRLF
  388. CALL DELBATCH ;delete any batch file.
  389. JP CMMND1 ;and restart from console input.
  390. ;
  391. ; Check character at (DE) for legal command input. Note that the
  392. ; zero flag is set if the character is a delimiter.
  393. ;
  394. CHECK: LD A,(DE)
  395. OR A
  396. RET Z
  397. CP ' ' ;control characters are not legal here.
  398. JP C,SYNERR
  399. RET Z ;check for valid delimiter.
  400. CP '='
  401. RET Z
  402. CP '_'
  403. RET Z
  404. CP '.'
  405. RET Z
  406. CP ':'
  407. RET Z
  408. CP 03BH ; ';'
  409. RET Z
  410. CP '<'
  411. RET Z
  412. CP '>'
  413. RET Z
  414. RET
  415. ;
  416. ; Get the next non-blank character from (DE).
  417. ;
  418. NONBLANK: LD A,(DE)
  419. OR A ;string ends with a null.
  420. RET Z
  421. CP ' '
  422. RET NZ
  423. INC DE
  424. JP NONBLANK
  425. ;
  426. ; Add (HL)=(HL)+(A)
  427. ;
  428. ADDHL: ADD A,L
  429. LD L,A
  430. RET NC ;take care of any carry.
  431. INC H
  432. RET
  433. ;
  434. ; Convert the first name in (FCB).
  435. ;
  436. CONVFST:LD A,0
  437. ;
  438. ; Format a file name (convert * to '?', etc.). On return,
  439. ; (A)=0 is an unambigeous name was specified. Enter with (A) equal to
  440. ; the position within the fcb for the name (either 0 or 16).
  441. ;
  442. CONVERT:LD HL,FCB
  443. CALL ADDHL
  444. PUSH HL
  445. PUSH HL
  446. XOR A
  447. LD (CHGDRV),A ;initialize drive change flag.
  448. LD HL,(INPOINT) ;set (HL) as pointer into input line.
  449. EX DE,HL
  450. CALL NONBLANK ;get next non-blank character.
  451. EX DE,HL
  452. LD (NAMEPNT),HL ;save pointer here for any error message.
  453. EX DE,HL
  454. POP HL
  455. LD A,(DE) ;get first character.
  456. OR A
  457. JP Z,CONVRT1
  458. SBC A,'A'-1 ;might be a drive name, convert to binary.
  459. LD B,A ;and save.
  460. INC DE ;check next character for a ':'.
  461. LD A,(DE)
  462. CP ':'
  463. JP Z,CONVRT2
  464. DEC DE ;nope, move pointer back to the start of the line.
  465. CONVRT1:LD A,(CDRIVE)
  466. LD (HL),A
  467. JP CONVRT3
  468. CONVRT2:LD A,B
  469. LD (CHGDRV),A ;set change in drives flag.
  470. LD (HL),B
  471. INC DE
  472. ;
  473. ; Convert the basic file name.
  474. ;
  475. CONVRT3:LD B,08H
  476. CONVRT4:CALL CHECK
  477. JP Z,CONVRT8
  478. INC HL
  479. CP '*' ;note that an '*' will fill the remaining
  480. JP NZ,CONVRT5 ;field with '?'.
  481. LD (HL),'?'
  482. JP CONVRT6
  483. CONVRT5:LD (HL),A
  484. INC DE
  485. CONVRT6:DEC B
  486. JP NZ,CONVRT4
  487. CONVRT7:CALL CHECK ;get next delimiter.
  488. JP Z,GETEXT
  489. INC DE
  490. JP CONVRT7
  491. CONVRT8:INC HL ;blank fill the file name.
  492. LD (HL),' '
  493. DEC B
  494. JP NZ,CONVRT8
  495. ;
  496. ; Get the extension and convert it.
  497. ;
  498. GETEXT: LD B,03H
  499. CP '.'
  500. JP NZ,GETEXT5
  501. INC DE
  502. GETEXT1:CALL CHECK
  503. JP Z,GETEXT5
  504. INC HL
  505. CP '*'
  506. JP NZ,GETEXT2
  507. LD (HL),'?'
  508. JP GETEXT3
  509. GETEXT2:LD (HL),A
  510. INC DE
  511. GETEXT3:DEC B
  512. JP NZ,GETEXT1
  513. GETEXT4:CALL CHECK
  514. JP Z,GETEXT6
  515. INC DE
  516. JP GETEXT4
  517. GETEXT5:INC HL
  518. LD (HL),' '
  519. DEC B
  520. JP NZ,GETEXT5
  521. GETEXT6:LD B,3
  522. GETEXT7:INC HL
  523. LD (HL),0
  524. DEC B
  525. JP NZ,GETEXT7
  526. EX DE,HL
  527. LD (INPOINT),HL ;save input line pointer.
  528. POP HL
  529. ;
  530. ; Check to see if this is an ambigeous file name specification.
  531. ; Set the (A) register to non zero if it is.
  532. ;
  533. LD BC,11 ;set name length.
  534. GETEXT8:INC HL
  535. LD A,(HL)
  536. CP '?' ;any question marks?
  537. JP NZ,GETEXT9
  538. INC B ;count them.
  539. GETEXT9:DEC C
  540. JP NZ,GETEXT8
  541. LD A,B
  542. OR A
  543. RET
  544. ;
  545. ; CP/M command table. Note commands can be either 3 or 4 characters long.
  546. ;
  547. NUMCMDS EQU 6 ;number of commands
  548. CMDTBL: DB "DIR "
  549. DB "ERA "
  550. DB "TYPE"
  551. DB "SAVE"
  552. DB "REN "
  553. DB "USER"
  554. ;
  555. ; The following six bytes must agree with those at (PATTRN2)
  556. ; or cp/m will HALT. Why?
  557. ;
  558. PATTRN1: DB 0,22,0,0,0,0 ;(* serial number bytes *).
  559. ;
  560. ; Search the command table for a match with what has just
  561. ; been entered. If a match is found, then we jump to the
  562. ; proper section. Else jump to (UNKNOWN).
  563. ; On return, the (C) register is set to the command number
  564. ; that matched (or NUMCMDS+1 if no match).
  565. ;
  566. SEARCH: LD HL,CMDTBL
  567. LD C,0
  568. SEARCH1:LD A,C
  569. CP NUMCMDS ;this commands exists.
  570. RET NC
  571. LD DE,FCB+1 ;check this one.
  572. LD B,4 ;max command length.
  573. SEARCH2:LD A,(DE)
  574. CP (HL)
  575. JP NZ,SEARCH3 ;not a match.
  576. INC DE
  577. INC HL
  578. DEC B
  579. JP NZ,SEARCH2
  580. LD A,(DE) ;allow a 3 character command to match.
  581. CP ' '
  582. JP NZ,SEARCH4
  583. LD A,C ;set return register for this command.
  584. RET
  585. SEARCH3:INC HL
  586. DEC B
  587. JP NZ,SEARCH3
  588. SEARCH4:INC C
  589. JP SEARCH1
  590. ;
  591. ; Set the input buffer to empty and then start the command
  592. ; processor (ccp).
  593. ;
  594. CLEARBUF: XOR A
  595. LD (INBUFF+1),A ;second byte is actual length.
  596. ;
  597. ;**************************************************************
  598. ;*
  599. ;*
  600. ;* C C P - C o n s o l e C o m m a n d P r o c e s s o r
  601. ;*
  602. ;**************************************************************
  603. ;*
  604. COMMAND:LD SP,CCPSTACK ;setup stack area.
  605. PUSH BC ;note that (C) should be equal to:
  606. LD A,C ;(uuuudddd) where 'uuuu' is the user number
  607. RRA ;and 'dddd' is the drive number.
  608. RRA
  609. RRA
  610. RRA
  611. AND 0FH ;isolate the user number.
  612. LD E,A
  613. CALL GETSETUC ;and set it.
  614. CALL RESDSK ;reset the disk system.
  615. LD (BATCH),A ;clear batch mode flag.
  616. POP BC
  617. LD A,C
  618. AND 0FH ;isolate the drive number.
  619. LD (CDRIVE),A ;and save.
  620. CALL DSKSEL ;...and select.
  621. LD A,(INBUFF+1)
  622. OR A ;anything in input buffer already?
  623. JP NZ,CMMND2 ;yes, we just process it.
  624. ;
  625. ; Entry point to get a command line from the console.
  626. ;
  627. CMMND1: LD SP,CCPSTACK ;set stack straight.
  628. CALL CRLF ;start a new line on the screen.
  629. CALL GETDSK ;get current drive.
  630. ADD A,'A'
  631. CALL PRINT ;print current drive.
  632. LD A,'>'
  633. CALL PRINT ;and add prompt.
  634. CALL GETINP ;get line from user.
  635. ;
  636. ; Process command line here.
  637. ;
  638. CMMND2: LD DE,TBUFF
  639. CALL DMASET ;set standard dma address.
  640. CALL GETDSK
  641. LD (CDRIVE),A ;set current drive.
  642. CALL CONVFST ;convert name typed in.
  643. CALL NZ,SYNERR ;wild cards are not allowed.
  644. LD A,(CHGDRV) ;if a change in drives was indicated,
  645. OR A ;then treat this as an unknown command
  646. JP NZ,UNKNOWN ;which gets executed.
  647. CALL SEARCH ;else search command table for a match.
  648. ;
  649. ; Note that an unknown command returns
  650. ; with (A) pointing to the last address
  651. ; in our table which is (UNKNOWN).
  652. ;
  653. LD HL,CMDADR ;now, look thru our address table for command (A).
  654. LD E,A ;set (DE) to command number.
  655. LD D,0
  656. ADD HL,DE
  657. ADD HL,DE ;(HL)=(CMDADR)+2*(command number).
  658. LD A,(HL) ;now pick out this address.
  659. INC HL
  660. LD H,(HL)
  661. LD L,A
  662. JP (HL) ;now execute it.
  663. ;
  664. ; CP/M command address table.
  665. ;
  666. CMDADR: DW DIRECT,ERASE,TYPE,SAVE
  667. DW RENAME,USER,UNKNOWN
  668. ;
  669. ; Halt the system. Reason for this is unknown at present.
  670. ;
  671. HALT: LD HL,76F3H ;'DI HLT' instructions.
  672. LD (CBASE),HL
  673. LD HL,CBASE
  674. JP (HL)
  675. ;
  676. ; Read error while TYPEing a file.
  677. ;
  678. RDERROR:LD BC,RDERR
  679. JP PLINE
  680. RDERR: DB "Read error"
  681. DB 0
  682. ;
  683. ; Required file was not located.
  684. ;
  685. NONE: LD BC,NOFILE
  686. JP PLINE
  687. NOFILE: DB "No file"
  688. DB 0
  689. ;
  690. ; Decode a command of the form 'A>filename number{ filename}.
  691. ; Note that a drive specifier is not allowed on the first file
  692. ; name. On return, the number is in register (A). Any error
  693. ; causes 'filename?' to be printed and the command is aborted.
  694. ;
  695. DECODE: CALL CONVFST ;convert filename.
  696. LD A,(CHGDRV) ;do not allow a drive to be specified.
  697. OR A
  698. JP NZ,SYNERR
  699. LD HL,FCB+1 ;convert number now.
  700. LD BC,11 ;(B)=sum register, (C)=max digit count.
  701. DECODE1:LD A,(HL)
  702. CP ' ' ;a space terminates the numeral.
  703. JP Z,DECODE3
  704. INC HL
  705. SUB '0' ;make binary from ascii.
  706. CP 10 ;legal digit?
  707. JP NC,SYNERR
  708. LD D,A ;yes, save it in (D).
  709. LD A,B ;compute (B)=(B)*10 and check for overflow.
  710. AND 0E0H
  711. JP NZ,SYNERR
  712. LD A,B
  713. RLCA
  714. RLCA
  715. RLCA ;(A)=(B)*8
  716. ADD A,B ;.......*9
  717. JP C,SYNERR
  718. ADD A,B ;.......*10
  719. JP C,SYNERR
  720. ADD A,D ;add in new digit now.
  721. DECODE2:JP C,SYNERR
  722. LD B,A ;and save result.
  723. DEC C ;only look at 11 digits.
  724. JP NZ,DECODE1
  725. RET
  726. DECODE3:LD A,(HL) ;spaces must follow (why?).
  727. CP ' '
  728. JP NZ,SYNERR
  729. INC HL
  730. DECODE4:DEC C
  731. JP NZ,DECODE3
  732. LD A,B ;set (A)=the numeric value entered.
  733. RET
  734. ;
  735. ; Move 3 bytes from (HL) to (DE). Note that there is only
  736. ; one reference to this at (A2D5h).
  737. ;
  738. MOVE3: LD B,3
  739. ;
  740. ; Move (B) bytes from (HL) to (DE).
  741. ;
  742. HL2DE: LD A,(HL)
  743. LD (DE),A
  744. INC HL
  745. INC DE
  746. DEC B
  747. JP NZ,HL2DE
  748. RET
  749. ;
  750. ; Compute (HL)=(TBUFF)+(A)+(C) and get the byte that's here.
  751. ;
  752. EXTRACT:LD HL,TBUFF
  753. ADD A,C
  754. CALL ADDHL
  755. LD A,(HL)
  756. RET
  757. ;
  758. ; Check drive specified. If it means a change, then the new
  759. ; drive will be selected. In any case, the drive byte of the
  760. ; fcb will be set to null (means use current drive).
  761. ;
  762. DSELECT:XOR A ;null out first byte of fcb.
  763. LD (FCB),A
  764. LD A,(CHGDRV) ;a drive change indicated?
  765. OR A
  766. RET Z
  767. DEC A ;yes, is it the same as the current drive?
  768. LD HL,CDRIVE
  769. CP (HL)
  770. RET Z
  771. JP DSKSEL ;no. Select it then.
  772. ;
  773. ; Check the drive selection and reset it to the previous
  774. ; drive if it was changed for the preceeding command.
  775. ;
  776. RESETDR:LD A,(CHGDRV) ;drive change indicated?
  777. OR A
  778. RET Z
  779. DEC A ;yes, was it a different drive?
  780. LD HL,CDRIVE
  781. CP (HL)
  782. RET Z
  783. LD A,(CDRIVE) ;yes, re-select our old drive.
  784. JP DSKSEL
  785. ;
  786. ;**************************************************************
  787. ;*
  788. ;* D I R E C T O R Y C O M M A N D
  789. ;*
  790. ;**************************************************************
  791. ;
  792. DIRECT: CALL CONVFST ;convert file name.
  793. CALL DSELECT ;select indicated drive.
  794. LD HL,FCB+1 ;was any file indicated?
  795. LD A,(HL)
  796. CP ' '
  797. JP NZ,DIRECT2
  798. LD B,11 ;no. Fill field with '?' - same as *.*.
  799. DIRECT1:LD (HL),'?'
  800. INC HL
  801. DEC B
  802. JP NZ,DIRECT1
  803. DIRECT2:LD E,0 ;set initial cursor position.
  804. PUSH DE
  805. CALL SRCHFCB ;get first file name.
  806. CALL Z,NONE ;none found at all?
  807. DIRECT3:JP Z,DIRECT9 ;terminate if no more names.
  808. LD A,(RTNCODE) ;get file's position in segment (0-3).
  809. RRCA
  810. RRCA
  811. RRCA
  812. AND 60H ;(A)=position*32
  813. LD C,A
  814. LD A,10
  815. CALL EXTRACT ;extract the tenth entry in fcb.
  816. RLA ;check system file status bit.
  817. JP C,DIRECT8 ;we don't list them.
  818. POP DE
  819. LD A,E ;bump name count.
  820. INC E
  821. PUSH DE
  822. AND 03H ;at end of line?
  823. PUSH AF
  824. JP NZ,DIRECT4
  825. CALL CRLF ;yes, end this line and start another.
  826. PUSH BC
  827. CALL GETDSK ;start line with ('A:').
  828. POP BC
  829. ADD A,'A'
  830. CALL PRINTB
  831. LD A,':'
  832. CALL PRINTB
  833. JP DIRECT5
  834. DIRECT4:CALL SPACE ;add seperator between file names.
  835. LD A,':'
  836. CALL PRINTB
  837. DIRECT5:CALL SPACE
  838. LD B,1 ;'extract' each file name character at a time.
  839. DIRECT6:LD A,B
  840. CALL EXTRACT
  841. AND 7FH ;strip bit 7 (status bit).
  842. CP ' ' ;are we at the end of the name?
  843. JP NZ,DRECT65
  844. POP AF ;yes, don't print spaces at the end of a line.
  845. PUSH AF
  846. CP 3
  847. JP NZ,DRECT63
  848. LD A,9 ;first check for no extension.
  849. CALL EXTRACT
  850. AND 7FH
  851. CP ' '
  852. JP Z,DIRECT7 ;don't print spaces.
  853. DRECT63:LD A,' ' ;else print them.
  854. DRECT65:CALL PRINTB
  855. INC B ;bump to next character psoition.
  856. LD A,B
  857. CP 12 ;end of the name?
  858. JP NC,DIRECT7
  859. CP 9 ;nope, starting extension?
  860. JP NZ,DIRECT6
  861. CALL SPACE ;yes, add seperating space.
  862. JP DIRECT6
  863. DIRECT7:POP AF ;get the next file name.
  864. DIRECT8:CALL CHKCON ;first check console, quit on anything.
  865. JP NZ,DIRECT9
  866. CALL SRCHNXT ;get next name.
  867. JP DIRECT3 ;and continue with our list.
  868. DIRECT9:POP DE ;restore the stack and return to command level.
  869. JP GETBACK
  870. ;
  871. ;**************************************************************
  872. ;*
  873. ;* E R A S E C O M M A N D
  874. ;*
  875. ;**************************************************************
  876. ;
  877. ERASE: CALL CONVFST ;convert file name.
  878. CP 11 ;was '*.*' entered?
  879. JP NZ,ERASE1
  880. LD BC,YESNO ;yes, ask for confirmation.
  881. CALL PLINE
  882. CALL GETINP
  883. LD HL,INBUFF+1
  884. DEC (HL) ;must be exactly 'y'.
  885. JP NZ,CMMND1
  886. INC HL
  887. LD A,(HL)
  888. CP 'Y'
  889. JP NZ,CMMND1
  890. INC HL
  891. LD (INPOINT),HL ;save input line pointer.
  892. ERASE1: CALL DSELECT ;select desired disk.
  893. LD DE,FCB
  894. CALL DELETE ;delete the file.
  895. INC A
  896. CALL Z,NONE ;not there?
  897. JP GETBACK ;return to command level now.
  898. YESNO: DB "All (y/n)?"
  899. DB 0
  900. ;
  901. ;**************************************************************
  902. ;*
  903. ;* T Y P E C O M M A N D
  904. ;*
  905. ;**************************************************************
  906. ;
  907. TYPE: CALL CONVFST ;convert file name.
  908. JP NZ,SYNERR ;wild cards not allowed.
  909. CALL DSELECT ;select indicated drive.
  910. CALL OPENFCB ;open the file.
  911. JP Z,TYPE5 ;not there?
  912. CALL CRLF ;ok, start a new line on the screen.
  913. LD HL,NBYTES ;initialize byte counter.
  914. LD (HL),0FFH ;set to read first sector.
  915. TYPE1: LD HL,NBYTES
  916. TYPE2: LD A,(HL) ;have we written the entire sector?
  917. CP 128
  918. JP C,TYPE3
  919. PUSH HL ;yes, read in the next one.
  920. CALL READFCB
  921. POP HL
  922. JP NZ,TYPE4 ;end or error?
  923. XOR A ;ok, clear byte counter.
  924. LD (HL),A
  925. TYPE3: INC (HL) ;count this byte.
  926. LD HL,TBUFF ;and get the (A)th one from the buffer (TBUFF).
  927. CALL ADDHL
  928. LD A,(HL)
  929. CP CNTRLZ ;end of file mark?
  930. JP Z,GETBACK
  931. CALL PRINT ;no, print it.
  932. CALL CHKCON ;check console, quit if anything ready.
  933. JP NZ,GETBACK
  934. JP TYPE1
  935. ;
  936. ; Get here on an end of file or read error.
  937. ;
  938. TYPE4: DEC A ;read error?
  939. JP Z,GETBACK
  940. CALL RDERROR ;yes, print message.
  941. TYPE5: CALL RESETDR ;and reset proper drive
  942. JP SYNERR ;now print file name with problem.
  943. ;
  944. ;**************************************************************
  945. ;*
  946. ;* S A V E C O M M A N D
  947. ;*
  948. ;**************************************************************
  949. ;
  950. SAVE: CALL DECODE ;get numeric number that follows SAVE.
  951. PUSH AF ;save number of pages to write.
  952. CALL CONVFST ;convert file name.
  953. JP NZ,SYNERR ;wild cards not allowed.
  954. CALL DSELECT ;select specified drive.
  955. LD DE,FCB ;now delete this file.
  956. PUSH DE
  957. CALL DELETE
  958. POP DE
  959. CALL CREATE ;and create it again.
  960. JP Z,SAVE3 ;can't create?
  961. XOR A ;clear record number byte.
  962. LD (FCB+32),A
  963. POP AF ;convert pages to sectors.
  964. LD L,A
  965. LD H,0
  966. ADD HL,HL ;(HL)=number of sectors to write.
  967. LD DE,TBASE ;and we start from here.
  968. SAVE1: LD A,H ;done yet?
  969. OR L
  970. JP Z,SAVE2
  971. DEC HL ;nope, count this and compute the start
  972. PUSH HL ;of the next 128 byte sector.
  973. LD HL,128
  974. ADD HL,DE
  975. PUSH HL ;save it and set the transfer address.
  976. CALL DMASET
  977. LD DE,FCB ;write out this sector now.
  978. CALL WRTREC
  979. POP DE ;reset (DE) to the start of the last sector.
  980. POP HL ;restore sector count.
  981. JP NZ,SAVE3 ;write error?
  982. JP SAVE1
  983. ;
  984. ; Get here after writing all of the file.
  985. ;
  986. SAVE2: LD DE,FCB ;now close the file.
  987. CALL CLOSE
  988. INC A ;did it close ok?
  989. JP NZ,SAVE4
  990. ;
  991. ; Print out error message (no space).
  992. ;
  993. SAVE3: LD BC,NOSPACE
  994. CALL PLINE
  995. SAVE4: CALL STDDMA ;reset the standard dma address.
  996. JP GETBACK
  997. NOSPACE: DB "No space"
  998. DB 0
  999. ;
  1000. ;**************************************************************
  1001. ;*
  1002. ;* R E N A M E C O M M A N D
  1003. ;*
  1004. ;**************************************************************
  1005. ;
  1006. RENAME: CALL CONVFST ;convert first file name.
  1007. JP NZ,SYNERR ;wild cards not allowed.
  1008. LD A,(CHGDRV) ;remember any change in drives specified.
  1009. PUSH AF
  1010. CALL DSELECT ;and select this drive.
  1011. CALL SRCHFCB ;is this file present?
  1012. JP NZ,RENAME6 ;yes, print error message.
  1013. LD HL,FCB ;yes, move this name into second slot.
  1014. LD DE,FCB+16
  1015. LD B,16
  1016. CALL HL2DE
  1017. LD HL,(INPOINT) ;get input pointer.
  1018. EX DE,HL
  1019. CALL NONBLANK ;get next non blank character.
  1020. CP '=' ;only allow an '=' or '_' seperator.
  1021. JP Z,RENAME1
  1022. CP '_'
  1023. JP NZ,RENAME5
  1024. RENAME1:EX DE,HL
  1025. INC HL ;ok, skip seperator.
  1026. LD (INPOINT),HL ;save input line pointer.
  1027. CALL CONVFST ;convert this second file name now.
  1028. JP NZ,RENAME5 ;again, no wild cards.
  1029. POP AF ;if a drive was specified, then it
  1030. LD B,A ;must be the same as before.
  1031. LD HL,CHGDRV
  1032. LD A,(HL)
  1033. OR A
  1034. JP Z,RENAME2
  1035. CP B
  1036. LD (HL),B
  1037. JP NZ,RENAME5 ;they were different, error.
  1038. RENAME2:LD (HL),B ; reset as per the first file specification.
  1039. XOR A
  1040. LD (FCB),A ;clear the drive byte of the fcb.
  1041. RENAME3:CALL SRCHFCB ;and go look for second file.
  1042. JP Z,RENAME4 ;doesn't exist?
  1043. LD DE,FCB
  1044. CALL RENAM ;ok, rename the file.
  1045. JP GETBACK
  1046. ;
  1047. ; Process rename errors here.
  1048. ;
  1049. RENAME4:CALL NONE ;file not there.
  1050. JP GETBACK
  1051. RENAME5:CALL RESETDR ;bad command format.
  1052. JP SYNERR
  1053. RENAME6:LD BC,EXISTS ;destination file already exists.
  1054. CALL PLINE
  1055. JP GETBACK
  1056. EXISTS: DB "File exists"
  1057. DB 0
  1058. ;
  1059. ;**************************************************************
  1060. ;*
  1061. ;* U S E R C O M M A N D
  1062. ;*
  1063. ;**************************************************************
  1064. ;
  1065. USER: CALL DECODE ;get numeric value following command.
  1066. CP 16 ;legal user number?
  1067. JP NC,SYNERR
  1068. LD E,A ;yes but is there anything else?
  1069. LD A,(FCB+1)
  1070. CP ' '
  1071. JP Z,SYNERR ;yes, that is not allowed.
  1072. CALL GETSETUC ;ok, set user code.
  1073. JP GETBACK1
  1074. ;
  1075. ;**************************************************************
  1076. ;*
  1077. ;* T R A N S I A N T P R O G R A M C O M M A N D
  1078. ;*
  1079. ;**************************************************************
  1080. ;
  1081. UNKNOWN:CALL VERIFY ;check for valid system (why?).
  1082. LD A,(FCB+1) ;anything to execute?
  1083. CP ' '
  1084. JP NZ,UNKWN1
  1085. LD A,(CHGDRV) ;nope, only a drive change?
  1086. OR A
  1087. JP Z,GETBACK1 ;neither???
  1088. DEC A
  1089. LD (CDRIVE),A ;ok, store new drive.
  1090. CALL MOVECD ;set (TDRIVE) also.
  1091. CALL DSKSEL ;and select this drive.
  1092. JP GETBACK1 ;then return.
  1093. ;
  1094. ; Here a file name was typed. Prepare to execute it.
  1095. ;
  1096. UNKWN1: LD DE,FCB+9 ;an extension specified?
  1097. LD A,(DE)
  1098. CP ' '
  1099. JP NZ,SYNERR ;yes, not allowed.
  1100. UNKWN2: PUSH DE
  1101. CALL DSELECT ;select specified drive.
  1102. POP DE
  1103. LD HL,COMFILE ;set the extension to 'COM'.
  1104. CALL MOVE3
  1105. CALL OPENFCB ;and open this file.
  1106. JP Z,UNKWN9 ;not present?
  1107. ;
  1108. ; Load in the program.
  1109. ;
  1110. LD HL,TBASE ;store the program starting here.
  1111. UNKWN3: PUSH HL
  1112. EX DE,HL
  1113. CALL DMASET ;set transfer address.
  1114. LD DE,FCB ;and read the next record.
  1115. CALL RDREC
  1116. JP NZ,UNKWN4 ;end of file or read error?
  1117. POP HL ;nope, bump pointer for next sector.
  1118. LD DE,128
  1119. ADD HL,DE
  1120. LD DE,CBASE ;enough room for the whole file?
  1121. LD A,L
  1122. SUB E
  1123. LD A,H
  1124. SBC A,D
  1125. JP NC,UNKWN0 ;no, it can't fit.
  1126. JP UNKWN3
  1127. ;
  1128. ; Get here after finished reading.
  1129. ;
  1130. UNKWN4: POP HL
  1131. DEC A ;normal end of file?
  1132. JP NZ,UNKWN0
  1133. CALL RESETDR ;yes, reset previous drive.
  1134. CALL CONVFST ;convert the first file name that follows
  1135. LD HL,CHGDRV ;command name.
  1136. PUSH HL
  1137. LD A,(HL) ;set drive code in default fcb.
  1138. LD (FCB),A
  1139. LD A,16 ;put second name 16 bytes later.
  1140. CALL CONVERT ;convert second file name.
  1141. POP HL
  1142. LD A,(HL) ;and set the drive for this second file.
  1143. LD (FCB+16),A
  1144. XOR A ;clear record byte in fcb.
  1145. LD (FCB+32),A
  1146. LD DE,TFCB ;move it into place at(005Ch).
  1147. LD HL,FCB
  1148. LD B,33
  1149. CALL HL2DE
  1150. LD HL,INBUFF+2 ;now move the remainder of the input
  1151. UNKWN5: LD A,(HL) ;line down to (0080h). Look for a non blank.
  1152. OR A ;or a null.
  1153. JP Z,UNKWN6
  1154. CP ' '
  1155. JP Z,UNKWN6
  1156. INC HL
  1157. JP UNKWN5
  1158. ;
  1159. ; Do the line move now. It ends in a null byte.
  1160. ;
  1161. UNKWN6: LD B,0 ;keep a character count.
  1162. LD DE,TBUFF+1 ;data gets put here.
  1163. UNKWN7: LD A,(HL) ;move it now.
  1164. LD (DE),A
  1165. OR A
  1166. JP Z,UNKWN8
  1167. INC B
  1168. INC HL
  1169. INC DE
  1170. JP UNKWN7
  1171. UNKWN8: LD A,B ;now store the character count.
  1172. LD (TBUFF),A
  1173. CALL CRLF ;clean up the screen.
  1174. CALL STDDMA ;set standard transfer address.
  1175. CALL SETCDRV ;reset current drive.
  1176. CALL TBASE ;and execute the program.
  1177. ;
  1178. ; Transiant programs return here (or reboot).
  1179. ;
  1180. LD SP,BATCH ;set stack first off.
  1181. CALL MOVECD ;move current drive into place (TDRIVE).
  1182. CALL DSKSEL ;and reselect it.
  1183. JP CMMND1 ;back to comand mode.
  1184. ;
  1185. ; Get here if some error occured.
  1186. ;
  1187. UNKWN9: CALL RESETDR ;inproper format.
  1188. JP SYNERR
  1189. UNKWN0: LD BC,BADLOAD ;read error or won't fit.
  1190. CALL PLINE
  1191. JP GETBACK
  1192. BADLOAD: DB "Bad load"
  1193. DB 0
  1194. COMFILE: DB "COM" ;command file extension.
  1195. ;
  1196. ; Get here to return to command level. We will reset the
  1197. ; previous active drive and then either return to command
  1198. ; level directly or print error message and then return.
  1199. ;
  1200. GETBACK:CALL RESETDR ;reset previous drive.
  1201. GETBACK1: CALL CONVFST ;convert first name in (FCB).
  1202. LD A,(FCB+1) ;if this was just a drive change request,
  1203. SUB ' ' ;make sure it was valid.
  1204. LD HL,CHGDRV
  1205. OR (HL)
  1206. JP NZ,SYNERR
  1207. JP CMMND1 ;ok, return to command level.
  1208. ;
  1209. ; ccp stack area.
  1210. ;
  1211. DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  1212. CCPSTACK EQU $ ;end of ccp stack area.
  1213. ;
  1214. ; Batch (or SUBMIT) processing information storage.
  1215. ;
  1216. BATCH: DB 0 ;batch mode flag (0=not active).
  1217. BATCHFCB: DB 0,
  1218. DB "$$$ SUB"
  1219. DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  1220. ;
  1221. ; File control block setup by the CCP.
  1222. ;
  1223. FCB: DB 0
  1224. DB " "
  1225. DB 0,0,0,0,0
  1226. DB " "
  1227. DB 0,0,0,0,0
  1228. RTNCODE: DB 0 ;status returned from bdos call.
  1229. CDRIVE: DB 0 ;currently active drive.
  1230. CHGDRV: DB 0 ;change in drives flag (0=no change).
  1231. NBYTES: DW 0 ;byte counter used by TYPE.
  1232. ;
  1233. ; Room for expansion?
  1234. ;
  1235. DB 0,0,0,0,0,0,0,0,0,0,0,0,0
  1236. ;
  1237. ; Note that the following six bytes must match those at
  1238. ; (PATTRN1) or cp/m will HALT. Why?
  1239. ;
  1240. PATTRN2: DB 0,22,0,0,0,0 ;(* serial number bytes *).
  1241. ;
  1242. ;**************************************************************
  1243. ;*
  1244. ;* B D O S E N T R Y
  1245. ;*
  1246. ;**************************************************************
  1247. ;
  1248. FBASE: JP FBASE1
  1249. ;
  1250. ; Bdos error table.
  1251. ;
  1252. BADSCTR: DW ERROR1 ;bad sector on read or write.
  1253. BADSLCT: DW ERROR2 ;bad disk select.
  1254. RODISK: DW ERROR3 ;disk is read only.
  1255. ROFILE: DW ERROR4 ;file is read only.
  1256. ;
  1257. ; Entry into bdos. (DE) or (E) are the parameters passed. The
  1258. ; function number desired is in register (C).
  1259. ;
  1260. FBASE1: EX DE,HL ;save the (DE) parameters.
  1261. LD (PARAMS),HL
  1262. EX DE,HL
  1263. LD A,E ;and save register (E) in particular.
  1264. LD (EPARAM),A
  1265. LD HL,0
  1266. LD (STATUS),HL ;clear return status.
  1267. ADD HL,SP
  1268. LD (USRSTACK),HL ;save users stack pointer.
  1269. LD SP,STKAREA ;and set our own.
  1270. XOR A ;clear auto select storage space.
  1271. LD (AUTOFLAG),A
  1272. LD (AUTO),A
  1273. LD HL,GOBACK ;set return address.
  1274. PUSH HL
  1275. LD A,C ;get function number.
  1276. CP NFUNCTS ;valid function number?
  1277. RET NC
  1278. LD C,E ;keep single register function here.
  1279. LD HL,FUNCTNS ;now look thru the function table.
  1280. LD E,A
  1281. LD D,0 ;(DE)=function number.
  1282. ADD HL,DE
  1283. ADD HL,DE ;(HL)=(start of table)+2*(function number).
  1284. LD E,(HL)
  1285. INC HL
  1286. LD D,(HL) ;now (DE)=address for this function.
  1287. LD HL,(PARAMS) ;retrieve parameters.
  1288. EX DE,HL ;now (DE) has the original parameters.
  1289. JP (HL) ;execute desired function.
  1290. ;
  1291. ; BDOS function jump table.
  1292. ;
  1293. NFUNCTS EQU 41 ;number of functions in followin table.
  1294. ;
  1295. FUNCTNS: DW WBOOT,GETCON,OUTCON,GETRDR,PUNCH,LIST,DIRCIO,GETIOB
  1296. DW SETIOB,PRTSTR,RDBUFF,GETCSTS,GETVER,RSTDSK,SETDSK,OPENFIL
  1297. DW CLOSEFIL,GETFST,GETNXT,DELFILE,READSEQ,WRTSEQ,FCREATE
  1298. DW RENFILE,GETLOG,GETCRNT,PUTDMA,GETALOC,WRTPRTD,GETROV,SETATTR
  1299. DW GETPARM,GETUSER,RDRANDOM,WTRANDOM,FILESIZE,SETRAN,LOGOFF,RTN
  1300. DW RTN,WTSPECL
  1301. ;
  1302. ; Bdos error message section.
  1303. ;
  1304. ERROR1: LD HL,BADSEC ;bad sector message.
  1305. CALL PRTERR ;print it and get a 1 char responce.
  1306. CP CNTRLC ;re-boot request (control-c)?
  1307. JP Z,0 ;yes.
  1308. RET ;no, return to retry i/o function.
  1309. ;
  1310. ERROR2: LD HL,BADSEL ;bad drive selected.
  1311. JP ERROR5
  1312. ;
  1313. ERROR3: LD HL,DISKRO ;disk is read only.
  1314. JP ERROR5
  1315. ;
  1316. ERROR4: LD HL,FILERO ;file is read only.
  1317. ;
  1318. ERROR5: CALL PRTERR
  1319. JP 0 ;always reboot on these errors.
  1320. ;
  1321. BDOSERR: DB "Bdos Err On "
  1322. BDOSDRV: DB " : $"
  1323. BADSEC: DB "Bad Sector$"
  1324. BADSEL: DB "Select$"
  1325. FILERO: DB "File "
  1326. DISKRO: DB "R/O$"
  1327. ;
  1328. ; Print bdos error message.
  1329. ;
  1330. PRTERR: PUSH HL ;save second message pointer.
  1331. CALL OUTCRLF ;send (cr)(lf).
  1332. LD A,(ACTIVE) ;get active drive.
  1333. ADD A,'A' ;make ascii.
  1334. LD (BDOSDRV),A ;and put in message.
  1335. LD BC,BDOSERR ;and print it.
  1336. CALL PRTMESG
  1337. POP BC ;print second message line now.
  1338. CALL PRTMESG
  1339. ;
  1340. ; Get an input character. We will check our 1 character
  1341. ; buffer first. This may be set by the console status routine.
  1342. ;
  1343. GETCHAR:LD HL,CHARBUF ;check character buffer.
  1344. LD A,(HL) ;anything present already?
  1345. LD (HL),0 ;...either case clear it.
  1346. OR A
  1347. RET NZ ;yes, use it.
  1348. JP CONIN ;nope, go get a character responce.
  1349. ;
  1350. ; Input and echo a character.
  1351. ;
  1352. GETECHO:CALL GETCHAR ;input a character.
  1353. CALL CHKCHAR ;carriage control?
  1354. RET C ;no, a regular control char so don't echo.
  1355. PUSH AF ;ok, save character now.
  1356. LD C,A
  1357. CALL OUTCON ;and echo it.
  1358. POP AF ;get character and return.
  1359. RET
  1360. ;
  1361. ; Check character in (A). Set the zero flag on a carriage
  1362. ; control character and the carry flag on any other control
  1363. ; character.
  1364. ;
  1365. CHKCHAR:CP CR ;check for carriage return, line feed, backspace,
  1366. RET Z ;or a tab.
  1367. CP LF
  1368. RET Z
  1369. CP TAB
  1370. RET Z
  1371. CP BS
  1372. RET Z
  1373. CP ' ' ;other control char? Set carry flag.
  1374. RET
  1375. ;
  1376. ; Check the console during output. Halt on a control-s, then
  1377. ; reboot on a control-c. If anything else is ready, clear the
  1378. ; zero flag and return (the calling routine may want to do
  1379. ; something).
  1380. ;
  1381. CKCONSOL: LD A,(CHARBUF) ;check buffer.
  1382. OR A ;if anything, just return without checking.
  1383. JP NZ,CKCON2
  1384. CALL CONST ;nothing in buffer. Check console.
  1385. AND 01H ;look at bit 0.
  1386. RET Z ;return if nothing.
  1387. CALL CONIN ;ok, get it.
  1388. CP CNTRLS ;if not control-s, return with zero cleared.
  1389. JP NZ,CKCON1
  1390. CALL CONIN ;halt processing until another char
  1391. CP CNTRLC ;is typed. Control-c?
  1392. JP Z,0 ;yes, reboot now.
  1393. XOR A ;no, just pretend nothing was ever ready.
  1394. RET
  1395. CKCON1: LD (CHARBUF),A ;save character in buffer for later processing.
  1396. CKCON2: LD A,1 ;set (A) to non zero to mean something is ready.
  1397. RET
  1398. ;
  1399. ; Output (C) to the screen. If the printer flip-flop flag
  1400. ; is set, we will send character to printer also. The console
  1401. ; will be checked in the process.
  1402. ;
  1403. OUTCHAR:LD A,(OUTFLAG) ;check output flag.
  1404. OR A ;anything and we won't generate output.
  1405. JP NZ,OUTCHR1
  1406. PUSH BC
  1407. CALL CKCONSOL ;check console (we don't care whats there).
  1408. POP BC
  1409. PUSH BC
  1410. CALL CONOUT ;output (C) to the screen.
  1411. POP BC
  1412. PUSH BC
  1413. LD A,(PRTFLAG) ;check printer flip-flop flag.
  1414. OR A
  1415. CALL NZ,LIST ;print it also if non-zero.
  1416. POP BC
  1417. OUTCHR1:LD A,C ;update cursors position.
  1418. LD HL,CURPOS
  1419. CP DEL ;rubouts don't do anything here.
  1420. RET Z
  1421. INC (HL) ;bump line pointer.
  1422. CP ' ' ;and return if a normal character.
  1423. RET NC
  1424. DEC (HL) ;restore and check for the start of the line.
  1425. LD A,(HL)
  1426. OR A
  1427. RET Z ;ingnore control characters at the start of the line.
  1428. LD A,C
  1429. CP BS ;is it a backspace?
  1430. JP NZ,OUTCHR2
  1431. DEC (HL) ;yes, backup pointer.
  1432. RET
  1433. OUTCHR2:CP LF ;is it a line feed?
  1434. RET NZ ;ignore anything else.
  1435. LD (HL),0 ;reset pointer to start of line.
  1436. RET
  1437. ;
  1438. ; Output (A) to the screen. If it is a control character
  1439. ; (other than carriage control), use ^x format.
  1440. ;
  1441. SHOWIT: LD A,C
  1442. CALL CHKCHAR ;check character.
  1443. JP NC,OUTCON ;not a control, use normal output.
  1444. PUSH AF
  1445. LD C,'^' ;for a control character, preceed it with '^'.
  1446. CALL OUTCHAR
  1447. POP AF
  1448. OR '@' ;and then use the letter equivelant.
  1449. LD C,A
  1450. ;
  1451. ; Function to output (C) to the console device and expand tabs
  1452. ; if necessary.
  1453. ;
  1454. OUTCON: LD A,C
  1455. CP TAB ;is it a tab?
  1456. JP NZ,OUTCHAR ;use regular output.
  1457. OUTCON1:LD C,' ' ;yes it is, use spaces instead.
  1458. CALL OUTCHAR
  1459. LD A,(CURPOS) ;go until the cursor is at a multiple of 8
  1460. AND 07H ;position.
  1461. JP NZ,OUTCON1
  1462. RET
  1463. ;
  1464. ; Echo a backspace character. Erase the prevoius character
  1465. ; on the screen.
  1466. ;
  1467. BACKUP: CALL BACKUP1 ;backup the screen 1 place.
  1468. LD C,' ' ;then blank that character.
  1469. CALL CONOUT
  1470. BACKUP1:LD C,BS ;then back space once more.
  1471. JP CONOUT
  1472. ;
  1473. ; Signal a deleted line. Print a '#' at the end and start
  1474. ; over.
  1475. ;
  1476. NEWLINE:LD C,'#'
  1477. CALL OUTCHAR ;print this.
  1478. CALL OUTCRLF ;start new line.
  1479. NEWLN1: LD A,(CURPOS) ;move the cursor to the starting position.
  1480. LD HL,STARTING
  1481. CP (HL)
  1482. RET NC ;there yet?
  1483. LD C,' '
  1484. CALL OUTCHAR ;nope, keep going.
  1485. JP NEWLN1
  1486. ;
  1487. ; Output a (cr) (lf) to the console device (screen).
  1488. ;
  1489. OUTCRLF:LD C,CR
  1490. CALL OUTCHAR
  1491. LD C,LF
  1492. JP OUTCHAR
  1493. ;
  1494. ; Print message pointed to by (BC). It will end with a '$'.
  1495. ;
  1496. PRTMESG:LD A,(BC) ;check for terminating character.
  1497. CP '$'
  1498. RET Z
  1499. INC BC
  1500. PUSH BC ;otherwise, bump pointer and print it.
  1501. LD C,A
  1502. CALL OUTCON
  1503. POP BC
  1504. JP PRTMESG
  1505. ;
  1506. ; Function to execute a buffered read.
  1507. ;
  1508. RDBUFF: LD A,(CURPOS) ;use present location as starting one.
  1509. LD (STARTING),A
  1510. LD HL,(PARAMS) ;get the maximum buffer space.
  1511. LD C,(HL)
  1512. INC HL ;point to first available space.
  1513. PUSH HL ;and save.
  1514. LD B,0 ;keep a character count.
  1515. RDBUF1: PUSH BC
  1516. PUSH HL
  1517. RDBUF2: CALL GETCHAR ;get the next input character.
  1518. AND 7FH ;strip bit 7.
  1519. POP HL ;reset registers.
  1520. POP BC
  1521. CP CR ;en of the line?
  1522. JP Z,RDBUF17
  1523. CP LF
  1524. JP Z,RDBUF17
  1525. CP BS ;how about a backspace?
  1526. JP NZ,RDBUF3
  1527. LD A,B ;yes, but ignore at the beginning of the line.
  1528. OR A
  1529. JP Z,RDBUF1
  1530. DEC B ;ok, update counter.
  1531. LD A,(CURPOS) ;if we backspace to the start of the line,
  1532. LD (OUTFLAG),A ;treat as a cancel (control-x).
  1533. JP RDBUF10
  1534. RDBUF3: CP DEL ;user typed a rubout?
  1535. JP NZ,RDBUF4
  1536. LD A,B ;ignore at the start of the line.
  1537. OR A
  1538. JP Z,RDBUF1
  1539. LD A,(HL) ;ok, echo the prevoius character.
  1540. DEC B ;and reset pointers (counters).
  1541. DEC HL
  1542. JP RDBUF15
  1543. RDBUF4: CP CNTRLE ;physical end of line?
  1544. JP NZ,RDBUF5
  1545. PUSH BC ;yes, do it.
  1546. PUSH HL
  1547. CALL OUTCRLF
  1548. XOR A ;and update starting position.
  1549. LD (STARTING),A
  1550. JP RDBUF2
  1551. RDBUF5: CP CNTRLP ;control-p?
  1552. JP NZ,RDBUF6
  1553. PUSH HL ;yes, flip the print flag filp-flop byte.
  1554. LD HL,PRTFLAG
  1555. LD A,1 ;PRTFLAG=1-PRTFLAG
  1556. SUB (HL)
  1557. LD (HL),A
  1558. POP HL
  1559. JP RDBUF1
  1560. RDBUF6: CP CNTRLX ;control-x (cancel)?
  1561. JP NZ,RDBUF8
  1562. POP HL
  1563. RDBUF7: LD A,(STARTING) ;yes, backup the cursor to here.
  1564. LD HL,CURPOS
  1565. CP (HL)
  1566. JP NC,RDBUFF ;done yet?
  1567. DEC (HL) ;no, decrement pointer and output back up one space.
  1568. CALL BACKUP
  1569. JP RDBUF7
  1570. RDBUF8: CP CNTRLU ;cntrol-u (cancel line)?
  1571. JP NZ,RDBUF9
  1572. CALL NEWLINE ;start a new line.
  1573. POP HL
  1574. JP RDBUFF
  1575. RDBUF9: CP CNTRLR ;control-r?
  1576. JP NZ,RDBUF14
  1577. RDBUF10:PUSH BC ;yes, start a new line and retype the old one.
  1578. CALL NEWLINE
  1579. POP BC
  1580. POP HL
  1581. PUSH HL
  1582. PUSH BC
  1583. RDBUF11:LD A,B ;done whole line yet?
  1584. OR A
  1585. JP Z,RDBUF12
  1586. INC HL ;nope, get next character.
  1587. LD C,(HL)
  1588. DEC B ;count it.
  1589. PUSH BC
  1590. PUSH HL
  1591. CALL SHOWIT ;and display it.
  1592. POP HL
  1593. POP BC
  1594. JP RDBUF11
  1595. RDBUF12:PUSH HL ;done with line. If we were displaying
  1596. LD A,(OUTFLAG) ;then update cursor position.
  1597. OR A
  1598. JP Z,RDBUF2
  1599. LD HL,CURPOS ;because this line is shorter, we must
  1600. SUB (HL) ;back up the cursor (not the screen however)
  1601. LD (OUTFLAG),A ;some number of positions.
  1602. RDBUF13:CALL BACKUP ;note that as long as (OUTFLAG) is non
  1603. LD HL,OUTFLAG ;zero, the screen will not be changed.
  1604. DEC (HL)
  1605. JP NZ,RDBUF13
  1606. JP RDBUF2 ;now just get the next character.
  1607. ;
  1608. ; Just a normal character, put this in our buffer and echo.
  1609. ;
  1610. RDBUF14:INC HL
  1611. LD (HL),A ;store character.
  1612. INC B ;and count it.
  1613. RDBUF15:PUSH BC
  1614. PUSH HL
  1615. LD C,A ;echo it now.
  1616. CALL SHOWIT
  1617. POP HL
  1618. POP BC
  1619. LD A,(HL) ;was it an abort request?
  1620. CP CNTRLC ;control-c abort?
  1621. LD A,B
  1622. JP NZ,RDBUF16
  1623. CP 1 ;only if at start of line.
  1624. JP Z,0
  1625. RDBUF16:CP C ;nope, have we filled the buffer?
  1626. JP C,RDBUF1
  1627. RDBUF17:POP HL ;yes end the line and return.
  1628. LD (HL),B
  1629. LD C,CR
  1630. JP OUTCHAR ;output (cr) and return.
  1631. ;
  1632. ; Function to get a character from the console device.
  1633. ;
  1634. GETCON: CALL GETECHO ;get and echo.
  1635. JP SETSTAT ;save status and return.
  1636. ;
  1637. ; Function to get a character from the tape reader device.
  1638. ;
  1639. GETRDR: CALL READER ;get a character from reader, set status and return.
  1640. JP SETSTAT
  1641. ;
  1642. ; Function to perform direct console i/o. If (C) contains (FF)
  1643. ; then this is an input request. If (C) contains (FE) then
  1644. ; this is a status request. Otherwise we are to output (C).
  1645. ;
  1646. DIRCIO: LD A,C ;test for (FF).
  1647. INC A
  1648. JP Z,DIRC1
  1649. INC A ;test for (FE).
  1650. JP Z,CONST
  1651. JP CONOUT ;just output (C).
  1652. DIRC1: CALL CONST ;this is an input request.
  1653. OR A
  1654. JP Z,GOBACK1 ;not ready? Just return (directly).
  1655. CALL CONIN ;yes, get character.
  1656. JP SETSTAT ;set status and return.
  1657. ;
  1658. ; Function to return the i/o byte.
  1659. ;
  1660. GETIOB: LD A,(IOBYTE)
  1661. JP SETSTAT
  1662. ;
  1663. ; Function to set the i/o byte.
  1664. ;
  1665. SETIOB: LD HL,IOBYTE
  1666. LD (HL),C
  1667. RET
  1668. ;
  1669. ; Function to print the character string pointed to by (DE)
  1670. ; on the console device. The string ends with a '$'.
  1671. ;
  1672. PRTSTR: EX DE,HL
  1673. LD C,L
  1674. LD B,H ;now (BC) points to it.
  1675. JP PRTMESG
  1676. ;
  1677. ; Function to interigate the console device.
  1678. ;
  1679. GETCSTS:CALL CKCONSOL
  1680. ;
  1681. ; Get here to set the status and return to the cleanup
  1682. ; section. Then back to the user.
  1683. ;
  1684. SETSTAT:LD (STATUS),A
  1685. RTN: RET
  1686. ;
  1687. ; Set the status to 1 (read or write error code).
  1688. ;
  1689. IOERR1: LD A,1
  1690. JP SETSTAT
  1691. ;
  1692. OUTFLAG: DB 0 ;output flag (non zero means no output).
  1693. STARTING: DB 2 ;starting position for cursor.
  1694. CURPOS: DB 0 ;cursor position (0=start of line).
  1695. PRTFLAG: DB 0 ;printer flag (control-p toggle). List if non zero.
  1696. CHARBUF: DB 0 ;single input character buffer.
  1697. ;
  1698. ; Stack area for BDOS calls.
  1699. ;
  1700. USRSTACK: DW 0 ;save users stack pointer here.
  1701. ;
  1702. DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  1703. DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  1704. STKAREA EQU $ ;end of stack area.
  1705. ;
  1706. USERNO: DB 0 ;current user number.
  1707. ACTIVE: DB 0 ;currently active drive.
  1708. PARAMS: DW 0 ;save (DE) parameters here on entry.
  1709. STATUS: DW 0 ;status returned from bdos function.
  1710. ;
  1711. ; Select error occured, jump to error routine.
  1712. ;
  1713. SLCTERR:LD HL,BADSLCT
  1714. ;
  1715. ; Jump to (HL) indirectly.
  1716. ;
  1717. JUMPHL: LD E,(HL)
  1718. INC HL
  1719. LD D,(HL) ;now (DE) contain the desired address.
  1720. EX DE,HL
  1721. JP (HL)
  1722. ;
  1723. ; Block move. (DE) to (HL), (C) bytes total.
  1724. ;
  1725. DE2HL: INC C ;is count down to zero?
  1726. DE2HL1: DEC C
  1727. RET Z ;yes, we are done.
  1728. LD A,(DE) ;no, move one more byte.
  1729. LD (HL),A
  1730. INC DE
  1731. INC HL
  1732. JP DE2HL1 ;and repeat.
  1733. ;
  1734. ; Select the desired drive.
  1735. ;
  1736. SELECT: LD A,(ACTIVE) ;get active disk.
  1737. LD C,A
  1738. CALL SELDSK ;select it.
  1739. LD A,H ;valid drive?
  1740. OR L ;valid drive?
  1741. RET Z ;return if not.
  1742. ;
  1743. ; Here, the BIOS returned the address of the parameter block
  1744. ; in (HL). We will extract the necessary pointers and save them.
  1745. ;
  1746. LD E,(HL) ;yes, get address of translation table into (DE).
  1747. INC HL
  1748. LD D,(HL)
  1749. INC HL
  1750. LD (SCRATCH1),HL ;save pointers to scratch areas.
  1751. INC HL
  1752. INC HL
  1753. LD (SCRATCH2),HL ;ditto.
  1754. INC HL
  1755. INC HL
  1756. LD (SCRATCH3),HL ;ditto.
  1757. INC HL
  1758. INC HL
  1759. EX DE,HL ;now save the translation table address.
  1760. LD (XLATE),HL
  1761. LD HL,DIRBUF ;put the next 8 bytes here.
  1762. LD C,8 ;they consist of the directory buffer
  1763. CALL DE2HL ;pointer, parameter block pointer,
  1764. LD HL,(DISKPB) ;check and allocation vectors.
  1765. EX DE,HL
  1766. LD HL,SECTORS ;move parameter block into our ram.
  1767. LD C,15 ;it is 15 bytes long.
  1768. CALL DE2HL
  1769. LD HL,(DSKSIZE) ;check disk size.
  1770. LD A,H ;more than 256 blocks on this?
  1771. LD HL,BIGDISK
  1772. LD (HL),0FFH ;set to samll.
  1773. OR A
  1774. JP Z,SELECT1
  1775. LD (HL),0 ;wrong, set to large.
  1776. SELECT1:LD A,0FFH ;clear the zero flag.
  1777. OR A
  1778. RET
  1779. ;
  1780. ; Routine to home the disk track head and clear pointers.
  1781. ;
  1782. HOMEDRV:CALL HOME ;home the head.
  1783. XOR A
  1784. LD HL,(SCRATCH2) ;set our track pointer also.
  1785. LD (HL),A
  1786. INC HL
  1787. LD (HL),A
  1788. LD HL,(SCRATCH3) ;and our sector pointer.
  1789. LD (HL),A
  1790. INC HL
  1791. LD (HL),A
  1792. RET
  1793. ;
  1794. ; Do the actual disk read and check the error return status.
  1795. ;
  1796. DOREAD: CALL READ
  1797. JP IORET
  1798. ;
  1799. ; Do the actual disk write and handle any bios error.
  1800. ;
  1801. DOWRITE:CALL WRITE
  1802. IORET: OR A
  1803. RET Z ;return unless an error occured.
  1804. LD HL,BADSCTR ;bad read/write on this sector.
  1805. JP JUMPHL
  1806. ;
  1807. ; Routine to select the track and sector that the desired
  1808. ; block number falls in.
  1809. ;
  1810. TRKSEC: LD HL,(FILEPOS) ;get position of last accessed file
  1811. LD C,2 ;in directory and compute sector #.
  1812. CALL SHIFTR ;sector #=file-position/4.
  1813. LD (BLKNMBR),HL ;save this as the block number of interest.
  1814. LD (CKSUMTBL),HL ;what's it doing here too?
  1815. ;
  1816. ; if the sector number has already been set (BLKNMBR), enter
  1817. ; at this point.
  1818. ;
  1819. TRKSEC1:LD HL,BLKNMBR
  1820. LD C,(HL) ;move sector number into (BC).
  1821. INC HL
  1822. LD B,(HL)
  1823. LD HL,(SCRATCH3) ;get current sector number and
  1824. LD E,(HL) ;move this into (DE).
  1825. INC HL
  1826. LD D,(HL)
  1827. LD HL,(SCRATCH2) ;get current track number.
  1828. LD A,(HL) ;and this into (HL).
  1829. INC HL
  1830. LD H,(HL)
  1831. LD L,A
  1832. TRKSEC2:LD A,C ;is desired sector before current one?
  1833. SUB E
  1834. LD A,B
  1835. SBC A,D
  1836. JP NC,TRKSEC3
  1837. PUSH HL ;yes, decrement sectors by one track.
  1838. LD HL,(SECTORS) ;get sectors per track.
  1839. LD A,E
  1840. SUB L
  1841. LD E,A
  1842. LD A,D
  1843. SBC A,H
  1844. LD D,A ;now we have backed up one full track.
  1845. POP HL
  1846. DEC HL ;adjust track counter.
  1847. JP TRKSEC2
  1848. TRKSEC3:PUSH HL ;desired sector is after current one.
  1849. LD HL,(SECTORS) ;get sectors per track.
  1850. ADD HL,DE ;bump sector pointer to next track.
  1851. JP C,TRKSEC4
  1852. LD A,C ;is desired sector now before current one?
  1853. SUB L
  1854. LD A,B
  1855. SBC A,H
  1856. JP C,TRKSEC4
  1857. EX DE,HL ;not yes, increment track counter
  1858. POP HL ;and continue until it is.
  1859. INC HL
  1860. JP TRKSEC3
  1861. ;
  1862. ; here we have determined the track number that contains the
  1863. ; desired sector.
  1864. ;
  1865. TRKSEC4:POP HL ;get track number (HL).
  1866. PUSH BC
  1867. PUSH DE
  1868. PUSH HL
  1869. EX DE,HL
  1870. LD HL,(OFFSET) ;adjust for first track offset.
  1871. ADD HL,DE
  1872. LD B,H
  1873. LD C,L
  1874. CALL SETTRK ;select this track.
  1875. POP DE ;reset current track pointer.
  1876. LD HL,(SCRATCH2)
  1877. LD (HL),E
  1878. INC HL
  1879. LD (HL),D
  1880. POP DE
  1881. LD HL,(SCRATCH3) ;reset the first sector on this track.
  1882. LD (HL),E
  1883. INC HL
  1884. LD (HL),D
  1885. POP BC
  1886. LD A,C ;now subtract the desired one.
  1887. SUB E ;to make it relative (1-# sectors/track).
  1888. LD C,A
  1889. LD A,B
  1890. SBC A,D
  1891. LD B,A
  1892. LD HL,(XLATE) ;translate this sector according to this table.
  1893. EX DE,HL
  1894. CALL SECTRN ;let the bios translate it.
  1895. LD C,L
  1896. LD B,H
  1897. JP SETSEC ;and select it.
  1898. ;
  1899. ; Compute block number from record number (SAVNREC) and
  1900. ; extent number (SAVEXT).
  1901. ;
  1902. GETBLOCK: LD HL,BLKSHFT ;get logical to physical conversion.
  1903. LD C,(HL) ;note that this is base 2 log of ratio.
  1904. LD A,(SAVNREC) ;get record number.
  1905. GETBLK1:OR A ;compute (A)=(A)/2^BLKSHFT.
  1906. RRA
  1907. DEC C
  1908. JP NZ,GETBLK1
  1909. LD B,A ;save result in (B).
  1910. LD A,8
  1911. SUB (HL)
  1912. LD C,A ;compute (C)=8-BLKSHFT.
  1913. LD A,(SAVEXT)
  1914. GETBLK2:DEC C ;compute (A)=SAVEXT*2^(8-BLKSHFT).
  1915. JP Z,GETBLK3
  1916. OR A
  1917. RLA
  1918. JP GETBLK2
  1919. GETBLK3:ADD A,B
  1920. RET
  1921. ;
  1922. ; Routine to extract the (BC) block byte from the fcb pointed
  1923. ; to by (PARAMS). If this is a big-disk, then these are 16 bit
  1924. ; block numbers, else they are 8 bit numbers.
  1925. ; Number is returned in (HL).
  1926. ;
  1927. EXTBLK: LD HL,(PARAMS) ;get fcb address.
  1928. LD DE,16 ;block numbers start 16 bytes into fcb.
  1929. ADD HL,DE
  1930. ADD HL,BC
  1931. LD A,(BIGDISK) ;are we using a big-disk?
  1932. OR A
  1933. JP Z,EXTBLK1
  1934. LD L,(HL) ;no, extract an 8 bit number from the fcb.
  1935. LD H,0
  1936. RET
  1937. EXTBLK1:ADD HL,BC ;yes, extract a 16 bit number.
  1938. LD E,(HL)
  1939. INC HL
  1940. LD D,(HL)
  1941. EX DE,HL ;return in (HL).
  1942. RET
  1943. ;
  1944. ; Compute block number.
  1945. ;
  1946. COMBLK: CALL GETBLOCK
  1947. LD C,A
  1948. LD B,0
  1949. CALL EXTBLK
  1950. LD (BLKNMBR),HL
  1951. RET
  1952. ;
  1953. ; Check for a zero block number (unused).
  1954. ;
  1955. CHKBLK: LD HL,(BLKNMBR)
  1956. LD A,L ;is it zero?
  1957. OR H
  1958. RET
  1959. ;
  1960. ; Adjust physical block (BLKNMBR) and convert to logical
  1961. ; sector (LOGSECT). This is the starting sector of this block.
  1962. ; The actual sector of interest is then added to this and the
  1963. ; resulting sector number is stored back in (BLKNMBR). This
  1964. ; will still have to be adjusted for the track number.
  1965. ;
  1966. LOGICAL:LD A,(BLKSHFT) ;get log2(physical/logical sectors).
  1967. LD HL,(BLKNMBR) ;get physical sector desired.
  1968. LOGICL1:ADD HL,HL ;compute logical sector number.
  1969. DEC A ;note logical sectors are 128 bytes long.
  1970. JP NZ,LOGICL1
  1971. LD (LOGSECT),HL ;save logical sector.
  1972. LD A,(BLKMASK) ;get block mask.
  1973. LD C,A
  1974. LD A,(SAVNREC) ;get next sector to access.
  1975. AND C ;extract the relative position within physical block.
  1976. OR L ;and add it too logical sector.
  1977. LD L,A
  1978. LD (BLKNMBR),HL ;and store.
  1979. RET
  1980. ;
  1981. ; Set (HL) to point to extent byte in fcb.
  1982. ;
  1983. SETEXT: LD HL,(PARAMS)
  1984. LD DE,12 ;it is the twelth byte.
  1985. ADD HL,DE
  1986. RET
  1987. ;
  1988. ; Set (HL) to point to record count byte in fcb and (DE) to
  1989. ; next record number byte.
  1990. ;
  1991. SETHLDE:LD HL,(PARAMS)
  1992. LD DE,15 ;record count byte (#15).
  1993. ADD HL,DE
  1994. EX DE,HL
  1995. LD HL,17 ;next record number (#32).
  1996. ADD HL,DE
  1997. RET
  1998. ;
  1999. ; Save current file data from fcb.
  2000. ;
  2001. STRDATA:CALL SETHLDE
  2002. LD A,(HL) ;get and store record count byte.
  2003. LD (SAVNREC),A
  2004. EX DE,HL
  2005. LD A,(HL) ;get and store next record number byte.
  2006. LD (SAVNXT),A
  2007. CALL SETEXT ;point to extent byte.
  2008. LD A,(EXTMASK) ;get extent mask.
  2009. AND (HL)
  2010. LD (SAVEXT),A ;and save extent here.
  2011. RET
  2012. ;
  2013. ; Set the next record to access. If (MODE) is set to 2, then
  2014. ; the last record byte (SAVNREC) has the correct number to access.
  2015. ; For sequential access, (MODE) will be equal to 1.
  2016. ;
  2017. SETNREC:CALL SETHLDE
  2018. LD A,(MODE) ;get sequential flag (=1).
  2019. CP 2 ;a 2 indicates that no adder is needed.
  2020. JP NZ,STNREC1
  2021. XOR A ;clear adder (random access?).
  2022. STNREC1:LD C,A
  2023. LD A,(SAVNREC) ;get last record number.
  2024. ADD A,C ;increment record count.
  2025. LD (HL),A ;and set fcb's next record byte.
  2026. EX DE,HL
  2027. LD A,(SAVNXT) ;get next record byte from storage.
  2028. LD (HL),A ;and put this into fcb as number of records used.
  2029. RET
  2030. ;
  2031. ; Shift (HL) right (C) bits.
  2032. ;
  2033. SHIFTR: INC C
  2034. SHIFTR1:DEC C
  2035. RET Z
  2036. LD A,H
  2037. OR A
  2038. RRA
  2039. LD H,A
  2040. LD A,L
  2041. RRA
  2042. LD L,A
  2043. JP SHIFTR1
  2044. ;
  2045. ; Compute the check-sum for the directory buffer. Return
  2046. ; integer sum in (A).
  2047. ;
  2048. CHECKSUM: LD C,128 ;length of buffer.
  2049. LD HL,(DIRBUF) ;get its location.
  2050. XOR A ;clear summation byte.
  2051. CHKSUM1:ADD A,(HL) ;and compute sum ignoring carries.
  2052. INC HL
  2053. DEC C
  2054. JP NZ,CHKSUM1
  2055. RET
  2056. ;
  2057. ; Shift (HL) left (C) bits.
  2058. ;
  2059. SHIFTL: INC C
  2060. SHIFTL1:DEC C
  2061. RET Z
  2062. ADD HL,HL ;shift left 1 bit.
  2063. JP SHIFTL1
  2064. ;
  2065. ; Routine to set a bit in a 16 bit value contained in (BC).
  2066. ; The bit set depends on the current drive selection.
  2067. ;
  2068. SETBIT: PUSH BC ;save 16 bit word.
  2069. LD A,(ACTIVE) ;get active drive.
  2070. LD C,A
  2071. LD HL,1
  2072. CALL SHIFTL ;shift bit 0 into place.
  2073. POP BC ;now 'or' this with the original word.
  2074. LD A,C
  2075. OR L
  2076. LD L,A ;low byte done, do high byte.
  2077. LD A,B
  2078. OR H
  2079. LD H,A
  2080. RET
  2081. ;
  2082. ; Extract the write protect status bit for the current drive.
  2083. ; The result is returned in (A), bit 0.
  2084. ;
  2085. GETWPRT:LD HL,(WRTPRT) ;get status bytes.
  2086. LD A,(ACTIVE) ;which drive is current?
  2087. LD C,A
  2088. CALL SHIFTR ;shift status such that bit 0 is the
  2089. LD A,L ;one of interest for this drive.
  2090. AND 01H ;and isolate it.
  2091. RET
  2092. ;
  2093. ; Function to write protect the current disk.
  2094. ;
  2095. WRTPRTD:LD HL,WRTPRT ;point to status word.
  2096. LD C,(HL) ;set (BC) equal to the status.
  2097. INC HL
  2098. LD B,(HL)
  2099. CALL SETBIT ;and set this bit according to current drive.
  2100. LD (WRTPRT),HL ;then save.
  2101. LD HL,(DIRSIZE) ;now save directory size limit.
  2102. INC HL ;remember the last one.
  2103. EX DE,HL
  2104. LD HL,(SCRATCH1) ;and store it here.
  2105. LD (HL),E ;put low byte.
  2106. INC HL
  2107. LD (HL),D ;then high byte.
  2108. RET
  2109. ;
  2110. ; Check for a read only file.
  2111. ;
  2112. CHKROFL:CALL FCB2HL ;set (HL) to file entry in directory buffer.
  2113. CKROF1: LD DE,9 ;look at bit 7 of the ninth byte.
  2114. ADD HL,DE
  2115. LD A,(HL)
  2116. RLA
  2117. RET NC ;return if ok.
  2118. LD HL,ROFILE ;else, print error message and terminate.
  2119. JP JUMPHL
  2120. ;
  2121. ; Check the write protect status of the active disk.
  2122. ;
  2123. CHKWPRT:CALL GETWPRT
  2124. RET Z ;return if ok.
  2125. LD HL,RODISK ;else print message and terminate.
  2126. JP JUMPHL
  2127. ;
  2128. ; Routine to set (HL) pointing to the proper entry in the
  2129. ; directory buffer.
  2130. ;
  2131. FCB2HL: LD HL,(DIRBUF) ;get address of buffer.
  2132. LD A,(FCBPOS) ;relative position of file.
  2133. ;
  2134. ; Routine to add (A) to (HL).
  2135. ;
  2136. ADDA2HL:ADD A,L
  2137. LD L,A
  2138. RET NC
  2139. INC H ;take care of any carry.
  2140. RET
  2141. ;
  2142. ; Routine to get the 's2' byte from the fcb supplied in
  2143. ; the initial parameter specification.
  2144. ;
  2145. GETS2: LD HL,(PARAMS) ;get address of fcb.
  2146. LD DE,14 ;relative position of 's2'.
  2147. ADD HL,DE
  2148. LD A,(HL) ;extract this byte.
  2149. RET
  2150. ;
  2151. ; Clear the 's2' byte in the fcb.
  2152. ;
  2153. CLEARS2:CALL GETS2 ;this sets (HL) pointing to it.
  2154. LD (HL),0 ;now clear it.
  2155. RET
  2156. ;
  2157. ; Set bit 7 in the 's2' byte of the fcb.
  2158. ;
  2159. SETS2B7:CALL GETS2 ;get the byte.
  2160. OR 80H ;and set bit 7.
  2161. LD (HL),A ;then store.
  2162. RET
  2163. ;
  2164. ; Compare (FILEPOS) with (SCRATCH1) and set flags based on
  2165. ; the difference. This checks to see if there are more file
  2166. ; names in the directory. We are at (FILEPOS) and there are
  2167. ; (SCRATCH1) of them to check.
  2168. ;
  2169. MOREFLS:LD HL,(FILEPOS) ;we are here.
  2170. EX DE,HL
  2171. LD HL,(SCRATCH1) ;and don't go past here.
  2172. LD A,E ;compute difference but don't keep.
  2173. SUB (HL)
  2174. INC HL
  2175. LD A,D
  2176. SBC A,(HL) ;set carry if no more names.
  2177. RET
  2178. ;
  2179. ; Call this routine to prevent (SCRATCH1) from being greater
  2180. ; than (FILEPOS).
  2181. ;
  2182. CHKNMBR:CALL MOREFLS ;SCRATCH1 too big?
  2183. RET C
  2184. INC DE ;yes, reset it to (FILEPOS).
  2185. LD (HL),D
  2186. DEC HL
  2187. LD (HL),E
  2188. RET
  2189. ;
  2190. ; Compute (HL)=(DE)-(HL)
  2191. ;
  2192. SUBHL: LD A,E ;compute difference.
  2193. SUB L
  2194. LD L,A ;store low byte.
  2195. LD A,D
  2196. SBC A,H
  2197. LD H,A ;and then high byte.
  2198. RET
  2199. ;
  2200. ; Set the directory checksum byte.
  2201. ;
  2202. SETDIR: LD C,0FFH
  2203. ;
  2204. ; Routine to set or compare the directory checksum byte. If
  2205. ; (C)=0ffh, then this will set the checksum byte. Else the byte
  2206. ; will be checked. If the check fails (the disk has been changed),
  2207. ; then this disk will be write protected.
  2208. ;
  2209. CHECKDIR: LD HL,(CKSUMTBL)
  2210. EX DE,HL
  2211. LD HL,(ALLOC1)
  2212. CALL SUBHL
  2213. RET NC ;ok if (CKSUMTBL) > (ALLOC1), so return.
  2214. PUSH BC
  2215. CALL CHECKSUM ;else compute checksum.
  2216. LD HL,(CHKVECT) ;get address of checksum table.
  2217. EX DE,HL
  2218. LD HL,(CKSUMTBL)
  2219. ADD HL,DE ;set (HL) to point to byte for this drive.
  2220. POP BC
  2221. INC C ;set or check ?
  2222. JP Z,CHKDIR1
  2223. CP (HL) ;check them.
  2224. RET Z ;return if they are the same.
  2225. CALL MOREFLS ;not the same, do we care?
  2226. RET NC
  2227. CALL WRTPRTD ;yes, mark this as write protected.
  2228. RET
  2229. CHKDIR1:LD (HL),A ;just set the byte.
  2230. RET
  2231. ;
  2232. ; Do a write to the directory of the current disk.
  2233. ;
  2234. DIRWRITE: CALL SETDIR ;set checksum byte.
  2235. CALL DIRDMA ;set directory dma address.
  2236. LD C,1 ;tell the bios to actually write.
  2237. CALL DOWRITE ;then do the write.
  2238. JP DEFDMA
  2239. ;
  2240. ; Read from the directory.
  2241. ;
  2242. DIRREAD:CALL DIRDMA ;set the directory dma address.
  2243. CALL DOREAD ;and read it.
  2244. ;
  2245. ; Routine to set the dma address to the users choice.
  2246. ;
  2247. DEFDMA: LD HL,USERDMA ;reset the default dma address and return.
  2248. JP DIRDMA1
  2249. ;
  2250. ; Routine to set the dma address for directory work.
  2251. ;
  2252. DIRDMA: LD HL,DIRBUF
  2253. ;
  2254. ; Set the dma address. On entry, (HL) points to
  2255. ; word containing the desired dma address.
  2256. ;
  2257. DIRDMA1:LD C,(HL)
  2258. INC HL
  2259. LD B,(HL) ;setup (BC) and go to the bios to set it.
  2260. JP SETDMA
  2261. ;
  2262. ; Move the directory buffer into user's dma space.
  2263. ;
  2264. MOVEDIR:LD HL,(DIRBUF) ;buffer is located here, and
  2265. EX DE,HL
  2266. LD HL,(USERDMA) ; put it here.
  2267. LD C,128 ;this is its length.
  2268. JP DE2HL ;move it now and return.
  2269. ;
  2270. ; Check (FILEPOS) and set the zero flag if it equals 0ffffh.
  2271. ;
  2272. CKFILPOS: LD HL,FILEPOS
  2273. LD A,(HL)
  2274. INC HL
  2275. CP (HL) ;are both bytes the same?
  2276. RET NZ
  2277. INC A ;yes, but are they each 0ffh?
  2278. RET
  2279. ;
  2280. ; Set location (FILEPOS) to 0ffffh.
  2281. ;
  2282. STFILPOS: LD HL,0FFFFH
  2283. LD (FILEPOS),HL
  2284. RET
  2285. ;
  2286. ; Move on to the next file position within the current
  2287. ; directory buffer. If no more exist, set pointer to 0ffffh
  2288. ; and the calling routine will check for this. Enter with (C)
  2289. ; equal to 0ffh to cause the checksum byte to be set, else we
  2290. ; will check this disk and set write protect if checksums are
  2291. ; not the same (applies only if another directory sector must
  2292. ; be read).
  2293. ;
  2294. NXENTRY:LD HL,(DIRSIZE) ;get directory entry size limit.
  2295. EX DE,HL
  2296. LD HL,(FILEPOS) ;get current count.
  2297. INC HL ;go on to the next one.
  2298. LD (FILEPOS),HL
  2299. CALL SUBHL ;(HL)=(DIRSIZE)-(FILEPOS)
  2300. JP NC,NXENT1 ;is there more room left?
  2301. JP STFILPOS ;no. Set this flag and return.
  2302. NXENT1: LD A,(FILEPOS) ;get file position within directory.
  2303. AND 03H ;only look within this sector (only 4 entries fit).
  2304. LD B,5 ;convert to relative position (32 bytes each).
  2305. NXENT2: ADD A,A ;note that this is not efficient code.
  2306. DEC B ;5 'ADD A's would be better.
  2307. JP NZ,NXENT2
  2308. LD (FCBPOS),A ;save it as position of fcb.
  2309. OR A
  2310. RET NZ ;return if we are within buffer.
  2311. PUSH BC
  2312. CALL TRKSEC ;we need the next directory sector.
  2313. CALL DIRREAD
  2314. POP BC
  2315. JP CHECKDIR
  2316. ;
  2317. ; Routine to to get a bit from the disk space allocation
  2318. ; map. It is returned in (A), bit position 0. On entry to here,
  2319. ; set (BC) to the block number on the disk to check.
  2320. ; On return, (D) will contain the original bit position for
  2321. ; this block number and (HL) will point to the address for it.
  2322. ;
  2323. CKBITMAP: LD A,C ;determine bit number of interest.
  2324. AND 07H ;compute (D)=(E)=(C and 7)+1.
  2325. INC A
  2326. LD E,A ;save particular bit number.
  2327. LD D,A
  2328. ;
  2329. ; compute (BC)=(BC)/8.
  2330. ;
  2331. LD A,C
  2332. RRCA ;now shift right 3 bits.
  2333. RRCA
  2334. RRCA
  2335. AND 1FH ;and clear bits 7,6,5.
  2336. LD C,A
  2337. LD A,B
  2338. ADD A,A ;now shift (B) into bits 7,6,5.
  2339. ADD A,A
  2340. ADD A,A
  2341. ADD A,A
  2342. ADD A,A
  2343. OR C ;and add in (C).
  2344. LD C,A ;ok, (C) ha been completed.
  2345. LD A,B ;is there a better way of doing this?
  2346. RRCA
  2347. RRCA
  2348. RRCA
  2349. AND 1FH
  2350. LD B,A ;and now (B) is completed.
  2351. ;
  2352. ; use this as an offset into the disk space allocation
  2353. ; table.
  2354. ;
  2355. LD HL,(ALOCVECT)
  2356. ADD HL,BC
  2357. LD A,(HL) ;now get correct byte.
  2358. CKBMAP1:RLCA ;get correct bit into position 0.
  2359. DEC E
  2360. JP NZ,CKBMAP1
  2361. RET
  2362. ;
  2363. ; Set or clear the bit map such that block number (BC) will be marked
  2364. ; as used. On entry, if (E)=0 then this bit will be cleared, if it equals
  2365. ; 1 then it will be set (don't use anyother values).
  2366. ;
  2367. STBITMAP: PUSH DE
  2368. CALL CKBITMAP ;get the byte of interest.
  2369. AND 0FEH ;clear the affected bit.
  2370. POP BC
  2371. OR C ;and now set it acording to (C).
  2372. ;
  2373. ; entry to restore the original bit position and then store
  2374. ; in table. (A) contains the value, (D) contains the bit
  2375. ; position (1-8), and (HL) points to the address within the
  2376. ; space allocation table for this byte.
  2377. ;
  2378. STBMAP1:RRCA ;restore original bit position.
  2379. DEC D
  2380. JP NZ,STBMAP1
  2381. LD (HL),A ;and stor byte in table.
  2382. RET
  2383. ;
  2384. ; Set/clear space used bits in allocation map for this file.
  2385. ; On entry, (C)=1 to set the map and (C)=0 to clear it.
  2386. ;
  2387. SETFILE:CALL FCB2HL ;get address of fcb
  2388. LD DE,16
  2389. ADD HL,DE ;get to block number bytes.
  2390. PUSH BC
  2391. LD C,17 ;check all 17 bytes (max) of table.
  2392. SETFL1: POP DE
  2393. DEC C ;done all bytes yet?
  2394. RET Z
  2395. PUSH DE
  2396. LD A,(BIGDISK) ;check disk size for 16 bit block numbers.
  2397. OR A
  2398. JP Z,SETFL2
  2399. PUSH BC ;only 8 bit numbers. set (BC) to this one.
  2400. PUSH HL
  2401. LD C,(HL) ;get low byte from table, always
  2402. LD B,0 ;set high byte to zero.
  2403. JP SETFL3
  2404. SETFL2: DEC C ;for 16 bit block numbers, adjust counter.
  2405. PUSH BC
  2406. LD C,(HL) ;now get both the low and high bytes.
  2407. INC HL
  2408. LD B,(HL)
  2409. PUSH HL
  2410. SETFL3: LD A,C ;block used?
  2411. OR B
  2412. JP Z,SETFL4
  2413. LD HL,(DSKSIZE) ;is this block number within the
  2414. LD A,L ;space on the disk?
  2415. SUB C
  2416. LD A,H
  2417. SBC A,B
  2418. CALL NC,STBITMAP ;yes, set the proper bit.
  2419. SETFL4: POP HL ;point to next block number in fcb.
  2420. INC HL
  2421. POP BC
  2422. JP SETFL1
  2423. ;
  2424. ; Construct the space used allocation bit map for the active
  2425. ; drive. If a file name starts with '$' and it is under the
  2426. ; current user number, then (STATUS) is set to minus 1. Otherwise
  2427. ; it is not set at all.
  2428. ;
  2429. BITMAP: LD HL,(DSKSIZE) ;compute size of allocation table.
  2430. LD C,3
  2431. CALL SHIFTR ;(HL)=(HL)/8.
  2432. INC HL ;at lease 1 byte.
  2433. LD B,H
  2434. LD C,L ;set (BC) to the allocation table length.
  2435. ;
  2436. ; Initialize the bitmap for this drive. Right now, the first
  2437. ; two bytes are specified by the disk parameter block. However
  2438. ; a patch could be entered here if it were necessary to setup
  2439. ; this table in a special mannor. For example, the bios could
  2440. ; determine locations of 'bad blocks' and set them as already
  2441. ; 'used' in the map.
  2442. ;
  2443. LD HL,(ALOCVECT) ;now zero out the table now.
  2444. BITMAP1:LD (HL),0
  2445. INC HL
  2446. DEC BC
  2447. LD A,B
  2448. OR C
  2449. JP NZ,BITMAP1
  2450. LD HL,(ALLOC0) ;get initial space used by directory.
  2451. EX DE,HL
  2452. LD HL,(ALOCVECT) ;and put this into map.
  2453. LD (HL),E
  2454. INC HL
  2455. LD (HL),D
  2456. ;
  2457. ; End of initialization portion.
  2458. ;
  2459. CALL HOMEDRV ;now home the drive.
  2460. LD HL,(SCRATCH1)
  2461. LD (HL),3 ;force next directory request to read
  2462. INC HL ;in a sector.
  2463. LD (HL),0
  2464. CALL STFILPOS ;clear initial file position also.
  2465. BITMAP2:LD C,0FFH ;read next file name in directory
  2466. CALL NXENTRY ;and set checksum byte.
  2467. CALL CKFILPOS ;is there another file?
  2468. RET Z
  2469. CALL FCB2HL ;yes, get its address.
  2470. LD A,0E5H
  2471. CP (HL) ;empty file entry?
  2472. JP Z,BITMAP2
  2473. LD A,(USERNO) ;no, correct user number?
  2474. CP (HL)
  2475. JP NZ,BITMAP3
  2476. INC HL
  2477. LD A,(HL) ;yes, does name start with a '$'?
  2478. SUB '$'
  2479. JP NZ,BITMAP3
  2480. DEC A ;yes, set atatus to minus one.
  2481. LD (STATUS),A
  2482. BITMAP3:LD C,1 ;now set this file's space as used in bit map.
  2483. CALL SETFILE
  2484. CALL CHKNMBR ;keep (SCRATCH1) in bounds.
  2485. JP BITMAP2
  2486. ;
  2487. ; Set the status (STATUS) and return.
  2488. ;
  2489. STSTATUS: LD A,(FNDSTAT)
  2490. JP SETSTAT
  2491. ;
  2492. ; Check extents in (A) and (C). Set the zero flag if they
  2493. ; are the same. The number of 16k chunks of disk space that
  2494. ; the directory extent covers is expressad is (EXTMASK+1).
  2495. ; No registers are modified.
  2496. ;
  2497. SAMEXT: PUSH BC
  2498. PUSH AF
  2499. LD A,(EXTMASK) ;get extent mask and use it to
  2500. CPL ;to compare both extent numbers.
  2501. LD B,A ;save resulting mask here.
  2502. LD A,C ;mask first extent and save in (C).
  2503. AND B
  2504. LD C,A
  2505. POP AF ;now mask second extent and compare
  2506. AND B ;with the first one.
  2507. SUB C
  2508. AND 1FH ;(* only check buts 0-4 *)
  2509. POP BC ;the zero flag is set if they are the same.
  2510. RET ;restore (BC) and return.
  2511. ;
  2512. ; Search for the first occurence of a file name. On entry,
  2513. ; register (C) should contain the number of bytes of the fcb
  2514. ; that must match.
  2515. ;
  2516. FINDFST:LD A,0FFH
  2517. LD (FNDSTAT),A
  2518. LD HL,COUNTER ;save character count.
  2519. LD (HL),C
  2520. LD HL,(PARAMS) ;get filename to match.
  2521. LD (SAVEFCB),HL ;and save.
  2522. CALL STFILPOS ;clear initial file position (set to 0ffffh).
  2523. CALL HOMEDRV ;home the drive.
  2524. ;
  2525. ; Entry to locate the next occurence of a filename within the
  2526. ; directory. The disk is not expected to have been changed. If
  2527. ; it was, then it will be write protected.
  2528. ;
  2529. FINDNXT:LD C,0 ;write protect the disk if changed.
  2530. CALL NXENTRY ;get next filename entry in directory.
  2531. CALL CKFILPOS ;is file position = 0ffffh?
  2532. JP Z,FNDNXT6 ;yes, exit now then.
  2533. LD HL,(SAVEFCB) ;set (DE) pointing to filename to match.
  2534. EX DE,HL
  2535. LD A,(DE)
  2536. CP 0E5H ;empty directory entry?
  2537. JP Z,FNDNXT1 ;(* are we trying to reserect erased entries? *)
  2538. PUSH DE
  2539. CALL MOREFLS ;more files in directory?
  2540. POP DE
  2541. JP NC,FNDNXT6 ;no more. Exit now.
  2542. FNDNXT1:CALL FCB2HL ;get address of this fcb in directory.
  2543. LD A,(COUNTER) ;get number of bytes (characters) to check.
  2544. LD C,A
  2545. LD B,0 ;initialize byte position counter.
  2546. FNDNXT2:LD A,C ;are we done with the compare?
  2547. OR A
  2548. JP Z,FNDNXT5
  2549. LD A,(DE) ;no, check next byte.
  2550. CP '?' ;don't care about this character?
  2551. JP Z,FNDNXT4
  2552. LD A,B ;get bytes position in fcb.
  2553. CP 13 ;don't care about the thirteenth byte either.
  2554. JP Z,FNDNXT4
  2555. CP 12 ;extent byte?
  2556. LD A,(DE)
  2557. JP Z,FNDNXT3
  2558. SUB (HL) ;otherwise compare characters.
  2559. AND 7FH
  2560. JP NZ,FINDNXT ;not the same, check next entry.
  2561. JP FNDNXT4 ;so far so good, keep checking.
  2562. FNDNXT3:PUSH BC ;check the extent byte here.
  2563. LD C,(HL)
  2564. CALL SAMEXT
  2565. POP BC
  2566. JP NZ,FINDNXT ;not the same, look some more.
  2567. ;
  2568. ; So far the names compare. Bump pointers to the next byte
  2569. ; and continue until all (C) characters have been checked.
  2570. ;
  2571. FNDNXT4:INC DE ;bump pointers.
  2572. INC HL
  2573. INC B
  2574. DEC C ;adjust character counter.
  2575. JP FNDNXT2
  2576. FNDNXT5:LD A,(FILEPOS) ;return the position of this entry.
  2577. AND 03H
  2578. LD (STATUS),A
  2579. LD HL,FNDSTAT
  2580. LD A,(HL)
  2581. RLA
  2582. RET NC
  2583. XOR A
  2584. LD (HL),A
  2585. RET
  2586. ;
  2587. ; Filename was not found. Set appropriate status.
  2588. ;
  2589. FNDNXT6:CALL STFILPOS ;set (FILEPOS) to 0ffffh.
  2590. LD A,0FFH ;say not located.
  2591. JP SETSTAT
  2592. ;
  2593. ; Erase files from the directory. Only the first byte of the
  2594. ; fcb will be affected. It is set to (E5).
  2595. ;
  2596. ERAFILE:CALL CHKWPRT ;is disk write protected?
  2597. LD C,12 ;only compare file names.
  2598. CALL FINDFST ;get first file name.
  2599. ERAFIL1:CALL CKFILPOS ;any found?
  2600. RET Z ;nope, we must be done.
  2601. CALL CHKROFL ;is file read only?
  2602. CALL FCB2HL ;nope, get address of fcb and
  2603. LD (HL),0E5H ;set first byte to 'empty'.
  2604. LD C,0 ;clear the space from the bit map.
  2605. CALL SETFILE
  2606. CALL DIRWRITE ;now write the directory sector back out.
  2607. CALL FINDNXT ;find the next file name.
  2608. JP ERAFIL1 ;and repeat process.
  2609. ;
  2610. ; Look through the space allocation map (bit map) for the
  2611. ; next available block. Start searching at block number (BC-1).
  2612. ; The search procedure is to look for an empty block that is
  2613. ; before the starting block. If not empty, look at a later
  2614. ; block number. In this way, we return the closest empty block
  2615. ; on either side of the 'target' block number. This will speed
  2616. ; access on random devices. For serial devices, this should be
  2617. ; changed to look in the forward direction first and then start
  2618. ; at the front and search some more.
  2619. ;
  2620. ; On return, (DE)= block number that is empty and (HL) =0
  2621. ; if no empry block was found.
  2622. ;
  2623. FNDSPACE: LD D,B ;set (DE) as the block that is checked.
  2624. LD E,C
  2625. ;
  2626. ; Look before target block. Registers (BC) are used as the lower
  2627. ; pointer and (DE) as the upper pointer.
  2628. ;
  2629. FNDSPA1:LD A,C ;is block 0 specified?
  2630. OR B
  2631. JP Z,FNDSPA2
  2632. DEC BC ;nope, check previous block.
  2633. PUSH DE
  2634. PUSH BC
  2635. CALL CKBITMAP
  2636. RRA ;is this block empty?
  2637. JP NC,FNDSPA3 ;yes. use this.
  2638. ;
  2639. ; Note that the above logic gets the first block that it finds
  2640. ; that is empty. Thus a file could be written 'backward' making
  2641. ; it very slow to access. This could be changed to look for the
  2642. ; first empty block and then continue until the start of this
  2643. ; empty space is located and then used that starting block.
  2644. ; This should help speed up access to some files especially on
  2645. ; a well used disk with lots of fairly small 'holes'.
  2646. ;
  2647. POP BC ;nope, check some more.
  2648. POP DE
  2649. ;
  2650. ; Now look after target block.
  2651. ;
  2652. FNDSPA2:LD HL,(DSKSIZE) ;is block (DE) within disk limits?
  2653. LD A,E
  2654. SUB L
  2655. LD A,D
  2656. SBC A,H
  2657. JP NC,FNDSPA4
  2658. INC DE ;yes, move on to next one.
  2659. PUSH BC
  2660. PUSH DE
  2661. LD B,D
  2662. LD C,E
  2663. CALL CKBITMAP ;check it.
  2664. RRA ;empty?
  2665. JP NC,FNDSPA3
  2666. POP DE ;nope, continue searching.
  2667. POP BC
  2668. JP FNDSPA1
  2669. ;
  2670. ; Empty block found. Set it as used and return with (HL)
  2671. ; pointing to it (true?).
  2672. ;
  2673. FNDSPA3:RLA ;reset byte.
  2674. INC A ;and set bit 0.
  2675. CALL STBMAP1 ;update bit map.
  2676. POP HL ;set return registers.
  2677. POP DE
  2678. RET
  2679. ;
  2680. ; Free block was not found. If (BC) is not zero, then we have
  2681. ; not checked all of the disk space.
  2682. ;
  2683. FNDSPA4:LD A,C
  2684. OR B
  2685. JP NZ,FNDSPA1
  2686. LD HL,0 ;set 'not found' status.
  2687. RET
  2688. ;
  2689. ; Move a complete fcb entry into the directory and write it.
  2690. ;
  2691. FCBSET: LD C,0
  2692. LD E,32 ;length of each entry.
  2693. ;
  2694. ; Move (E) bytes from the fcb pointed to by (PARAMS) into
  2695. ; fcb in directory starting at relative byte (C). This updated
  2696. ; directory buffer is then written to the disk.
  2697. ;
  2698. UPDATE: PUSH DE
  2699. LD B,0 ;set (BC) to relative byte position.
  2700. LD HL,(PARAMS) ;get address of fcb.
  2701. ADD HL,BC ;compute starting byte.
  2702. EX DE,HL
  2703. CALL FCB2HL ;get address of fcb to update in directory.
  2704. POP BC ;set (C) to number of bytes to change.
  2705. CALL DE2HL
  2706. UPDATE1:CALL TRKSEC ;determine the track and sector affected.
  2707. JP DIRWRITE ;then write this sector out.
  2708. ;
  2709. ; Routine to change the name of all files on the disk with a
  2710. ; specified name. The fcb contains the current name as the
  2711. ; first 12 characters and the new name 16 bytes into the fcb.
  2712. ;
  2713. CHGNAMES: CALL CHKWPRT ;check for a write protected disk.
  2714. LD C,12 ;match first 12 bytes of fcb only.
  2715. CALL FINDFST ;get first name.
  2716. LD HL,(PARAMS) ;get address of fcb.
  2717. LD A,(HL) ;get user number.
  2718. LD DE,16 ;move over to desired name.
  2719. ADD HL,DE
  2720. LD (HL),A ;keep same user number.
  2721. CHGNAM1:CALL CKFILPOS ;any matching file found?
  2722. RET Z ;no, we must be done.
  2723. CALL CHKROFL ;check for read only file.
  2724. LD C,16 ;start 16 bytes into fcb.
  2725. LD E,12 ;and update the first 12 bytes of directory.
  2726. CALL UPDATE
  2727. CALL FINDNXT ;get te next file name.
  2728. JP CHGNAM1 ;and continue.
  2729. ;
  2730. ; Update a files attributes. The procedure is to search for
  2731. ; every file with the same name as shown in fcb (ignoring bit 7)
  2732. ; and then to update it (which includes bit 7). No other changes
  2733. ; are made.
  2734. ;
  2735. SAVEATTR: LD C,12 ;match first 12 bytes.
  2736. CALL FINDFST ;look for first filename.
  2737. SAVATR1:CALL CKFILPOS ;was one found?
  2738. RET Z ;nope, we must be done.
  2739. LD C,0 ;yes, update the first 12 bytes now.
  2740. LD E,12
  2741. CALL UPDATE ;update filename and write directory.
  2742. CALL FINDNXT ;and get the next file.
  2743. JP SAVATR1 ;then continue until done.
  2744. ;
  2745. ; Open a file (name specified in fcb).
  2746. ;
  2747. OPENIT: LD C,15 ;compare the first 15 bytes.
  2748. CALL FINDFST ;get the first one in directory.
  2749. CALL CKFILPOS ;any at all?
  2750. RET Z
  2751. OPENIT1:CALL SETEXT ;point to extent byte within users fcb.
  2752. LD A,(HL) ;and get it.
  2753. PUSH AF ;save it and address.
  2754. PUSH HL
  2755. CALL FCB2HL ;point to fcb in directory.
  2756. EX DE,HL
  2757. LD HL,(PARAMS) ;this is the users copy.
  2758. LD C,32 ;move it into users space.
  2759. PUSH DE
  2760. CALL DE2HL
  2761. CALL SETS2B7 ;set bit 7 in 's2' byte (unmodified).
  2762. POP DE ;now get the extent byte from this fcb.
  2763. LD HL,12
  2764. ADD HL,DE
  2765. LD C,(HL) ;into (C).
  2766. LD HL,15 ;now get the record count byte into (B).
  2767. ADD HL,DE
  2768. LD B,(HL)
  2769. POP HL ;keep the same extent as the user had originally.
  2770. POP AF
  2771. LD (HL),A
  2772. LD A,C ;is it the same as in the directory fcb?
  2773. CP (HL)
  2774. LD A,B ;if yes, then use the same record count.
  2775. JP Z,OPENIT2
  2776. LD A,0 ;if the user specified an extent greater than
  2777. JP C,OPENIT2 ;the one in the directory, then set record count to 0.
  2778. LD A,128 ;otherwise set to maximum.
  2779. OPENIT2:LD HL,(PARAMS) ;set record count in users fcb to (A).
  2780. LD DE,15
  2781. ADD HL,DE ;compute relative position.
  2782. LD (HL),A ;and set the record count.
  2783. RET
  2784. ;
  2785. ; Move two bytes from (DE) to (HL) if (and only if) (HL)
  2786. ; point to a zero value (16 bit).
  2787. ; Return with zero flag set it (DE) was moved. Registers (DE)
  2788. ; and (HL) are not changed. However (A) is.
  2789. ;
  2790. MOVEWORD: LD A,(HL) ;check for a zero word.
  2791. INC HL
  2792. OR (HL) ;both bytes zero?
  2793. DEC HL
  2794. RET NZ ;nope, just return.
  2795. LD A,(DE) ;yes, move two bytes from (DE) into
  2796. LD (HL),A ;this zero space.
  2797. INC DE
  2798. INC HL
  2799. LD A,(DE)
  2800. LD (HL),A
  2801. DEC DE ;don't disturb these registers.
  2802. DEC HL
  2803. RET
  2804. ;
  2805. ; Get here to close a file specified by (fcb).
  2806. ;
  2807. CLOSEIT:XOR A ;clear status and file position bytes.
  2808. LD (STATUS),A
  2809. LD (FILEPOS),A
  2810. LD (FILEPOS+1),A
  2811. CALL GETWPRT ;get write protect bit for this drive.
  2812. RET NZ ;just return if it is set.
  2813. CALL GETS2 ;else get the 's2' byte.
  2814. AND 80H ;and look at bit 7 (file unmodified?).
  2815. RET NZ ;just return if set.
  2816. LD C,15 ;else look up this file in directory.
  2817. CALL FINDFST
  2818. CALL CKFILPOS ;was it found?
  2819. RET Z ;just return if not.
  2820. LD BC,16 ;set (HL) pointing to records used section.
  2821. CALL FCB2HL
  2822. ADD HL,BC
  2823. EX DE,HL
  2824. LD HL,(PARAMS) ;do the same for users specified fcb.
  2825. ADD HL,BC
  2826. LD C,16 ;this many bytes are present in this extent.
  2827. CLOSEIT1: LD A,(BIGDISK) ;8 or 16 bit record numbers?
  2828. OR A
  2829. JP Z,CLOSEIT4
  2830. LD A,(HL) ;just 8 bit. Get one from users fcb.
  2831. OR A
  2832. LD A,(DE) ;now get one from directory fcb.
  2833. JP NZ,CLOSEIT2
  2834. LD (HL),A ;users byte was zero. Update from directory.
  2835. CLOSEIT2: OR A
  2836. JP NZ,CLOSEIT3
  2837. LD A,(HL) ;directories byte was zero, update from users fcb.
  2838. LD (DE),A
  2839. CLOSEIT3: CP (HL) ;if neither one of these bytes were zero,
  2840. JP NZ,CLOSEIT7 ;then close error if they are not the same.
  2841. JP CLOSEIT5 ;ok so far, get to next byte in fcbs.
  2842. CLOSEIT4: CALL MOVEWORD ;update users fcb if it is zero.
  2843. EX DE,HL
  2844. CALL MOVEWORD ;update directories fcb if it is zero.
  2845. EX DE,HL
  2846. LD A,(DE) ;if these two values are no different,
  2847. CP (HL) ;then a close error occured.
  2848. JP NZ,CLOSEIT7
  2849. INC DE ;check second byte.
  2850. INC HL
  2851. LD A,(DE)
  2852. CP (HL)
  2853. JP NZ,CLOSEIT7
  2854. DEC C ;remember 16 bit values.
  2855. CLOSEIT5: INC DE ;bump to next item in table.
  2856. INC HL
  2857. DEC C ;there are 16 entries only.
  2858. JP NZ,CLOSEIT1 ;continue if more to do.
  2859. LD BC,0FFECH ;backup 20 places (extent byte).
  2860. ADD HL,BC
  2861. EX DE,HL
  2862. ADD HL,BC
  2863. LD A,(DE)
  2864. CP (HL) ;directory's extent already greater than the
  2865. JP C,CLOSEIT6 ;users extent?
  2866. LD (HL),A ;no, update directory extent.
  2867. LD BC,3 ;and update the record count byte in
  2868. ADD HL,BC ;directories fcb.
  2869. EX DE,HL
  2870. ADD HL,BC
  2871. LD A,(HL) ;get from user.
  2872. LD (DE),A ;and put in directory.
  2873. CLOSEIT6: LD A,0FFH ;set 'was open and is now closed' byte.
  2874. LD (CLOSEFLG),A
  2875. JP UPDATE1 ;update the directory now.
  2876. CLOSEIT7: LD HL,STATUS ;set return status and then return.
  2877. DEC (HL)
  2878. RET
  2879. ;
  2880. ; Routine to get the next empty space in the directory. It
  2881. ; will then be cleared for use.
  2882. ;
  2883. GETEMPTY: CALL CHKWPRT ;make sure disk is not write protected.
  2884. LD HL,(PARAMS) ;save current parameters (fcb).
  2885. PUSH HL
  2886. LD HL,EMPTYFCB ;use special one for empty space.
  2887. LD (PARAMS),HL
  2888. LD C,1 ;search for first empty spot in directory.
  2889. CALL FINDFST ;(* only check first byte *)
  2890. CALL CKFILPOS ;none?
  2891. POP HL
  2892. LD (PARAMS),HL ;restore original fcb address.
  2893. RET Z ;return if no more space.
  2894. EX DE,HL
  2895. LD HL,15 ;point to number of records for this file.
  2896. ADD HL,DE
  2897. LD C,17 ;and clear all of this space.
  2898. XOR A
  2899. GETMT1: LD (HL),A
  2900. INC HL
  2901. DEC C
  2902. JP NZ,GETMT1
  2903. LD HL,13 ;clear the 's1' byte also.
  2904. ADD HL,DE
  2905. LD (HL),A
  2906. CALL CHKNMBR ;keep (SCRATCH1) within bounds.
  2907. CALL FCBSET ;write out this fcb entry to directory.
  2908. JP SETS2B7 ;set 's2' byte bit 7 (unmodified at present).
  2909. ;
  2910. ; Routine to close the current extent and open the next one
  2911. ; for reading.
  2912. ;
  2913. GETNEXT:XOR A
  2914. LD (CLOSEFLG),A ;clear close flag.
  2915. CALL CLOSEIT ;close this extent.
  2916. CALL CKFILPOS
  2917. RET Z ;not there???
  2918. LD HL,(PARAMS) ;get extent byte.
  2919. LD BC,12
  2920. ADD HL,BC
  2921. LD A,(HL) ;and increment it.
  2922. INC A
  2923. AND 1FH ;keep within range 0-31.
  2924. LD (HL),A
  2925. JP Z,GTNEXT1 ;overflow?
  2926. LD B,A ;mask extent byte.
  2927. LD A,(EXTMASK)
  2928. AND B
  2929. LD HL,CLOSEFLG ;check close flag (0ffh is ok).
  2930. AND (HL)
  2931. JP Z,GTNEXT2 ;if zero, we must read in next extent.
  2932. JP GTNEXT3 ;else, it is already in memory.
  2933. GTNEXT1:LD BC,2 ;Point to the 's2' byte.
  2934. ADD HL,BC
  2935. INC (HL) ;and bump it.
  2936. LD A,(HL) ;too many extents?
  2937. AND 0FH
  2938. JP Z,GTNEXT5 ;yes, set error code.
  2939. ;
  2940. ; Get here to open the next extent.
  2941. ;
  2942. GTNEXT2:LD C,15 ;set to check first 15 bytes of fcb.
  2943. CALL FINDFST ;find the first one.
  2944. CALL CKFILPOS ;none available?
  2945. JP NZ,GTNEXT3
  2946. LD A,(RDWRTFLG) ;no extent present. Can we open an empty one?
  2947. INC A ;0ffh means reading (so not possible).
  2948. JP Z,GTNEXT5 ;or an error.
  2949. CALL GETEMPTY ;we are writing, get an empty entry.
  2950. CALL CKFILPOS ;none?
  2951. JP Z,GTNEXT5 ;error if true.
  2952. JP GTNEXT4 ;else we are almost done.
  2953. GTNEXT3:CALL OPENIT1 ;open this extent.
  2954. GTNEXT4:CALL STRDATA ;move in updated data (rec #, extent #, etc.)
  2955. XOR A ;clear status and return.
  2956. JP SETSTAT
  2957. ;
  2958. ; Error in extending the file. Too many extents were needed
  2959. ; or not enough space on the disk.
  2960. ;
  2961. GTNEXT5:CALL IOERR1 ;set error code, clear bit 7 of 's2'
  2962. JP SETS2B7 ;so this is not written on a close.
  2963. ;
  2964. ; Read a sequential file.
  2965. ;
  2966. RDSEQ: LD A,1 ;set sequential access mode.
  2967. LD (MODE),A
  2968. RDSEQ1: LD A,0FFH ;don't allow reading unwritten space.
  2969. LD (RDWRTFLG),A
  2970. CALL STRDATA ;put rec# and ext# into fcb.
  2971. LD A,(SAVNREC) ;get next record to read.
  2972. LD HL,SAVNXT ;get number of records in extent.
  2973. CP (HL) ;within this extent?
  2974. JP C,RDSEQ2
  2975. CP 128 ;no. Is this extent fully used?
  2976. JP NZ,RDSEQ3 ;no. End-of-file.
  2977. CALL GETNEXT ;yes, open the next one.
  2978. XOR A ;reset next record to read.
  2979. LD (SAVNREC),A
  2980. LD A,(STATUS) ;check on open, successful?
  2981. OR A
  2982. JP NZ,RDSEQ3 ;no, error.
  2983. RDSEQ2: CALL COMBLK ;ok. compute block number to read.
  2984. CALL CHKBLK ;check it. Within bounds?
  2985. JP Z,RDSEQ3 ;no, error.
  2986. CALL LOGICAL ;convert (BLKNMBR) to logical sector (128 byte).
  2987. CALL TRKSEC1 ;set the track and sector for this block #.
  2988. CALL DOREAD ;and read it.
  2989. JP SETNREC ;and set the next record to be accessed.
  2990. ;
  2991. ; Read error occured. Set status and return.
  2992. ;
  2993. RDSEQ3: JP IOERR1
  2994. ;
  2995. ; Write the next sequential record.
  2996. ;
  2997. WTSEQ: LD A,1 ;set sequential access mode.
  2998. LD (MODE),A
  2999. WTSEQ1: LD A,0 ;allow an addition empty extent to be opened.
  3000. LD (RDWRTFLG),A
  3001. CALL CHKWPRT ;check write protect status.
  3002. LD HL,(PARAMS)
  3003. CALL CKROF1 ;check for read only file, (HL) already set to fcb.
  3004. CALL STRDATA ;put updated data into fcb.
  3005. LD A,(SAVNREC) ;get record number to write.
  3006. CP 128 ;within range?
  3007. JP NC,IOERR1 ;no, error(?).
  3008. CALL COMBLK ;compute block number.
  3009. CALL CHKBLK ;check number.
  3010. LD C,0 ;is there one to write to?
  3011. JP NZ,WTSEQ6 ;yes, go do it.
  3012. CALL GETBLOCK ;get next block number within fcb to use.
  3013. LD (RELBLOCK),A ;and save.
  3014. LD BC,0 ;start looking for space from the start
  3015. OR A ;if none allocated as yet.
  3016. JP Z,WTSEQ2
  3017. LD C,A ;extract previous block number from fcb
  3018. DEC BC ;so we can be closest to it.
  3019. CALL EXTBLK
  3020. LD B,H
  3021. LD C,L
  3022. WTSEQ2: CALL FNDSPACE ;find the next empty block nearest number (BC).
  3023. LD A,L ;check for a zero number.
  3024. OR H
  3025. JP NZ,WTSEQ3
  3026. LD A,2 ;no more space?
  3027. JP SETSTAT
  3028. WTSEQ3: LD (BLKNMBR),HL ;save block number to access.
  3029. EX DE,HL ;put block number into (DE).
  3030. LD HL,(PARAMS) ;now we must update the fcb for this
  3031. LD BC,16 ;newly allocated block.
  3032. ADD HL,BC
  3033. LD A,(BIGDISK) ;8 or 16 bit block numbers?
  3034. OR A
  3035. LD A,(RELBLOCK) ;(* update this entry *)
  3036. JP Z,WTSEQ4 ;zero means 16 bit ones.
  3037. CALL ADDA2HL ;(HL)=(HL)+(A)
  3038. LD (HL),E ;store new block number.
  3039. JP WTSEQ5
  3040. WTSEQ4: LD C,A ;compute spot in this 16 bit table.
  3041. LD B,0
  3042. ADD HL,BC
  3043. ADD HL,BC
  3044. LD (HL),E ;stuff block number (DE) there.
  3045. INC HL
  3046. LD (HL),D
  3047. WTSEQ5: LD C,2 ;set (C) to indicate writing to un-used disk space.
  3048. WTSEQ6: LD A,(STATUS) ;are we ok so far?
  3049. OR A
  3050. RET NZ
  3051. PUSH BC ;yes, save write flag for bios (register C).
  3052. CALL LOGICAL ;convert (BLKNMBR) over to loical sectors.
  3053. LD A,(MODE) ;get access mode flag (1=sequential,
  3054. DEC A ;0=random, 2=special?).
  3055. DEC A
  3056. JP NZ,WTSEQ9
  3057. ;
  3058. ; Special random i/o from function #40. Maybe for M/PM, but the
  3059. ; current block, if it has not been written to, will be zeroed
  3060. ; out and then written (reason?).
  3061. ;
  3062. POP BC
  3063. PUSH BC
  3064. LD A,C ;get write status flag (2=writing unused space).
  3065. DEC A
  3066. DEC A
  3067. JP NZ,WTSEQ9
  3068. PUSH HL
  3069. LD HL,(DIRBUF) ;zero out the directory buffer.
  3070. LD D,A ;note that (A) is zero here.
  3071. WTSEQ7: LD (HL),A
  3072. INC HL
  3073. INC D ;do 128 bytes.
  3074. JP P,WTSEQ7
  3075. CALL DIRDMA ;tell the bios the dma address for directory access.
  3076. LD HL,(LOGSECT) ;get sector that starts current block.
  3077. LD C,2 ;set 'writing to unused space' flag.
  3078. WTSEQ8: LD (BLKNMBR),HL ;save sector to write.
  3079. PUSH BC
  3080. CALL TRKSEC1 ;determine its track and sector numbers.
  3081. POP BC
  3082. CALL DOWRITE ;now write out 128 bytes of zeros.
  3083. LD HL,(BLKNMBR) ;get sector number.
  3084. LD C,0 ;set normal write flag.
  3085. LD A,(BLKMASK) ;determine if we have written the entire
  3086. LD B,A ;physical block.
  3087. AND L
  3088. CP B
  3089. INC HL ;prepare for the next one.
  3090. JP NZ,WTSEQ8 ;continue until (BLKMASK+1) sectors written.
  3091. POP HL ;reset next sector number.
  3092. LD (BLKNMBR),HL
  3093. CALL DEFDMA ;and reset dma address.
  3094. ;
  3095. ; Normal disk write. Set the desired track and sector then
  3096. ; do the actual write.
  3097. ;
  3098. WTSEQ9: CALL TRKSEC1 ;determine track and sector for this write.
  3099. POP BC ;get write status flag.
  3100. PUSH BC
  3101. CALL DOWRITE ;and write this out.
  3102. POP BC
  3103. LD A,(SAVNREC) ;get number of records in file.
  3104. LD HL,SAVNXT ;get last record written.
  3105. CP (HL)
  3106. JP C,WTSEQ10
  3107. LD (HL),A ;we have to update record count.
  3108. INC (HL)
  3109. LD C,2
  3110. ;
  3111. ;* This area has been patched to correct disk update problem
  3112. ;* when using blocking and de-blocking in the BIOS.
  3113. ;
  3114. WTSEQ10:NOP ;was 'dcr c'
  3115. NOP ;was 'dcr c'
  3116. LD HL,0 ;was 'jnz wtseq99'
  3117. ;
  3118. ; * End of patch.
  3119. ;
  3120. PUSH AF
  3121. CALL GETS2 ;set 'extent written to' flag.
  3122. AND 7FH ;(* clear bit 7 *)
  3123. LD (HL),A
  3124. POP AF ;get record count for this extent.
  3125. WTSEQ99:CP 127 ;is it full?
  3126. JP NZ,WTSEQ12
  3127. LD A,(MODE) ;yes, are we in sequential mode?
  3128. CP 1
  3129. JP NZ,WTSEQ12
  3130. CALL SETNREC ;yes, set next record number.
  3131. CALL GETNEXT ;and get next empty space in directory.
  3132. LD HL,STATUS ;ok?
  3133. LD A,(HL)
  3134. OR A
  3135. JP NZ,WTSEQ11
  3136. DEC A ;yes, set record count to -1.
  3137. LD (SAVNREC),A
  3138. WTSEQ11:LD (HL),0 ;clear status.
  3139. WTSEQ12:JP SETNREC ;set next record to access.
  3140. ;
  3141. ; For random i/o, set the fcb for the desired record number
  3142. ; based on the 'r0,r1,r2' bytes. These bytes in the fcb are
  3143. ; used as follows:
  3144. ;
  3145. ; fcb+35 fcb+34 fcb+33
  3146. ; | 'r-2' | 'r-1' | 'r-0' |
  3147. ; |7 0 | 7 0 | 7 0|
  3148. ; |0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0|
  3149. ; | overflow | | extra | extent | record # |
  3150. ; | ______________| |_extent|__number___|_____________|
  3151. ; also 's2'
  3152. ;
  3153. ; On entry, register (C) contains 0ffh if this is a read
  3154. ; and thus we can not access unwritten disk space. Otherwise,
  3155. ; another extent will be opened (for writing) if required.
  3156. ;
  3157. POSITION: XOR A ;set random i/o flag.
  3158. LD (MODE),A
  3159. ;
  3160. ; Special entry (function #40). M/PM ?
  3161. ;
  3162. POSITN1:PUSH BC ;save read/write flag.
  3163. LD HL,(PARAMS) ;get address of fcb.
  3164. EX DE,HL
  3165. LD HL,33 ;now get byte 'r0'.
  3166. ADD HL,DE
  3167. LD A,(HL)
  3168. AND 7FH ;keep bits 0-6 for the record number to access.
  3169. PUSH AF
  3170. LD A,(HL) ;now get bit 7 of 'r0' and bits 0-3 of 'r1'.
  3171. RLA
  3172. INC HL
  3173. LD A,(HL)
  3174. RLA
  3175. AND 1FH ;and save this in bits 0-4 of (C).
  3176. LD C,A ;this is the extent byte.
  3177. LD A,(HL) ;now get the extra extent byte.
  3178. RRA
  3179. RRA
  3180. RRA
  3181. RRA
  3182. AND 0FH
  3183. LD B,A ;and save it in (B).
  3184. POP AF ;get record number back to (A).
  3185. INC HL ;check overflow byte 'r2'.
  3186. LD L,(HL)
  3187. INC L
  3188. DEC L
  3189. LD L,6 ;prepare for error.
  3190. JP NZ,POSITN5 ;out of disk space error.
  3191. LD HL,32 ;store record number into fcb.
  3192. ADD HL,DE
  3193. LD (HL),A
  3194. LD HL,12 ;and now check the extent byte.
  3195. ADD HL,DE
  3196. LD A,C
  3197. SUB (HL) ;same extent as before?
  3198. JP NZ,POSITN2
  3199. LD HL,14 ;yes, check extra extent byte 's2' also.
  3200. ADD HL,DE
  3201. LD A,B
  3202. SUB (HL)
  3203. AND 7FH
  3204. JP Z,POSITN3 ;same, we are almost done then.
  3205. ;
  3206. ; Get here when another extent is required.
  3207. ;
  3208. POSITN2:PUSH BC
  3209. PUSH DE
  3210. CALL CLOSEIT ;close current extent.
  3211. POP DE
  3212. POP BC
  3213. LD L,3 ;prepare for error.
  3214. LD A,(STATUS)
  3215. INC A
  3216. JP Z,POSITN4 ;close error.
  3217. LD HL,12 ;put desired extent into fcb now.
  3218. ADD HL,DE
  3219. LD (HL),C
  3220. LD HL,14 ;and store extra extent byte 's2'.
  3221. ADD HL,DE
  3222. LD (HL),B
  3223. CALL OPENIT ;try and get this extent.
  3224. LD A,(STATUS) ;was it there?
  3225. INC A
  3226. JP NZ,POSITN3
  3227. POP BC ;no. can we create a new one (writing?).
  3228. PUSH BC
  3229. LD L,4 ;prepare for error.
  3230. INC C
  3231. JP Z,POSITN4 ;nope, reading unwritten space error.
  3232. CALL GETEMPTY ;yes we can, try to find space.
  3233. LD L,5 ;prepare for error.
  3234. LD A,(STATUS)
  3235. INC A
  3236. JP Z,POSITN4 ;out of space?
  3237. ;
  3238. ; Normal return location. Clear error code and return.
  3239. ;
  3240. POSITN3:POP BC ;restore stack.
  3241. XOR A ;and clear error code byte.
  3242. JP SETSTAT
  3243. ;
  3244. ; Error. Set the 's2' byte to indicate this (why?).
  3245. ;
  3246. POSITN4:PUSH HL
  3247. CALL GETS2
  3248. LD (HL),0C0H
  3249. POP HL
  3250. ;
  3251. ; Return with error code (presently in L).
  3252. ;
  3253. POSITN5:POP BC
  3254. LD A,L ;get error code.
  3255. LD (STATUS),A
  3256. JP SETS2B7
  3257. ;
  3258. ; Read a random record.
  3259. ;
  3260. READRAN:LD C,0FFH ;set 'read' status.
  3261. CALL POSITION ;position the file to proper record.
  3262. CALL Z,RDSEQ1 ;and read it as usual (if no errors).
  3263. RET
  3264. ;
  3265. ; Write to a random record.
  3266. ;
  3267. WRITERAN: LD C,0 ;set 'writing' flag.
  3268. CALL POSITION ;position the file to proper record.
  3269. CALL Z,WTSEQ1 ;and write as usual (if no errors).
  3270. RET
  3271. ;
  3272. ; Compute the random record number. Enter with (HL) pointing
  3273. ; to a fcb an (DE) contains a relative location of a record
  3274. ; number. On exit, (C) contains the 'r0' byte, (B) the 'r1'
  3275. ; byte, and (A) the 'r2' byte.
  3276. ;
  3277. ; On return, the zero flag is set if the record is within
  3278. ; bounds. Otherwise, an overflow occured.
  3279. ;
  3280. COMPRAND: EX DE,HL ;save fcb pointer in (DE).
  3281. ADD HL,DE ;compute relative position of record #.
  3282. LD C,(HL) ;get record number into (BC).
  3283. LD B,0
  3284. LD HL,12 ;now get extent.
  3285. ADD HL,DE
  3286. LD A,(HL) ;compute (BC)=(record #)+(extent)*128.
  3287. RRCA ;move lower bit into bit 7.
  3288. AND 80H ;and ignore all other bits.
  3289. ADD A,C ;add to our record number.
  3290. LD C,A
  3291. LD A,0 ;take care of any carry.
  3292. ADC A,B
  3293. LD B,A
  3294. LD A,(HL) ;now get the upper bits of extent into
  3295. RRCA ;bit positions 0-3.
  3296. AND 0FH ;and ignore all others.
  3297. ADD A,B ;add this in to 'r1' byte.
  3298. LD B,A
  3299. LD HL,14 ;get the 's2' byte (extra extent).
  3300. ADD HL,DE
  3301. LD A,(HL)
  3302. ADD A,A ;and shift it left 4 bits (bits 4-7).
  3303. ADD A,A
  3304. ADD A,A
  3305. ADD A,A
  3306. PUSH AF ;save carry flag (bit 0 of flag byte).
  3307. ADD A,B ;now add extra extent into 'r1'.
  3308. LD B,A
  3309. PUSH AF ;and save carry (overflow byte 'r2').
  3310. POP HL ;bit 0 of (L) is the overflow indicator.
  3311. LD A,L
  3312. POP HL ;and same for first carry flag.
  3313. OR L ;either one of these set?
  3314. AND 01H ;only check the carry flags.
  3315. RET
  3316. ;
  3317. ; Routine to setup the fcb (bytes 'r0', 'r1', 'r2') to
  3318. ; reflect the last record used for a random (or other) file.
  3319. ; This reads the directory and looks at all extents computing
  3320. ; the largerst record number for each and keeping the maximum
  3321. ; value only. Then 'r0', 'r1', and 'r2' will reflect this
  3322. ; maximum record number. This is used to compute the space used
  3323. ; by a random file.
  3324. ;
  3325. RANSIZE:LD C,12 ;look thru directory for first entry with
  3326. CALL FINDFST ;this name.
  3327. LD HL,(PARAMS) ;zero out the 'r0, r1, r2' bytes.
  3328. LD DE,33
  3329. ADD HL,DE
  3330. PUSH HL
  3331. LD (HL),D ;note that (D)=0.
  3332. INC HL
  3333. LD (HL),D
  3334. INC HL
  3335. LD (HL),D
  3336. RANSIZ1:CALL CKFILPOS ;is there an extent to process?
  3337. JP Z,RANSIZ3 ;no, we are done.
  3338. CALL FCB2HL ;set (HL) pointing to proper fcb in dir.
  3339. LD DE,15 ;point to last record in extent.
  3340. CALL COMPRAND ;and compute random parameters.
  3341. POP HL
  3342. PUSH HL ;now check these values against those
  3343. LD E,A ;already in fcb.
  3344. LD A,C ;the carry flag will be set if those
  3345. SUB (HL) ;in the fcb represent a larger size than
  3346. INC HL ;this extent does.
  3347. LD A,B
  3348. SBC A,(HL)
  3349. INC HL
  3350. LD A,E
  3351. SBC A,(HL)
  3352. JP C,RANSIZ2
  3353. LD (HL),E ;we found a larger (in size) extent.
  3354. DEC HL ;stuff these values into fcb.
  3355. LD (HL),B
  3356. DEC HL
  3357. LD (HL),C
  3358. RANSIZ2:CALL FINDNXT ;now get the next extent.
  3359. JP RANSIZ1 ;continue til all done.
  3360. RANSIZ3:POP HL ;we are done, restore the stack and
  3361. RET ;return.
  3362. ;
  3363. ; Function to return the random record position of a given
  3364. ; file which has been read in sequential mode up to now.
  3365. ;
  3366. SETRAN: LD HL,(PARAMS) ;point to fcb.
  3367. LD DE,32 ;and to last used record.
  3368. CALL COMPRAND ;compute random position.
  3369. LD HL,33 ;now stuff these values into fcb.
  3370. ADD HL,DE
  3371. LD (HL),C ;move 'r0'.
  3372. INC HL
  3373. LD (HL),B ;and 'r1'.
  3374. INC HL
  3375. LD (HL),A ;and lastly 'r2'.
  3376. RET
  3377. ;
  3378. ; This routine select the drive specified in (ACTIVE) and
  3379. ; update the login vector and bitmap table if this drive was
  3380. ; not already active.
  3381. ;
  3382. LOGINDRV: LD HL,(LOGIN) ;get the login vector.
  3383. LD A,(ACTIVE) ;get the default drive.
  3384. LD C,A
  3385. CALL SHIFTR ;position active bit for this drive
  3386. PUSH HL ;into bit 0.
  3387. EX DE,HL
  3388. CALL SELECT ;select this drive.
  3389. POP HL
  3390. CALL Z,SLCTERR ;valid drive?
  3391. LD A,L ;is this a newly activated drive?
  3392. RRA
  3393. RET C
  3394. LD HL,(LOGIN) ;yes, update the login vector.
  3395. LD C,L
  3396. LD B,H
  3397. CALL SETBIT
  3398. LD (LOGIN),HL ;and save.
  3399. JP BITMAP ;now update the bitmap.
  3400. ;
  3401. ; Function to set the active disk number.
  3402. ;
  3403. SETDSK: LD A,(EPARAM) ;get parameter passed and see if this
  3404. LD HL,ACTIVE ;represents a change in drives.
  3405. CP (HL)
  3406. RET Z
  3407. LD (HL),A ;yes it does, log it in.
  3408. JP LOGINDRV
  3409. ;
  3410. ; This is the 'auto disk select' routine. The firsst byte
  3411. ; of the fcb is examined for a drive specification. If non
  3412. ; zero then the drive will be selected and loged in.
  3413. ;
  3414. AUTOSEL:LD A,0FFH ;say 'auto-select activated'.
  3415. LD (AUTO),A
  3416. LD HL,(PARAMS) ;get drive specified.
  3417. LD A,(HL)
  3418. AND 1FH ;look at lower 5 bits.
  3419. DEC A ;adjust for (1=A, 2=B) etc.
  3420. LD (EPARAM),A ;and save for the select routine.
  3421. CP 1EH ;check for 'no change' condition.
  3422. JP NC,AUTOSL1 ;yes, don't change.
  3423. LD A,(ACTIVE) ;we must change, save currently active
  3424. LD (OLDDRV),A ;drive.
  3425. LD A,(HL) ;and save first byte of fcb also.
  3426. LD (AUTOFLAG),A ;this must be non-zero.
  3427. AND 0E0H ;whats this for (bits 6,7 are used for
  3428. LD (HL),A ;something)?
  3429. CALL SETDSK ;select and log in this drive.
  3430. AUTOSL1:LD A,(USERNO) ;move user number into fcb.
  3431. LD HL,(PARAMS) ;(* upper half of first byte *)
  3432. OR (HL)
  3433. LD (HL),A
  3434. RET ;and return (all done).
  3435. ;
  3436. ; Function to return the current cp/m version number.
  3437. ;
  3438. GETVER: LD A,022H ;version 2.2
  3439. JP SETSTAT
  3440. ;
  3441. ; Function to reset the disk system.
  3442. ;
  3443. RSTDSK: LD HL,0 ;clear write protect status and log
  3444. LD (WRTPRT),HL ;in vector.
  3445. LD (LOGIN),HL
  3446. XOR A ;select drive 'A'.
  3447. LD (ACTIVE),A
  3448. LD HL,TBUFF ;setup default dma address.
  3449. LD (USERDMA),HL
  3450. CALL DEFDMA
  3451. JP LOGINDRV ;now log in drive 'A'.
  3452. ;
  3453. ; Function to open a specified file.
  3454. ;
  3455. OPENFIL:CALL CLEARS2 ;clear 's2' byte.
  3456. CALL AUTOSEL ;select proper disk.
  3457. JP OPENIT ;and open the file.
  3458. ;
  3459. ; Function to close a specified file.
  3460. ;
  3461. CLOSEFIL: CALL AUTOSEL ;select proper disk.
  3462. JP CLOSEIT ;and close the file.
  3463. ;
  3464. ; Function to return the first occurence of a specified file
  3465. ; name. If the first byte of the fcb is '?' then the name will
  3466. ; not be checked (get the first entry no matter what).
  3467. ;
  3468. GETFST: LD C,0 ;prepare for special search.
  3469. EX DE,HL
  3470. LD A,(HL) ;is first byte a '?'?
  3471. CP '?'
  3472. JP Z,GETFST1 ;yes, just get very first entry (zero length match).
  3473. CALL SETEXT ;get the extension byte from fcb.
  3474. LD A,(HL) ;is it '?'? if yes, then we want
  3475. CP '?' ;an entry with a specific 's2' byte.
  3476. CALL NZ,CLEARS2 ;otherwise, look for a zero 's2' byte.
  3477. CALL AUTOSEL ;select proper drive.
  3478. LD C,15 ;compare bytes 0-14 in fcb (12&13 excluded).
  3479. GETFST1:CALL FINDFST ;find an entry and then move it into
  3480. JP MOVEDIR ;the users dma space.
  3481. ;
  3482. ; Function to return the next occurence of a file name.
  3483. ;
  3484. GETNXT: LD HL,(SAVEFCB) ;restore pointers. note that no
  3485. LD (PARAMS),HL ;other dbos calls are allowed.
  3486. CALL AUTOSEL ;no error will be returned, but the
  3487. CALL FINDNXT ;results will be wrong.
  3488. JP MOVEDIR
  3489. ;
  3490. ; Function to delete a file by name.
  3491. ;
  3492. DELFILE:CALL AUTOSEL ;select proper drive.
  3493. CALL ERAFILE ;erase the file.
  3494. JP STSTATUS ;set status and return.
  3495. ;
  3496. ; Function to execute a sequential read of the specified
  3497. ; record number.
  3498. ;
  3499. READSEQ:CALL AUTOSEL ;select proper drive then read.
  3500. JP RDSEQ
  3501. ;
  3502. ; Function to write the net sequential record.
  3503. ;
  3504. WRTSEQ: CALL AUTOSEL ;select proper drive then write.
  3505. JP WTSEQ
  3506. ;
  3507. ; Create a file function.
  3508. ;
  3509. FCREATE:CALL CLEARS2 ;clear the 's2' byte on all creates.
  3510. CALL AUTOSEL ;select proper drive and get the next
  3511. JP GETEMPTY ;empty directory space.
  3512. ;
  3513. ; Function to rename a file.
  3514. ;
  3515. RENFILE:CALL AUTOSEL ;select proper drive and then switch
  3516. CALL CHGNAMES ;file names.
  3517. JP STSTATUS
  3518. ;
  3519. ; Function to return the login vector.
  3520. ;
  3521. GETLOG: LD HL,(LOGIN)
  3522. JP GETPRM1
  3523. ;
  3524. ; Function to return the current disk assignment.
  3525. ;
  3526. GETCRNT:LD A,(ACTIVE)
  3527. JP SETSTAT
  3528. ;
  3529. ; Function to set the dma address.
  3530. ;
  3531. PUTDMA: EX DE,HL
  3532. LD (USERDMA),HL ;save in our space and then get to
  3533. JP DEFDMA ;the bios with this also.
  3534. ;
  3535. ; Function to return the allocation vector.
  3536. ;
  3537. GETALOC:LD HL,(ALOCVECT)
  3538. JP GETPRM1
  3539. ;
  3540. ; Function to return the read-only status vector.
  3541. ;
  3542. GETROV: LD HL,(WRTPRT)
  3543. JP GETPRM1
  3544. ;
  3545. ; Function to set the file attributes (read-only, system).
  3546. ;
  3547. SETATTR:CALL AUTOSEL ;select proper drive then save attributes.
  3548. CALL SAVEATTR
  3549. JP STSTATUS
  3550. ;
  3551. ; Function to return the address of the disk parameter block
  3552. ; for the current drive.
  3553. ;
  3554. GETPARM:LD HL,(DISKPB)
  3555. GETPRM1:LD (STATUS),HL
  3556. RET
  3557. ;
  3558. ; Function to get or set the user number. If (E) was (FF)
  3559. ; then this is a request to return the current user number.
  3560. ; Else set the user number from (E).
  3561. ;
  3562. GETUSER:LD A,(EPARAM) ;get parameter.
  3563. CP 0FFH ;get user number?
  3564. JP NZ,SETUSER
  3565. LD A,(USERNO) ;yes, just do it.
  3566. JP SETSTAT
  3567. SETUSER:AND 1FH ;no, we should set it instead. keep low
  3568. LD (USERNO),A ;bits (0-4) only.
  3569. RET
  3570. ;
  3571. ; Function to read a random record from a file.
  3572. ;
  3573. RDRANDOM: CALL AUTOSEL ;select proper drive and read.
  3574. JP READRAN
  3575. ;
  3576. ; Function to compute the file size for random files.
  3577. ;
  3578. WTRANDOM: CALL AUTOSEL ;select proper drive and write.
  3579. JP WRITERAN
  3580. ;
  3581. ; Function to compute the size of a random file.
  3582. ;
  3583. FILESIZE: CALL AUTOSEL ;select proper drive and check file length
  3584. JP RANSIZE
  3585. ;
  3586. ; Function #37. This allows a program to log off any drives.
  3587. ; On entry, set (DE) to contain a word with bits set for those
  3588. ; drives that are to be logged off. The log-in vector and the
  3589. ; write protect vector will be updated. This must be a M/PM
  3590. ; special function.
  3591. ;
  3592. LOGOFF: LD HL,(PARAMS) ;get drives to log off.
  3593. LD A,L ;for each bit that is set, we want
  3594. CPL ;to clear that bit in (LOGIN)
  3595. LD E,A ;and (WRTPRT).
  3596. LD A,H
  3597. CPL
  3598. LD HL,(LOGIN) ;reset the login vector.
  3599. AND H
  3600. LD D,A
  3601. LD A,L
  3602. AND E
  3603. LD E,A
  3604. LD HL,(WRTPRT)
  3605. EX DE,HL
  3606. LD (LOGIN),HL ;and save.
  3607. LD A,L ;now do the write protect vector.
  3608. AND E
  3609. LD L,A
  3610. LD A,H
  3611. AND D
  3612. LD H,A
  3613. LD (WRTPRT),HL ;and save. all done.
  3614. RET
  3615. ;
  3616. ; Get here to return to the user.
  3617. ;
  3618. GOBACK: LD A,(AUTO) ;was auto select activated?
  3619. OR A
  3620. JP Z,GOBACK1
  3621. LD HL,(PARAMS) ;yes, but was a change made?
  3622. LD (HL),0 ;(* reset first byte of fcb *)
  3623. LD A,(AUTOFLAG)
  3624. OR A
  3625. JP Z,GOBACK1
  3626. LD (HL),A ;yes, reset first byte properly.
  3627. LD A,(OLDDRV) ;and get the old drive and select it.
  3628. LD (EPARAM),A
  3629. CALL SETDSK
  3630. GOBACK1:LD HL,(USRSTACK) ;reset the users stack pointer.
  3631. LD SP,HL
  3632. LD HL,(STATUS) ;get return status.
  3633. LD A,L ;force version 1.4 compatability.
  3634. LD B,H
  3635. RET ;and go back to user.
  3636. ;
  3637. ; Function #40. This is a special entry to do random i/o.
  3638. ; For the case where we are writing to unused disk space, this
  3639. ; space will be zeroed out first. This must be a M/PM special
  3640. ; purpose function, because why would any normal program even
  3641. ; care about the previous contents of a sector about to be
  3642. ; written over.
  3643. ;
  3644. WTSPECL:CALL AUTOSEL ;select proper drive.
  3645. LD A,2 ;use special write mode.
  3646. LD (MODE),A
  3647. LD C,0 ;set write indicator.
  3648. CALL POSITN1 ;position the file.
  3649. CALL Z,WTSEQ1 ;and write (if no errors).
  3650. RET
  3651. ;
  3652. ;**************************************************************
  3653. ;*
  3654. ;* BDOS data storage pool.
  3655. ;*
  3656. ;**************************************************************
  3657. ;
  3658. EMPTYFCB: DB 0E5H ;empty directory segment indicator.
  3659. WRTPRT: DW 0 ;write protect status for all 16 drives.
  3660. LOGIN: DW 0 ;drive active word (1 bit per drive).
  3661. USERDMA: DW 080H ;user's dma address (defaults to 80h).
  3662. ;
  3663. ; Scratch areas from parameter block.
  3664. ;
  3665. SCRATCH1: DW 0 ;relative position within dir segment for file (0-3).
  3666. SCRATCH2: DW 0 ;last selected track number.
  3667. SCRATCH3: DW 0 ;last selected sector number.
  3668. ;
  3669. ; Disk storage areas from parameter block.
  3670. ;
  3671. DIRBUF: DW 0 ;address of directory buffer to use.
  3672. DISKPB: DW 0 ;contains address of disk parameter block.
  3673. CHKVECT: DW 0 ;address of check vector.
  3674. ALOCVECT: DW 0 ;address of allocation vector (bit map).
  3675. ;
  3676. ; Parameter block returned from the bios.
  3677. ;
  3678. SECTORS: DW 0 ;sectors per track from bios.
  3679. BLKSHFT: DB 0 ;block shift.
  3680. BLKMASK: DB 0 ;block mask.
  3681. EXTMASK: DB 0 ;extent mask.
  3682. DSKSIZE: DW 0 ;disk size from bios (number of blocks-1).
  3683. DIRSIZE: DW 0 ;directory size.
  3684. ALLOC0: DW 0 ;storage for first bytes of bit map (dir space used).
  3685. ALLOC1: DW 0
  3686. OFFSET: DW 0 ;first usable track number.
  3687. XLATE: DW 0 ;sector translation table address.
  3688. ;
  3689. ;
  3690. CLOSEFLG: DB 0 ;close flag (=0ffh is extent written ok).
  3691. RDWRTFLG: DB 0 ;read/write flag (0ffh=read, 0=write).
  3692. FNDSTAT: DB 0 ;filename found status (0=found first entry).
  3693. MODE: DB 0 ;I/o mode select (0=random, 1=sequential, 2=special random).
  3694. EPARAM: DB 0 ;storage for register (E) on entry to bdos.
  3695. RELBLOCK: DB 0 ;relative position within fcb of block number written.
  3696. COUNTER: DB 0 ;byte counter for directory name searches.
  3697. SAVEFCB: DW 0,0 ;save space for address of fcb (for directory searches).
  3698. BIGDISK: DB 0 ;if =0 then disk is > 256 blocks long.
  3699. AUTO: DB 0 ;if non-zero, then auto select activated.
  3700. OLDDRV: DB 0 ;on auto select, storage for previous drive.
  3701. AUTOFLAG: DB 0 ;if non-zero, then auto select changed drives.
  3702. SAVNXT: DB 0 ;storage for next record number to access.
  3703. SAVEXT: DB 0 ;storage for extent number of file.
  3704. SAVNREC: DW 0 ;storage for number of records in file.
  3705. BLKNMBR: DW 0 ;block number (physical sector) used within a file or logical sect
  3706. LOGSECT: DW 0 ;starting logical (128 byte) sector of block (physical sector).
  3707. FCBPOS: DB 0 ;relative position within buffer for fcb of file of interest.
  3708. FILEPOS: DW 0 ;files position within directory (0 to max entries -1).
  3709. ;
  3710. ; Disk directory buffer checksum bytes. One for each of the
  3711. ; 16 possible drives.
  3712. ;
  3713. CKSUMTBL: DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  3714. ;
  3715. ; Extra space ?
  3716. ;
  3717. DB 0,0,0,0
  3718. ;
  3719. ;**************************************************************
  3720. ;*
  3721. ;* B I O S J U M P T A B L E
  3722. ;*
  3723. ;**************************************************************
  3724. ;
  3725. BOOT: EQU $+0
  3726. WBOOT: EQU $+3
  3727. CONST: EQU $+6
  3728. CONIN: EQU $+9
  3729. CONOUT: EQU $+12
  3730. LIST: EQU $+15
  3731. PUNCH: EQU $+18
  3732. READER: EQU $+21
  3733. HOME: EQU $+24
  3734. SELDSK: EQU $+27
  3735. SETTRK: EQU $+30
  3736. SETSEC: EQU $+33
  3737. SETDMA: EQU $+36
  3738. READ: EQU $+39
  3739. WRITE: EQU $+42
  3740. PRSTAT: EQU $+45
  3741. SECTRN: EQU $+48
  3742. ;
  3743. ;*
  3744. ;****************** E N D O F C P / M *****************
  3745. ;*
  3746. END