title MS-LIBrary Handler LIB80 name ('LIB80') ; DASMed version of LIB80 ; By W.Cirsovius FALSE equ 0 TRUE equ NOT FALSE OS equ 0000h BDOS equ 0005h TPATOP equ BDOS+1 CCPbuf equ 0080h TPA equ 0100h .conout equ 2 .rdrin equ 3 .lstout equ 5 .getlin equ 10 .resdsk equ 13 .seldsk equ 14 .open equ 15 .close equ 16 .delete equ 19 .rdseq equ 20 .wrseq equ 21 .make equ 22 .rename equ 23 .curdsk equ 25 .setdma equ 26 CPMerr equ 255 .drv equ 1 .nam equ 8 .ext equ 3 _EX equ 12 _DIR equ 16 _CR equ 32 FCBlen equ 33 RecLng equ 128 null equ 00h tab equ 09h lf equ 0ah ff equ 0ch cr equ 0dh eof equ 1ah MSB equ 10000000b NoMSB equ 01111111b LoMask equ 00001111b COLTAB equ 00000111b ; ; Address modes ; @@mod equ 11b ; Two bits ; @cseg equ 01b ; CSEG @dseg equ 10b ; DSEG @COMM equ 11b ; COMMON relbits equ 8 ; ; Microsoft REL types ; _ENTRY equ 0000b _SELCOM equ 0001b _PRGNAM equ 0010b _LIBRQ equ 0011b _MSLNK equ 0100b _DEFCOM equ 0101b _CHNEXT equ 0110b _DEFENT equ 0111b _EXTOFF equ 1001b _DATSIZ equ 1010b _LOCATE equ 1011b _PRGSIZ equ 1101b _ENDMOD equ 1110b _ENDPRG equ 1111b ; Label flag definition .COMMON equ 10000000b .Public equ 01000000b .Libreq equ 00100000b .Unk equ 00010000b .Known equ 00001000b .LenMsk equ 00000111b ; ModLen equ 6 ; Max module name length SymLen equ 6 ; Max symbol name length LabLen equ 16 ; Max label length .Uopt equ 10000000b .Lopt equ 01000000b .Copt equ 00100000b .Eopt equ 00010000b .Ropt equ 00001000b .Minus equ 10000000b .Module equ 1 .File equ 3 ; +++++ START THE CODE +++++ ld hl,ConsRow ; Init data field ld bc,dat.len ld e,0 ini.data: ld (hl),e ; .. clear it inc hl dec bc ld a,b or c jp nz,ini.data ld a,128 ld (.ConsLine),a ; Init length of console line ld hl,(BDOS+1) ; Get top of TPA ld (LIB.stack),hl ld sp,hl ld de,-300 ; Set stack space add hl,de ld (TopTPA),hl ; Get top of memory ld a,' ' ld (DST.FCB+1),a ; Init destination ReStart: ld hl,(LIB.stack) ; Get stack ld sp,hl xor a ld (LIB.opt),a ; Clear options ld (L.Mode),a call ParamStr ; Get command line ld a,(hl) cp cr ; Test any in buffer jp z,ReStart ld hl,Heap ld (Heap.Ptr),hl ; Init heap ld hl,ConsLine call Parse ; Parse line cp '=' ; Check assignment jp z,AssigMod ld hl,Heap ld (hl),.File ; Init heap inc hl ld b,11 ld (hl),b inc hl ld (hl),0 inc hl ld a,' ' ClrDestFile: ld (hl),a ; Clear destination file name inc hl dec b jp nz,ClrDestFile ld (Heap.Ptr),hl ld hl,ConsLine ; Init input line AssigMod: xor a ld (EmptyFlg),a ; Set no file SampleModules: call GetModule ; Get modules cp ',' jp z,SampleModules ; Till end cp cr jp nz,CmdERR ld (FileFlag),a ; Force init ld hl,(TopTPA) ld (CurPtr),hl ld hl,(Heap.Ptr) ld (CurHeap),hl ; Init top of heap ld (NewPtr),hl ; Init module pointer xor a ld (SRC.FCB+1),a ; Set current drive ld a,(LIB.opt) ; Get option ld b,a and .Uopt+.Lopt ; Isolate list options cp .Uopt+.Lopt ; .. test both jp z,CmdERR ; .. illegal rlca rlca ; Get /U and /L option and 3 ; .. as lower bits push af jp nz,LIBverbose ld a,(ChGot) ; Test any character got or a jp z,LIBverbose ld hl,Heap+1 ; Point to destination file ld b,(hl) ; Get count inc hl ld c,(hl) ; .. and drive ld de,DST.FCB ; Set FCB inc hl ld a,(hl) cp ' ' ; Test empty destination jp nz,DestFileHere ld a,(DST.FCB+1) ; Test FCB filled cp ' '+1 jp nc,BegLIBaction ld hl,$DefLIB ; Set default ld c,0 ; .. and drive DestFileHere: ld a,c ; Get drive ld (de),a ; .. set inc de UnpackDest: ld a,(hl) inc hl ld (de),a ; Unpack file inc de dec b jp nz,UnpackDest ld hl,-3 ld bc,SavExt add hl,de ; Bump to extension ld a,(hl) ; Save current extension ld (bc),a inc bc ld (hl),'L' ; Set .LIB inc hl ld a,(hl) ld (bc),a inc bc ld (hl),'I' inc hl ld a,(hl) ld (bc),a ld (hl),'B' BegLIBaction: ld a,(LIB.opt) and .Copt ; Test /C.lear call nz,ClrLIB ld a,(WrOpen) or a call z,ClrLIB LIBverbose: pop af ld hl,ProcRET ; Set return address push hl push af ld hl,Heap ld (Heap.Ptr),hl ; Init heap call SelHeap ; Get file ld a,(EmptyFlg) ; Test file or a jp z,AF.pop pop af add a,a ld hl,LstTab ; Get execution address ld e,a ld d,0 add hl,de ld e,(hl) inc hl ld d,(hl) ex de,hl jp (hl) ; -->> GO ; ; Execution table ; LstTab: dw Exec.. ; No /U, /L dw Exec.L ; /L dw Exec.U ; /U ; ; Return processing ; ProcRET: ld a,(LIB.opt) and .Eopt+.Ropt ; Test /E or /R call nz,LIBrename ; Rename if so and .Eopt ; Test /E selected jp nz,ExitLIB ld a,(LIB.mode) ; Test more or a jp z,ReStart ; .. restart ExitLIB: jp OS ; Exit to OS ; ; Check characters for naming ; ENTRY Reg HL points to current buffer ; EXIT Reg HL updated ; Reg DE holds entry buffer pointer ; Reg B holds length of 'normal' characters ; Accu and reg C hold last character read ; ChkChar: ld b,0 ; Clear count push hl ; Save buffer Chk..next: call GetChar ; Get character cp '$' ; Check legal ones jp z,Chk..bump cp 'Z'+1 jp nc,Chk..exit cp '0' jp c,Chk..exit cp 'A' jp nc,Chk..bump cp '9'+1 jp nc,Chk..exit Chk..bump: inc b ; Bump count jp Chk..next Chk..exit: ld c,a ; Unpack last character pop de ; Get pointer ret ; ; Concatenate modules ; EXIT Accu holds last character read ; ConcatMod: call ChkChar ; Read next push hl ld hl,(Heap.Ptr) ; Get heap cp '-' ; Test minus offset jp nz,ConcatNoMin ld a,.Minus ConcatNoMin: and .Minus ; Set flag ld (hl),a inc hl ld (hl),b ; Set count inc hl jp nz,ConcatOffs ld a,c ; Test sign cp '+' ld a,0 ; .. default 0 jp nz,ConcatNoOffs ConcatOffs: ex (sp),hl call Offset ; Get offset ex (sp),hl ConcatNoOffs: ld (hl),a ; Set offset ex de,hl ld a,b or a ; Test any got jp z,ConcatSkip ConcatPack: call GetChar inc de ld (de),a dec b jp nz,ConcatPack ConcatSkip: inc de pop hl ld a,c ret ; ; Get module offset ; EXIT Accu holds offset ; Offset: push bc ld b,0 ; Clear result OffsetLoop: call GetChar ; Get character cp '9'+1 ; Test range jp nc,OffsetEnd sub '0' jp c,OffsetEnd ld c,a ; .. save digit ld a,b ; Get old add a,a ; * 2 add a,a ; * 4 add a,b ; * 5 add a,a ; *10 add a,c ; Add digit ld b,a jp OffsetLoop OffsetEnd: ld a,b ; Get number pop bc dec hl ld c,(hl) ; Load last character inc hl ret ; ; Combine modules ; EXIT Accu holds last character read ; BuildMod: call ConcatMod ; Concat a bit cp ',' ; Test more follows jp z,BuildEnd cp '>' ; Test end selection jp z,BuildEnd cp '.' ; Test from..to jp nz,CmdERR call GetChar cp '.' jp nz,CmdERR push hl ld hl,(Heap.Ptr) inc (hl) ; Bump indicator ex de,hl call Check.Mem pop hl call ConcatMod ; Get next push hl ld hl,(Heap.Ptr) inc (hl) ; Bump indicator inc (hl) pop hl cp ',' ; Test legal end ret z cp '>' ret z jp CmdERR BuildEnd: push hl ld hl,(Heap.Ptr) ; Get heap ex de,hl ex (sp),hl inc de ld a,(de) ; Test legal building or a ld a,b jp nz,BuildSkip inc de ld a,(de) or a ld a,b jp z,CmdERR BuildSkip: pop de ld a,c ret ; ; Get module from command line into heap ; EXIT Accu holds last character read ; GetModule: call Parse ; Parse file sub '<' ; Check module jp z,ExtModule push hl ld hl,(Heap.Ptr) ld (hl),.Module ; Init heap inc hl xor a ld (hl),a inc hl ld (hl),a inc hl ld (hl),2 inc hl ld (hl),a inc hl ld (hl),a inc hl call Check.Mem ; Check room ld a,c pop hl ret ExtModule: call BuildMod ; Build modules ex de,hl call Check.Mem ; Save heap ex de,hl cp '>' ; Test end jp nz,ExtModule ; .. loop jp GetChar ; ; Parse line ; EXIT Accu holds last character read ; Parse: call ChkChar ; Get character cp ':' ; Test file delimiter scf ld a,0 jp nz,ParseNoDrv ex de,hl call GetChar ; Get next sub 'A'-1 ; Strip off drive ret c ex de,hl ParseNoDrv: ex de,hl push hl ld hl,(Heap.Ptr) ; Init heap ld (hl),.File inc hl ld (hl),11 inc hl ld (hl),a ; Set drive inc hl ex (sp),hl ex de,hl call nc,ChkChar ld a,b or a jp z,ParseNotEmpty ld (EmptyFlg),a ; Set file here ParseNotEmpty: cp 8 ; Test length jp c,ParseFLOk ld b,8 ; .. set max ParseFLOk: ex (sp),hl ex de,hl push bc inc b ParseSmpName: dec b ; Test done jp z,ParseGotName call GetChar ld (de),a inc de jp ParseSmpName ParseGotName: pop bc pop hl ld a,11-1 sub b ; Test remainder jp c,ParseFull ex de,hl ParsePad: ld (hl),' ' ; Fill with blanks inc hl dec a jp p,ParsePad ex de,hl ParseFull: ld a,c ld b,0 cp '.' ; Test delimiter push de call z,ChkChar ; Get next if so ex (sp),hl ex de,hl push de dec de dec de dec de ld a,b cp 4 ; Test length jp c,ParseFXOk ld b,3 ; .. truncate ParseFXOk: inc b ParseSmpExt: dec b jp z,ParseGotExt call GetChar ld (de),a ; Fill extension inc de jp ParseSmpExt ParseGotExt: pop hl ld (Heap.Ptr),hl ; Set heap ex de,hl pop hl ld a,c ret ; ; Attache symbol ; EXIT Reg HL points to label flag of symbol ; Carry set if new label ; SymbolNew: xor a ; Clear flag ; ; Attache symbol ; ENTRY Accu holds symbol flag ; EXIT Reg HL points to label flag of symbol ; Carry set if new label ; SymbolFlg: ld hl,(TopTPA) ; Get start of symbols push af SymbolLoop: ex de,hl ld hl,(CurPtr) ; Get current pointer ex de,hl call Cmp.HL.DE ; . test end jp z,InsertSymbol ld a,(hl) and .LenMsk ; Get length of symbol ld c,a pop af push af xor (hl) and .COMMON+.Public ; Test special jp nz,SymbolSkip ; .. skip ld de,BF.buf ld a,(de) inc de xor c ; Test same length jp nz,SymbolSkip push hl ld b,c ld a,(L.Mode) ; Test L.option or a call nz,FixPtr ; Skip linkage if so call FixPtr ; Skip entry dec hl SymbolSearch: ld a,(de) cp (hl) ; Find symbol jp nz,SymbolSkip. ; .. not equal inc de dec hl dec b jp nz,SymbolSearch pop hl ld a,(L.Mode) ; Test L.option or a jp nz,l03ff pop af xor a ; Reset insert flag ret l03ff: pop af push af and .Public ; Test name of module scf call z,l047e push hl jp nc,l040d ld b,h ld c,l l040d: ld a,(l1315) or a jp nz,l0431 l0414: push hl ld e,(hl) dec hl ld d,(hl) ld a,(l1313) cp d dec hl dec hl dec hl dec hl dec hl jp nz,l043b inc hl ld a,b cp (hl) dec hl jp nz,l043b ld a,c cp (hl) jp nz,l043b pop hl l0431: pop de pop af and .Public ; Test name of module ret z ld (NamePtr),hl ; Save address xor a ret l043b: ld a,e pop de and .Libreq ; Test chaining jp nz,l044a dec hl ld a,(hl) dec hl ld l,(hl) ld h,a jp l0414 l044a: ex de,hl ld a,(hl) and 0dfh ld (hl),a ld hl,(CurPtr) ex de,hl dec hl ld (hl),d dec hl ld (hl),e pop hl pop af ex de,hl push hl add a,' ' ld (hl),a and .Public ; Test name of module jp z,l0466 ld (NamePtr),hl ; Save address l0466: dec hl call SetEnv dec hl xor a ld (hl),a dec hl ld (hl),a dec hl ld (hl),b dec hl ld (hl),c dec hl ld (hl),d dec hl ld (hl),e dec hl HeapCheck.: call HeapCheck pop hl scf ret l047e: push hl ld hl,(NamePtr) ; Test name defined ld a,l or h call z,l048a ex (sp),hl pop bc ret l048a: ld hl,(CurPtr) ld (NamePtr),hl ; Init name push hl push de dec hl call SetEnv dec hl dec hl dec hl ld a,(L.Mode) or a call nz,FixPtr ld a,(l1313) ld c,0 call CnvDecbyte call HeapCheck pop de pop hl ld a,.Public ; Set module name add a,c ld (hl),a ret ; ; Build ASCII decimal string ; ENTRY Accu holds hex byte ; Reg HL points to end of string ; EXIT Reg C holds count ; CnvDecbyte: ld b,-1 ; Init divisor CnvByteRek: sub 10 ; .. divide inc b ; Bump tens jp nc,CnvByteRek push af ld a,b call nz,CnvDecbyte pop af add a,'9'+1 ; Fix ASCII ld (hl),a dec hl inc c ; Bump digit counter ret ; ; Insert symbol into table ; InsertSymbol: ld a,(l1315) or a ; Test flag jp nz,pop.AF ; .. end pop af push af and .Public ; Test module name call z,l047e ld hl,(CurPtr) ; Get current table ex de,hl pop af ; Get flag push de ld hl,BF.buf add a,(hl) ; Add length ld (de),a ; .. set combined flag ex de,hl and .Public ; Test module name jp z,InsertNoName ld (NamePtr),hl ; Save pointer ld b,h ; .. copy it ld c,l InsertNoName: dec hl call SetEnv ; Set modes ex de,hl dec de ; Fix count dec de dec de ld a,(L.Mode) ; Test L.option or a jp z,SymNoL ex (sp),hl ex de,hl ld (hl),b ; If so, set linkage dec hl ld (hl),c dec hl ld (hl),d dec hl ld (hl),e dec hl ex de,hl ld a,(hl) add a,.Libreq ld (hl),a ; Fix flag for chaining ex (sp),hl SymNoL: ld b,(hl) ; Get length of symbol inc hl SymbolMove: ld a,(hl) ld (de),a ; Unpack symbol inc hl dec de dec b jp nz,SymbolMove ex de,hl jp HeapCheck. ; Check memory ; ; Didn't find symbol, skip to next ; SymbolSkip.: pop hl SymbolSkip: ld a,(L.Mode) ; Test L.option or a jp z,SymbolSKL ld a,4 ; Fix linkage SymbolSKL: add a,c ; Adjust length add a,4 cpl ; .. negate ld c,a ld b,-1 add hl,bc ; Address next jp SymbolLoop ; ; Set pointer to start of label string ; ENTRY Reg HL points to length field ; EXIT Reg HL fixed ; FixPtr: dec hl ; Bump four times dec hl dec hl dec hl ret ; ; Save values into label descriptor ; ENTRY Reg HL points to descriptor ; SetEnv: ld a,(l1313) ld (hl),a ; .. set ??? dec hl ld a,(Addr.Mode) ld (hl),a ; .. and address mode ret ; ; Pop Accu, set carry ; pop.AF: pop af scf ret ; ; Print character to console ; ENTRY Accu holds character ; conout: push af push bc push de push hl and NoMSB ; Mask for seven bit ld e,a ld c,.conout call BDOS ; .. print pop hl pop de pop bc pop af ret ; ; Load line from console ; EXIT Reg HL points to line ; GetLine: ld c,.getlin ld de,.ConsLine call BDOS ; Read line from console ld a,lf call conout CloseLine: ld a,(.ConsLine+1) ; Get real length ld hl,ConsLine push hl add a,l ; Point to end ld l,a ld a,0 adc a,h ld h,a ld (hl),cr ; Close line pop hl ret ; ; Get parameter line ; EXIT Reg HL points to start of line ; ParamStr: push de push bc ld hl,CCPbuf ; Get default CCP buffer ld a,(hl) ; Get length ld (hl),0 ; .. clear or a ld b,a ParSkpBlnk: jp z,ConsoleLine ; Check empty buffer inc hl ld a,(hl) cp ' ' ; Skip leading blanks jp nz,ParNoBlnk dec b jp ParSkpBlnk ParNoBlnk: ld de,ConsLine-1 ; Point to line ld a,b dec hl inc b ParMove: ld (de),a ; Unpack CCP buffer inc de inc hl dec b jp z,ParEnd ld a,(hl) jp ParMove ParEnd: pop de pop bc ld (LIB.mode),a ; Set end jp CloseLine ; ; CCP buffer empty, so get from console ; ConsoleLine: call NL ; Close line ld a,'*' ; Indicate command mode call conout call GetLine ; Load line from console pop de pop bc ret ; ; Close console line ; NL: ld a,cr ; Give CR call conout xor a ld (ConsRow),a ; Clear row counter ld a,lf ; Give LF jp conout ; ; Position next tabulator or set end of line ; PosRow: ld a,(ConsRow) cp COLTAB ; Test last position jp z,NL ; .. new line if so inc a ld (ConsRow),a ; Else bump ld a,tab jp conout ; .. give tab ; ; Output string to console ; ENTRY Reg HL points to 00 closed string ; string: ld a,(hl) and NoMSB ret z ; End on zero call conout ; .. print inc hl jp string ; .. loop ; ; Print string by length ; ENTRY Accu holds length of string ; Reg HL points to string in REVERSED order ; PrFix: ld b,a ; Save length rev.str: ld a,(hl) call conout ; Print dec hl ; Fix pointer dec b jp nz,rev.str jp PosRow ; Position to nex tab ; ; Get non-blank character from buffer ; ENTRY Reg HL points to buffer ; EXIT Accu holds character ; GetChar: ld a,(hl) ; Get it and NoMSB ; .. as seven bit inc hl cp ' ' ; Skip blank jp z,GetChar cp lf ; .. and LF jp z,GetChar cp 'a'-1 ; Test lower case jp c,GetChUPP sub 'a'-'A' ; Make UPPER GetChUPP: cp '/' ; Test option jp z,GetOpt cp cr ; Test end of line dec hl ret z inc hl ld (ChGot),a ; Save character ret GetOpt: call GetChar push bc ld bc,GetRET push bc ; Set return ld b,.Uopt cp 'U' ; Test list /U.ndefined ret z ld b,.Lopt cp 'L' ; Test /L.ist modules ret z ld b,.Copt cp 'C' ; Test /C.lear lib ret z ld b,.Eopt cp 'E' ; Test /E.xit to OS ret z ld b,.Ropt cp 'R' ; Test /R.ename lib file ret z ld b,0 cp 'O' ; Test /O.ctal radix jp z,GetRADIX sub 'H' ; Test /H.ex radix jp nz,CmdERR GetRADIX: ld (LibRadix),a ; Set radix ret GetRET: ld a,(LIB.opt) or b ; Insert option selected ld (LIB.opt),a pop bc jp GetChar ; ; Execute /U option ; Exec.U: call GetItem ; Get item jp c,Exec.U ; .. loop on constant jp z,Exec.U ; .. and address ld a,c cp _CHNEXT ; Search chain external jp z,MarkExt cp _DEFENT ; .. or entry jp z,MarkEntry cp _ENDPRG ; Loop till end jp nz,Exec.U xor a ld (Un.Head),a ; Set end ld hl,(TopTPA) ; Init pointer U.loop: ex de,hl ld hl,(CurPtr) ex de,hl call Cmp.HL.DE ; Test label here jp z,NL ; .. no ore ld a,(hl) and .Unk ; Test unknown call nz,Unsatisfied ld a,(hl) and .LenMsk ; Isolate count add a,4 ; .. add overhead cpl ld e,a ; Negate ld d,-1 add hl,de ; Point to previous jp U.loop MarkExt: push de call SymbolNew ; Attache symbol ld a,(hl) and NOT .Known ; Strip off bit or .Unk ; Mark as EXTRN ld (hl),a jp MarkAddr MarkEntry: push de call SymbolNew ; Attache symbol ld a,(hl) and NOT .Unk ; Strip off bit or .Known ; Mark as ENTRY ld (hl),a MarkAddr: pop de dec hl ; Point to value dec hl dec hl ld (hl),d ; Save it dec hl ld (hl),e jp Exec.U ; ; Tell unknown label ; ENTRY Reg HL points to label descriptor ; Unsatisfied: ld a,(Un.Head) ; Test flag or a call z,UnsolvedHead ; .. give header ld a,(hl) and .LenMsk ; Mask length push hl call FixPtr ; Set pointer to string dec hl call PrFix ; .. print label pop hl ret ; ; Give header for unsolved labels ; UnsolvedHead: push hl inc a ld (Un.Head),a ; Indicate done call DoubleNL ld hl,$UnsolvedHead call string ; Give text call NL pop hl ret ; $UnsolvedHead: db 'Unsatisfied external request(s)',':'+MSB,0 ; ; Execute any option ; Exec..: call GetItem ; Get item jp c,Put.Const ; .. test constant jp z,Put.Addr ; .. or address ld a,c cp _ENDPRG ; Test end of file ret z call Write.Item ; Write item to disk jp Exec.. Put.Const: call Wrt.Const ; Write constant to disk jp Exec.. Put.Addr: call Wrt.Addr ; Write address to disk jp Exec.. ; ; Write control header and 16 bit address ; ENTRY Reg B holds control bits ; Reg DE holds address ; Wrt.Addr: call Wrt.Ctrl.2 ; Give control ld b,e call Wrt.8.Bit ; .. LO ld b,d call Wrt.8.Bit ; .. HI ret ; ; Write 8 bit constant ; ENTRY Reg B holds constant ; Wrt.Const: xor a call Wrt.1.Bit ; Write 0 ; ; Write 8 bit ; ENTRY Reg B holds value ; Wrt.8.Bit: push bc ld c,-relbits ; Set count Wrt..8: ld a,b ; Get bit rla ld b,a call Wrt.1.Bit ; .. write inc c jp nz,Wrt..8 pop bc ret ; ; Write control head ; ENTRY Reg B holds two bits for control ; Wrt.Ctrl.2: scf call Wrt.1.Bit ; Indicate control ld a,b ; Get bits rra rra call Wrt.1.Bit ld a,b rra ; ; Put one bit to stream ; ENTRY Carry flag reflects state of the bit ; Wrt.1.Bit: push hl ld hl,DST.Data ld a,(hl) rla ; Shift a bit ld (hl),a inc hl inc (hl) ; Bump count jp nz,Wrt.Bit.skp call Put ld hl,-relbits*256 ld (DST.Data),hl ; Init count Wrt.Bit.skp: pop hl ret ; ; Execute /L option ; Exec.L: ld a,1 ; Set flag ld (L.Mode),a Exec..L: ld hl,(CurPtr) ; Save pointer push hl ld hl,0 ld (DataSize),hl ; Clear data size Ex.L.loop: call GetItem ; Get item jp c,Ex.L.loop ; Skip constant jp z,Ex.L.loop ; .. and address ld a,c cp _DATSIZ ; Check data size jp z,SetDat cp _PRGSIZ ; .. program size jp z,SetPrg cp _DEFCOM ; .. common size jp z,SetCom cp _CHNEXT ; .. external chain jp z,SetExt cp _DEFENT ; .. entry point jp z,SetEntry cp _ENDMOD ; .. end of module jp z,SetModEnd cp _ENDPRG ; .. end of file jp nz,Ex.L.loop ld hl,$StatHead call DoubleNL call string ; Give statistic header call DoubleNL ld hl,(TopTPA) ; Init label pointer L..loop: ex de,hl ld hl,(CurPtr) ex de,hl call Cmp.HL.DE ; Test done jp z,NL.pop ld a,(hl) ; Get flag cp .Public ; Test special jp nc,L..skip and .LenMsk ; Extract count jp nz,L..symbol ; Process label L..skip: call PosLabel ; Position to next jp L..loop DoubleNL: call NL jp NL ; $StatHead: db 'Symbol',tab db 'Value',tab db 'Defined',tab db 'Reference','d'+MSB,0 ; SetDat: ex de,hl ld (DataSize),hl ; Save data size jp Ex.L.loop SetPrg: ex de,hl ld (ProgSize),hl ; Save program size jp Ex.L.loop SetCom: ld a,.COMMON ; Set COMMON flag l07e7: push de call SymbolFlg ; Attache symbol ld a,(hl) or .Known ; Set flag l07ee: ld (hl),a dec hl call SetEnv ; Set mode dec hl pop de ld (hl),d ; Save value dec hl ld (hl),e jp Ex.L.loop ; .. loop on SetEntry: xor a jp l07e7 SetExt: push de call SymbolNew ; Attache symbol ld a,(hl) or .Unk ; Set EXTRN jp l07ee SetModEnd: ld hl,$Module ; Tell module call DoubleNL call string ld hl,(NamePtr) ; Get address of name ld a,1 ld (ConsRow),a ; Init tab call PrItem ; Print module name ld hl,$of call string ld hl,SRC.FCB ; Get FCB ld a,(hl) inc hl or a ; Test default drive jp z,Skp..drv add a,'A'-1 ; Make real call conout ld a,':' ; Print delimiter call conout Skp..drv: ld b,11 call PrFN ; Print name of file call DoubleNL ld hl,$PrgLen call string ; Give length of CSEG ld hl,(ProgSize) call PrDec call NL ld hl,$DatLen call string ; Give length of DSEG ld hl,(DataSize) call PrDec call DoubleNL xor a ld (Un.Head),a pop hl push hl l0862: ex de,hl ld hl,(CurPtr) ex de,hl call Cmp.HL.DE jp z,l0892 ld a,(hl) and .COMMON+.Public ; Extract bits cp .COMMON ; Test COMMON call z,l087b call PosLabel ; Position to next jp l0862 l087b: push hl ld a,(Un.Head) or a call z,Com.Head call GetSymbol call PrFix ex de,hl call PrDec call PosRow pop hl ret l0892: xor a ld (Un.Head),a pop hl push hl l0898: ex de,hl ld hl,(CurPtr) ex de,hl call Cmp.HL.DE ; Test end of table jp z,l08cb ld a,(hl) cp .Public ; Test special jp nc,l08ae and .Known ; Test ENTRY call nz,l08b4 l08ae: call PosLabel ; Position to next jp l0898 l08b4: push hl ld a,(Un.Head) or a call z,Entry.Head l08bc: call GetSymbol call PrFix ex de,hl call Pr.Addr.Mode call PosRow pop hl ret l08cb: xor a ld (Un.Head),a pop hl push hl l08d1: ex de,hl ld hl,(CurPtr) ex de,hl call Cmp.HL.DE jp z,l08f8 ld a,(hl) cp .Public ; Test special jp nc,l08e7 and .Unk ; Test EXTRN call nz,l08ed l08e7: call PosLabel ; Position to next jp l08d1 l08ed: push hl ld a,(Un.Head) or a call z,Ext.Head jp l08bc l08f8: pop hl jp Exec..L ; ; Get symbol pointer ; ENTRY Reg HL points to descriptor byte ; EXIT Reg HL points to start of symbol ; Accu holds length of symbol ; GetSymbol: ld a,(hl) ; Get flag dec hl dec hl ; Point to address mode push af ld a,(hl) and 3 ld (Addr.Mode),a ; .. save it pop af dec hl ld d,(hl) ; Get value dec hl ld e,(hl) dec hl push de GetSChain: dec hl dec hl ld d,(hl) ; Get possible chain address dec hl ld e,(hl) and .Libreq ; Test chaining ex de,hl ld a,(hl) ; Get chain flag call FixPtr ; Fix pointer dec hl jp z,GetSChain ; Loop till link and .LenMsk ; Return count call FixPtr ; Position to label pop de ret ; ; Position to next item ; ENTRY Reg HL points to length field ; EXIT Reg HL fixed ; PosLabel: ld a,(hl) and .LenMsk ; Get count add a,8 ; .. add overhead cpl ld d,-1 ; Make <0 ld e,a add hl,de ; .. fix ret ; ; Print name of file ; ENTRY Reg HL points to FCB ; Reg B holds length ; PrFN: ld a,(hl) call conout ; .. print dec b inc hl jp nz,PrFN ret ; ; Print head for COMMON references ; Com.Head: push hl inc a ld (Un.Head),a ; Set flag call NL ld hl,$com.blk call string ; .. print text NL.pop: call DoubleNL pop hl ret ; ; Print head for ENTRY references ; Entry.Head: push hl inc a ld (Un.Head),a ; Set flag call DoubleNL ld hl,$Entry call string ; .. print text jp NL.pop ; ; Print head for EXTRN references ; Ext.Head: push hl inc a ld (Un.Head),a ; Set flag call DoubleNL ld hl,$Ext call string ; .. print text jp NL.pop ; $com.blk: db 'Common block(s)',':'+MSB,0 $Entry: db 'Entry point(s)',':'+MSB,0 $Ext: db 'External reference(s)',':'+MSB,0 ; ; Process label ; L..symbol: xor a ; Reset flag ld (KnownFlg),a push hl scf ; Force descriptor byte l09ac: push hl l09ad: call ChainSymbol ; Get chain jp c,l09f9 and .Known ; Wait for known jp z,l09ad ld (KnownFlg),a ; Set known push hl call GetSymbol call PrFix ex de,hl call Pr.Addr.Mode call PosRow pop hl call PrItem ; Print symbol l09cd: ex de,hl pop hl push hl scf l09d1: call ChainSymbol jp c,l09ea and .Unk jp nz,l0a20 call Cmp.HL.DE or a jp nz,l09d1 ld a,(hl) and .Libreq ; Test chaining jp nz,l09ea ld a,(hl) l09ea: push af call NL pop af pop de and .Known jp nz,l09ac pop hl jp L..skip l09f9: ld a,(KnownFlg) or a jp nz,l0a11 push hl call GetSymbol call PrFix pop hl call PosRow ; Bump cursor twice call PosRow jp l09cd l0a11: call PositionRow ; Position on screen jp l09cd ; ; Fix cursor three positions ; PositionRow: call PosRow ; One call PosRow ; Two jp PosRow ; Three l0a20: call PrItem ; Print or a jp l09d1 ; ; Print symbol name ; ENTRY Reg HL points to descriptor ; PrItem: push hl call FixPtr ; Fix pointer to linkage dec hl ld d,(hl) dec hl ld e,(hl) ex de,hl call GetSymbol ; Get symbol push af ld a,(ConsRow) or a call z,PositionRow ; Set proper position pop af call PrFix ; Print name pop hl ret ; $DatLen: db 'Length of Data area',tab+MSB,0 $PrgLen: db 'Length of Program',tab+MSB,0 $Module: db 'Module',' '+MSB,0 $of: db ' of',' '+MSB,0 ; ; Get descriptor bytes ; ENTRY Reg HL points to descriptor ; Carry set forces descriptor field to be fetched ; EXIT Carry set indicates chaining link mode ; If carry not set ; Accu holds desciptor byte (current or chained) ; Reg HL holds chained descriptor ; ChainSymbol: jp c,ChainSSKP ; Skip on carry ld a,(hl) and .Libreq ; Test chaining scf ret nz call FixPtr ; Fix over values dec hl ; .. fix for chain dec hl dec hl ld a,(hl) dec hl ld l,(hl) ; Get chain address ld h,a ChainSSKP: ld a,(hl) or a ret ; ; Compare HL : DE ; ENTRY Regs HL and DE hold 16 bit ; EXIT Zero set if equal ; Carry set if DE > HL ; Cmp.HL.DE: ld a,h sub d ; Compare HI ret nz ld a,l sub e ; .. and LO ret ; ; Read one bit from stream ; EXIT Carry reflects state of the bit ; Read.1.Bit: push hl ld hl,SRC.Data ld a,(hl) ; Get byte inc hl inc (hl) ; Bump count jp nz,Read..skp call Get ; Get byte ld (hl),-relbits ; Reset bit count Read..skp: add a,a ; Get the bit dec hl ld (hl),a ; .. bring back byte pop hl ret ; ; Read 8 bits from stream ; EXIT Reg B holds value ; Read.8.Bit: ld c,8 ; Set count ; ; Read bits from stream ; ENRY Reg C holds bit count ; EXIT Reg B holds value ; Read.?.Bit: ld b,0 ; Init result Read..loop: call Read.1.Bit ; Get bit ld a,b rla ; .. shift in ld b,a dec c jp nz,Read..loop ; .. loop ret ; ; Read one item from stream ; EXIT Carry set if constant byte found ; Zero set if 16 bit address field found ; Otherwise link item encountered ; Reg C holds link item ; Reg B holds address mode ; Read.Item: xor a ld (Addr.Mode),a ; Reset to absolute mode call Read.1.Bit ; Get bit jp c,Read.. ; Test control call Read.8.Bit ; Read constant scf ; Indicate it ret Read..: ld c,2 call Read.?.Bit ; Get control or a ; Test special jp z,Read.Ctrl call Read.AField ; Read address ld b,a xor a ret Read.Ctrl: push hl ld c,4 call Read.?.Bit ; Read sub-control cp _DEFCOM ; Test AField only push af jp c,Rd.BF.only cp _ENDPRG ; Test end of file jp z,Item.End ld c,2 call Read.?.Bit ; Get control bits call Read.AField ; Read value Rd.BF.only: pop af push af cp _EXTOFF ; Test BField follows jp nc,Item.End push de ld c,3 call Read.?.Bit ; Read length ld hl,BF.buf or a ld (hl),a jp nz,BF.skp inc (hl) ; Map 0 --> 1 BF.skp: inc hl ld (hl),' ' ; Blank 1st place ld e,a Rd.BF.loop: dec e jp m,Rd.BF.end call Read.8.Bit and NoMSB ld (hl),a ; Store item inc hl jp Rd.BF.loop Rd.BF.end: pop de Item.End: pop af ld hl,-1*256 cp _ENDMOD ; Test end jp nz,Rd.Itm.more ld (SRC.Data),hl ; Set end into buffer Rd.Itm.more: ld c,a ld a,(Addr.Mode) ld b,a inc a or a pop hl ret ; ; Read AField ; ENTRY Accu holds address mode ; EXIT Reg DE holds 16 bit address ; Read.AField: push af ld (Addr.Mode),a ; Set mode call Read.8.Bit ld e,b ; .. get LO call Read.8.Bit ld d,b ; .. and HI pop af ret ; ; Print value hex or octal ; ENTRY Reg HL holds value ; ; Note octal : 1.111.111.111.111.111 ; PrVal16: ld a,(LibRadix) or a ; Test mode jp z,PrHex16 ; .. hex xor a add hl,hl ; Get MSB adc a,'0' call conout ; .. print push bc ld b,5 ; Five octal digits PrOct: xor a ld c,3 ; Three bits per digit PrOctloop: add hl,hl adc a,a ; Shift dec c jp nz,PrOctloop add a,'0' call conout ; .. print dec b jp nz,PrOct pop bc ret PrHex16: ld a,h ; Get HI call PrHex8 ld a,l ; .. then LO PrHex8: push bc ld b,a rra ; Isolate HI rra rra rra call PrHex4 ld a,b ; .. get LO pop bc PrHex4: and LoMask ; Mask lower bits add a,'0' ; .. make ASCII cp '9'+1 ; Test range jp c,prHex0..9 add a,7 ; .. fix for A .. F prHex0..9: jp conout ; ; Print decimal value ; ENTRY Reg HL holds value ; PrDec: ld bc,-10 ; Init divisor ConvDec: ld d,b ; Init to -1 ld e,b ConvDig: add hl,bc ; Subtract inc de ; .. bump jp c,ConvDig ; .. till < 0 push hl ex de,hl ld a,h or l ; Test end call nz,ConvDec ; .. recursive call ld a,'9'+1 pop bc add a,c ; .. make ASCII jp conout ; .. and print ; ; Print 16 bit value and indicate mode ; ENTRY Reg HL holds value ; $Addr.Mode: db ' ''"!' Pr.Addr.Mode: call PrVal16 ; Give address ld hl,$Addr.Mode ld a,(Addr.Mode) ; Get mode ld c,a ld b,0 add hl,bc ; .. as index ld a,(hl) jp conout ; .. print ; ; Write link item to disk ; ENTRY Reg C holds item ; Reg B holds address mode ; Write.Item: push bc ld b,0 ; Set special control call Wrt.Ctrl.2 ld b,c ; Get item ld a,4 call JustifyBits pop bc ld a,c cp _DEFCOM ; Test BField only jp c,Wr.BF.only cp _ENDPRG ; Test end ret z ld a,2 ; Write prefix call JustifyBits ld b,e call Wrt.8.Bit ; Write address ld b,d call Wrt.8.Bit ld a,c cp _ENDMOD ; Test end of module jp z,Wr.EndModule cp _EXTOFF ; Test BField follows ret nc Wr.BF.only: ld a,(BF.buf) ; Get count ld b,a ld d,a ld a,3 call JustifyBits ; Output it push hl ld hl,BF.buf+1 ; Point to name buffer Wr.BF.loop: ld b,(hl) call Wrt.8.Bit inc hl dec d jp nz,Wr.BF.loop pop hl ret ; ; Justify bits left and write it ; ENTRY Accu holds number of bits to be shifted ; Reg B holds bits to be written ; JustifyBits: push de ld d,a ; Save count ld a,8 sub d ; Test byte boundary jp z,Wrt.Just.Bits ld e,a ; Get remainder ld a,b SetLeftMarg: add a,a ; Shift to left margin dec e jp nz,SetLeftMarg ld b,a Wrt.Just.Bits: ld a,b add a,a ; Get carry ld b,a call Wrt.1.Bit ; .. and write it dec d jp nz,Wrt.Just.Bits pop de ret ; ; Process end of module, output till byte boundary ; Wr.EndModule: ld a,(DST.Count) ; Check end cp -relbits ret z call Wrt.1.Bit ; .. write jp Wr.EndModule ; ; Check enough memory available ; ENTRY Reg HL points to heap top ; Check.Mem: push af push de ld (Heap.Ptr),hl ; Save heap ex de,hl ld hl,(TopTPA) call Cmp.HL.DE ; .. check against top jp c,MemOvfl ; .. oops, out of memory ex de,hl pop de pop af ret ; ; Check dynamic memory ; ENTRY Reg HL holds pointer ; HeapCheck: ld (CurPtr),hl ; .. save entry ex de,hl push hl ld hl,(NewPtr) ; Get new top inc h call Cmp.HL.DE ; Compare pointers ex de,hl pop de ret c push bc ld hl,(CurHeap) ld e,(hl) inc hl ld d,(hl) dec hl push hl ld hl,(NewPtr) ld a,e or d jp z,MemOvfl ld a,(l1311) inc a ld (l1311),a push de call Sub.HL.DE ex de,hl ex (sp),hl pop bc ex de,hl pop hl push de call Sub.HL.DE ex de,hl ex (sp),hl l0c5d: ld a,b or c jp z,l0c6a ld a,(hl) ld (de),a inc hl inc de dec bc jp l0c5d l0c6a: pop bc ld hl,(NewPtr) add hl,bc ld (NewPtr),hl ld hl,(OldPtr) add hl,bc ld (OldPtr),hl ld hl,(CurHeap) l0c7c: ld e,(hl) inc hl ld d,(hl) ld a,e or d jp z,l0c97 ex de,hl add hl,bc ex de,hl ld (hl),d dec hl ld (hl),e ld hl,(NewPtr) call Cmp.HL.DE jp z,l0c97 ex de,hl jp l0c7c l0c97: pop bc xor a ld hl,(NewPtr) ld (hl),a inc hl ld (hl),a ret ; ; Subtract HL - DE --> DE ; Sub.HL.DE: ld a,l sub e ; Subtract LO ld e,a ld a,h sbc a,d ; .. and HI ld d,a ret ; ; ERROR Routines ; MemOvfl: ld hl,$MemOvfl Proc.ERR: ld a,'?' call conout ; Indicate error call string ; .. print it call NL jp ReStart ; .. restart ; $MemOvfl: db 'Out of memor','y'+MSB,0 ; CmdERR: ld hl,$CmdERR jp Proc.ERR ; $CmdERR: db 'Command erro','r'+MSB,0 ; ReadERR: ld hl,$ReadERR jp Proc.ERR ; $ReadERR: db 'File read erro','r'+MSB,0 ; CanntOpen: ld hl,$CanntOpen jp Proc.ERR ; $CanntOpen: db 'File not foun','d'+MSB,0 ; CanntEnter: ld hl,$CanntEnter jp Proc.ERR ; $CanntEnter: db 'Can''t enter fil','e'+MSB,0 ; ModUnkn: ld hl,$ModUnkn jp Proc.ERR ; $ModUnkn: db 'Module name/number not found in fil','e'+MSB,0 ; Clause: ld hl,$Clause jp Proc.ERR ; $Clause: db 'First module in Until clause after las' db 't'+MSB,0 ; WrtERR: ld hl,$WrtERR jp Proc.ERR ; $WrtERR: db 'Library write erro','r'+MSB,0 ; ; Reset file for reading ; Reset: ld a,RecLng ld (GetPtr),a ; Force record read ld de,SRC.FCB call PrepFCB ; Clear some values push de ld c,.setdma ld de,SRC.buff call BDOS ; Set buffer pop de ld c,.open call BDOS ; Open file inc a jp z,CanntOpen ; .. oops, not on board ld a,-1 ld (SRC.Count),a ; Init bit count ret ; ; Read record from file ; GetRec: push bc ld de,SRC.buff ld c,.setdma call BDOS ; Set disk buffer ld de,SRC.FCB ld c,.rdseq call BDOS ; Read record pop bc inc a ; Test end jp z,ReadERR xor a ; Return 0 ret ; ; Write record to file ; PutRec: push bc ld de,DST.buff ld c,.setdma call BDOS ; Set disk buffer ld de,DST.FCB ld c,.wrseq call BDOS ; .. write it or a jp nz,WrtERR ; Test error pop bc xor a ret ret ; ; Close library file ; CloseLIB: ld c,_ENDPRG call Write.Item ; Write EOF ld b,0 call Wrt.8.Bit ; Fill byte ld a,(PutPtr) or a call nz,PutRec ; Write remainder ld de,DST.buff ld c,.setdma call BDOS ; Reset buffer ld de,DST.FCB ld c,.close call BDOS ; Close file xor a ld (WrOpen),a ; Reset open ret ; ; Clear LIB - e.g. /C selected ; ClrLIB: xor a ld (PutPtr),a ; Init pointer ld a,(WrOpen) or a ; Test write open call nz,CloseLIB ; .. close if so ld de,DST.FCB call PrepFCB ; Prepare FCB push de ld de,DST.buff ld c,.setdma call BDOS ; Set buffer pop de push de ld c,.delete ; Delete old file call BDOS pop de ld c,.make push de call BDOS ; .. create new file inc a jp z,CanntEnter ; .. oops, cannot do ld (WrOpen),a ; Set write open pop de call PrepFCB ld c,.open call BDOS ld hl,-relbits*256 ld (DST.Data),hl ; Init count ret ; ; Prepare FCB for accessing ; ENTRY Reg DE points to FCB ; PrepFCB: ld hl,_EX add hl,de ; Point to extension ld b,4 xor a Clr..FCB: ld (hl),a ; .. clear fields inc hl dec b jp nz,Clr..FCB ld bc,_CR-_EX-4 add hl,bc ld (hl),a ; Clear current record ret ; ; Put byte to file ; ENTRY Accu holds byte ; Put: push af push de ld a,(PutPtr) ; Test buffer full or a call m,PutRec ; .. write it inc a ld (PutPtr),a ; Bump pointer ld e,a ld d,0 ld hl,DST.buff-1 add hl,de ; Point to buffer pop de pop af ld (hl),a ; Put the byte ret ; ; Get byte from stream ; EXIT Accu holds byte ; Get: push hl ld a,(Get.mode) or a ; Test from memory module jp z,GetMem push de ld a,(GetPtr) or a ; Test read new record call m,GetRec ld e,a ld d,0 inc a ld (GetPtr),a ld hl,SRC.buff add hl,de ; Point to buffer ld a,(hl) ; Get byte ld hl,(NewPtr) ; Get memory pointer ld (hl),a ; .. save inc hl ; .. bump ld (NewPtr),hl push af ex de,hl ld hl,(CurPtr) call HeapCheck ; Check memory pop af pop de pop hl ret GetMem: ld hl,(OldPtr) ; Get pointer ld a,(hl) ; .. laod inc hl ; .. bump ld (OldPtr),hl pop hl ret ; ; Rename LIB - e.g. /R and /E ; LIBrename: push af ld a,(WrOpen) ; Test write open or a jp z,AF.pop call CloseLIB ; Close file ld hl,DST.FCB ld de,DST.FCB.2 ld b,16 CopyFCB: ld a,(hl) ld (de),a ; Set 1st to 2nd name inc hl inc de dec b jp nz,CopyFCB ld de,SavExt ; Get extension ld a,(de) cp ' ' ; Test empty jp nz,Skp..ext ld de,$REL ; Get default instead Skp..ext: ld hl,DST.FCB.2+9 ld b,3 CopyExt: ld a,(de) ; Unpack extension ld (hl),a inc hl inc de dec b jp nz,CopyExt ld hl,SRC.FCB ; Prepare moving ld de,DST.FCB.2 ld b,11 CopyName: ld a,(de) ld (hl),a ; Set old name inc hl inc de dec b jp nz,CopyName ld de,SRC.FCB ld c,.delete call BDOS ; Delete old one ld c,.rename ld de,DST.FCB call BDOS ; Rename xor a ld (WrOpen),a ; Indicate not open pop af ret ; ; Get item ; GetItem: ld a,(FileFlag) ; Test read OK or a jp nz,PrepFile call Read.Item ret c ; End on constant ret z ; .. or address push af ld a,c ; Get item cp _PRGNAM ; Test name jp z,PutModName cp _ENDMOD ; .. or end of module jp nz,AF.pop ld (FileFlag),a ; Force new init AF.pop: pop af ret PutModName: ld a,.Public ; Init flag push bc call SymbolFlg ; Attache symbol pop bc pop af ret PrepFile: xor a ld (FileFlag),a ; Set file open ld h,a ld l,a ld (NamePtr),hl ; Clear name of module ld a,(l1308) or a jp z,l0f49 ld b,a ld a,(l1313) sub b jp nz,l0f7e ld (l1308),a l0f49: call SelHeap ; Get file jp c,l0f85 ; .. empty cp .File ; Test right selection jp z,l0f78 or a jp z,l0f72 call l10a1 push af call SelHeap ; Get file call l10a1 ld (l1308),a ld b,a pop af inc b cp b jp nc,Clause l0f6c: call l0fe3 jp GetItem l0f72: call l10a1 jp GetItem l0f78: call Reset. ; Reset file jp l0f49 l0f7e: ld a,(l1313) inc a jp l0f6c l0f85: ld c,_ENDPRG ld a,c or a ret ; ; Select file from heap ; EXIT Carry set on end of list ; Accu holds type found in descriptor ; SelHeap: ld hl,(CurHeap) ex de,hl ld hl,(Heap.Ptr) xor a ld (ChngFile),a ; Clear flag call Cmp.HL.DE ; Test end reached scf ret z ; .. exit ld a,(hl) and .LenMsk cp .File ; Test file jp nz,SelHeapNoFile push af push hl inc hl ld c,(hl) ; Get length of file name inc hl ld b,(hl) ; Get drive inc hl push hl ld de,8 add hl,de ; Point to extension ld a,(hl) cp ' ' ; .. test defined jp nz,SelFileNoExt ld (hl),'R' ; Set .REL inc hl ld (hl),'E' inc hl ld (hl),'L' SelFileNoExt: pop hl ld de,SRC.FCB ex de,hl ld a,b ; Test drive ;; ;; A BUG ??? ;; ;; cp b call nz,IndicateFile ; Set flag if drive ld (hl),b ; Save drive inc hl SelFilePack: ld a,(de) cp (hl) ; Test file known call nz,IndicateFile ; .. indicate unknown ld (hl),a ; Unpack file name inc hl inc de dec c jp nz,SelFilePack pop hl pop af SelHeapNoFile: push hl inc hl ld c,(hl) ; Get length ld b,0 inc hl inc hl add hl,bc ; Point to next in list ld (Heap.Ptr),hl ; .. set pointer pop hl ret l0fe3: ld b,a l0fe4: ld a,(l1311) inc b sub b dec b jp nc,l1026 cpl ld hl,(CurHeap) inc a l0ff2: dec a jp z,l1013 ld e,(hl) inc hl ld d,(hl) ex de,hl inc h dec h jp nz,l0ff2 l0fff: ld a,(l1312) ld c,a ld a,b sub c l1005: push af call l102c jp c,ModUnkn pop af dec a jp nz,l1005 ex de,hl dec hl l1013: inc hl or (hl) jp z,l0fff ld a,0ffh ld (SRC.Count),a ld a,b ld (l1313),a inc hl ld (OldPtr),hl ret l1026: call ForceReset jp l0fe4 l102c: push bc ld a,(l1312) inc a ld (l1313),a ld (l1312),a ld (Get.mode),a ; Set mode disk ld a,(l1311) or a jp nz,l1045 inc a ld (l1311),a l1045: ld hl,0 ld (NamePtr),hl ld hl,(NewPtr) ld (OldPtr),hl inc hl inc hl ld (NewPtr),hl l1056: call Read.Item jp c,l1056 ; Test constant jp z,l1056 ; .. or address ld a,c ; Check item cp _PRGNAM ; Test name of module jp z,l1099 cp _ENDMOD ; .. or end of module jp c,l1056 cp _ENDPRG ; .. or end of file ccf push af ld hl,(NewPtr) ex de,hl ld hl,(OldPtr) ld (hl),e inc hl ld (hl),d xor a ld (Get.mode),a ; Set mode memory ex de,hl ld (hl),a inc hl ld (hl),a pop af jp c,l1089 push af call l047e pop af l1089: pop bc ret nc ld a,(l1313) dec a ld (l1313),a ld (l1312),a ld (l1314),a ret l1099: ld a,.Public ; Init flag call SymbolFlg ; Attache module name jp l1056 l10a1: inc hl ld a,(hl) or a jp z,l1107 ld de,BF.buf ld (de),a ld b,a inc de inc hl ld c,(hl) push hl push bc l10b1: inc hl ld a,(hl) ld (de),a inc de dec b jp nz,l10b1 ld a,.Public ; Save flag ld (l1315),a call SymbolFlg ; Attache symbol ld a,0 ld (l1315),a dec hl ld a,(hl) jp nc,l10fc l10cb: call l102c jp c,ModUnkn ld hl,(NamePtr) ld a,(hl) and .LenMsk pop bc push bc cp b jp nz,l10cb pop bc pop de push de push bc push hl call FixPtr ld a,(L.Mode) or a call nz,FixPtr dec hl inc de l10ee: ld a,(de) cp (hl) jp nz,l1103 inc de dec hl dec b jp nz,l10ee pop hl dec hl ld a,(hl) l10fc: pop bc pop hl dec hl dec hl jp l1135 l1103: pop hl jp l10cb l1107: inc hl ld c,(hl) add a,c dec hl ld a,0 jp nz,l1135 dec hl ld a,(hl) and .LenMsk cp 2 ld a,1 jp nz,l1135 ld a,(l1314) or a jp nz,l1135 inc a ld (Get.mode),a ; Set mode disk push hl l1127: call l102c jp nc,l1127 xor a ld (Get.mode),a ; Set mode memory ld a,(l1314) pop hl l1135: add a,c ld b,a ld a,(hl) or a ld a,b jp p,l0fe3 sub c sub c jp l0fe3 ; ; Reset file ; Reset.: ld a,(ChngFile) ; Test file changed or a ret z ; .. no exit ForceReset: push bc call Reset ; Prepare file xor a ld hl,ChngFile ld b,5 l1151: ld (hl),a ; Clear locations inc hl dec b jp nz,l1151 ld hl,(CurHeap) ld (NewPtr),hl ; Init pointer ld (hl),a ; .. clear entry inc hl ld (hl),a pop bc ld hl,(TopTPA) l1164: ex de,hl ld hl,(CurPtr) ; Test end of table call Cmp.HL.DE ex de,hl ret z ld a,(hl) add a,a ld a,(hl) jp p,l1176 or .COMMON ; Set COMMON ld (hl),a l1176: and .LenMsk add a,4 cpl ld e,a ld d,-1 add hl,de ; Point to next ld a,(L.Mode) or a call nz,FixPtr ; Fix on L.option jp l1164 ; ; Set file flag to nonzero ; IndicateFile: push af ld a,h ld (ChngFile),a ; .. set pop af ret ; SavExt: ds 3 $DefLIB: db 'FORLIB ' $REL: db 'REL' ; ***** DATA FIELD INITIALIZED ***** ConsRow: db 0 Heap.Ptr: dw 0 SRC.FCB: ds 33 DST.FCB: ds 16 DST.FCB.2: ds 17 .ConsLine: db 128,0 SRC.buff: ConsLine: ds 128 DST.buff: ds 128 DataSize: dw 0 ProgSize: dw 0 Un.Head: db 0 NewPtr: dw 0 WrOpen: db 0 ; 0 = not open for write LIB.mode: db 0 ; 0 = run, else exit to OS EmptyFlg: db 0 DST.Data: db 0 DST.Count: db 0 L.Mode: db 0 ; 1 = /L option NamePtr: dw 0 ; Hold address of module's name LibRadix: db 0 ; 0 = HEX, else OCTAL CurPtr: dw 0 TopTPA: dw 0 BF.buf: ds 8 ; BField buffer SRC.Data: db 0 SRC.Count: db 0 GetPtr: db 0 PutPtr: db 0 LIB.opt: db 0 ChGot: db 0 Addr.Mode: db 0 ; Two bits selecting mode l1308: db 0 Get.mode: db 0 ; 0 from memory, else from disk FileFlag: db 0 ; 0 read file, else prepare read CurHeap: dw 0 OldPtr: dw 0 KnownFlg: db 0 ChngFile: db 0 ; 0 if file already known l1311: db 0 l1312: db 0 l1313: db 0 l1314: db 0 l1315: db 0 LIB.stack: dw 0 dat.len equ $-ConsRow ; ***** END OF DATA FIELD INITIALIZED ***** Heap: end