title Microsoft M80 Assembler name ('M80') ; DASMed version of Microsoft assembler M80.COM ; By W. Cirsovius ; FIND SOME MYSTERIOUS DUE TO HIGH BIT OF CHARACTER SET ; (MAYBE LINE NUMBER INPUT) ;; l3ce7 l3ce8 ;;; HIGH 0300h ;;; l30dd: ????? ; PUBLIC l23bf l40f6 *** l0236: l05cc!!!!! ; This is the DASMed M80.COM ; MACRO-80 3.44 09-Dec-81 ; l0fcd: l0e74: ; l470c l48b8 l402b l1c46 l01de l4da1 l1c3a l2010 l164c ; l0ac6 -> Z80.exec.table ;; l0c50!!!! l4c4e: !!!! [Berechnung der Rekordgröße!!!!] l3294: .comment * The command_line may be: 1) obj,prn=src Generating obj.REL and prn.PRN (or prn.CRF) from src.MAC 2) obj,=src Generating obj.REL only =src obj=src 3) ,prn=src Generating prn.PRN only 4) ,=src Generating no file Any file name may be a standard CP/M device: CON: Input from console 0FFH LST: Output to list device 0FEH RDR: Input from auxiliary device 0FEH (Such as paper tape reader) The command line may my closed by "/" followed by one or more legal options: /O Octal listing /H Normal hex listing (DEFAULT) /R Force .REL file without regard to command_line /L Force .PRN file without regard to command_line - /Y Build symbols only into .PRN file /C Output cross-reference prn.CRF file instead of prn.PRN + /Z Assemble ZILOG Z80 code (DEFAULT) + /I Assemble INTEL 8080 code /P Allocate one extra stack page /M Initialize DS generated block data areas /X Suppress listing of FALSE conditionals - /D Insert date and time on print file - /E Error log to file src.ERR (or M80$$.ERR) - /W Give warning summary only - /G Forces all labels to be set global /S Allow strange MICROSOFT LINK-80 code - /B Build .COM file via LINK or L(D)80 - /V Be verbose on file opening - /Q Be quiet on .PRINTX - /U Set unknown labels to externals * .z80 aseg org 0100h FALSE equ 0 TRUE equ NOT FALSE OS equ 0000h BDOS equ 0005h TPATOP equ BDOS+1 CCP equ 0080h .conout equ 2 .rdrin equ 3 .lstout equ 5 .rdkbd 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 .retdsk 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 SRCrec equ 4 LSTrec equ 4 RELrec equ 2 SRCbfl equ SRCrec*reclng LSTbfl equ LSTrec*reclng RELbfl equ RELrec*reclng prf.lin equ 32 relbits equ 8 null equ 00h tab equ 09h lf equ 0ah ff equ 0ch cr equ 0dh eof equ 1ah ; EOFItm equ 0 ; CRF codes (MSB set) StrtItm equ 1 DefItm equ 2 EndItm equ 3 COMLEN equ 80 TITLEN equ 80 ; Lenght of title STITLEN equ 60 ; Lenght of subtitle DigLen equ 6 ; Max number length ModLen equ 6 ; Max module name length SymLen equ 6 ; Max symbol name length LabLen equ 16 ; Max label length SrcLen equ 130 ; Max source line length MinPAGE equ 10 ; Minimal page length StkDep equ 15 ; Stack depth RELf equ 10000000b LSTf equ 01000000b MSB equ 10000000b LoMask equ 00001111b NoMSB equ 01111111b LenMask equ 00000111b Mask2 equ 00000011b Mask3 equ 00000111b Mask6 equ 00111111b MaskOdd equ 00000110b COLTAB equ 00000111b _iflev equ 50 ; Max IF depth ; ; Registers and conditions ; _D equ 2 _ACCU equ 7 _HL equ 4 _cC equ 3 CB EQU 0cbh ; Special code prefix DD equ 0ddh ED equ 0edh IMmax equ 2 ; Max IM argument IRbit equ 00001000b r.p equ 00111000b .STAX equ 002h ; LD (rp),A .LDAX equ 00ah ; LD A,(rp) .DCR equ 005h ; DEC r .MVI equ 006h ; LD r,data .EXAFAF equ 008h ; EX AF,AF' .ADD equ 009h ; ADD rp,rp .DCX equ 00bh ; DEC rp .JRc equ 020h ; JR CC .SHLD equ 022h ; LD (adr),HL .LHLD equ 02ah ; LD HL,(adr) .STA equ 032h ; LD (adr),A .MVI.M equ 036h ; LD (HL),data .LDA equ 03ah ; LD A,(adr) .MOV equ 040h ; LD r1,r2 .HALT equ 076h ; HALT .RETc equ 0c0h ; RET CC .JPc equ 0c2h ; JP CC .CALLc equ 0c4h ; CALL CC .RET equ 0c9h ; RET .OUT equ 0d3h ; OUT .IN equ 0dbh ; IN .XTHL equ 0e3h ; EX (SP),HL .PCHL equ 0e9h ; JP (HL) .XCHG equ 0ebh ; EX DE,HL .SPHL equ 0f9h ; LD SP,HL ; ; ED prefixed code ; ..IN equ 040h ..OUT equ 041h .SBC equ 042h .LD.adr equ 043h .LDIA equ 047h .LD.rp equ 04bh .LDAI equ 057h ; ; Pseudo code control bits ; _cond equ 1000b ; Condition bit _endc equ 0100b ; End of condition bit _macro equ 0010b ; Macro bit _endm equ 0001b ; End macro bit ; ..else equ 08h ; Pseudocode ELSE ..equ equ 0dh ; Pseudocode EQU ..ext equ 0fh ; Pseudocode EXT ..extrn equ 10h ; Pseudocode EXTRN ..local equ 1bh ; Pseudocode LOCAL ..macro equ 1ch ; Pseudocode MACRO ..?set equ 22h ; Pseudocode SET, ASET, DEFL b_DEF equ 7 b_PUB equ 6 b_KNOW equ 5 b_INT equ 4 b_COMM equ 2 _DEF equ 1 SHL b_DEF _PUB equ 1 SHL b_PUB _KNOW equ 1 SHL b_KNOW _INT equ 1 SHL b_INT _COMM equ 1 SHL b_COMM _ErrBit equ 4 ; Error indicator ErrBit equ 1 SHL _ErrBit NoGlbl equ _KNOW $ADR$ equ 2 ; Where ADDRESS goes in output line $CODE$ equ $ADR$+8 ; Where CODE goes in output line $NUM$ equ $CODE$+8 $INCL$ equ $NUM$+7 ; Where 'C' goes in output line $MAC$ equ $INCL$+1 ; Where '+C' goes in output line defRAD equ 10 defPAG equ 59 ; ; Function codes ; .Number equ 1 .LftPar equ 2 .RgtPar equ 3 .LE equ 4 .TYPE equ 5 .NUL equ 6 .HIGH equ 7 .PLUS equ 8 .MINUS equ 9 .MULT equ 10 .DIV equ 11 .LOW equ 12 .GE equ 13 .GT equ 14 .LT equ 15 .NE equ 16 .EQ equ 17 .OR equ 18 .SHR equ 19 .SHL equ 20 .MOD equ 21 .NOT equ 22 .XOR equ 30 .AND equ -1 ; Chn.Len equ 'Z'-'A'+8 LinLen equ 64 ; ; Address modes ; @@mod equ 11b ; Two bits ; @@cs equ 01b ; CSEG @@ds equ 10b ; DSEG @@com equ 11b ; COMMON ; $ext equ '*' $cs equ '''' $ds equ '"' $com equ '!' ; ; 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 _ds equ 2 MEMPAGE equ 256 l0006 equ 06h _ORI macro db 0f6h endm _LDBC macro db 001h endm _LDDE macro db 011h endm _LDAI macro db 03eh endm _JPNZ macro db 0c2h endm _JPZ macro db 0cah endm _JPC macro db 0dah endm l0000 equ 00h l0004 equ 04h l0005 equ 05h l0008 equ 08h l0010 equ 10h l0020 equ 20h l0100: ld hl,l010a ; Set entry address jp l470c ; Parse command line ; l0106: db 'MAC',null ; ; Start M80 ; ENTRY Reg HL holds available top of memory ; Accu holds number of pages for extra stack (P option) ; l010a: ld (l4027),hl ; Save top of memory inc a ; Fix stack pages cpl ld d,a ld e,0 add hl,de ; Calculate new top of memory ld (l4029),hl ; Save it xor a ld bc,l4027-l3cec ; Calculate length ld hl,l3cec ld e,a l011e: ld (hl),e ; Init data area inc hl dec bc ld a,b or c jp nz,l011e ld hl,l4f35 ld (l3d41),hl ; Set up symbol table base ld (hl),a ; Clear 1st entry inc h ; Let some pages inc h inc h inc h ld (l401d),hl ; Init top ld bc,32 add hl,bc ; Fix address ld (l401f),hl ld hl,-relbits*256 ld (l3ec3),hl ; Set .REL bit count and byte ; ; Move register (pairs) and condition codes to symbol table ; ld hl,l402b ; Point to regs and condition codes l0144: ld de,l3de9 ld a,(hl) ; Get from table or a ; Test end jp z,l0176 ; Yeap, start assembly push af and LenMask ; Strip off index ld (de),a ; Set length ld c,a l0151: inc hl inc de ld a,(hl) ; Unpack code ld (de),a dec c jp nz,l0151 push hl call l0cfc ; Put into symbol table pop de pop af and not LenMask ; Extract code ld (hl),a ; Save it inc hl inc de ld a,(de) inc de ld (hl),' ' ; Set delimiter inc hl ld (hl),a ; Set bit combination ex de,hl jp l0144 ; ; Enter pass 2 ; l016e: call l4b84 ; Re-Init source file ld a,1 ld (l3cec),a ; Set second pass ; ; Enter pass 1 ; l0176: xor a ld (l4006),a ld (l3e81),a ; Disable subtitle ld (l3d2d),a ; Enable cross reference (.CREF) ld (l3cf3),a ; Clear IF level 1 ld (l3cf4),a ; Clear IF level 2 ld (l3de8),a ld (l3cf5),a ld (l3ffa),a ; Clear macro active ld (l3de4),a ; Clear phase flag ld hl,l3dd2 ld b,l3ddc-l3dd2 l0197: ld (hl),a ; Init field inc hl dec b jp nz,l0197 inc a ld (l3d28),a ld (l3d2e),a ; Enable generated macros (.XALL) ld (l3d2f),a ; Enable list (.LIST) ld (l3dd1),a ; Set ASEG for code flag ld a,defRAD ld (l3cf1),a ; Init radix ld a,(l4088) ; Get /I option ld (l3cea),a ; Set for CPU type ld a,(l408d) ; Get /X option ld (l3d2a),a ; Save as condition flag ld a,defPAG ld (l3d33),a ; Set page count inc a ld (l3d32),a ; Init page length ld hl,1 ld (l3d34),hl ; Init page number dec hl ld (l4016),hl ; Set 0 dec hl ld (l3d36),hl ; Init page to -1 ld hl,(l4027) ; Get stack ld sp,hl ld hl,l02cc ; Set direction push hl ld hl,l0236 push hl ; ; ***** M80 Main loop ***** ; l01de: xor a ld (l3f5b),a ; Init .PRN device ld (l3d31),a ld (l3d2b),a ; Set no empty line ld (l3d39),a ; Set no line number ld (l3ffb),a inc a ld (l3d29),a call l043f ; Init line pop hl ; Get last caller push hl ld bc,l01fc push bc ; Set return jp (hl) ; Proceed last caller ; ; Start the scanner ; l01fc: ld hl,l3d48 ; Init source line ld (l3d46),hl ld bc,256*(SrcLen+2)+ff l0205: ld a,(hl) cp c ; Find formfeed call z,l021d ; Process it inc hl cp cr ; Maybe end of line jp z,l0214 dec b jp nz,l0205 l0214: pop bc ; Get old two level caller pop hl push hl push bc ld bc,l0452 push bc ; Set retutn jp (hl) ; Execute last caller ; ; Process formfeed ; l021d: push af push hl ld hl,(l3d34) inc hl ; Advance page number ld (l3d34),hl ld hl,-1 ld (l3d36),hl ; Reset page flag ld a,(l3d32) ; Get page length dec a ld (l3d33),a ; Set page count pop hl pop af ret ; ; Fill line ; ; FIND SOME MYSTERIOUS DUE TO HIGH BIT OF CHARACTER SET ; (MAYBE LINE NUMBER INPUT) ; l0236: ld hl,l3d39 ; Init digit pointer ld a,1 ld (l4010),a ld (l400f),a ld c,DigLen ; Init possible line number length l0243: call l0296 ; Get from file cp lf ; Test new line jp z,l0243 ; Yeap, try next call l02c6 ; Test form feed jp z,l0243 ; Yeap, try next or a ; Test hi bit jp p,l026c ; Not set ; ; HI ON ; and NoMSB ; Mask bit inc c ; Test room in line dec c jp z,l0243 ; Nop, skip next call l02c6 ; Test form feed jp z,l0243 ; Yeap, ignore it cp '0' ; Test number jp c,l0243 ; Nope ld (hl),a ; Save number inc hl jp l0243 ; ; HI OFF ; l026c: ld c,SrcLen+1 ld hl,l3d48 l0271: cp lf ; Test new line jp z,l028e ; Yeap, get next dec c ; Test room in line inc c jp z,l027e ; Nope, skip next ld (hl),a ; Unpack character inc hl dec c l027e: cp cr ; Test end of line jp nz,l028e ld (hl),a ; Unpack it ld a,(l3d39) ; Test line number or a ret z ; Nope dec a ld (l3d38),a ; Set number flag ret l028e: call l0296 ; Get character and NoMSB ; Less bit jp l0271 ; ; Get character from selected source file ; EXIT Accu holds character ; Carry set on end of file ; (Fall in error if so) ; l0296: ld a,(l3d2c) ; Test selection or a jp z,l02a8 ; Get from source file call l4ef4 ; Read character from include file ret nc ; Ok xor a ld (l3d2c),a ; Clear include flag call l4f34 ; Close include file l02a8: call l4d04 ; Read character from source file jp c,l02af ; End of file ret l02af: ld hl,l0500 call l46cc ; Tell no END statement ld a,cr ld (l3d48),a ; Close line call l4aee ; Also on console ld a,lf call l4aee scf jp l2db2 ; Process real end ; ; Test character a form feed ; l02c6: cp ff ; Test it ret nz ; Nope jp l021d ; Process form feed ; ; Scan current line ; l02cc: ld hl,0 ld (l3d43),hl ; Clear pointer xor a ld (l3d30),a dec a ld (l3ffb),a ld hl,(l3dda) ; Get COMMON size ld (l3dde),hl ; Set value ld a,(l3d48) cp '*' ; Test special prefix jp nz,l02ed ; Nope ld a,'$' ld (l3d48),a ; Change it l02ed: sub '$' ld (l3d45),a ; Set flag call l0b55 ; Get substring jp nz,l040d cp ':' ; Test label jp z,l038b ld a,(l3d45) ; Test special prefix or a jp nz,l0324 ld a,(l3de9) ; Get length dec a jp nz,l0324 call l0b55 ; Get substring ld b,LabLen+2 ld hl,l3de9 ld a,(hl) ; Get length cp b jp nc,l0319 inc (hl) l0319: inc hl ld a,'$' l031c: ld c,(hl) ; Get current ld (hl),a ; Store new ld a,c ; Swap inc hl dec b jp nz,l031c l0324: ld hl,(l3d46) dec hl ; Get previous line pointer ld a,(hl) ; Get character inc hl cp cr ; Test end of line jp z,l03bf push hl call l042b ; Swap operands call l0b55 ; Get next item call l0515 ; Decode statement jp nz,l0381 ; Not found ld a,(hl) ; Get desriptor or a jp p,l0381 ; Normal code inc hl ld a,(hl) ; Get code cp ..?set ; Test ASET, DEFL or SET jp z,l0352 cp ..macro ; Test MACRO jp z,l0352 cp ..equ ; Test EQU jp nz,l0381 l0352: pop hl ; Clean stack ld hl,(l3d46) dec hl ; Adjust line pointer ld (l3d46),hl push af ; Save code ld a,(l3d28) or a jp z,l046b call l042b ; Swap operands pop af ; Get back code push af cp ..macro ; Skip MACRO jp z,l0373 or a call l0cfc ; Put EQU/SET to symbol table call l2d15 l0373: pop af ; Get back code again cp ..?set ; Test any SET jp z,l2d78 cp ..macro ; Test MACRO jp z,l37af jp l2d44 ; Process EQU l0381: pop hl ; Get back pointer ld (l3d46),hl ; Save line pointer call l042b ; Swap operands jp l03bf l038b: ld a,(l3d28) or a jp z,l03b9 call l1b31 call l0cfc ; Put into symbol table call l2d15 ld (l3d43),hl ; Set current pointer ex de,hl call l1b6a ex de,hl or NoGlbl ; Set known push af call l0b23 ; Get current character cp ':' ; Test label jp nz,l03b5 ; Nope, EQU or other pop af or _PUB ; Force PUBLIC push af call l0aea ; Check character l03b5: pop af call l0ddb l03b9: call l0b55 ; Get substring jp nz,l040d l03bf: call l0b36 ; Get previous pointer ld a,(l3d28) or a jp z,l03cf call l0c0e jp z,l3892 l03cf: call l0515 ; Decode statement jp nz,l040d ; Not found or a push af ; Save code ld a,(l3d28) or a jp nz,l03e8 pop af ; Get back code jp p,l046c ; Normal statement push af and (_cond + _endc) shl 3 jp z,l046b ; No conditional l03e8: pop af jp p,l03fb ; Skip if normal statement inc hl ld a,(hl) ; Get index ld hl,l0a06 ; Into pseudo code table l03f1: add a,a ; Double index ld e,a ld d,0 add hl,de ; Point into table ld e,(hl) ; Get address inc hl ld d,(hl) ex de,hl jp (hl) ; Execute from table l03fb: rra ; Extract index rra rra and LoMask ; Mask them inc hl ld c,(hl) ; Get opcode push af call l1b31 ld hl,l09e8 ; Point to mnemonic table pop af jp l03f1 ; Execute code l040d: cp ';' ; Test comment ret z cp cr ; Test end of line ret z ld hl,l3d48 ; Init source line ld (l3d46),hl ld hl,(l3d43) ; Get pointer ld a,h ; Test NIL or l call nz,l0b55 ; Get substring if empty ld a,(l3d28) or a jp z,l046c jp l278d ; Treat as constant byte ; ; Swap sampled operands ; l042b: ld hl,l3de9 ; Set buffers ld de,l3dfc ld b,LabLen+3 l0433: ld c,(hl) ; Get actual one ld a,(de) ; Get old one ld (hl),a ; Save into actual place ld a,c ld (de),a ; Save into old place inc hl inc de dec b jp nz,l0433 ret ; ; Init output line ; l043f: ld hl,l3e11+$CODE$ ld (l3e0f),hl ; Set line code pointer ld hl,l3e11 ld bc,prf.lin*256+' ' l044b: ld (hl),c ; Blank line inc hl dec b jp nz,l044b ret ; ; Test legal start of line ; l0452: call l0b36 ; Get previous pointer l0455: call l0bc8 ; Skip white spaces or a jp z,l0455 l045c: push hl cp cr ; Test end of line jp z,l046c cp ';' ; Test comment jp z,l046c call l04cd ; Error if neither push af l046b: pop af l046c: pop hl ld a,(l3cec) ; Get pass or a jp nz,l0497 ; Got pass 2 ld a,(l3e11) ; Filter errors cp 'V' ; Value error jp z,l048b cp 'M' ; Multiple definition jp z,l048b cp 'D' ; Double definition jp z,l048b cp 'X' ; Invalid macro exit jp nz,l01de l048b: ld (l3f5b),a ; Set console device call l1b16 ; Fix error count call l197e jp l01de l0497: call l192b jp l01de ; ; ***** ERROR handler ***** ; l049d: push bc ld b,'A' jp l04e8 ; Argument error l04a3: push bc ld b,'C' jp l04e8 ; Conditional nesting error l04a9: push bc ld b,'D' jp l04e8 ; Double-defined error l04af: push bc ld b,'E' jp l04e8 ; External error l04b5: push bc ld b,'M' jp l04e8 ; Multiply-defined error l04bb: push bc ld b,'N' jp l04e8 ; Number error l04c1: push bc ld b,'O' jp l04e8 ; Bad opcode or objectionable syntax l04c7: push bc ld b,'P' jp l04e8 ; Phase error l04cd: push bc ld b,'Q' jp l04e8 ; Questionable l04d3: push bc ld b,'R' jp l04e8 ; Relocation l04d9: push bc ld b,'U' jp l04e8 ; Undefined symbol l04df: push bc ld b,'V' jp l04e8 ; Value error l04e5: push bc ld b,'X' ; Error on special link item l04e8: push hl push af ld hl,l3e11 ld a,(hl) cp ' ' ; Test error already set jp nz,l04fc ; Skip if so ld (hl),b ; Set error code ld a,(l3ed4) or ErrBit ; Set error bit ld (l3ed4),a l04fc: pop af pop hl pop bc ret ; l0500: db '%No END statement',null ; ; Pseudocode ASET, DEFL, SET, EQU, MACRO, .PASS2 ; l0512: jp l04c1 ; Bad opcode or objectionable syntax ; ; Decode statement ; EXIT Zero flag set if statement found ; Accu holds code of statement descriptor ; Reg HL points to statement descriptor ; l0515: ld a,(l3de9+1) ; Get character cp '.' ; Test pseudo opcode jp z,l058a ; Try it cp '$' ; Test special control jp z,l0592 ; Try it cp 'Z'+1 ; Test legal letter range inc a ret nc ; Nope sub 'A'+1 ; Strip off offset or a ret m ; Invalid range add a,a ; Build index push bc push de ld e,a ld d,0 ld hl,l0598 add hl,de ; Get pointer into table ld e,(hl) ; Fetch address inc hl ld d,(hl) ex de,hl ; ; Common decode loop ; l0538: ld a,(l3de9) ; Get length dec a ld c,a l053d: ld a,(hl) ; Get from table or a ; Test end of table jp z,l0586 ; Yeap, not found or a ; Test CPU jp m,l055b ld a,(l3cea) ; Get CPU type add a,a ld a,(hl) jp nz,l0556 ; Got INTEL cp Z80.cod ; Test Z80 code fond jp nc,l055b jp l057a l0556: cp Z80.cod ; Verify Z80 code jp nc,l057a l055b: and LenMask ; Mask length cp c ; Check against requested jp nz,l057a ; Not same ld de,l3de9+2 push hl ld b,c inc hl inc hl l0568: ld a,(de) cp (hl) ; Compare jp nz,l0579 ; No match inc hl inc de dec b jp nz,l0568 ; Loop on pop hl xor a ; Set success ld a,(hl) ; Get descriptor pop de pop bc ret l0579: pop hl l057a: ld a,(hl) ; Get descriptor and LenMask ; Isolate length add a,2 ; Fix for control ld e,a ; Build index ld d,0 add hl,de ; Point to next entry jp l053d l0586: pop de pop de inc a ; Not found, indicate it ret ; ; Found pseudo opcodes starting with '.' ; l058a: ld hl,l0948 ; Point to table l058d: push bc push de jp l0538 ; Get special code ; ; Found pseudo opcodes starting with '$' ; l0592: ld hl,l09d0 ; Point to table jp l058d ; ; Indices to menemonic table ; Each address represents a letter A..Z ; l0598: dw l05cc dw l05fb dw l0605 dw l066a dw l06b8 dw l0702 dw l0703 dw l070b dw l0715 dw l0787 dw l07ae dw l07af dw l07dd dw l07f3 dw l0805 dw l0831 dw l0855 dw l0856 dw l08d2 dw l0925 dw l092c dw l092d dw l092e dw l092f dw l0946 dw l0947 ; ; Macro building following mnemonic entry ; ; TYPE 0=normal, 1=special ; IDX Table index ; VAL 2nd byte (Index for Z80, code for 8080 -- mostly) ; STRING Mnemonic string ; code macro type,idx,val,string local part,len sys aset type shl 7 shf aset idx shl 3 part: db sys+shf+len,val,string len aset $-part-2 endm endcode macro db null endm ; ; Code tables ; Contains of ; Byte 0 : Statement descriptor ; Byte 1 : Index or code ; Byte 2..n : ASCII representation of statement ; ; The descriptor bits are coded as follows: ; pcccclll, with ; p indicates pseudo opcode ; cccc index into statement code table ; lll length of ASCII presentation ; ; Normal statements: ; cccc = 0.. 9 : 8080 code ; cccc = 10..14 : Z80 code ; Pseudo statements: ; 1000 Conditional ; 0100 End Conditional ; 0010 Macro ; 0001 End Macro ; l05cc: code 0, 5,0ceh,'CI' code 0, 3,088h,'DC' code 0,10,000h,'DC' code 0, 3,080h,'DD' code 0,10,002h,'DD' code 0, 5,0c6h,'DI' code 0, 3,0a0h,'NA' code 0,10,004h,'ND' code 0, 5,0e6h,'NI' code 1, 0,000h,'SEG' code 1, 0,022h,'SET' endcode l05fb: code 0,11,006h,'IT' code 1, 0,03eh,'YTE' endcode l0605: code 0, 6,0cdh,'ALL' code 0,10,008h,'ALL' code 0, 6,0dch,'C' code 0,13,03fh,'CF' code 0, 6,0fch,'M' code 0, 0,02fh,'MA' code 0, 0,03fh,'MC' code 0, 3,0b8h,'MP' code 0, 6,0d4h,'NC' code 0, 6,0c4h,'NZ' code 1, 0,001h,'OMMON' code 1, 8,014h,'OND' code 0, 6,0f4h,'P' code 0,10,00ah,'P' code 0,14,0a9h,'PD' code 0,14,0b9h,'PDR' code 0, 6,0ech,'PE' code 0, 5,0feh,'PI' code 0,14,0a1h,'PI' code 0,14,0b1h,'PIR' code 0,13,02fh,'PL' code 0, 6,0e4h,'PO' code 1, 0,002h,'SEG' code 0, 6,0cch,'Z' endcode l066a: code 0, 0,027h,'AA' code 0,13,027h,'AA' code 0, 2,009h,'AD' code 1, 0,003h,'B' code 1, 0,004h,'C' code 0, 4,005h,'CR' code 0, 2,00bh,'CX' code 0,10,00ch,'EC' code 1, 0,003h,'EFB' code 1, 0,022h,'EFL' code 1, 0,003h,'EFM' code 1, 0,005h,'EFS' code 1, 0,007h,'EFW' code 0, 0,0f3h,'I' code 0,13,0f3h,'I' code 0,10,00eh,'JNZ' code 1, 0,005h,'S' code 1, 0,006h,'SEG' code 1, 0,007h,'W' endcode l06b8: code 0, 0,0fbh,'I' code 0,13,0fbh,'I' code 1, 8,008h,'LSE' code 1, 0,009h,'ND' code 1, 4,00ah,'NDC' code 1, 4,00ah,'NDIF' code 1, 1,00bh,'NDM' code 1, 0,00ch,'NTRY' code 1, 0,00dh,'QU' code 0,10,010h,'X' code 0,13,0d9h,'XX' code 1, 0,00eh,'XITM' code 1, 0,00fh,'XT' code 1, 0,00fh,'XTERNAL' code 1, 0,010h,'XTRN' endcode l0702: endcode l0703: code 1, 0,020h,'LOBAL' endcode l070b: code 0,13,076h,'ALT' code 0, 0,076h,'LT' endcode l0715: code 1, 8,011h,'F' code 1, 8,032h,'FB' code 1, 8,039h,'FDIF' code 1, 8,012h,'FE' code 1, 8,013h,'FF' code 1, 8,03ah,'FIDN' code 1, 8,033h,'FNB' code 1, 8,014h,'FT' code 0,12,012h,'M' code 0, 5,0dbh,'N' code 0,10,014h,'N' code 0,10,016h,'NC' code 1, 0,038h,'NCLUDE' code 0,14,0aah,'ND' code 0,14,0bah,'NDR' code 0,14,0a2h,'NI' code 0,14,0b2h,'NIR' code 0, 4,004h,'NR' code 0, 2,003h,'NX' code 1, 8,015h,'F1' code 1, 8,016h,'F2' code 1, 8,017h,'FDEF' code 1, 8,018h,'FNDEF' code 1, 2,019h,'RP' code 1, 2,01ah,'RPC' endcode l0787: code 0, 6,0dah,'C' code 0, 6,0fah,'M' code 0, 6,0c3h,'MP' code 0, 6,0d2h,'NC' code 0, 6,0c2h,'NZ' code 0, 6,0f2h,'P' code 0,10,018h,'P' code 0, 6,0eah,'PE' code 0, 6,0e2h,'PO' code 0,10,01ah,'R' code 0, 6,0cah,'Z' endcode l07ae: endcode l07af: code 0,10,01ch,'D' code 0, 6,03ah,'DA' code 0, 1,00ah,'DAX' code 0,14,00a8h,'DD' code 0,14,0b8h,'DDR' code 0,14,0a0h,'DI' code 0,14,0b0h,'DIR' code 0, 6,02ah,'HLD' code 1, 0,01bh,'OCAL' code 0, 9,001h,'XI' endcode l07dd: code 1, 0,038h,'ACLIB' code 1, 2,01ch,'ACRO' code 0, 7,040h,'OV' code 0, 8,006h,'VI' endcode l07f3: code 1, 0,01dh,'AME' code 0,14,044h,'EG' code 0, 0,000h,'OP' code 0,13,000h,'OP' endcode l0805: code 0,10,01eh,'R' code 0, 3,0b0h,'RA' code 1, 0,01eh,'RG' code 0, 5,0f6h,'RI' code 0,14,0bbh,'TDR' code 0,14,0b3h,'TIR' code 0, 5,0d3h,'UT' code 0,10,020h,'UT' code 0,14,0abh,'UTD' code 0,14,0a3h,'UTI' endcode l0831: code 1, 0,01fh,'AGE' code 0, 0,0e9h,'CHL' code 0, 2,0c1h,'OP' code 0,10,022h,'OP' code 1, 0,020h,'UBLIC' code 0, 2,0c5h,'USH' code 0,10,024h,'USH' endcode l0855: endcode l0856: code 0, 0,017h,'AL' code 0, 0,01fh,'AR' code 0, 0,0d8h,'C' code 1, 2,021h,'EPT' code 0,11,026h,'ES' code 0, 0,0c9h,'ET' code 0,10,028h,'ET' code 0,14,04dh,'ETI' code 0,14,045h,'ETN' code 0, 0,020h,'IM' code 0,11,02ah,'L' code 0,13,017h,'LA' code 0, 0,007h,'LC' code 0,11,02ch,'LC' code 0,13,007h,'LCA' code 0,14,06fh,'LD' code 0, 0,0f8h,'M' code 0, 0,0d0h,'NC' code 0, 0,0c0h,'NZ' code 0, 0,0f0h,'P' code 0, 0,0e8h,'PE' code 0, 0,0e0h,'PO' code 0,11,02eh,'R' code 0,13,01fh,'RA' code 0, 0,00fh,'RC' code 0,11,030h,'RC' code 0,13,00fh,'RCA' code 0,14,067h,'RD' code 0, 4,0c7h,'ST' code 0,10,032h,'ST' code 0, 0,0c8h,'Z' endcode l08d2: code 0, 3,098h,'BB' code 0, 5,0deh,'BI' code 0,10,034h,'BC' code 0,13,037h,'CF' code 0,11,036h,'ET' code 1, 0,022h,'ET' code 0, 6,022h,'HLD' code 0, 0,030h,'IM' code 0,11,038h,'LA' code 0, 0,0f9h,'PHL' code 0,11,03ah,'RA' code 0,11,03ch,'RL' code 0, 6,032h,'TA' code 0, 1,002h,'TAX' code 0, 0,037h,'TC' code 0, 3,090h,'UB' code 0,10,03eh,'UB' code 1, 0,023h,'UBTTL' code 0, 5,0d6h,'UI' endcode l0925: code 1, 0,024h,'ITLE' endcode l092c: endcode l092d: endcode l092e: endcode l092f: code 0, 0,0ebh,'CHG' code 0,10,040h,'OR' code 0, 3,0a8h,'RA' code 0, 5,0eeh,'RI' code 0, 0,0e3h,'THL' endcode l0946: endcode l0947: endcode ; ; Pseudo opcodes starting with '.' ; l0948: code 1,0,036h,'8080' code 1,0,037h,'Z80' code 1,0,025h,'COMMENT' code 1,0,026h,'CREF' code 1,0,027h,'DEPHASE' code 1,0,028h,'LALL' code 1,0,03bh,'LFCOND' code 1,0,029h,'LIST' code 1,0,02ah,'PASS2' code 1,0,02bh,'PHASE' code 1,0,02ch,'PRINTX' code 1,0,02dh,'RADIX' code 1,0,035h,'REQUEST' code 1,0,02eh,'SALL' code 1,0,03ch,'SFCOND' code 1,0,03dh,'TFCOND' code 1,0,02fh,'XALL' code 1,0,030h,'XCREF' code 1,0,031h,'XLIST' endcode ; ; Pseudo opcodes starting with '$' ; l09d0: code 1,0,01fh,'EJECT' code 1,0,038h,'INCLUDE' code 1,0,034h,'TITLE' endcode ; ; Part 1 : 8080 code - Index 0..9 ; l09e8: dw l0e79 ; 0 dw l0e80 ; 1 dw l0e8f ; 2 dw l0e9e ; 3 dw l0eaa ; 4 dw l0eb9 ; 5 dw l0ec7 ; 6 dw l0ed3 ; 7 dw l0ef4 ; 8 dw l0f10 ; 9 ; ; Part 2 : Z80 code - Index 10..14 ; Z80.cod equ (($-l09e8) /2) shl 3 dw l0f68 ; 10 dw l0f6b ; 11 dw l0f6e ; 12 dw l0e79 ; 13 dw l0e74 ; 14 ; ; Pseudo code table ; l0a06: ; hex code ; ========= dw l26ef ; 00 : ASEG dw l2c8e ; 01 : COMMON, LOCAL dw l2708 ; 02 : CSEG dw l278d ; 03 : DB, DEFB, DEFM dw l283e ; 04 : DC dw l2883 ; 05 : DS, DEFS dw l271d ; 06 : DSEG dw l28d7 ; 07 : DW, DEFW dw l2916 ; 08 : ELSE dw l2db2 ; 09 : END dw l28ea ; 0a : ENDIF, ENDC dw l3528 ; 0b : ENDM dw l2a89 ; 0c : ENTRY dw l04c1 ; 0d : EQU dw l350e ; 0e : EXITM dw l2cdd ; 0f : EXT, EXTERNAL dw l2cdd ; 10 : EXTRN dw l297f ; 11 : IF dw l2987 ; 12 : IFE dw l2987 ; 13 : IFF dw l297f ; 14 : COND dw l2994 ; 15 : IF1 dw l299e ; 16 : IF2 dw l29a8 ; 17 : IFDEF dw l29a9 ; 18 : IFNDEF dw l3668 ; 19 : IRP dw l3666 ; 1a : IRPC dw l3528 ; 1b : LOCAL dw l04c1 ; 1c : MACRO dw l2c43 ; 1d : NAME dw l267e ; 1e : ORG dw l2bbe ; 1f : $EJECT, PAGE dw l2a89 ; 20 : PUBLIC, GLOBAL dw l3441 ; 21 : REPT dw l04c1 ; 22 : ASET, DEFL, SET dw l2abe ; 23 : SUBTTL dw l2ab5 ; 24 : TITLE dw l3769 ; 25 : .COMMENT dw l2b1a ; 26 : .CREF dw l3986 ; 27 : .DEPHASE dw l2b4d ; 28 : .LALL dw l2b0b ; 29 : .LIST dw l0512 ; 2a : .PASS2 dw l395b ; 2b : .PHASE dw l373b ; 2c : .PRINTX dw l2b92 ; 2d : .RADIX dw l2b55 ; 2e : .SALL dw l2b5c ; 2f : .XALL dw l2b21 ; 30 : .XCREF dw l2b13 ; 31 : XLIST dw l29e3 ; 32 : IFB dw l29e4 ; 33 : IFNB dw l2ae9 ; 34 : $TITLE dw l2bea ; 35 : .REQUEST dw l2b83 ; 36 : .8080 dw l2b8b ; 37 : .Z80 dw l2c16 ; 38 : $INCLUDE, MACLIB dw l29f8 ; 39 : IFDIF dw l29f7 ; 3a : IFIDN dw l2b64 ; 3b : .LFCOND dw l2b68 ; 3c : .SFCOND dw l2b6d ; 3d : .TFCOND dw l2d27 ; 3e : BYTE ; ; Z80 code table ; Byte 1 holds index to execution table ; Byte 2 holds opcode of instruction ; l0a84: db 4,088h ; 0 : ADC db 6,080h ; 2 : ADD db 0,0a0h ; 4 : AND db 2,040h ; 6 : BIT db 12,0cdh ; 8 : CALL db 0,0b8h ; 10 : CP db 8,005h ; 12 : DEC db 22,010h ; 14 : DJNZ db 30,000h ; 16 : EX db 10,046h ; 18 : IM db 26,000h ; 20 : IN db 8,004h ; 22 : INC db 16,0c3h ; 24 : JP db 18,018h ; 26 : JR db 34,000h ; 28 : LD db 0,0b0h ; 30 : OR db 28,000h ; 32 : OUT db 32,0c1h ; 34 : POP db 32,0c5h ; 36 : PUSH db 2,080h ; 38 : RES db 14,000h ; 40 : RET db 20,010h ; 42 : RL db 20,000h ; 44 : RLC db 20,018h ; 46 : RR db 20,008h ; 48 : RRC db 24,0c7h ; 50 : RST db 4,098h ; 52 : SBC db 2,0c0h ; 54 : SET db 20,020h ; 56 : SLA db 20,028h ; 58 : SRA db 20,038h ; 60 : SRL db 0,090h ; 62 : SUB db 0,0a8h ; 64 : XOR ; ; Z80 code execution table ; l0ac6: dw l1335 ; 0 : AND, CP, OR, SUB, XOR dw l1284 ; 2 : BIT, RES, SET dw l1376 ; 4 : ADC, SBC dw l13bf ; 6 : ADD dw l12e9 ; 8 : DEC, INC dw l0f83 ; 10 : IM dw l1043 ; 12 : CALL dw l0fcd ; 14 : RET dw l1064 ; 16 : JP dw l1090 ; 18 : JR dw l1298 ; 20 : RL, RLC, RR, RRC, ; SLA, SRA, SRL dw l1101 ; 22 : DJNZ dw l0fa3 ; 24 : RST dw l11cf ; 26 : IN dw l117d ; 28 : OUT dw l1212 ; 30 : EX dw l0fb5 ; 32 : POP, PUSH dw l1420 ; 34 : LD ; ; Check character in current line position ; EXIT Accu holds character ; Sign set indicates non alpha-numeric character ; If sign reset: Zero set indicates alpha character ; Zero reset indicates number ; l0aea: push hl l0aeb: ld hl,(l3d46) ; Get line pointer ld a,(hl) ; Load character inc hl ld (l3d46),hl cp ff ; Ignore form feed jp z,l0aeb ld l,a cp 'A' ; Test letter jp nc,l0b10 cp '0' ; Test digit jp c,l0b08 cp '9'+1 jp c,l0b0d l0b08: scf sbc a,a ; Calculate sign set, not zero ld a,l pop hl ret l0b0d: or a ; No sign, not zero pop hl ret l0b10: cp 'Z'+1 ; Verify letter jp c,l0b1f cp 'a' ; Look for lower case, too jp c,l0b08 cp 'z'+1 jp nc,l0b08 l0b1f: xor a ; No sign, zero ld a,l pop hl ret ; ; Get character ; EXIT Accu holds character ; l0b23: call l0aea ; Check character jp l0b36 ; Get previous pointer ; ; Get character, verify NO EOL ; EXIT Accu holds character ; l0b29: call l0aea ; Check character push af cp cr ; Verify not end of line jp nz,l18c7 call l04c1 ; Bad opcode or objectionable syntax pop af ; ; Get predictor of current line pointer ; l0b36: push hl ld hl,(l3d46) dec hl ; Decrement ld (l3d46),hl pop hl ret ; ; Get successor of current line pointer ; l0b40: ld hl,(l3d46) inc hl ; Increment ld (l3d46),hl ret ; ; Get UPPER case letter ; EXIT Accu holds character in UPPER case ; Sign set indicates non alpha-numeric character ; If sign reset: Zero set indicates alpha character ; Zero reset indicates number ; l0b48: call l0aea ; Check character ret nz ; Got a number cp 'a' ; Test lowr case jp c,l0b53 sub 'a'-'A' l0b53: cp a ; Reset sign, set zero ret ; ; Sample ASCII operand ; l0b55: call l0bc8 ; Skip white spaces call l0b36 ; Get previous pointer ld hl,l3de9+1 ld bc,256*(LabLen+2)+' ' l0b61: ld (hl),c ; Blank buffer inc hl dec b jp nz,l0b61 ld hl,l3de9 ld (hl),0 ; Clear length inc hl call l0bb1 ; Check legal label call nz,l0c02 ; Exit if not ld (l3ce6),a ; Save character ld c,0 ; Clear counter l0b78: cp 'a' ; Test range jp c,l0b7f sub 'a'-'A' ; Convert to upper case l0b7f: ld (hl),a ; Bring back character inc hl inc c ; Count up ld a,c cp LabLen+2 ; Test buffer filled jp z,l0b9f ; Truncate on overflow call l0bb1 ; Check legal label jp p,l0b78 ; Yeap call l0bda jp nc,l0b97 jp p,l0b78 l0b97: ld b,a ; Save character ld a,c ld (l3de9),a ; Store length xor a ; Set success ld a,b ; Get back character ret l0b9f: call l0bb1 ; Check legal label jp p,l0b9f ; Loop till end call l0bda jp nc,l0b97 jp p,l0b9f jp l0b97 ; ; Test legal label ; EXIT Accu holds character ; Sign reset indicates character alpha-numeric ; Sign set indicates any other character type ; Zero set indicates other legal character ; l0bb1: call l0aea ; Check character ret p ; Got alpha-numeric cp '$' ; Check some characters ret z cp '.' ret z cp '@' ret z cp '?' ret z cp '_' ret z cpl or a cpl ret ; ; Skip white space (BLANK or TAB) ; EXIT Accu holds character ; Sign reset indicates character alpha-numeric ; Sign set indicates any other character type ; l0bc8: call l0aea ; Check character ret p ; Got alpha-numeric cp ' ' ; Test blank jp z,l0bc8 cp tab ; Test tab jp z,l0bc8 cpl or a cpl ret ; ; ; l0bda:: push af or a jp z,l0be4 cp '&' jp nz,l18c7 l0be4: ld a,(l3ffb) or a jp nz,l0bed pop af ret l0bed: pop af l0bee: call l0bb1 ; Check legal label or a jp z,l0bee cp '&' jp z,l0bee call l0b36 ; Get previous pointer call l0bb1 ; Check legal label scf ret ; ; Test ampersand in label ; EXIT Zero flag set if not ; Return less one level if so ; l0c02: call l0bda jp nc,l0c09 ret z l0c09: pop bc ; Get old caller ld c,0 ; Fix return ld b,a ret ; Return to previous level ; ; ; l0c0e:: ld hl,l3f72 ld a,(l3de9) ; Get length push af call l0c27 ; Get symbol pointer jp z,l0c22 ; Empty pop af ld (l3de9),a ; Reset length or a ld a,(hl) ret l0c22: pop bc ret ; ; Get symbol table pointer ; EXIT Reg HL holds pointer ; Zero flag not set indicates no entry in chain ; l0c24: ld hl,l3fb4 ; Set chain table ; ; Get symbol table pointer ; ENTRY Reg HL holds base chain table address ; EXIT Reg HL holds pointer ; Zero flag not set indicates no entry in chain ; l0c27: call l0cdc ; Get index ld b,0 add hl,bc add hl,bc ld (l3f70),hl ; Save base pointer ld e,(hl) ; Fetch tree address inc hl ld d,(hl) ld hl,l3f67 ; Point to temporary area ld b,ChnLen xor a l0c3a: ld (hl),a ; Clear field inc hl dec b jp nz,l0c3a ld hl,l3de9 ; Point to buffer ld a,(hl) ; Get length cp LabLen ; Test it jp c,l0c4b ld (hl),LabLen ; Truncate on overflow l0c4b: ld hl,l3de9 ld c,(hl) ; Load length dec c l0c50: ld a,d ; Test node grounded or e jp z,l0cbe ; Yeap ex de,hl ld e,(hl) ; Get left node inc hl ld d,(hl) push de inc hl ld e,(hl) ; Get right node inc hl ld d,(hl) push de push hl inc hl ld a,(hl) dec a jp z,l0c79 ld de,l0008 add hl,de ld de,l3de9+2 ld b,a l0c6e: ld a,(de) cp (hl) ; Compare jp nz,l0c8b inc hl inc de dec b jp nz,l0c6e l0c79: pop hl inc hl ld a,(hl) dec a cp c jp nz,l0cb8 inc hl ld (l3d3f),hl ; Save pointer to name field inc hl ld a,(hl) dec hl pop bc pop bc ret l0c8b: ccf sbc a,a and 2 ; Calculate direction pop hl l0c90: push af ex de,hl dec de ; Fix pointer dec de dec de push af push de ld de,l3f6a ld hl,l3f67 ld b,ChnLen-3 l0c9f: ld a,(de) ld (hl),a ; Unpack inc hl inc de dec b jp nz,l0c9f pop de pop af ld (hl),a ; Put into chain inc hl ld (hl),e inc hl ld (hl),d pop af pop hl pop de jp z,l0c50 ; Above zero result ex de,hl ; Swap pointers jp l0c50 l0cb8: dec hl ld a,2 jp l0c90 l0cbe: inc a ; Set non zero ld hl,(l3d41) ; Get symbol table ld a,(hl) ; Get entry - NULL is empty ret ; ; Get current symbol pointer ; EXIT Reg HL holds pointer to type field ; Carry set if zero length ; l0cc4: ld hl,(l401b) ; Get pointer inc hl ; Advance to length inc hl inc hl inc hl ld a,(hl) ; Get length or a scf ret z ; Zero inc hl push hl ; Save pointer add a,11-5 ; Add header ld d,0 ld e,a add hl,de ; Get next pointer ld (l401b),hl pop hl ; Get previous ret ; ; Decode characters ; EXIT Reg C returns index ; l0cdc: ld a,(l3de9+1) ; Get from buffer cp '$' ld c,0 ret z ; $ - 0 cp '.' ld c,1 ret z ; . - 1 cp '?' ld c,2 ret z ; ? - 2 cp '_' ld c,3 ret z ; _ - 3 cp ' ' ld c,4 ret z ; SPACE - 4 sub ';' ld c,a ; Map @..Z -> 5..31 ret ; ; Put symbol into table ; ENTRY Carry flag indicates mode for cross-reference ; EXIT Reg HL points to symbol ; ; Symbol structure: ; ; 0 1 2 3 4 5 6 7 8 ; +-----+-----+-----+-----+-----+-----+-----+-----+-----+ ; | Left Node | Right Node| Len | CC1 | CC2 | Offset | ; +-----+-----+-----+-----+-----+-----+-----+-----+-----+ ; ^ ; +-- Current Symbol pointer ; ; 9 10 11.. ; +-----+-----+--....--+ ; | xxx | xxx | Name | ; +-----+-----+--....--+ ; ; 'x Node' is left or right hook in binary tree ; 'Len' is the length of symbol 'Name' ; 'Offset' is reference of label or COMMON size ; ; 'CC1' is defined as: ; ; 7 6 5 4 3 2 1 0 ; +-----+-----+-----+-----+-----+-----+-----+-----+ ; | Def | Pub | Kno | Int | xxx | xxx | xxx | xxx | ; +-----+-----+-----+-----+-----+-----+-----+-----+ ; ; 'CC2' is defined as: ; ; 7 6 5 4 3 2 1 0 ; +-----+-----+-----+-----+-----+-----+-----+-----+ ; | Def | Pub | Kno | xxx | xxx | Com | Mode | ; +-----+-----+-----+-----+-----+-----+-----+-----+ ; ; 'Def' if defined ; 'Pub' set on PUBLIC ; 'Kno' if known ; 'Int' if M80 internal ; 'Com' on COMMON definition ; 'Mode' address mode bits ; ; Both modes together form the valid entry after pass 1 ; ; For example (less mode bits): ; ; Pass1 Pass2 ; +++++ +++++ ; 00 80 40 80 EXTERN symbol ; 00 20 40 20 Internal COMMON definition ; 00 00 40 00 Unknown symbol ; 80 20 C0 20 EQU definition, internal symbol ; 80 60 C0 60 ENTRY symbol ; 50 20 Internal single register ; 60 20 Internal register pair ; 70 20 Internal condition flag ; l0cfc: push af ; Save flag call l0c24 ; Get symbol table pointer l0d00: ld (l3d3f),hl ; Save address we got pop bc ; Get entry flag push af ; Save new one push bc pop af ; Swap call l0d93 ; Mark into cross-ref pop af ret z ; Return on chain push hl ld hl,(l3f6e) ex de,hl ld a,d or e jp z,l0dce ld a,(l3f6d) ex de,hl ld b,0 ld c,a add hl,bc l0d1e: pop de ; Get back pointer ld (hl),e ; Save into chain inc hl ld (hl),d ex de,hl ld c,4 xor a l0d26: ld (hl),a ; Clear node addresses inc hl dec c jp nz,l0d26 ld de,l3de9 ld a,(de) ; Get length cp LabLen ; Test it jp c,l0d37 ld a,LabLen ; Truncate l0d37: ld (hl),a ; Store length ld b,a inc hl inc de xor a ld (hl),a ; Clear type 1 ld (l3d3f),hl ; Save pointer inc hl ld (hl),a ; Clear type 2 inc hl ld (hl),a ; Clear offset inc hl ld (hl),a inc hl inc hl ; Skip inc hl l0d49: ld a,(de) ld (hl),a ; Unpack name of symbol inc hl inc de dec b jp nz,l0d49 ld (l3d41),hl ; Save new symbol table pointer inc hl inc hl inc hl inc hl ld (hl),b ; Clear length of next ld de,MEMPAGE add hl,de ex de,hl ld hl,(l401d) ; Get top of symbol table call l0d8d ; Test against top call c,l3b00 ; Fix if pointer higher max ld hl,(l3d3f) ; Return pointer ld a,h or a ; Fix flag ld a,0 ; Set return ret ; ; Give symbol table overflow message ; l0d6f: ld hl,l0d78 l0d72: call l46cc ; Give message jp l0100 ; Re-enter ; l0d78: db '?Symbol table full',cr l0d8b: db lf,null ; ; Compare HL against DE ; ENTRY Reg HL and DE hold pointer ; EXIT Carry set if HL 2 cp ')' jp z,l1caf ; ) --> 3 cp '+' jp z,l1cb2 ; + --> 8 cp '-' jp z,l1cb5 ; - --> 9 cp '*' jp z,l1cb8 ; * --> 10 cp '/' jp z,l1cbb ; / --> 11 cp ';' jp z,l1ca8 ; End of ... --> 0 cp ',' jp z,l1ca8 cp cr call nz,l04c1 ; Bad opcode or objectionable syntax l1ca8: xor a jp l1cc0 l1cac: ld a,.LftPar _LDDE l1caf: ld a,.RgtPar _LDDE l1cb2: ld a,.PLUS _LDDE l1cb5: ld a,.MINUS _LDDE l1cb8: ld a,.MULT _LDDE l1cbb: ld a,.DIV _LDDE l1cbe: ld a,.Number l1cc0: cp .Number ; Z set if number ret ; ; Process string ; l1cc3: ld hl,0 push bc ld b,a ; Save ' or " call l0b29 ; Get character cp b ; Test match jp nz,l1cd9 ; Nope call l0b23 ; Get current character cp b ; Test second match jp nz,l1cf9 call l0b29 ; Get character l1cd9: ld l,a ; Save character ld (l3de2),a call l0b29 ; Get character cp b ; Test match jp nz,l1cef call l0b23 ; Get current character cp b ; Test second match ld a,b jp nz,l1cf4 ; Nope call l0b29 ; Get character l1cef: ld h,l ; Unpack ld l,a call l0b29 ; Get character l1cf4: cp b ; Verify match pop bc jp l1d6e l1cf9: ld de,l3de2 ld a,(de) ; Get character or a ; Test NULL jp nz,l1d03 ; Nope dec a ld (de),a ; Map NULL -> -1 l1d03: ld a,b jp l1cf4 ; ; Process normal character ; l1d07: ld hl,(l3d46) dec hl ; Get previous pointer push hl l1d0c: call l0b48 ; Get upper case jp p,l1d0c ; Skip alpha-numeric ld (l3de2),a ; Save character ld hl,(l3d46) dec hl ; Fix line pointer dec hl ld (l3d46),hl ; Save it call l0b48 ; Get upper case pop hl ld (l3d46),hl ; Save line pointer jp nz,l1dfb ; Got number cp 'F'+1 ; Test pssible hex range jp nc,l1d48 ; Nope ld h,a ld a,(l3cf1) ; Get radix cp 14 ; Test range jp nc,l1dfb ld l,a ld a,h cp 'D' ; Test decimal jp z,l1d48 cp 'B' ; Test binary jp nz,l1dfb ld a,l ; Get back radix cp 12 jp nc,l1dfb ld a,h l1d48: cp 'B' jp z,l1d77 ; Convert binary cp 'D' jp z,l1d95 ; Convert decimal cp 'H' jp z,l1d9d ; Convert hexadecimal cp 'O' jp z,l1d64 ; Convert octal cp 'Q' call nz,l04c1 ; Bad opcode or objectionable syntax jp nz,l1d95 l1d64: call l1dbc ; Convert from octal cp 'O' ; Verify correct end jp z,l1d71 cp 'Q' l1d6e: call nz,l04c1 ; Bad opcode or objectionable syntax l1d71: ld c,' ' ex de,hl jp l1cbe ; ; Convert binary ASCII string to hex ; EXIT Reg HL holds number ; Accu holds non valid end character ; l1d77: ld hl,0 ; Init number l1d7a: call l0b48 ; Get upper case cp 'B' jp z,l1d71 sub '0' ; Verify number range 0..1 call m,l04bb ; Number error if not cp '1'-'0'+1 call nc,l04bb add hl,hl ; Double old value or a ; Test 0 jp z,l1d7a inc hl ; Insert 1 jp l1d7a ; ; Convert and check for possible indicator ; l1d95: call l1da5 ; Convert from decimal cp 'D' ; Test indicator follows jp l1d6e l1d9d: call l1dd5 ; Convert from hexadecimal cp 'H' ; Test indicator follows jp l1d6e ; ; Convert decimal ASCII string to hex ; EXIT Reg HL holds number ; Accu holds non valid end character ; l1da5: ld hl,0 ; Init number l1da8: call l0b48 ; Get upper case ret z ; Got letter ret m ; Or non alpha-numeric sub '0' ; Get digit add hl,hl ; * 2 ld d,h ld e,l add hl,hl ; * 4 add hl,hl ; * 8 add hl,de ; *10 ld d,0 ld e,a add hl,de ; Insert digit jp l1da8 ; ; Convert octal ASCII string to hex ; EXIT Reg HL holds number ; Accu holds non valid end character ; l1dbc: ld hl,0 ; Init number l1dbf: call l0b48 ; Get upper case ret z ; Got letter ret m ; Or non alpha-numeric sub '0' cp 7+1 ; Verify 0..7 call nc,l04bb ; Number error if not add hl,hl ; * 2 add hl,hl ; * 4 add hl,hl ; * 8 ld e,a ld d,0 add hl,de ; Insert digit jp l1dbf ; ; Convert hex ASCII string to hex ; EXIT Reg HL holds number ; Accu holds non valid end character ; l1dd5: ld hl,0 ; Init number l1dd8: call l0b48 ; Get upper case ret m ; Got non alpha-numeric cp 'F'+1 ; Check max jp nc,l1df5 sub '0' cp 9+1 ; Test 0..9 jp c,l1dea ; Yeap sub 'A'-'0'-10 ; Fix hex l1dea: add hl,hl ; * 2 add hl,hl ; * 4 add hl,hl ; * 8 add hl,hl ; *16 ld e,a ld d,0 add hl,de ; Insert digit jp l1dd8 l1df5: cp 'H' ; Verify legal end of hex ret z jp l04bb ; Number error if not l1dfb: ld a,(l3cf2) ; Test .RADIX in progress or a jp nz,l1e34 ; Yeap ; ; Convert ASCII string to number ; EXIT Reg HL holds number ; Accu holds non valid end character ; ld hl,0 ; Init result push bc l1e06: call l0b48 ; Get upper case jp m,l1e30 ; Got non alpha-numeric sub '0' cp 9+1 ; Test decimal jp c,l1e18 ; Yeap sub 'A'-'0'-10 ; Fix hex call c,l04bb ; Number error if invalid range l1e18: ld c,a ; Save digit ld b,0 ld a,(l3cf1) ; Get radix dec a cp c ; Verify in range call c,l04bb ; Number error if not inc a ld e,a ld d,b push bc call l2463 ; Multiply ex de,hl pop bc add hl,bc ; Insert digit jp l1e06 l1e30: pop bc jp l1e3d l1e34: call l1da5 ; Convert from decimal jp l1e3d ; ; *** NEVER CALLED *** ; l1e3a:: ;;** call l1dbc ; Convert from octal l1e3d: call l0b36 ; Get previous pointer jp l1d71 ; ; Process label ; l1e43: push bc call l0b36 ; Get previous pointer ld a,(l3de9) ; Get length ld (l3de2),a cp log.itm+1 ; Check length jp nc,l1ebf ; Not a logical dec a ; Test one character only jp z,l1fe4 ; Yeap call l0c24 ; Get symbol table pointer jp z,l1ebf ; Empty ld hl,l2010 ; Init table ld bc,log.len+1 l1e62: dec c ; Test ready jp z,l1ebf ; Yeap inc b ; Test dummy 1 l1e67: dec b ; Test scanned to next jp z,l1e6f ; Yeap inc hl ; Skip over item jp l1e67 l1e6f: ld b,log.itm ; Set item length ld de,l3de9+1 ; Init buffer l1e74: ld a,(de) cp (hl) ; Compare jp nz,l1e62 ; No match, try next inc de inc hl dec b jp nz,l1e74 ld hl,log.code-1 add hl,bc ; Position in table ld a,(hl) ; Get code cp .XOR ; Test special jp nz,l1e8c ld (l3ceb),a ; Set flag l1e8c: pop bc or a ; Test AND (code 0xFF) jp p,l1cc0 ; Nope, get result call l0bc8 ; Skip white spaces ld de,-1 l1e97: cp ';' ; Test comment jp z,l1eb9 cp cr ; Test end of line jp z,l1eb9 or a jp nz,l1eb0 call l0aea ; Check character cp '&' ; Test it call z,l0aea ; Check character jp l1e97 l1eb0: call l0aea ; Check character cp cr ; Test end jp nz,l1eb0 inc de l1eb9: call l0b36 ; Get previous pointer jp l1cbe ; ; No logical statement found ; l1ebf: ld hl,(l3d46) ; Get current line pointer push hl call l0aea ; Check character cp '#' ; Test EXTRN via ## jp nz,l1eed call l0aea ; Check character cp '#' jp nz,l1eed scf call l0cfc ; Put into symbol table call l2d15 inc hl ld a,(hl) ld b,a and _KNOW ; Test already defined call nz,l04b5 ; Multiply-defined error if so ld a,b and 11b ; Get lower mode bits or _DEF ; Indicate defined ld (hl),a pop bc dec hl jp l1f21 l1eed: pop hl ld (l3d46),hl ; Save line pointer call l0c24 ; Get symbol table pointer jp z,l1f74 ; Empty ld a,(l3cea) ; Get CPU type add a,a jp z,l1f04 ; Got ZILOG call l0515 ; Decode statement jp z,l1fae ; Got it l1f04: ld a,(l3ceb) ; Get flag or a ; Test XOR jp z,l1f1d ; Nope scf call l0d93 ; Mark PUBLIC call l0c24 ; Get symbol table pointer jp z,l1f21 ; Empty xor a ld hl,(l401d) ; Get top of symbol table ld (hl),a ; Clear entry jp l1f21 l1f1d: scf call l0cfc ; Put into symbol table l1f21: and _KNOW+_DEF+11b ; Mask bits ld b,a and _DEF ; Test defined ld a,b jp z,l1f32 ; Nope ld (l3ebe),a ld b,_DEF ld (l3ebf),hl l1f32: and _INT ; Test internal call nz,l04a9 ; Double-defined error if so ld a,(l3cea) ; Get CPU type add a,a ld a,0 jp nz,l1f43 ; Got INTEL ld a,(hl) and _PUB ; Test public l1f43: or a ld a,b inc hl inc hl ld e,(hl) inc hl ld d,(hl) pop bc ld c,a jp z,l1f51 ld e,0 l1f51: and 00000011b cp 00000011b jp nz,l1f62 push de inc hl ld e,(hl) inc hl ld d,(hl) ex de,hl ld (l3dde),hl ; Set value pop de l1f62: ld a,c and _KNOW ; Test known ld a,c jp nz,l1cbe ; Yeap and _DEF ; Test defined call z,l04d9 ; Undefined symbol if not ld de,0 jp l1cbe l1f74: push hl push af scf call l0d93 ; Mark PUBLIC pop af pop hl ld (l3d3f),hl ; Set pointer to name field ld a,(hl) and NoMSB cp 'B' jp c,l1fa8 ld a,(hl) and r.p ; Mask it push af ld a,(l3ce7) ; Get old result or a call nz,l04c1 ; Bad opcode or objectionable syntax if not zero pop af ld (l3ce7),a ; Set new result inc hl inc hl ld a,(hl) ld (l3ce8),a ; Set value call l2065 call z,l207a dec hl ld a,(hl) ; Get flags dec hl jp l1f21 l1fa8: inc hl ld a,(hl) ; Get flags dec hl jp l1f21 l1fae: or a ; Test mode jp m,l1f04 ; Got pseudo code inc hl ld e,(hl) ; Get opcode and LoMask shl 3 ; Mask control rra rra rra ld c,a ld d,0 ld b,d ld hl,l1fda add hl,bc ; Point into table ld a,(hl) ; Get 8080 control byte or a jp z,l1fd4 ; Single, immediate or address cp 1dh ; Test dual register access jp nz,l1fce ld (l3ec7),a ; Set flag l1fce: pop bc ld c,' ' jp l1cc0 l1fd4: pop bc ld c,' ' jp l1cbe ; ; 8080 code type table ; l1fda: db 00h,1bh,1ah,18h,19h,00h,00h,1dh,19h,1ah ; ; ; l1fe4: ld a,(l3de9+1) cp 'X' jp nz,l2000 call l0b23 ; Get current character cp '''' jp nz,l1ebf call l0aea ; Check character call l1dd5 ; Convert from hexadecimal cp '''' pop bc jp l1d6e l2000: cp '$' jp nz,l1ebf call l1b6a ex de,hl add a,' ' pop bc ld c,a jp l1cbe ; ; ; l2010: db 'XOR ' ; 01eh log.itm equ $-l2010 db 'AND ' ; 0ffh db 'NOT ' ; 016h db 'MOD ' ; 015h db 'SHL ' ; 014h db 'SHR ' ; 013h db 'OR ' ; 012h db 'EQ ' ; 011h db 'NE ' ; 010h db 'LT ' ; 00fh db 'LE ' ; 004h db 'GT ' ; 00eh db 'GE ' ; 00dh db 'LOW ' ; 00ch db 'HIGH' ; 007h db 'NUL ' ; 006h db 'TYPE' ; 005h ; ; Corresponding value table ; log.code: ; db 01eh,0ffh,016h,015h,014h,013h,012h,011h,010h db .XOR,.AND,.NOT,.MOD,.SHL,.SHR,.OR,.EQ,.NE ; db 00fh,004h,00eh,00dh,00ch,007h,006h,005h db .LT,.LE,.GT,.GE,.LOW,.HIGH,.NUL,.TYPE log.len equ $-log.code ; ; ; l2065: ld a,(l3ce7) cp 20h ret nz ld a,(l3ce8) ; Get value cp 6 ret nz ld a,(l3ce6) ; Get character cp 'A' ret z cp 'a' ret ; ; ; l207a: call l0b23 ; Get current character cp '''' call z,l0aea ; Check character ret ; ; Get complexe function ; l2083: xor a ld b,a ld c,' ' ; Init return character ld l,a ld h,a ld (l3ec7),a ; Clear r1,r2 flag ld (l3ebd),a ld (l3de2),a ld (l3ceb),a ; Clear XOR flag ld (l3ed4),a ; Clear result ld (l3ed5),a ; Clear length ld (l3ed3),a ld (l3ce7),a ld (l3ce8),a ; Init value add hl,sp ; Copy stack ld (l3ec8),hl ; Save it ex de,hl ld hl,(l4029) ; Get top of data call l0d8d ; HL:DE jp nc,l3414 ; Stack overflow push bc l20b3: call l1c5c ; Check legal operator jp m,l211b ; End found jp z,l215d ; Found number constant cp .RgtPar ; Test paranthesis open jp m,l217e ; Yeap jp z,l21f2 ; Paranthesis are closed cp 18h ; Test range jp c,l20ce cp .XOR ; .. and special call c,l2166 l20ce: ld c,a ld (l3ec6),a ; Set for special link item call l2183 ; Get code dec a cp b ld a,c jp nc,l220c cp .PLUS ; Test unary jp z,l2204 cp .MINUS jp z,l2204 l20e5: call l223f ld a,c ld (l3f57),a ; Save type call l218e cp 2 jp z,l213c or a jp nz,l2107 ld a,(l3ec6) ; Get special link item cp .RgtPar ; Test ) jp nz,l213c call z,l04c1 ; Bad opcode or objectionable syntax if so push bc jp l213c l2107: push bc call l2183 ; Get code push af ld a,(l3f57) ; Get type ld c,a pop af call l2166 ld b,a ld a,(l3ec6) ; Get special link item jp l20ce ; ; Found end operator ; l211b: push af call l0b36 ; Get previous pointer call l0aea ; Check character cp ',' ; Test delimiter jp nz,l2138 ; Nope ld a,(l3ec7) ; Get r1,r2 flag or a jp z,l2138 ; Single register pop af xor a ld (l3ec7),a ; Clear r1,r2 flag ld a,1ch ; Change code jp l20ce l2138: pop af jp l219f l213c: ld a,(l3f57) ; Get type ld c,a ld a,(l3ec6) ; Get special link item cp .RgtPar ; Test ) jp z,l214f ; Yeap push bc call l2166 jp l220c l214f: pop bc push bc ld a,b call l2183 ; Get code ld b,a ld a,(l3f57) ; Get type ld c,a jp l2160 ; ; Found number ; l215d: call l22c4 l2160: call l2166 jp l20b3 ; ; ; l2166: pop hl push de ld e,a ld a,c and 00000011b cp 00000011b ld a,e jp nz,l2179 ex de,hl ld hl,(l3dde) ; Get value ex (sp),hl push hl ex de,hl l2179: ld d,1 ld e,c push de l217d: jp (hl) l217e: ld b,a push bc jp l20b3 ; ; Get corresponding type code ; ENTRY Accu holds special index ; EXIT Accu holds type code ; l2183: push de ld hl,l22fb ld e,a ld d,0 add hl,de ; Point into table ld a,(hl) ; Fetch type code pop de ret ; ; ; l218e: pop hl ; Get back caller pop bc ; Get parameter ld a,b cp 1 ; Test value jp nz,l219e call l04c1 ; Bad opcode or objectionable syntax push bc xor a ld b,a cp 1 l219e: jp (hl) ; Jump back to caller ; ; ; l219f: pop hl ld a,h cp 1 sbc a,a ld (l3ec2),a ; Set/Reset function error push hl l21a8: call l223f ld a,c ld (l3f57),a ; Set type call l218e jp m,l21cf cp 2 jp z,l2546 push bc ld a,(l3f57) ; Get type ld c,a call l2166 jp l21a8 ; ; ; l21c5: ld de,0 call l0b40 ; Update line pointer xor a ld (l3f57),a ; Clear type l21cf: ld a,(l3f57) ; Get type ld b,a ld (l3ec1),a ; Set address mode and Mask2 ; Mask ld c,a jp z,l21de ld c,20h l21de: ld a,b ; Get type and 80h ; Extract bit or c ; Insert bit(a) ld hl,l3ed4 or (hl) ; Build result ld (hl),a ld hl,(l3d46) ; Get line pointer dec hl ld c,(hl) ld a,e ld hl,(l3ec8) ; Get back stack ld sp,hl ret ; ; ; l21f2: ld (l3ec6),a ; Set special link item pop de ld a,d cp 2 call z,l04c1 ; Bad opcode or objectionable syntax or a call z,l04c1 ; Bad opcode or objectionable syntax push de jp l20e5 ; ; ; l2204: ex (sp),hl ; Get stack value ld a,h ex (sp),hl dec a ; Test value jp z,l20e5 ld a,c l220c: pop bc ld d,a push bc ld a,b dec a ld a,d jp z,l2236 ld a,d cp 07h jp z,l2236 cp 08h jp z,l20b3 cp 15h jp z,l2236 cp 16h jp z,l2236 cp 1eh jp z,l2236 cp 09h call nz,l04c1 ; Bad opcode or objectionable syntax ld a,17h l2236: ld b,a push bc call l2183 ; Get code ld b,a jp l20b3 ; ; ; l223f: pop hl ; Get caller ld (l3f59),hl ; Save it pop de ld a,d ; Get code or a push de jp nz,l2252 ld de,0 push de ld de,256*1+20h push de l2252: call l22aa ld (l3de0),hl ; Save operands ex de,hl ld (l3eca),hl ex de,hl ld a,c ld (l3f57),a ; Set type call l218e jp m,l22a1 sub 2 jp z,l22a1 ld (l3f58),a ; Save code cp 7-2 ; Test NOT jp z,l228b cp 16h-2 ; Test HIGH jp z,l228b cp 15h-2 ; Test LOW jp z,l228b cp 17h-2 ; Test unary - jp z,l228b cp 1eh-2 ; Test TYPE jp z,l228b call l22aa l228b: ld a,(l3f58) ; Get back code ld hl,(l3f59) push hl ; Set old caller for return ld hl,l231a-4 add a,a add a,l ld l,a ; Build pointer into table ld a,0 adc a,h ld h,a ld a,(hl) ; Fetch address inc hl ld h,(hl) ld l,a jp (hl) ; Go l22a1: push bc ld a,(l3f57) ; Get type ld c,a ld hl,(l3f59) ; Get back caller jp (hl) ; And exit ; ; ; l22aa: pop hl ; Get back caller pop bc ; Get result dec b call nz,l04c1 ; Bad opcode or objectionable syntax jp z,l22b6 inc b push bc ; Bring back result jp (hl) ; Enter caller l22b6: pop de ld a,c and 00000011b cp 00000011b jp nz,l217d ex (sp),hl ; Get result ld (l3dde),hl ; Set value ret ; ; ; l22c4: push af push de push hl ld a,c rlca and 00000111b or 10000000b call l25cc and 00000111b cp 00000110b jp nz,l22e3 push de ld hl,(l3dde) ; Get value ex de,hl call l22f3 pop de jp l22ec l22e3: cp 00000001b jp nz,l22ec ld hl,(l3ebf) ex de,hl l22ec: call l22f3 pop hl pop de pop af ret ; ; ; l22f3: ld a,e call l25cc ld a,d jp l25cc ; ; ; l22fb: db 01h,01h,01h,01h,04h,04h,05h db 06h,08h,08h,09h,09h,09h,09h db 09h,07h,07h,07h,07h,07h,07h db 0ah,0ah,0ah,02h,02h,02h,02h db 03h,02h,0ah ; ; Operator table ; l231a:: dw l2350 ; 00 dw l235a ; 01 dw l2364 ; 02 dw l236e ; 03 dw l23cf ; 04 dw l23fe ; 05 dw l244e ; 06 dw l249e ; 07 dw l2517 ; 08 dw l239d ; 09 dw l23ae ; 0a dw l2551 ; 0b dw l255c ; 0c dw l2568 ; 0d dw l2575 ; 0e dw l257b ; 0f dw l2584 ; 10 dw l25b6 ; 11 dw l25a7 ; 12 dw l2385 ; 13 dw l25f4 ; 14 dw l2600 ; 15 dw l260f ; 16 dw l261e ; 17 dw l262d ; 18 dw l2643 ; 19 dw l2663 ; 1a ; ; Operator Oper.1 OR Oper.2 ; l2350: call l2484 ; Get 2nd operator ld a,d or h ; OR them ld d,a ld a,e or l ld e,a ret ; ; Operator Oper.1 XOR Oper.2 ; l235a: call l2484 ; Get 2nd operator ld a,d xor h ; XOR them ld d,a ld a,e xor l ld e,a ret ; ; Operator Oper.1 AND Oper.2 ; l2364: call l2484 ; Get 2nd operator ld a,d and h ; AND them ld d,a ld a,e and l ld e,a ret ; ; Operator NOT Oper.2 ; l236e: ld hl,(l3eca) ; Get operand 2 ld a,h cpl ; Build complement ld d,a ld a,l cpl ld e,a ld a,(l3f57) ; Get type ld c,a and 83h ld a,5 jp nz,l25c2 jp l25cc ; ; Operator NEG Oper.2 ; l2385: ld hl,(l3eca) ; Get operand 2 ld a,h cpl ; Build complement ld d,a ld a,l cpl ld e,a inc de ; Negate it ld a,(l3f57) ; Get type ld c,a and 83h ld a,6 jp nz,l25c2 jp l25cc ; ; Operator Oper.1 SHL Oper.2 ; l239d: call l2484 ; Get 2nd operator ex de,hl inc de l23a2: dec de ld a,d or e jp z,l23ac add hl,hl ; SHL jp l23a2 l23ac: ex de,hl ret ; ; Operator Oper.1 SHR Oper.2 ; l23ae: call l2484 ; Get 2nd operator inc hl l23b2: dec hl ld a,l or h ret z ld a,d rra ; SHR ld d,a ld a,e rra ld e,a jp l23b2 ; ; *** NEVER CALLED *** ; l23bf:: ;;** ld hl,(l3eca) ; Get operand 2 ld a,(l3f57) ; Get type and 80h ret z ld a,c and 80h call m,l04af ; External error ret ; ; ; l23cf: call l23e0 ld a,(l3f57) ; Get type or c ld c,a and 83h cp 80h ret nz ld (l3ebd),a ret ; ; ; l23e0: ld a,(l3f57) ; Get type cp 20h jp z,l23ee ld hl,(l3de0) ; Get operand 1 ld (l3dde),hl ; Unpack it l23ee: ld hl,(l3eca) ; Get operand 2 add hl,de ex de,hl call l2494 ld a,8 jp nz,l25c2 jp l25cc ; ; ; l23fe: ld hl,(l3eca) ; Get operand 2 call l2447 ; Subtract DE - HL --> DE ld a,(l3f57) ; Get type and 83h jp m,l2425 jp z,l2425 ld a,c and 83h jp m,l2425 jp z,l2424 ld a,(l3f57) ; Get type cp c jp nz,l2425 ld c,20h jp l243f l2424: dec a l2425: push af ld a,(l3f57) ; Get type and 83h jp nz,l2439 ld a,c and 83h cp 80h jp nz,l2439 ld (l3ebd),a l2439: ld a,(l3f57) ; Get type or c ld c,a pop af l243f: ld a,7 jp nz,l25c2 jp l25cc ; ; Subtract DE - HL --> DE ; l2447: ld a,e sub l ; Subtract ld e,a ld a,d sbc a,h ld d,a ret ; ; ; l244e: ld hl,(l3eca) ; Get operand 2 call l2469 ld a,(l3f57) ; Get type or c ld c,a and 83h ld a,9 jp nz,l25c2 jp l25cc ; ; ; l2463: call l2469 ; Multiply ld c,20h ; Change mode ret ; ; Multiply HL*DE-->DE ; l2469: ld b,h ; Copy multiplicand ld c,l ld hl,0 ; Init product ld a,17 ; Set count l2470: dec a jp z,l2482 add hl,hl ; Shift product push hl push bc pop hl add hl,hl ; And multiplicand ex (sp),hl pop bc jp nc,l2470 add hl,de ; Take care of bit shifted out jp l2470 l2482: ex de,hl ret ; ; Get 2nd operand ; EXIT Reg HL holds operand ; l2484: ld a,(l3f57) ; Get type cp c ; Verify same as 1st operand call nz,l04d3 ; Relocation cp 20h call nz,l04d3 ; Relocation ld hl,(l3eca) ; Fetch operand 2 ret ; ; Check resulting and expected types ; EXIT Zero set if ??? ; l2494: ld a,(l3f57) ; Get type and 83h ; Test bits ret z ld a,c and 83h ret ; ; ; l249e: ld hl,(l3eca) ; Get operand 2 call l24b3 ; Divide ld a,(l3f57) ; Get type or c ld c,a and 83h ld a,10 jp nz,l25c2 jp l25cc ; ; Signed divide DE/HL-->DE,HL ; l24b3: push bc ex de,hl ; Get divisor ld a,d or e call z,l04c1 ; Bad opcode or objectionable syntax on zero ld a,d or a ld b,d call m,l250f ; Make >0 if less ld a,h xor b ld b,a ; Set common sign ld a,h ; Test zero result or l jp z,l24d8 ld a,h or a ex de,hl call m,l250f push bc call l24db ; Divide pop af or a call m,l250f ; Make >0 ex de,hl l24d8: ex de,hl pop bc ret ; ; Unsigned divide DE/HL-->DE,HL ; l24db: ld a,h cpl ld b,a ld a,l cpl ld c,a inc bc ; Build two's divisor complement ld hl,0 ; Init result ld a,17 ; Set bit length push af or a jp l24f6 l24ec: push af push hl add hl,bc ; Add divisor jp nc,l24f5 ; Check bit pop af scf _LDAI l24f5: pop hl l24f6: ld a,e ; Shift left 32 bit rla ld e,a ld a,d rla ld d,a ld a,l rla ld l,a ld a,h rla ld h,a pop af dec a ; Test end jp nz,l24ec ld a,h ; Fix remainder or a rra ld h,a ld a,l rra ld l,a ret ; ; Make number greater 0, DE=-DE ; l250f: xor a ; Clear entry ld c,a sub e ; Calculate 0-DE ld e,a ld a,c sbc a,d ld d,a ret ; ; ; l2517: ld hl,(l3eca) ; Get operand 2 push bc ex de,hl ld a,d ; Test zero or e jp z,l2535 ; Yeap ld a,h ; Test 2nd for zero or l jp z,l2535 ld a,h xor d ; Combine sign push af push de ex de,hl call l24b3 ; Divide ex de,hl pop hl pop af call m,l250f ; Make >0 ex de,hl l2535: ex de,hl pop bc ld a,(l3f57) ; Get type or c ld c,a and 83h ld a,11 jp nz,l25c2 jp l25cc ; ; ; l2546: ld a,'O' ld de,l21c5 push de push bc ld b,a jp l04e8 ; Bad opcode or objectionable syntax ; ; ; l2551: call l2599 call l0d8d ; HL:DE sub 1 jp l256f ; ; ; l255c: call l2599 call l0d8d ; HL:DE sub 1 ccf jp l256f ; ; ; l2568: call l2599 ex de,hl call l0d8d ; HL:DE l256f: sbc a,a ; Get boolean result (0x0000 or 0xFFFF) ld d,a ld e,a ld c,20h ret ; ; ; l2575: call l2599 jp l2588 l257b: call l2599 call l0d8d ; HL:DE jp l256f ; ; ; l2584: call l2599 ex de,hl l2588: ld a,e sub l ld e,a ld a,d sbc a,h jp c,l256f or e scf jp z,l256f ccf jp l256f ; ; ; l2599: ld a,(l3f57) ; Get type cp c call nz,l04d3 ; Relocation call l264c ld hl,(l3eca) ; Get operand 2 ret ; ; Operator HIGH Oper.2 ; l25a7: ld hl,(l3eca) ; Get operand 2 ld e,h ; Unpack HI to LO xor a ld d,a ; Clear HI ld a,(l3f57) ; Get type ld c,a ld a,3 jp l25c2 ; ; Operator LOW Oper.2 ; l25b6: ld hl,(l3eca) ; Get operand 2 ld e,l ; Unpack LO to LO xor a ld d,a ; Clear HI ld a,(l3f57) ; Get type ld c,a ld a,4 ; ; ; l25c2: push af ld a,(l3ed4) ; Get result or 40h ; Set bit ld (l3ed4),a pop af ; ; ; l25cc: push hl push af ld hl,l3ed5 inc (hl) ; Bump ld a,(hl) and Mask6 ; Mask bits jp z,l25e2 add a,l ; Add to line ld l,a jp nc,l25de inc h l25de: pop af ld (hl),a ; Insert into line pop hl ret l25e2: dec (hl) ld a,c and 83h jp z,l25f1 ld a,(l3ed4) ; Get result or 10h ; Set error ld (l3ed4),a l25f1: pop af pop hl ret ; ; ; l25f4: call l2484 ; Get 2nd operator ld a,l call l0f52 ; Validate register and 00000111b ; Mask it add a,e ld e,a ret ; ; ; l2600: call l2484 ; Get 2nd operator ld a,l call l0f52 ; Validate register and 00000111b ; Mask it rla ; Shift into right place rla rla add a,e ld e,a ret l260f: call l2484 ; Get 2nd operator ld a,l call l0f40 ; Validate register pair and 00000110b ; Mask it rla ; Shift into right place rla rla add a,e ld e,a ret ; ; ; l261e: call l2484 ; Get 2nd operator ld a,l call l0f36 ; Validate registers BC/DE and 00000010b ; Mask bit rla ; Shift into right place rla rla add a,e ld e,a ret ; ; ; l262d: call l2484 ; Get 2nd operator ld a,l call l0f52 ; Validate register and 00000111b ; Mask it ld l,a ld a,e call l0f52 ; Validate register and 00000111b ; Mask it rla ; Shift into right place rla rla add a,l ; Combine bits ld e,a ret ; ; ; l2643: call l2484 ; Get 2nd operator ld a,l and 00111111b ; Mask bits add a,e ld e,a ret ; ; ; l264c: and 00000011b ; Mask bits cp 00000011b ; Test expected one ret nz ; Nope push hl push de ld hl,(l3dde) ; Get value ex de,hl ld hl,(l3de0) ; Get operand 1 call l0d8d ; HL:DE call nz,l04d3 ; Relocation pop de pop hl ret ; ; Operator TYPE ; l2663: ld a,(l3f57) ; Get type ld e,a ; Expand for 16 bit ld d,0 ld c,20h ld a,(l3e11) cp ' ' ; Test error ret z ; Nope cp 'O' ; Test overflow jp nz,l2678 ; Nope ld e,0 l2678: ld a,' ' ld (l3e11),a ; Clear error ret ; ; Pseudocode ORG ; l267e: call l2cd4 call l2083 ; Get function ex de,hl ld a,b and 20h jp z,l04df ; Value error xor a ld (l3de8),a ld a,b and 00000011b ld b,a jp z,l26b1 ld a,(l3dd1) ; Get code flag cp b jp nz,l04d3 ; Relocation cp 00000011b jp nz,l26b1 push hl ld hl,(l3dda) ; Get COMMON size ex de,hl ld hl,(l3dde) ; Get value call l0d8d ; HL:DE jp nz,l04d3 ; Relocation pop hl l26b1: ld a,(l3dd1) ; Get code flag ld b,a l26b5: ex de,hl ld hl,(l3dda) ; Get COMMON size ld (l3dde),hl ; Set value ld a,(l3cec) ; Get pass or a call nz,l1b83 ; Got pass 2 ex de,hl ld (l3dd2),hl ; Set pointer ex de,hl ld c,_LOCATE ld a,(l3de8) or a jp nz,l26df ld a,(l3cec) ; Get pass or a call nz,l1ba9 ; Got pass 2, so select set location counter ld a,(l3f5c) ; Get code segment or a call z,l2732 l26df: ld a,(l3f5c) ; Get code segment or a ret z xor a ld (l3f5c),a ; Clear code segment call l0b55 ; Get substring jp z,l04cd ; Questionable ret ; ; Pseudocode ASEG ; l26ef: call l2732 call l1b31 ld a,00b ld b,a ld (l3dd1),a ; Set code flag inc a ld (l3f5c),a ; Set code segment ld (l3de8),a ld hl,(l3dd4) ; Get absolute size jp l26b5 ; ; Pseudocode CSEG ; l2708: call l2732 call l1b31 ld a,01b ld (l3f5c),a ; Set code segment ld b,a ld (l3dd1),a ; Set code flag ld hl,(l3dd6) ; Get program size jp l26b5 ; ; Pseudocode DSEG ; l271d: call l2732 call l1b31 ld a,10b ld (l3f5c),a ; Set code segment ld b,a ld (l3dd1),a ; Set code flag ld hl,(l3dd8) ; Get data size jp l26b5 ; ; ; l2732: ld a,(l3f5c) ; Get code segment or a call nz,l2cd4 ld a,(l3dd1) ; Get code flag ld bc,l3dd4 ; Init code address pointer and 00000011b cp 00000011b ; Test COMMON jp z,l2760 ; Yeap add a,a ; Double index ld l,a ld h,0 add hl,bc ; Point into table l274b: push hl ld e,(hl) ; Fetch value from table inc hl ld d,(hl) ld hl,(l3dd2) ; Get pointer call l0d8d ; HL:DE pop de ret c ; End if HL Found DB 'string' or DB "string" ; l27a0: ld b,a ; Save indicator call l0b29 ; Get character call l0b29 ld hl,(l3d46) ; Get current line pointer dec hl dec hl push hl cp b ; Test indicator found ld c,0 ; Init character count jp z,l27c0 ; Empty string l27b3: inc c ; Count up characters call l0b29 ; Get character cp cr ; Test end of line jp z,l27c7 cp b ; Test end of string jp nz,l27b3 l27c0: call l0aea ; Check character cp b ; Maybe twice jp z,l27b3 l27c7: call l0b36 ; Get previous pointer call l0bc8 ; Skip white spaces cp ',' ; Test delimiter jp z,l27dd cp ';' jp z,l27dd cp b ; Test end of string jp z,l27dd cp cr ; Fix for end of line l27dd: pop hl ld (l3d46),hl ; Reset line pointer to beginning jp nz,l281c ld a,c cp 2 jp c,l281c call l0b23 ; Get current character ld b,a call l0b29 ; Get character call l0b29 jp l27ff l27f7: push bc call l164c ; Write code pop bc call l0b29 ; Get character l27ff: cp cr ; Test end of line ret z cp b jp nz,l27f7 call l0b23 ; Get current character cp b ; Test end of string jp z,l2816 call l0aea ; Check character cp ',' ; Test delimiter jp z,l278d ; Try next scan if so ret l2816: call l164c ; Write code jp l278d ; Start again ; ; -> Found DB byte ; l281c: call l0f5a ; Get operand push af ld a,(l3de2) or a jp m,l18c7 pop af call l16d9 ; Write byte ld a,c cp ',' ; Test more jp z,l278d ; Restart if so ret ; ; ; l2832: call l2083 ; Get function push af ld a,b and 83h call nz,l04d3 ; Relocation pop af ret ; ; Pseudocode DC ; l283e: call l1b31 l2841: call l0bc8 ; Skip white spaces cp '"' ; Verify string jp z,l284e cp '''' call nz,l049d ; Argument error if not a string l284e: ld c,a ; Save delimiter xor a l2850: push af call l0b29 ; Get character cp cr ; Test end of line jp z,l18c7 cp c ; Test delimiter jp nz,l2864 ; Nope call l0aea ; Check character cp c ; Test twice jp nz,l286f ; Nope, sample line l2864: ld b,a pop af push bc or a call nz,l164c ; Write code pop af jp l2850 l286f: pop bc push af ld a,b add a,a ld a,b jp z,l287c or MSB ; Set high bit call l164c ; Write last character l287c: pop af cp ',' ; Test more to scan jp z,l2841 ; Yeap ret ; ; Pseudocode DS, DEFS ; l2883: call l1b31 call l28c4 call l2768 ld a,c ; Test to be preset cp ',' jp nz,l289b ; Nope push de call l0f5a ; Get operand ld b,e ; Put into filler byte pop de jp l28a4 l289b: ld a,(l4091) ; Test /M option or a jp z,l28b9 ; Nope ld b,0 ; Set filler byte zero l28a4: ld a,d or e ret z dec de ld hl,(l3dd2) inc hl ; Bump pointer ld (l3dd2),hl ld a,(l3cec) ; Get pass or a call nz,l1c27 ; Got pass 2, write filler byte jp l28a4 l28b9: ld hl,(l3dd2) ; Get pointer add hl,de ; Advance behind DS ld a,(l3dd1) ; Get code flag ld b,a jp l26b5 ; ; ; l28c4: call l2832 ld a,(l3cec) ; Get pass or a ret nz ; End on pass 2 ld a,(l3e11) cp 'U' ; Test 'U'nknown error ret nz ; Nope inc a ; Map U->V ld (l3e11),a ; Set value error ret ; ; Pseudocode DW, DEFW ; l28d7: call l1b31 call l2768 call l2083 ; Get function call l17d5 ; Write 16 bit ld a,c cp ',' ; Test more jp z,l28d7 ; Scan on ret ; ; Pseudocode ENDIF, ENDC ; l28ea: ld a,(l3cf3) ; Get IF level 1 dec a ; Verify not zero jp m,l2912 ; Error if so ld b,a ld (l3cf3),a ; Set new IF level 1 ld a,(l3cf4) ; Get IF level 2 dec a cp b ; Test same jp nz,l2900 ; Nope ld (l3cf4),a ; Set IF level 2 if so l2900: ld a,(l3cf4) ; Get IF level 2 sub b sbc a,a inc a ld (l3d28),a call l293f ld (l3cf5),a jp l0b40 ; Update line pointer l2912: call l04a3 ; Conditional nesting error ret ; ; Pseudocode ELSE ; l2916: ld a,(l3cf5) or a call nz,l04a3 ; Conditional nesting error ld a,(l3cf3) ; Get IF level 1 or a call z,l04a3 ; Conditional nesting error if zero ld hl,l3cf4 ; Point to IF level 2 sub (hl) ; Test same jp z,l293b dec a jp nz,l0b40 ; Update line pointer inc (hl) dec a l2931: ld (l3d28),a inc a ld (l3cf5),a jp l0b40 ; Update line pointer l293b: dec (hl) jp l2931 ; ; ??????????????????????????????? ; EXIT Accu holds ???? ; Carry set on valid result ; l293f: ld a,(l3cf3) ; Get IF level 1 ld e,a cp _iflev ; Test max ld a,0 ret nc ; Out of range ld d,a ld hl,l3cf6 add hl,de ; Point into table scf ; Set success ld a,(hl) ; Fetch value ret ; ; ; l2950: push af call l293f ld de,l3cf5 jp nc,l295c ld a,(de) ld (hl),a l295c: xor a ld (de),a ld hl,l3cf3 inc (hl) ; Advance IF level 1 ld a,(l3d28) or a jp z,l18c7 pop af ld (l3d28),a ld hl,l3cf4 ; Point to IF level 2 or a jp z,l2976 inc (hl) ret l2976: ld a,(l3cf3) ; Get IF level 1 dec a sub (hl) ld (l3d29),a ret ; ; Pseudocode IF, COND ; l297f: call l29d1 ld a,d or e jp l2950 ; ; Pseudocode IFE, IFF ; l2987: call l29d1 ld a,d or e cpl jp z,l2950 xor a jp l2950 ; ; Pseudocode IF1 ; l2994: ld a,(l3cec) ; Get pass (0 is pass 1) call l0b40 ; Update line pointer dec a jp l2950 ; ; Pseudocode IF2 ; l299e: ld a,(l3cec) ; Get pass (0 is pass 1) call l0b40 ; Update line pointer or a jp l2950 ; ; Pseudocode IFDEF ; l29a8: _ORI ; ; Pseudocode IFNDEF ; l29a9: scf push af ld a,(l3d28) or a jp z,l29d8 call l0b55 ; Get substring call l0c24 ; Get symbol table pointer jp nz,l29c0 ; Not empty and 0a0h jp nz,l29cb l29c0: call l0c0e jp z,l29cb l29c6: pop af sbc a,a ; Build 0x00 or 0xFF jp l2950 l29cb: pop af ccf sbc a,a ; Build 0x00 or 0xFF jp l2950 ; ; ; l29d1: ld a,(l3d28) or a jp nz,l28c4 l29d8: pop bc xor a ld hl,l0d8b ld (l3d46),hl ; Set line closure jp l2950 ; ; Pseudocode IFB ; l29e3: _ORI ; ; Pseudocode IFNB ; l29e4: scf push af call l2a32 jp nz,l29d8 ld (l3d46),hl ; Set line pointer ld a,b or c jp z,l29cb jp l29c6 ; ; Pseudocode IFIDN ; l29f7: _ORI ; ; Pseudocode IFDIF ; l29f8: scf push af call l2a32 jp nz,l29d8 push de push bc ld a,(hl) cp ',' ; Verify comma jp nz,l2a2a inc hl ld (l3d46),hl ; Set line pointer call l2a32 jp nz,l2a2d ld (l3d46),hl ; Set line pointer ld a,c pop bc pop hl cp c jp nz,l29c6 l2a1c: ld a,(de) cp (hl) ; Compare jp nz,l29c6 ; No match inc de inc hl dec c jp nz,l2a1c jp l29cb l2a2a: call l04c1 ; Bad opcode or objectionable syntax l2a2d: pop hl pop hl jp l29d8 ; ; ; l2a32: call l0bc8 ; Skip white spaces cp '<' ; Test start character call nz,l049d ; Argument error if not l2a3a: call l0b23 ; Get current character or a ; Test end jp nz,l2a52 ; Nope call l0aea ; Check character call l0b23 ; Get current character cp '&' ; Test special jp nz,l2a52 ; Nope call l0aea ; Check character jp l2a3a l2a52: ld hl,(l3d46) ; Get current line pointer dec hl ld de,0 l2a59: inc hl ld a,(hl) ; Get character cp '>' ; Test closure jp nz,l2a62 ; Nope ld d,h ; Copy pointer ld e,l l2a62: cp ',' ; Test delimiter jp nz,l2a6c ; Nope ld a,d or e ; Test any sampled jp nz,l2a72 ; Yeap l2a6c: cp cr ; Test end of line jp nz,l2a59 ; Nope inc hl l2a72: push hl ld hl,(l3d46) ; Get current pointer ld a,d ; Verify result or e call z,l049d ; Argument error if not ex de,hl ld a,l sub e ; Calculate length ld c,a ld a,h sbc a,d ld b,a pop hl ld a,(l3e11) cp ' ' ; Test error ret ; Z set if not ; ; Pseudocode ENTRY, PUBLIC, GLOBAL ; l2a89: call l0b55 ; Get substring ld c,a push bc call nz,l049d ; Argument error scf call l0cfc ; Put into symbol table call l2d15 inc hl ld a,(hl) ; Get symbol type or _PUB ; Set ENTRY ld (hl),a pop bc and _KNOW ; Test known call z,l04d9 ; Undefined symbol if not ld a,(hl) and _DEF ; Test already defined call nz,l04b5 ; Multiply-defined error if so rra ; ?????? rra rra or (hl) ; Insert bit ld (hl),a ld a,c cp ',' ; Test more jp z,l2a89 ; Yeap, scan next ret ; ; Pseudocode TITLE ; l2ab5: ld de,l3e31 ; Point to title ld bc,256*(TITLEN-1)+null jp l2ac5 ; ; Pseudocode SUBTTL ; l2abe: ld c,null l2ac0: ld de,l3e81 ; Point to subtitle ld b,STITLEN-1 ; ; Sample characters for title ; ENTRY Reg C holds end character ; Reg B holds length ; Reg DE points to string to be filled ; l2ac5: call l0bc8 ; Skip white spaces ld hl,(l3d46) ; Get current line pointer dec hl l2acc: ld a,(hl) ; Get character inc hl cp cr ; Test end of line jp z,l2ae2 ; Yeap, that's it cp c ; Test end jp z,l2ae2 inc b dec b ; Test done jp z,l2acc ; Yeap, skip remainder ld (de),a ; Unpack inc de dec b jp l2acc l2ae2: xor a ld (de),a ; Close line inc hl ld (l3d46),hl ; Set new line pointer ret ; ; Pseudocode $TITLE ; l2ae9: call l0bc8 ; Skip white spaces cp '(' ; Check syntax jp nz,l049d ; Argument error if invalid call l0b29 ; Get character cp '''' jp nz,l049d ; Argument error ld c,a ; Set delimter call l2ac0 ; Get title call l0b36 ; Get previous pointer call l0b29 ; Get character cp ')' call nz,l049d ; Argument error jp l0b40 ; Update line pointer ; ; Pseudocode .LIST ; l2b0b: ld a,1 ld (l3d2f),a ; Enable list jp l2b59 ; ; Pseudocode .XLIST ; l2b13: xor a ld (l3d2f),a ; Disable list jp l2b59 ; ; Pseudocode .CREF ; l2b1a: xor a ld (l3d2d),a ; Enable cross reference jp l2b59 ; ; Pseudocode .XCREF ; l2b21: call l0b55 ; Get substring jp nz,l2b47 inc c dec c jp z,l2b47 l2b2c: push af call l0c0e call nz,l0c24 ; Get symbol table pointer jp nz,l2b3a ; Not empty ld a,(hl) ; Get type or 01000000b ; Insert bit ld (hl),a l2b3a: pop af cp ',' ; Test more ret nz ; Nope call l0b55 ; Get substring jp nz,l04c1 ; Bad opcode or objectionable syntax jp l2b2c l2b47: ld a,1 ld (l3d2d),a ; Disable cross reference ret ; ; Pseudocode .LALL ; l2b4d: ld a,TRUE ld (l3d2e),a ; Set .LALL jp l2b59 ; ; Pseudocode .SALL ; l2b55: xor a ld (l3d2e),a ; Set .SALL l2b59: jp l0b40 ; Update line pointer ; ; Pseudocode .XALL ; l2b5c: ld a,1 ld (l3d2e),a ; Set .XALL jp l2b59 ; ; Pseudocode .LFCOND ; l2b64: xor a jp l2b7d ; Set .LFCOND ; ; Pseudocode .SFCOND ; l2b68: ld a,TRUE jp l2b7d ; Set .SFCOND ; ; Pseudocode .TFCOND ; l2b6d: ld a,(l408d) ; Get /X option cpl ld l,a ld a,(l3cec) ; Get pass or a jp z,l2b59 ; Got pass 1 ld a,l ld (l408d),a ; Re-Set /X option l2b7d: ld (l3d2a),a ; Set condition flag jp l2b59 ; ; Pseudocode .8080 ; l2b83: ld a,1 ld (l3cea),a ; Set INTEL jp l2b59 ; ; Pseudocode .Z80 ; l2b8b: xor a ld (l3cea),a ; Set ZILOG jp l2b59 ; ; Pseudocode .RADIX ; l2b92: ld a,TRUE ld (l3cf2),a ; Indicate radix in progress call l28c4 xor a ld (l3cf2),a ; Indicate end of radix ld a,d or a jp nz,l049d ; Argument error ld a,(l3e11) cp ' ' ; Test error ret nz ; Yeap ld a,e ; Get result dec a ; Verify range 1..16 ret m jp z,l049d ; Argument error cp 16+1-1 jp nc,l049d ; Argument error inc a ld (l3cf1),a ; Set radix xor a ld h,a ; Get back for integer argument ld l,e jp l1b34 ; ; Pseudocode $EJECT, PAGE ; l2bbe: call l28c4 ; Get value ld a,d ; Verify max is 255 or a jp nz,l049d ; Argument error if not ld a,(l3cec) ; Get pass or a ret z ; End on pass 1 ld a,e or a ; Test zero argument jp z,l2be1 ; Yeap, so new page only cp MinPAGE ; Verify correct range call c,l049d ; Argument error if not valid ld a,(l3e11) cp ' ' ; Test error jp nz,l2be1 ; Yeap ld a,e ld (l3d32),a ; Set page length l2be1: call l192b call l043f ; Init line jp l1a70 ; Init page ; ; Pseudocode .REQUEST ; l2bea: call l0b55 ; Get substring jp nz,l049d ; Argument error push af ld a,(l3de9) ; Get length cp .nam ; Test range jp c,l2bfe call l04cd ; Questionable ld a,.nam-1 ; Truncate it l2bfe: ld hl,l3de3 ld (hl),a ; Store length inc hl ld (l3d3f),hl ; Set pointer to name field ld a,(l3cec) ; Get pass or a ld c,_LIBRQ call nz,l1ba9 ; Got pass 2, so set request library pop af cp ',' ; Test more jp z,l2bea ; Yeap ret ; ; Pseudocode $INCLUDE, MACLIB ; l2c16: ld a,(l3d2c) or a ; Test include file jp nz,l04c1 ; Bad opcode if already active call l0bc8 ; Skip white spaces ld hl,(l3d46) dec hl call l4e71 ; Prepare include file or a ; Test success jp z,l2c31 ; Yeap call l4f34 ; Close include file jp l04df ; Value error l2c31: dec a ld (l3d2c),a ; Set include file l2c35: ld hl,(l3d46) ; Get line pointer ld a,(hl) inc hl ld (l3d46),hl cp ' '+1 jp nc,l2c35 ; Skip printables ret ; ; Pseudocode NAME ; l2c43: call l0bc8 ; Skip white spaces cp '(' ; Verify syntax jp nz,l049d ; Argument error if invalid call l0b29 ; Get character cp '''' jp nz,l049d ; Argument error call l0b55 ; Get substring jp nz,l049d ; Argument error cp '''' jp nz,l049d ; Argument error call l0b29 ; Get character cp ')' jp nz,l049d ; Argument error call l0b40 ; Update line pointer ld a,(l3cec) ; Get pass or a ret nz ; End on pass 2 ld a,(l3de9) ; Get length cp SymLen ; Test range jp c,l2c78 ld a,SymLen ; Truncate it l2c78: ld de,l3de9+1 ; Point to line ld hl,l3f5d ; Point to name field ld b,a ; Unpack length ld a,(hl) ; Verify empty name or a jp nz,l04b5 ; Multiply-defined error l2c84: ld a,(de) ld (hl),a ; Unpack name inc hl inc de dec b jp nz,l2c84 ld (hl),b ; Close name ret ; ; Pseudocode COMMON, LOCAL ; l2c8e: call l2cd4 call l0bc8 ; Skip white spaces cp '/' ; Verify delimiter jp nz,l049d ; Argument error if not call l0b55 ; Get substring call nz,l2ccc cp '/' jp nz,l049d ; Argument error call l0b40 ; Update line pointer call l0cfc ; Put into symbol table inc hl ld a,(hl) ; Get bits and _DEF+_PUB+_INT ; Test them jp nz,l04b5 ; Multiply-defined error if any set push hl ld a,(hl) or _KNOW+_COMM ; Set COMMON ld (hl),a call l2732 pop hl dec hl ld (l3dda),hl ; Set COMMON size ld a,3 ld (l3dd1),a ; Set code flag ld hl,0 ld (l3dd2),hl ; Clear pointer jp l26b1 ; ; ; l2ccc: push af ld a,1 ld (l3de9),a ; Set length pop af ret ; ; ; l2cd4: ld a,(l3de4) or a ; Test .phase in progress ret z ; Nope pop bc jp l04c7 ; Phase error ; ; Pseudocode EXT, EXTERNAL, EXTRN ; l2cdd: ld de,0*256+_DEF ; Init bits l2ce0: call l0b55 ; Get substring jp nz,l2d06 push af or a push de call l0cfc ; Put into symbol table call l2d15 pop de ld a,(hl) or d ld (hl),a inc hl ld a,(hl) ; Get flags and _PUB+_KNOW+_COMM jp nz,l2d0c ; Error if already defined ld a,(hl) and 00000011b ; Reset all bits or e ; Set new one ld (hl),a l2cff: pop af l2d00: cp ',' ; Test more jp z,l2ce0 ; Yeap, so scan on ret l2d06: call l049d ; Argument error jp l2d00 l2d0c: or 00010000b ; Set bit ld (hl),a call l04b5 ; Multiply-defined error jp l2cff ; ; Check symbol ok ; ENTRY Reg HL points to symbol ; l2d15: ld a,(hl) ; Get control bits and NOT _DEF ; No DEF bit cp _PUB+2 ; Check range ret c xor a ld (hl),a ; Clear entry push hl xor a inc hl ld (hl),a ; Clear next bytes inc hl ld (hl),a inc hl ld (hl),a pop hl ret ; ; Pseudocode BYTE ; l2d27: call l0b55 ; Get substring call l0515 ; Decode statement ld a,(hl) ; Get desriptor add a,a call nc,l04c1 ; Bad opcode or objectionable syntax inc hl ld a,(hl) cp ..extrn ; Test EXTRN jp z,l2d3e cp ..ext ; Test EXT(ERNAL) call nz,l04c1 ; Bad opcode or objectionable syntax if neither l2d3e: ld de,_COMM*256+_DEF jp l2ce0 ; Insert bits ; ; Found pseudocode EQU ; l2d44: ld (l3d43),hl ; Set pointer call l2d6d ld a,(l3e11) ; Get error ld (l3d31),a cp 'U' ; Test 'U'nknown ret z ; Yeap ld a,b and 80h jp nz,l04af ; External error ld a,b or 20h ld (l3d30),a ld hl,(l3d43) ; Get pointer ld (l3d3f),hl ; Set pointer to name field call l0ddb ex de,hl ld a,b jp l1b34 ; ; Get value ; EXIT Reg DE holds value ; l2d6d: call l2083 ; Get function ld a,(l3ec2) or a ; Test function error ret z ; Nope jp l04cd ; Questionable ; ; Found pseudocode SET, ASET, DEFL ; l2d78: ld (l3d43),hl ; Set pointer ld a,(hl) or _DEF ; Set bit ld (hl),a ld a,h ld (l3d31),a call l2d6d ld a,b and 80h jp nz,l04af ; External error ld hl,(l3d43) ; Get pointer call l2d15 inc hl ld a,(hl) and _DEF+_INT+_COMM ; Test mode jp nz,l04b5 ; Multiply-defined error ld a,(hl) and _PUB ; Mask bit or b ; Set new or _KNOW ; .. and this one ld (hl),a ; Save new mode inc hl ld (hl),e ; Set value inc hl ld (hl),d inc hl push de ex de,hl ld hl,(l3dde) ; Get value ex de,hl ld (hl),e inc hl ld (hl),d pop hl jp l1b34 ; ; Pseudocode END ; l2db2: push af call l4bb8 ; Close source file ld a,(l3ffa) ; Test pending macro or a call nz,l2f77 ; Give warning if so ld a,(l3cf3) ; Get IF level 1 or a call nz,l2fa8 ; Warn on not terminated IF pop af ld hl,l3cec ; Get pass inc (hl) ; Advance it ld a,(hl) dec a jp nz,l2e5a ; Got pass 2 ld hl,l3f5d ld a,(hl) or a ; Test name given jp nz,l2de2 ; Yeap ld hl,l3e31 ; Point to title ld a,(hl) or a ; Test defined jp nz,l2de2 ; Yeap ld hl,l40d5 ; Else point to source file inc hl l2de2: ld bc,256*0+SymLen ; Init counters ld de,l3f5d ; Point to name l2de8: ld a,(hl) ; Get character inc hl cp ' ' ; Test end jp z,l2e04 cp tab jp z,l2e04 or a jp z,l2e04 cp cr jp z,l2e04 ld (de),a ; Unpack inc de inc b ; Count characters dec c jp nz,l2de8 l2e04: ld hl,l3f56 ld (hl),b ; Set length inc hl ld (l3d3f),hl ; Set pointer to name field ld c,_PRGNAM call l1ba9 ; Output program name call l2732 ld hl,l4f35 ld (l401b),hl l2e1a: call l0cc4 jp c,l2e41 ld (l3d3f),hl ; Set pointer to name field ld a,(hl) and NOT _DEF ; Clear definition bit ld (hl),a inc hl ld a,(hl) and _PUB ; Test definition jp nz,l2f6b ld a,(hl) and _COMM ; Test COMMON jp z,l2e1a inc hl ld e,(hl) ; Fetch COMMON size inc hl ld d,(hl) ld bc,256*0+_DEFCOM call l1ba9 ; Output define COMMON size jp l2e1a l2e41: ld hl,(l3dd8) ; Get data size ex de,hl ld bc,256*0+_DATSIZ call l1ba9 ; Output data size ld bc,256*1+_PRGSIZ ld hl,(l3dd6) ; Get program size ex de,hl ld a,e or d call nz,l1ba9 ; Output program size jp l016e ; Enter 2nd pass ; ; End of pass 2 ; l2e5a: ld hl,(l3d46) push af call nc,l2083 ; Get function push de push bc call l192b ld hl,-1 ld (l3d34),hl ; Reset page numbers ld (l3d36),hl ld a,l ld (l3d2f),a ; Enable list call l1a70 ; Init page ld hl,l2ff4 call l1ad5 ; Put title to print device ld hl,l3d33 ; Point to page count inc (hl) ; Fix it inc (hl) ld hl,l3f72 ld a,5 call l3b97 call l1a5a ; Close line of print device ld a,(l3d33) ; Get page count cp defPAG-3 call nc,l1a70 ; Init page ld hl,l3d33 ; Point to page count inc (hl) ; Fix it inc (hl) ld hl,l2fe9 call l1ad5 ; Put title to print device ld hl,l3fb4 ; Print public symbols ld a,3 call l3b97 call l1a5a ; Close line of print device call l2fb4 ; Close console line ld hl,(l3ced) ; Get error count ld a,h or l ; Test any jp z,l2ecb ; Nope push hl call l1adf ; Put number to print device pop hl ld a,(l40b4) ; Get list device inc a ld (l3f5b),a ; Force device call nz,l1adf ; Skip number output to CON xor a ld (l3f5b),a ; Set back .PRN jp l2ed1 l2ecb: ld hl,l2f4c call l2fd0 ; Tell no error l2ed1: ld hl,l2f4f call l2fd0 ; Tell (no) fatal errors ld hl,(l3cef) ; Get warning count ld a,h or l ; Test any jp z,l2f06 ; Nope ld a,',' call l4c76 ; Put to print device ld a,(l40b4) ; Get list device inc a ld a,',' call nz,l4aee ; Skip CON push hl call l1adf ; Put number to print device pop hl ld a,(l40b4) ; Get list device inc a ld (l3f5b),a ; Force device call nz,l1adf ; Put number to print device xor a ld (l3f5b),a ; Set back .PRN ld hl,l2f5f call l2fd0 l2f06: call l2fb4 ; Close console line pop bc pop de pop af jp nc,l2f14 ld b,0 ld de,0 ; Clear chain address l2f14: call l1b83 ld c,_ENDMOD call l1ba9 ; Output end of module l2f1c: ld hl,(l3ec3) ; Get REL byte and count ld a,h cp -relbits ; Test byte boundary jp z,l2f2c ; Nope xor a call l1c46 ; Write 0 jp l2f1c l2f2c: ld bc,256*0+_ENDPRG call l1ba9 ; Output end of file ld b,0 call l1c2b ; Write NULL ld a,(l408c) ; Test /C option or a jp z,l2f43 ; Nope ld a,EOFitm+MSB call l4c76 ; Put end to cross reference l2f43: call l4bdb ; Put to list device call l4c1b ; Close REL file jp l0100 ; Restart ; ; Statistic messages ; l2f4c: db 'No',null l2f4f: db ' Fatal error(s)',null l2f5f: db ' Warning(s)',null ; ; Found ENTRY - process it ; l2f6b: ld c,_ENTRY ld a,(l3dd1) ; Get code flag ld b,a call l1ba9 ; Output entry symbol jp l2e1a ; ; Give repetition warning ; l2f77: call l2fcd ; Tell unterminated repetition ld hl,l2f86 call l2fd0 call l1b29 ; Advance warning count jp l2fb4 ; Close console line ; ; Macro error messages ; l2f86: db 'REPT/IRP/IRPC/MACRO',null l2f9a: db 'Unterminated ',null ; ; ; l2fa8: call l2fcd ; Tell unterminated ld hl,l2fdd call l2fd0 call l1b29 ; Advance warning count ; ; Close console line ; l2fb4: ld a,cr ; *** WHY *** call l1a5a ; Close line of print device ld a,lf ; *** WHY *** call l1a5a ld a,(l40b4) ; Get list device inc a ret z ; End on CON ld a,cr call l4aee ; Put to console ld a,lf jp l4aee ; ; Give message on unterminated conditition ; l2fcd: ld hl,l2f9a ; ; Print string on print file and console ; ENTRY : Reg HL points to string closed by zero ; l2fd0: push hl call l1ad5 ; Put to print device pop hl ld a,(l40b4) ; Get list device inc a ret z ; End on CON jp l46cc ; l2fdd: db 'Conditional',null l2fe9: db 'Symbols:',cr,lf,null l2ff4: db 'Macros:',cr,lf,null ; ; Check enough room for stack ; l2ffe: ld hl,-2*StkDep add hl,sp ; Allow some depth ex de,hl ld hl,(l4029) ; Get top of data call l0d8d ; HL:DE jp nc,l3414 ; Stack overflow ld a,(l3ffa) ; Test macro active or a ld hl,0 ld (l4023),hl ld (l4025),hl ld hl,(l3ff8) ; Get macro pointer jp nz,l3023 ; Macro is active ld hl,(l4029) ; Get top of data dec hl l3023: inc a ; Bump macro level ld (l3ffa),a xor a ld (l3ffb),a ld (l4005),a ; Clear MACRO level l302e: ex de,hl ld hl,(l401f) inc h call l0d8d ; HL:DE jp nc,l303e ex de,hl ld (l3ff8),hl ; Set macro pointer ret l303e: dec h ex de,hl push hl call l3b4f pop hl jp l302e ; ; ; l3048: call l0515 ; Decode statement ret nz ; Not found ld a,(hl) ; Get desriptor or a inc a ; Check range ret p dec a push af and _macro shl 3 ; Test macro jp z,l3072 ld a,(l4005) inc a ; Advance MACRO level if so ld (l4005),a l305e: pop af and _endm shl 3 ; Test end macro xor _endm shl 3 ret nz ld a,(l4005) ; Get MACRO level or a ; Test empty ret z ld a,(l4005) dec a ; Fix level if not ld (l4005),a inc a ret l3072: inc hl ld a,(hl) cp ..local ; Test LOCAL jp nz,l305e ; Nope ld a,(l4005) ; Get MACRO level or a ; Test level jp nz,l305e ld a,(l400f) or a jp nz,l305e pop af scf ret ; ; Decrement macro level ; l308a: ld (l3ff8),hl ; Set macro pointer ld a,(l3ffa) ; Get macro active dec a ; Decrement ld (l3ffa),a ret ; ; ; l3095: call l0aea ; Check character cp '&' jp nz,l30d1 ld hl,(l3d46) ; Get pointer ld a,(hl) cp ' ' ; Test end of item jp z,l30cf cp tab jp z,l30cf push hl push bc call l0b55 ; Get substring call l30dd pop bc pop hl ld (l3d46),hl ; Reset pointer jp nz,l30cf ld a,'&' ld (l3ffc),a jp l313e l30c3: cp '&' jp nz,l30d1 ld a,(l3ffc) or a jp nz,l30d6 l30cf: ld a,'&' l30d1: call l3a3b or a ret m l30d6: push af xor a ld (l3ffc),a pop af ret ; ; ; l30dd: ld hl,(l4007) ld b,0 ; Init result l30e2: ld a,(hl) or a jp z,l310b ld de,l3de9 ld a,(de) ; Get length cp (hl) ; Compare jp nz,l3100 ; No match ld c,a ; Save length l30f0: dec hl inc de ld a,(de) cp (hl) ; Compare jp nz,l3100 ; No match dec c jp nz,l30f0 ld a,b ; Get value or MSB ; Set bit cp a ; Set result ret l3100: dec hl ld a,(hl) cp 7 ; Fix for next jp nc,l3100 inc b ; Count up result jp l30e2 ; Restart l310b: ld a,(l4010) or a ret nz ld hl,(l4011) ; Get macro start address ld b,0c0h l3115: ld a,(hl) or a jp z,l313c ld de,l3de9 ld a,(de) ; Get length cp (hl) jp nz,l3131 ld c,a l3123: dec hl inc de ld a,(de) cp (hl) jp nz,l3131 dec c jp nz,l3123 xor a ld a,b ret l3131: dec hl ld a,(hl) cp 7 jp nc,l3131 inc b jp l3115 l313c: inc a ret ; ; ; l313e: ld hl,(l3d46) ; Get current pointer push hl call l0b55 ; Get substring push af call l30dd jp nz,l3177 ld b,a pop af pop hl push af l3150: ld a,(hl) inc hl cp ' ' jp z,l315c cp tab jp nz,l3164 l315c: push hl call l30d1 pop hl jp l3150 l3164: ld a,b call l30d1 pop af ld b,a push af l316b: pop af jp nz,l30c3 cp '&' jp nz,l30c3 jp l0b36 ; Get previous pointer l3177: pop af pop hl push af ld (l3d46),hl l317d: call l0aea ; Check character cp ' ' jp z,l3190 cp tab jp z,l3190 call l0b36 ; Get previous pointer jp l3196 l3190: call l30d1 jp l317d l3196: call l0bb1 ; Check legal label jp nz,l316b jp l31a5 l319f: call l0bb1 ; Check legal label jp m,l316b l31a5: call l30d1 jp l319f l31ab: call l0aea ; Check character cp ';' jp z,l31c7 jp l31b9 l31b6: call l3ac6 l31b9: call l30d1 cp cr jp z,l3a9e call l0aea ; Check character jp l31b9 l31c7: call l3ac6 l31ca: call l3ac6 cp ' ' jp z,l31ca cp tab jp z,l31ca or a call l3aed ld (l4025),hl jp z,l3a9e cp cr jp z,l3a9e ld a,cr call l3a3b jp l3a9e l31ee: push hl push af ld a,(l4010) or a jp z,l31ff push de ex de,hl ld hl,(l401d) ; Get top of symbol table add hl,de inc (hl) pop de l31ff: pop af and NoMSB ; Clear hi bit push af add a,a jp m,l3249 ld hl,(l400b) ld a,(hl) or a jp z,l3238 pop af push bc ld b,a inc b dec hl l3214: dec b jp z,l3223 ld a,(hl) push de cpl ld e,a ld d,-1 add hl,de pop de jp l3214 l3223: ld a,(hl) or a jp z,l3246 dec a ld b,a l322a: dec hl ld a,(hl) ; Get character inc b dec b jp z,l3246 call l33d8 ; Store it dec b jp l322a l3238: pop af dec hl inc a l323b: dec a jp z,l3243 dec hl jp l323b l3243: ld a,(hl) pop hl ret l3246: pop bc pop hl ret l3249: ld a,'.' call l33d8 ; Store two dots call l33d8 pop af and 00111111b push bc ld hl,(l4018) ld c,a ld b,0 add hl,bc ld b,h call l1914 ; Store ASCII hex word ld b,l call l1914 pop bc pop hl dec de ld a,(de) ret ; ; Unpack substring ; ENTRY Reg HL points to address for substring in reversed order ; l3269: push hl ; Save address call l0b55 ; Get substring pop hl call nz,l3282 ; Verify end of statements push af ld de,l3de9 ld a,(de) ; Get length inc a ld c,a l3278: ld a,(de) ld (hl),a ; Unpack substring inc de dec hl dec c jp nz,l3278 pop af ret ; ; Verify end of statements ; l3282: cp cr ; Either end of line ret z cp ';' ; Or start of comment ret z pop de jp l049d ; Argument error ; ; ; l328c: ld b,0 push bc push hl dec hl call l0bc8 ; Skip white spaces l3294: cp '''' jp z,l337d cp '"' jp z,l337d cp '<' ; Test start of single list jp z,l339b cp '>' ; Test end of single list jp z,l33a6 cp '%' ; Test convert expression jp z,l32d3 cp ',' jp z,l33b0 cp ' ' jp z,l33b0 cp tab jp z,l33b0 cp ';' jp z,l33b0 cp '!' ; Test literally call z,l0b29 ; Get character cp cr jp z,l33cd l32cb: ld (hl),a ; Unpack MACRO dec hl l32cd: call l0aea ; Check character jp l3294 ; ; Found % - convert expression ; l32d3: ld (l337b),hl ; Save number address push bc ld bc,l3371 push bc ; Set return address call l28c4 ex de,hl ld c,0 ; Set suppress for leading zeroes ld a,(l3e11) cp ' ' ; Test error jp nz,l3336 ; Yeap, set 0 ld a,(l3cf1) ; Get radix cp 16 ; Test hex jp z,l332e cp 8 ; Test octal jp z,l330e ; ; Decimal output ; ld bc,-10 ; Init divisor l32f9: ld d,b ; Set quotient to -1 ld e,b l32fb: add hl,bc ; Divide by ten inc de ; Fix quotient jp c,l32fb push hl ; Save result ex de,hl ld a,h ; Test remainder or l call nz,l32f9 ; Nope, get recursive ld a,'9'+1 pop bc add a,c ; Make ASCII jp l3366 ; Store digit ; ; Octal output ; l330e: xor a add hl,hl ; Get MSB adc a,'0' ; Make ASCII call l3352 ; Store it ld a,5 ; Set octal digit count l3317: push af xor a ld b,3 ; Set octal bit count l331b: add hl,hl ; Create carry adc a,a ; Accumulate dec b jp nz,l331b add a,'0' ; Make ASCII call l3352 ; Store it pop af dec a jp nz,l3317 jp l3336 ; Put final 0 ; ; Hexadecimal output - word output ; l332e: ld b,h ; Get hi call l333e ; Convert it ld b,l ; Then low call l333e l3336: inc c ; Test epilog dec c ret nz ; Nope ld a,'0' jp l3366 ; Store final 0 ; ; Hexadecimal output - byte output ; l333e: ld a,b rra ; Extract hi bits rra rra rra call l3347 ; Convert to ASCII ld a,b ; Then get low bits ; ; Hexadecimal output - digit output ; l3347: and LoMask ; Get bits add a,'0' ; Make ASCII cp '9'+1 ; Test hex jp c,l3352 ; Nope add a,'A'-'0'-10 ; Fix for hex l3352: inc c ; Test leading zero to be suppressed dec c jp nz,l3366 ; Nope, store it cp '0' ; Test leading zero ret z ; Yeap, ignore ld c,a cp '9'+1 ; Test 1st character hex jp c,l3366 ; Nope, store it ld a,'0' call l3366 ; Store leading zero ld a,c l3366: push hl ld hl,(l337b) ; Get current pointer ld (hl),a ; Store character dec hl ; Fix pointer ld (l337b),hl pop hl ret ; ; Return from conversion ; l3371: pop bc call l0b36 ; Get previous pointer ld hl,(l337b) ; Load current number pointer jp l32cd ; Restart ; l337b: ds 2 ; ; Found ' or " - sample string ; l337d: ld c,a ; Save counterpart l337e: ld (hl),a ; Store it dec hl call l0aea ; Check character cp c ; Test end of string jp z,l338f ; Yeap cp cr ; Test end of line jp z,l33d2 ; Error if so jp l337e l338f: ld (hl),a ; Store end character dec hl call l0aea ; Check character cp c ; Test possible twice input jp z,l337e ; Yeap, sample more jp l3294 ; ; Found < - start of single list ; l339b: inc b ; Test 1st entry dec b jp z,l33a2 ; Yeap ld (hl),a ; Store into list dec hl l33a2: inc b jp l32cd ; ; Found > - end of single list ; l33a6: dec b ; Test one left jp z,l32cd ; Yeap jp m,l33b5 ; Test end jp l32cb ; ; Found delimiter - end sampling of macro ; l33b0: inc b ; Test 1st input dec b jp nz,l32cb l33b5: pop de ld a,e sub l dec a ld (de),a pop bc ex de,hl ld hl,(l3d46) ; Get current pointer dec hl ld a,(hl) cp ' ' call z,l0b36 ; Get previous pointer on space cp tab call z,l0b36 ; Get previous pointer on tab ex de,hl ret ; ; Founfd - End of input ; l33cd: inc b ; Testa balanced dec b jp z,l33b5 l33d2: call l04e5 ; Error on special link item jp l33b5 ; ; ENTRY Accu holds character to be stored ; l33d8: push af push hl ld hl,l3d48+SrcLen call l0d8d ; HL:DE jp nc,l33eb ; Still room inc hl ld (hl),cr ; Set end dec hl ex de,hl pop hl pop af ret l33eb: pop hl pop af ld (de),a ; Store character inc de ret ; ; ; l33f0: call l313e cp '&' jp z,l33f0 cp ':' jp z,l313e cp ' '+1 ret nc cp cr ret z push af call l0c0e jp z,l3410 call l0515 ; Decode statement jp z,l18c7 ; Got it l3410: pop af jp l313e ; ; Stack overflow ; l3414: ld hl,l341a jp l0d72 ; Give message and re-enter ; l341a: db '?Stack overflow, try more P switches' db cr,lf,null ; ; Pseudocode REPT ; l3441: call l28c4 ld a,(l3e11) cp ' ' ; Test error jp z,l344f ; Nope ld de,0 ; Clear value l344f: ex de,hl ld (l3ffd),hl ; Set value call l2ffe ; Check enough room for stack pop bc pop de pop hl ld bc,l3463 l345c: push bc ; Set return address push de ; ; ; l345e: ld a,cr jp l045c ; ; ; l3463: pop bc ld bc,l345e push bc call l0b55 ; Get substring cp ':' call z,l0b55 ; Get substring call l3048 jp z,l3484 ld de,l3d48 l3479: ld a,(de) call l3a3b inc de cp cr ; Wait for end of line jp nz,l3479 ret l3484: xor a call l3a3b call l3a9e pop bc pop de pop hl ld hl,l02cc push hl push de ld hl,(l4023) push hl push hl ld hl,(l3ffd) push hl ld hl,l02cc push hl ld hl,l34a6 push hl push bc ret ; ; ; l34a6: call l34f9 pop bc pop hl l34ab: pop de call l0d8d ; HL:DE jp nz,l34d5 ld a,(l4006) or a jp nz,l34be ld a,b or c jp nz,l34d5 l34be: ld hl,(l3ff8) ; Get macro pointer l34c1: push hl call l3994 pop hl l34c6: call l308a ; Decrement macro level xor a ld (l4006),a pop de push de ld hl,(l3fff) push hl ex de,hl jp (hl) l34d5: push de call l3a72 or a jp z,l3508 ld de,l3d48 l34e0: call l3a88 call l33d8 cp cr jp nz,l34e0 push hl push bc l34ed: ld hl,(l4001) push hl ld hl,(l4003) push hl ld hl,(l3fff) jp (hl) ; ; ; l34f9: pop de pop hl ld (l3fff),hl pop hl ld (l4003),hl pop hl ld (l4001),hl ex de,hl jp (hl) ; ; ; l3508: dec bc ld h,d ld l,e jp l34ab ; ; Pseudocode EXITM ; l350e: ld a,(l3ffa) ; Test macro active or a jp z,l04e5 ; Error on special link item if not ld (l4006),a pop bc pop hl pop de ld de,l352b push de push hl push bc xor a ld (l4005),a ; Clear MACRO level jp l0b40 ; Update line pointer ; ; Pseudo code ENDM, LOCAL ; l3528: jp l04c1 ; Bad opcode or objectionable syntax ; ; ; l352b: ld a,(l4006) or a ; Test ??? jp z,l358a ; Empty, reset pointer pop bc ld bc,l01de push bc call l0b55 ; Get substring cp ':' call z,l0b55 ; Get substring call l0515 ; Decode statement ret nz ; Not found or a ret p ; Exit if normal code found ld c,a and _endm shl 3 ; Test ending macro jp nz,l355e ; Yeap ld a,c and _macro shl 3 ; Test beginning macro jp nz,l3566 ld a,c and _endc shl 3 ; Test ending conditional jp nz,l356e ld a,c and _cond shl 3 ; Test starting conditional jp nz,l357b ret ; ; End macro ; l355e: ld a,(l4005) ; Get MACRO level dec a ; Decrement for end ld (l4005),a ret ; ; Start macro ; l3566: ld a,(l4005) ; Get MACRO level inc a ; Increment for start ld (l4005),a ret ; ; Conditional end macro ; l356e: ld a,(l4005) ; Get MACRO level or a ret nz ld a,(l3cf3) ; Get IF level 1 or a ret z jp l28ea ; Perform ENDIF, ENDC ; ; Conditional start macro ; l357b: ld a,(l4005) ; Get MACRO level or a ret nz inc hl ld a,(hl) ; Get code cp ..else ; Test ELSE ret z ld a,-1 jp l2950 l358a: pop bc pop de pop hl ld hl,l02cc push hl ; Change line routine push de push bc ret ; ; Perform pseudocode IRPC (A=0) and IRP (A=1) ; l3594: or a push af ; Save code call l2ffe ; Check enough room for stack ld (l4007),hl call l3269 ; Unpack substring ld c,a ld a,(l3e11) cp ' ' ; Test error jp z,l35b0 ; Nope ld hl,(l4007) call l308a ; Decrement macro level pop af ret l35b0: ld a,c ld (hl),0 ; Clear string dec hl cp ',' ; Verify delimiter call nz,l049d ; Argument error pop af ; Get back code push af jp z,l35ec ; Skip IRPC call l0b29 ; Get character cp '<' ; Verify valid start call nz,l049d ; Argument error l35c6: pop af ld (hl),a ; Set code push hl push af ld c,0 ; Init count dec hl ld a,(l3e11) cp ' ' ; Test error jp nz,l3647 ; Yeap pop af ; Get back pseudocode push af ld b,a jp z,l35fa ; Got IRPC l35db: call l328c ; Get character inc c ; Advance count cp cr ; Test end of input jp z,l3644 ; Invalid cp '>' ; Test end of IRP jp z,l3647 ; Yeap jp l35db ; Sample next l35ec: call l0b23 ; Get current character sub '<' ; Fix for opening ld (l400e),a call z,l0aea ; Check character if so jp l35c6 l35fa: call l0aea ; Check character cp cr ; Test end jp z,l363d push af ld a,(l400e) or a ; Test opening '<' jp z,l361f ; Yeap pop af ld de,l3647 push de ; Change return address cp ' ' ; Test end condition ret z cp tab ret z cp ';' ret z cp ',' ret z pop de jp l3637 l361f: pop af cp '<' ; Test possible nesting jp z,l3633 cp '>' ; Test closure jp nz,l3637 inc b dec b ; Test base level jp z,l3647 ; End if so dec b ; Get previous level jp l3637 l3633: inc b ; Get previous level jp l3637 ; *** WHY *** l3637: inc c ; Advance character count ld (hl),a ; Store character dec hl jp l35fa l363d: ld a,(l400e) or a ; Test opening '<' jp nz,l3647 ; Nope l3644: call l04cd ; Questionable error l3647: ld (hl),0 ; Close macro dec hl call l302e ld a,b or a call nz,l049d ; Argument error pop af pop hl ld (l4009),hl ld h,0 ld l,c ld (l3ffd),hl pop bc pop de pop hl ld bc,l366d jp l345c ; Change return address ; ; Pseudocode IRPC ; l3666: xor a _JPNZ ; ; Pseudocode IRP ; l3668: ld a,1 jp l3594 ; ; End of IRP/IRPC ; l366d: pop bc ld bc,l345e push bc ld hl,(l4025) ld a,1 ld (l4010),a push hl call l33f0 push af call l3048 jp z,l36b1 pop af pop hl l3687: cp cr ; Test end jp z,l31b6 cp ';' jp z,l31ab cp '''' ; Test string jp z,l36a1 cp '"' jp z,l36a1 l369b: call l313e jp l3687 l36a1: ld b,a ; Save string indicator l36a2: call l3095 cp cr ; Test end of line jp z,l31b6 cp b ; Test end of string jp z,l369b jp l36a2 l36b1: pop af pop hl ld (l4025),hl xor a call l3a3b call l3a9e pop bc pop de pop hl ld hl,l02cc push hl push de ld hl,(l4023) push hl push hl ld hl,(l4009) push hl ld hl,(l3ffd) push hl ld hl,l02cc push hl ld hl,l36dc push hl push bc ret ; ; ; l36dc: call l34f9 pop bc pop hl pop de ld a,1 ld (l4010),a ld (l400b),hl pop hl call l0d8d ; HL:DE jp nz,l370d l36f1: ld a,(l4006) or a jp nz,l36fd ld a,b or c jp nz,l370d l36fd: ld hl,(l400b) inc hl inc hl l3702: ld a,(hl) cp 8 inc hl jp nc,l3702 dec hl jp l34c1 l370d: ex de,hl push de call l3a72 or a jp z,l3734 ld de,l3d48 l3719: call l3a72 or a call m,l31ee call l3aed call l33d8 cp 0dh jp nz,l3719 push hl ld hl,(l400b) push hl push bc jp l34ed l3734: dec bc ld h,d ld l,e pop de jp l36f1 ; ; Pseudocode .PRINTX ; l373b: call l0bc8 ; Skip white spaces cp cr ; Test empty line jp z,l049d ; Argument error if so ld c,a ; Save sync character call l4aee ; Put to console l3747: call l0b29 ; Get character cp cr ; Test end of line jp z,l3756 call l4aee ; Put to console cp c ; Test end of text jp nz,l3747 l3756: ld a,cr call l4aee ; Put new line to console ld a,lf call l4aee ld a,(l3e11) cp ' ' ; Test error ret nz ; Yeap jp l0b40 ; Update line pointer ; ; Pseudocode .COMMENT ; l3769: call l0bc8 ; Skip white spaces cp cr ; Test empty line jp z,l049d ; Argument error if so ld (l400d),a ; Save sync character ld c,a l3775: call l0aea ; Check character cp cr ; Test end of line jp z,l3784 ; Yeap cp c ; Test sync character jp z,l0b40 ; Update line pointer if so jp l3775 l3784: pop hl pop de pop bc ld bc,l378d jp l345c ; Change return address l378d: pop bc ld bc,l345e push bc ; Change return address ld hl,l3d48 ld a,(l400d) ; Get sync character ld c,a l3799: ld a,(hl) ; Get character cp c ; Test sync jp z,l37a5 ; Yeap, end cp cr ; Find end of line ret z inc hl jp l3799 l37a5: pop bc pop de pop hl ld hl,l02cc push hl ; Change line routine push de push bc ret ; ; Found pseudocode MACRO ; l37af: or a call l0dd4 inc hl ld (l3ff6),hl ld a,(hl) ; Get code or 28h ; Fix it ld (hl),a call l2ffe ; Check enough room for stack ld (l4007),hl ld c,0 ; Init macro counter l37c3: push bc call l3269 ; Unpack substring pop bc inc c ; Advance macro counter cp ',' ; Test more jp z,l37c3 ; Yeap xor a ld (hl),a ; Set end dec hl ld (l400f),a ld (l4015),a inc a ld (hl),a ; Init value ??? dec hl ld (l4011),hl ; Save start of macro address ld (l4013),hl ld (hl),0 ; Close it ld a,c ; Get macro count ld (l401a),a ; Save it call l3a3b xor a call l3a3b pop bc pop de pop hl ld hl,l37f7 push hl ; Change return address push de push bc ret ; ; ; l37f7: pop bc ld bc,l345e push bc ; Change return address ld hl,(l4025) push hl xor a ld (l400f),a ld (l4010),a call l33f0 push af call l3048 jp c,l381c jp z,l384f pop af ld (l400f),a pop hl jp l3687 l381c: pop af l381d: call l0b55 ; Get substring call nz,l049d ; Argument error ld hl,(l4013) ; Get current address of macro push af jp nz,l3831 ld a,(l4015) inc a ld (l4015),a l3831: ld de,l3de9 ld a,(de) ; Get length inc a ld c,a l3837: ld a,(de) ld (hl),a ; Unpack dec hl inc de dec c jp nz,l3837 ld (hl),0 ld (l4013),hl ; Set current address of macro pop af cp ',' jp z,l381d pop hl ld (l4025),hl ret l384f: pop af pop hl xor a ld (l4025),hl call l3a3b call l3a9e ld hl,(l4023) ld de,l0005 add hl,de ex de,hl ld hl,(l401d) ; Get top of symbol table add hl,de ld a,(l4015) ld (hl),a ld hl,(l4023) ex de,hl ld hl,(l3ff6) inc hl push de push hl ld e,(hl) inc hl ld d,(hl) ld a,d or e call nz,l3994 pop hl pop de ld (hl),e inc hl ld (hl),d ld hl,(l4007) call l308a ; Decrement macro level pop bc pop de pop hl ld hl,l02cc push hl ; Change line routine push de push bc ret ; ; ; l3892: push hl scf call l0d93 ; Mark PUBLIC call l2ffe ; Check enough room for stack ld (hl),0 dec hl ld (hl),1 ld (l400b),hl dec hl ld c,0 ; Clear counter l38a5: call l328c ld b,a inc c ; Advance counter call l0b36 ; Get previous pointer call l0bc8 ; Skip white spaces cp cr ; Test end of line jp z,l38cd cp ';' ; Test comment jp z,l38cd cp ',' ; Test delimiter jp z,l38a5 ld a,b cp ' ' ; Test blank jp z,l38a5 cp tab ; Test tabulator call nz,l04cd ; Questionable if none jp l38a5 l38cd: ex (sp),hl ; Get pointer inc hl ; Fix it inc hl ld e,(hl) ; Fetch address inc hl ld d,(hl) ex de,hl call l3a88 ex (sp),hl ; Bring back pointer or a jp z,l38ea l38dc: cp c ; Test count value reached jp z,l38ea ; Yeap jp c,l38ea ld (hl),0 ; Fill with nulls dec hl inc c jp l38dc l38ea: ld (hl),0 ; Close line dec hl call l302e pop hl pop bc call l3a88 push hl ld hl,(l4016) push hl push bc ld c,a ld b,0 add hl,bc ld (l4016),hl pop bc ld hl,(l400b) push hl ld hl,l02cc push hl ld de,l3911 push de push bc ret ; ; ; l3911: call l34f9 pop hl ld (l400b),hl pop hl ld (l4018),hl pop hl xor a ld (l4010),a call l3a72 or a jp z,l3949 ld de,l3d48 l392b: call l3a72 or a call m,l31ee call l3aed call l33d8 cp cr jp nz,l392b push hl ld hl,(l4018) push hl ld hl,(l400b) push hl jp l34ed l3949: ld hl,(l400b) inc hl xor a ld (l4006),a jp l34c6 ; ; HL:=HL-DE ; l3954: ld a,l sub e ; Subtract ld e,a ld a,h sbc a,d ld d,a ret ; ; Pseudocode .PHASE ; l395b: ld a,(l3de4) or a ; Test .phase in progress jp nz,l04c7 ; Phase error if so call l2083 ; Get function ld a,(l3e11) cp ' ' ; Test error ret nz ; Yeap ld (l3de4),a ; Set .phase in progress ld a,b and 80h jp nz,l049d ; Argument error ld a,b and 3 ld (l3de7),a ld hl,(l3dd2) ; Get pointer ex de,hl call l3954 ; HL:=HL-DE ex de,hl ld (l3de5),hl ; Set phase difference ret ; ; Pseudocode .DEPHASE ; l3986: ld a,(l3de4) or a ; Test .phase in progress call z,l04cd ; Questionable if not xor a ld (l3de4),a ; Reset .phase in progress jp l0b40 ; Update line pointer ; ; ; l3994: ld hl,l4021 ld c,(hl) ; Get old ld (hl),e ; Set new inc hl ld b,(hl) ld (hl),d call l39a6 call l39af ld (hl),c inc hl ld (hl),b ret ; ; ; l39a6: ld hl,(l401d) ; Get top of symbol table add hl,de ; Add index ld e,(hl) ; Get chain inc hl ld d,(hl) dec hl ret ; ; ; l39af: ld hl,(l401d) ; Get top of symbol table add hl,de ; Add index inc hl ; Fix inc hl ld e,(hl) ; Get value inc hl ld d,(hl) dec hl ret ; ; ; l39ba: ld hl,(l4021) ld a,l or h jp z,l39cf ex de,hl push de call l39af ex de,hl ld (l4021),hl pop de jp l39fb l39cf: ld hl,(l401f) ld de,l0020 ex de,hl add hl,de ld (l401f),hl push de ex de,hl ld hl,(l4029) ; Get top of data call l0d8d ; HL:DE pop de jp c,l3b49 ld hl,(l3ff8) ; Get macro pointer dec h ld a,(l3ffa) ; Test macro active or a call l0d8d ; HL:DE jp c,l3b49 ld hl,(l401d) ; Get top of symbol table ex de,hl call l3954 ; HL:=HL-DE l39fb: push de call l39a6 ex de,hl ld hl,(l4025) ex de,hl ld a,e and 0e0h ld e,a ld a,e or d jp nz,l3a0f pop de push de l3a0f: ld (hl),e ; Store address inc hl ld (hl),d inc hl ld a,0 ld (hl),a ; Zero next inc hl ld (hl),a call l39af pop de jp z,l3a25 ld (hl),e inc hl ld (hl),d jp l3a2a l3a25: ex de,hl ld (l4023),hl ex de,hl l3a2a: ld hl,(l4023) push de ex de,hl call l39a6 pop de ld (hl),e inc hl ld (hl),d ld a,e or 4 ld e,a ret ; ; ; l3a3b: push de push af ld hl,(l4025) ex de,hl ld a,e and 00011111b call z,l39ba ld hl,(l401d) ; Get top of symbol table add hl,de pop af push af ld (hl),a ld a,e and 00011111b cp 00011111b jp z,l3a57 inc de l3a57: call z,l3a61 ex de,hl ld (l4025),hl pop af pop de ret ; ; ; l3a61: ld a,e and 11100000b ld e,a call l39af ld a,d or e jp z,l39ba inc de inc de inc de inc de ret ; ; ; l3a72: push de ex de,hl ld hl,(l401d) ; Get top of symbol table ex de,hl ld a,l and 00011111b jp nz,l3a82 ld a,l or 00000100b ld l,a l3a82: ex de,hl add hl,de ld a,(hl) ex de,hl pop de ret ; ; ; l3a88: call l3a72 push af push de ex de,hl ld a,e and 00011111b cp 00011111b jp z,l3a97 inc de l3a97: call z,l3a61 ex de,hl pop de pop af ret ; ; ; l3a9e: ex de,hl ld a,e and 11100000b ld e,a push de call l39af ld a,e or d pop bc ret z xor a ld (hl),a inc hl ld (hl),a ld hl,(l401d) ; Get top of symbol table add hl,de ld (hl),e inc hl ld (hl),d push bc call l3994 pop bc ld hl,(l4023) ex de,hl call l39a6 ld (hl),c inc hl ld (hl),b ret ; ; ; l3ac6: ld hl,(l4025) push de ex de,hl ld a,e and 00011111b dec de cp 00000100b call z,l3ae1 ld hl,(l401d) ; Get top of symbol table ex de,hl ld (l4025),hl ex de,hl add hl,de ld a,(hl) ex de,hl pop de ret ; ; ; l3ae1: ld a,e and 11100000b ld e,a call l39a6 ld a,e or 00011111b ld e,a ret ; ; ; l3aed: push de push af ex de,hl ld a,e and 00011111b cp 00011111b jp z,l3af9 inc de l3af9: call z,l3a61 ex de,hl pop af pop de ret ; ; Allocate memory for symbol table ; l3b00: ld hl,(l401f) ; Fetch pointers ex de,hl ld hl,(l3ff8) ; Get macro pointer ld a,(l3ffa) or a ; Test macro active jp nz,l3b12 ; Yeap ld hl,(l4029) ; Get top of data dec h l3b12: call l3954 ; HL:=HL-DE jp c,l0d6f ; Exhausted ld a,d or a ; Should be at least one page jp z,l0d6f rra ld d,a ; Divide by two ld a,e rra ld e,a push de ld hl,(l401d) ; Get top of symbol table ex de,hl ld hl,(l401f) call l3954 ; HL:=HL-DE ld b,d ; Save gap ld c,e pop de ld hl,(l401f) ex de,hl add hl,de ; Build new top ld (l401f),hl l3b38: ld a,b ; Test zero or c jp z,l3b45 ; Done dec hl dec de ld a,(de) ; Move down ld (hl),a dec bc jp l3b38 l3b45: ld (l401d),hl ; Set top of symbol table ret ; ; ; l3b49: call l3b4f jp l39cf ; ; ; l3b4f: push de ld hl,(l3d41) ; Get symbol table ex de,hl ld hl,(l401d) ; Get top of symbol table call l3954 ; HL:=HL-DE jp c,l0d6f ; No room ld a,d cp HIGH 0300h jp c,l0d6f rra ; Divide by two ld d,a ld a,e rra ld e,a pop hl push bc push hl ld hl,(l401d) ; Get top of symbol table ex de,hl ex (sp),hl call l3954 ; HL:=HL-DE ld b,d ; Save difference ld c,e pop de ld hl,(l401d) ; Get top of symbol table push hl ld hl,(l3d41) ; Get symbol table add hl,de push hl ld (l401d),hl ; Set top of symbol table add hl,bc ld (l401f),hl pop hl pop de l3b88: ld a,b or c jp z,l3b95 dec bc ld a,(de) ld (hl),a ; Unpack inc hl inc de jp l3b88 l3b95: pop bc ret ; ; ????????????????????????????????? ; ENTRY Accu holds address mode ; Reg HL points to chain field ; l3b97: ld (l3ec1),a ; Set address mode ld (l3ec2),a ; Set/Reset (?) function error ld c,a ld b,Chn.Len ; Get length l3ba0: ld e,(hl) ; Get address inc hl ld d,(hl) inc hl push hl push bc call l3bb7 pop bc pop hl dec b jp nz,l3ba0 ld a,(l3ec1) ; Get address mode cp c call nz,l1a5a ; Close line of print device if no match ret ; ; ENTRY Reg DE holds start of chain ; l3bb7: ld bc,0 push bc ld a,d ; Test empty or e jp z,l18c7 ; That's all l3bc0: ex de,hl push hl ; Push chain onto stack ld e,(hl) inc hl ld d,(hl) ld a,e or d jp nz,l3bc0 l3bca: pop hl ; Get back chain ld a,l or h ret z ; Loop until NIL call l3be6 dec hl dec hl ld d,(hl) dec hl ld e,(hl) ld a,e or d jp z,l3bca xor a ld (hl),a inc hl ld (hl),a dec hl dec hl dec hl push hl jp l3bc0 ; ; ENTRY Reg HL points to start of symbol ; l3be6: ld bc,l0004 add hl,bc ; Point to length ld b,(hl) ; And get it inc hl ld (l3d3f),hl ; Save base ld a,(hl) ; Get 1st control and _PUB ; Test attached ret nz ; Yeap, skip inc hl ld a,(hl) ; Get next control and _DEF ; Test defined call nz,l3cd4 ; Nope, set chain external ld a,(hl) inc hl ld e,(hl) ; Get chain address inc hl ld d,(hl) push bc push hl ld b,a ; Get control and 00001000b ; Test bit jp nz,l3c35 ; Skip push bc call l3cc0 pop af ; Get back mode ld e,a and _DEF ; Test external jp nz,l3c7f ; Yeap, indicate it ld a,e and _COMM ; Test COMMON jp nz,l3c85 ; Yeap ld a,e and _PUB ; Test public call nz,l3c90 ; Yeap ld a,e and _DEF+_KNOW ; Test known jp z,l3c88 ; Nope ld a,e and @@mod ; Extract address mode ld e,a ld d,0 ld hl,l1b66 add hl,de ld a,(hl) ; Get address indicator call l4c76 ; Put to print device l3c32: call l3c7a ; Put tab to print device l3c35: pop hl pop bc inc hl inc hl inc hl push bc ; Get length l3c3b: ld a,(hl) inc hl call l4c76 ; Put label to print device dec b jp nz,l3c3b pop bc ld a,l0010 ; Get gap sub b jp nz,l3c4c inc a ; Set 1 if 0 l3c4c: ld b,a l3c4d: call l3c75 ; Put blank to print device dec b jp nz,l3c4d ld hl,l3ec1 dec (hl) ; Count down address mode jp nz,l3c6d ld a,(l3ec2) ld (hl),a ; Set function error call l1a5a ; Close line of print device ld hl,l3d33 ; Point to page count inc (hl) ld a,(l3d32) ; Get page length cp (hl) call z,l1a70 ; Init page l3c6d: ld hl,(l3d3f) ; Get label address ld a,(hl) or _PUB ; Set attached ld (hl),a ret ; ; Put blank to print device ; l3c75: ld a,' ' jp l3c7c ; ; Put tab to print device ; l3c7a: ld a,tab l3c7c: jp l4c76 ; Put to print device ; ; Indicate external ; l3c7f: ld a,'*' _JPZ ; ; Indicate macro ** NEVER CALLED *** ; l3c82: ld a,'M' _JPZ ; ; Indicate COMMON ; l3c85: ld a,'C' _JPZ ; ; Indicate unknown ; l3c88: ld a,'U' call l4c76 ; Put to print device jp l3c32 ; ; Found PUBLIC ; l3c90: push de push bc ld hl,(l3d3f) ; Get label address push hl inc hl ld a,e and @@mod ; Isolate address field ld b,a ld c,_DEFENT ; Set entry point inc hl ld e,(hl) ; Get address inc hl ld d,(hl) inc hl push de ld e,(hl) inc hl ld d,(hl) ex de,hl ld (l3dde),hl ; Set value pop de call l1b83 ; Output code pop hl ld (l3d3f),hl ; Reset label address inc hl ld a,(hl) and _KNOW call nz,l1ba9 ; Output entry point if known pop bc pop de ld a,'I' jp l4c76 ; Put to print device ; ; ; l3cc0: ld hl,l3e11 ld (l3e0f),hl ; Set line code pointer call l18c9 ld hl,(l3e0f) ; Get line code pointer ld (hl),0 ld hl,l3e11 jp l1ad5 ; Put line to print device ; ; ; l3cd4: push bc push hl ld a,(hl) and @@mod ; Isolate address field ld b,a ld c,_CHNEXT inc hl ld e,(hl) inc hl ld d,(hl) call l1ba9 ; Output chain external pop hl pop bc ret ; ; Data field ; l3ce6: ; Last character read from source db 0 l3ce7: db 0 l3ce8: ; Opcode value db 0 l3ce9: ; Parenthesis flag (0 is not open) db 0 l3cea: ; CPU type (0 is Z80) db 0 l3ceb: ; XOR flag (0 is not XOR) db 0 ; ; %%% INITIALIZED DATA %%% ; l3cec: ; Pass count db 0 l3ced: ; Error count dw 0 l3cef: ; Warning count dw 0 l3cf1: ; Radix db 0 l3cf2: ; .RADIX flag (0xFF is in progress) db 0 l3cf3: ; IF level 1 db 0 l3cf4: ; IF level 2 db 0 l3cf5: db 0 l3cf6: ds _iflev l3d28: db 0 l3d29: db 0 l3d2a: ; FALSE condition flag (/X option) db 0 l3d2b: ; 0=any in line, else empty db 0 l3d2c: ; Source flag (.MAC is 0, .LIB otherwise) db 0 l3d2d: ; Cross reference flag (.CREF is zero, .XCREF is not) db 0 l3d2e: ; List macro flag (.XALL is 1, .LALL -1 and .SALL 0) db 0 l3d2f: db 0 ; List flag (.LIST is not zero, .XLIST is) l3d30: db 0 l3d31: db 0 l3d32: ; Page length db 0 l3d33: ; Page count db 0 l3d34: ; Page number dw 0 l3d36: ; Page number II dw 0 l3d38: ; Line number flag db 0 l3d39: ; Possible line number input ds DigLen l3d3f: ; BFIELD pointer dw 0 l3d41: ; Symbol table pointer dw 0 l3d43: ; Symbol table pointer dw 0 l3d45: db 0 l3d46: db 0,0 l3d48: ; Source line ds SrcLen+7 l3dd1: ; Segment code flag (0, 1, 2, 3) db 0 ; (ASEG, CSEG, DSEG, COMMON) ; ; %%% INITIALIZED DATA %%% ; l3dd2: dw 0 ; ; \ ; l3dd4: ; Absolute size dw 0 l3dd6: ; Program size dw 0 l3dd8: ; Data size dw 0 l3dda: ; COMMON size dw 0 ; / ; ; ; %%% END OF INITIALIZED DATA %%% ; l3ddc: dw 0 l3dde: ; Operand value dw 0 l3de0: ; Operand 1 dw 0 l3de2: db 0 l3de3: db 0 l3de4: ; .PHASE flag (0 is .DEPHASE) db 0 l3de5: ; Phase difference dw 0 l3de7: db 0 l3de8: db 0 l3de9: ; Line starting with length byte db 0 ds 18 l3dfc: db 0,0,0,0,0,0,0,0,0,0,0,0,0,0 db 0,0,0,0,0 l3e0f: ; Line code pointer dw 0 ; ; \ ; l3e11: ; Prefix line holding addresses and code ds 32 prf.lin equ $-l3e11 ; ; / ; l3e31: ; Title ds TITLEN l3e81: ; Subtitle ds STITLEN l3ebd: db 0 l3ebe: db 0 l3ebf: dw 0 l3ec1: ; Address mode db 0 l3ec2: ; Function error (0 is not) db 0 l3ec3: ; \ REL byte db 0 ; | l3ec4: ; | REL bit count db 0 ; / l3ec5: ; Length of special item db 0 l3ec6: ; Special link item field db 0 l3ec7: ; R1,r2 flag (0 is single register) db 0 l3ec8: ; Function stack pointer dw 0 l3eca: ; Operand 2 dw 0 l3ecc: ; ID of special link item db 0 l3ecd: db 0 l3ece: ds 5 l3ed3: db 0 l3ed4: db 0 l3ed5: ; Main print line ds LinLen l3f15: ; Copy of main print line ds LinLen+1 l3f56: db 0 l3f57: ; Function type ??? db 0 l3f58: db 0 l3f59: ; Caller's PC dw 0 l3f5b: ; Output device flag (0=.PRN) db 0 l3f5c: ; Code segment db 0 l3f5d: ; Name of modulr ds 10 ; ; \ ; l3f67: ds 3 l3f6a: ds 3 l3f6d: db 0 l3f6e: ds 2 ChnLen equ $-l3f67 ; ; / ; l3f70: ; Base symbol pointer dw 0 ; ; Symbol chain arrays ; Indices : 0 $ ; 1 . ; 2 ? ; 3 _ ; 4 ; 5 @ ; 6 .. 31 A .. Z ; l3f72: ds 2*Chn.Len l3fb4: ds 2*Chn.Len l3ff6: dw 0 l3ff8: ; Macro pointer dw 0 l3ffa: ; Macro active flag (0 is not) db 0 l3ffb: db 0 l3ffc: db 0 l3ffd: dw 0 l3fff: dw 0 l4001: dw 0 l4003: dw 0 l4005: ; MACRO level db 0 l4006: db 0 l4007: dw 0 l4009: dw 0 l400b: dw 0 l400d: ; .COMMENT sync character db 0 l400e: ; Macro opening flag (0='<') db 0 l400f: db 0 l4010: db 0 l4011: ; Macro start address dw 0 l4013: ; Current macro address dw 0 l4015: db 0 l4016: ; ???? dw 0 l4018: dw 0 l401a: ; Macro count db 0 l401b: dw 0 l401d: ; Top of symbol table dw 0 l401f: dw 0 l4021: dw 0 l4023: dw 0 l4025: dw 0 ; ; %%% END OF INITIALIZED DATA %%% ; l4027: ; Stack pointer dw 0 l4029: ; Top of data dw 0 ; ; Register and condition code table ; Byte 1 coded as ccccclll with ccccc code bits ; llll length of ASCII ; Next bytes ASCII name ; Last byte register code ; ; Macro building following register and condition code entries ; ; R.CODE Entry code ; STRING Mnemonic string ; VAL Register map ; r.cc macro r.code,string,val local part,len shf aset r.code shl 3 part: db shf+len,string,val len aset $-part-2 endm l402b: ; ; Part 1 : 8 bit registers ; r.cc 10,'A',111b r.cc 10,'B',000b r.cc 10,'C',001b r.cc 10,'D',010b r.cc 10,'E',011b r.cc 10,'H',100b r.cc 10,'L',101b r.cc 10,'M',110b ; ; Part 2 : Register pairs ; r.cc 12,'SP',11b*2 r.cc 12,'PSW',110b r.cc 10,'I',1000b r.cc 10,'R',1001b r.cc 12,'BC',00b*2 r.cc 12,'DE',01b*2 r.cc 12,'HL',10b*2 r.cc 12,'AF',110b r.cc 13,'IX',044h r.cc 13,'IY',064h ; ; Part 3 : Condition codes ; r.cc 14,'NZ',000b r.cc 14,'Z',001b r.cc 14,'NC',010b r.cc 14,'P',110b r.cc 14,'PO',100b r.cc 14,'PE',101b ; ; End ; db 0 ; l4081: ; REL file indicator db 0 l4082: dw 0 l4084: db 0 l4085: ; Extra stack page count db 0 l4086: ; LST file indicator db 0 l4087: ; Drive db 0 l4088: ; /I option db 0 l4089: ; /L option db 0 l408a: ; /P option db 0 l408b: ; /R option db 0 l408c: ; /C option db 0 l408d: ; /X option db 0 l408e: ; Stop flag db 0 l408f: ; /O option db 0 l4090: ; /N option db 0 l4091: ; /M option db 0 l4092: ; Printer column db 0 l4093: ; Object FCB ds fcblen l40b4: ; List FCB ds fcblen l40d5: ; Source FCB ds fcblen l40f6:: ;;** ds 54 ; ; Filename ; l412c: ds .drv+.nam+.ext l4138: db 'REL' l413b: db 'CRF' l413e: db 'PRN' l4141: ; Object buffer position dw 0 l4143: ; Object buffer ds RELbfl l4243: ; List buffer position dw 0 l4245: ; List buffer ds LSTbfl l4445: ; Source buffer position dw 0 l4447: ; Source buffer ds SRCbfl ; ; Command buffer ; l4647: db COMLEN,0 ds COMLEN l4699: ; Command line pointer dw 0 l469b: db '?Command error',null l46aa: db '?File not found',null l46ba: db '?Can''t enter file',null ; ; Print message ^HL on console ; l46cc: ld a,(hl) ; Get character and NoMSB ret z ; End on NULL call l4aee ; Put to console inc hl jp l46cc ; ; Command error ; l46d7: ld hl,l469b jp l46e6 ; ; File not found ; l46dd: ld hl,l46aa jp l46e6 ; ; File not createable ; l46e3: ld hl,l46ba l46e6: call l46cc ; Give message jp l4758 ; Retry ; db 'COM' db 'SCN' l46f2: db 0 ds 23 l470a: dw l46f2 ; ; Cold start of M80 - ^HL points to entry address ; ; On exit ^HL points to top of memory ; Reg B and Accu hold stack page count ; l470c: ld (l412c),hl ; Save address ld de,l46f2 ; Get pointer ld a,(de) ; Get byte or a ; Test set jp z,l473c ; Nope ; ; %%% MYSTERIOUS CODE %%% ; ld a,(l470a+1) ld b,a l471b: ld a,(l470a) ld c,a ld hl,(TPATOP) ld l,0 l4724: ld a,(de) cp (hl) jp nz,l4732 inc hl inc de dec c jp nz,l4724 jp l473c l4732: inc de dec c jp nz,l4732 dec b ret z jp l471b ; ; %%% END OF MYSTERIOUS CODE %%% ; l473c: xor a ld (l46f2),a ; Clear byte ld hl,(TPATOP) ; Get top of memory dec hl ld sp,hl ; Set for stack dec hl dec hl ld (l4082),hl ; Save address ld hl,(l412c) ; Get entry address push hl ; Save for return ld a,(l408e) ; Test stop or a jp nz,OS ; Yeap, so abort ld (l4085),a ; Clear extra stack page count l4758: ld hl,(l4082) ; Get top of address ld sp,hl ; Set for stack call l4a4b ; Input command line ld a,(l4647+2) ; Get first character cp cr ; Test empty line jp z,l4758 ; Retry if so xor a ; Clear ... ld (l4092),a ; ... printer column ld (l4089),a ; ... /L option ld (l4090),a ; ... /N option ld (l408f),a ; ... /O option ld (l408c),a ; ... /C option ld (l408d),a ; ... /X option ld (l408b),a ; ... /R option ld (l4091),a ; ... /M option inc a ; Set ... ld (l408a),a ; ... /P option ld (l4088),a ; ... /I option ld bc,l46d7 ; Set error return push bc xor a ld (l4081),a ; Enable REL file call l48e1 ; Scan line for filename and options ret c ; Error ld de,l4138 call l48c4 ; Set .REL ld de,l412c+.drv ; Point to name of file ld a,(de) cp ' ' ; Test name jp nz,l47a7 ; Yeap ld a,RELf ld (l4081),a ; Indicate no REL file l47a7: push hl ld hl,l4093 call l48b8 ; Unpack object file name pop hl ld a,' ' ld (l412c+.drv),a ; Clear name of file ld (l412c+.drv+.nam),a xor a ld (l412c),a ; Set default drive ld a,c sub ',' ; Test file delimiter or a ld (l408b),a ; Set /R option jp nz,l47d1 ; Got it ld a,(l4081) xor RELf ld (l408b),a ; Set /R option call l48e1 ; Scan line for filename and options ret c ; Error l47d1: ld de,l413e ld a,(l408c) ; Test /C option or a jp z,l47de ; Nope ld de,l413b l47de: call l48c4 ; Set .PRN or .CRF ld de,l412c+.drv ; Point to name of file ld a,(l412c) ; Get drive ld (l4087),a ; Save it ld a,(de) sub ' ' ; Test name of file ld (l4086),a ; Save flag jp nz,l47fb ; Got file ld a,(l4081) ; Get REL file indicator add a,LSTf ; Insert bit ld (l4081),a l47fb: push hl ld hl,l40b4 call l48b8 ; Unpack list filename pop hl ld a,c cp '=' ; Verify assignment scf ret nz ; Should be call l48e1 ; Scan line for filename and options cp cr ; Verify end scf ret nz ; Error ld de,l0106 call l48c4 ; Set .MAC ld de,l412c ; Point to drive ld a,(de) inc de or a ; Test device jp m,l4823 ; Yeap ld a,(de) cp ' ' ; Verify name given scf ret z ; Should be l4823: push hl ld hl,l40d5 call l48b8 ; Unpack source filename pop hl ld a,(l4081) ; Get REL file indicator add a,a ld hl,l4093 ; Point to object file call c,l4898 ; Got no REL file, do unpack it add a,a ld hl,l40b4 ; Point to list file push af ld a,(l408c) ; Test /C option or a jp z,l4853 ; Nope ld de,l40b4+.drv+.nam ld bc,l413b ld a,.ext l4849: push af ld a,(bc) ; Set extension .CRF ld (de),a inc de inc bc pop af dec a jp nz,l4849 l4853: pop af call c,l4898 ; Got no LST file, so unpack it ld a,(l4089) ; Test /L option or a jp nz,l4868 ; Yeap ld a,(l4086) ; Test LST file or a jp nz,l4868 ; Yeap ld a,(l4087) ; Get drive l4868: ld (l4089),a ; Set /L option ld c,.retdsk call BDOS ; Get current disk push af ld c,.resdsk call BDOS ; Reset disk system pop af ld e,a ld c,.seldsk call BDOS ; Select disk xor a ld (CCP),a ; Clear CCP input call l4b84 ; Prepare source file call l4b25 ; Prepare list file call l4b3b ; Prepare object file pop hl ; Clean error return ld hl,(l4082) ; Get back top address inc hl inc hl ld a,(l408a) ; Get /P option ld (l4085),a ; Save pages ld b,a ret ; ; Get FCB in ^HL ; l4898: push af ld de,l412c ; Point to drive ld c,.drv+.nam ld a,(hl) ; Test drive given or a jp nz,l48b2 ; Yeap ld a,(de) or a ; Test device jp m,l48b2 ; Yeap l48a8: ld a,(de) ; Unpack FCB ld (hl),a inc hl inc de dec c jp nz,l48a8 l48b0: pop af ret l48b2: dec c ; Skip drive or device inc hl inc de jp l48a8 ; ; Unpack filename ^DE -> ^HL ; l48b8: dec de ; Fix for drive ld b,.drv+.nam+.ext l48bb: ld a,(de) ; Unpack D:FN.EX ld (hl),a inc hl inc de dec b jp nz,l48bb ret ; ; Set default extension ^DE ; l48c4: ld a,(l4084) ; Get dot indicator or a ret z ; Got extension push hl ld hl,l412c+.drv+.nam ld a,(hl) cp ' ' ; Test extension jp nz,l48df ; Yeap ld b,.ext l48d5: ld a,(de) ; Get default extension and NoMSB ld (hl),a ; Unpack it inc hl inc de dec b jp nz,l48d5 l48df: pop hl ret ; ; Scan line for filename and options ; C set says error ; l48e1: call l4a2a ; Check line cp ':' ; Test drive delimiter scf ld a,0 jp nz,l4905 ; Nope, set default drive ld a,b ; Get length of line or a jp z,l48e1 ; Empty line, so retry ex de,hl call l4ad7 ; Test character ld c,a ; Save it ld a,b dec a ld a,c jp nz,l4926 ; Maybe devices cp 'Z'+1 ; Verify range of drive ret nc cp 'A' ret c sub 'A'-1 ; Build drive ex de,hl l4905: ld (l412c),a ; Save drive call nc,l4a2a ; Check line ld a,b ; Get length cp .nam+.ext ; Check range jp c,l4913 ld b,.nam+.ext ; Truncate if necessary l4913: push bc ex de,hl push de ld de,l412c+.drv ; Point to filename inc b l491a: dec b jp z,l496f call l4ad7 ; Get name character ld (de),a ; Unpack it inc de jp l491a l4926: cp 'T' ; Test 'TTY' jp nz,l493f call l4ad7 ; Get character cp 'T' scf ret nz call l4ad7 ; Get character cp 'Y' scf ret nz sbc a,a ; Map to 0FFH ex de,hl or a jp l4905 l493f: cp 'L' ; Test 'LST' jp nz,l4959 call l4ad7 ; Get character cp 'S' scf ret nz call l4ad7 ; Get character cp 'T' scf ret nz ld a,0feh ; Map to 0FEH ex de,hl or a jp l4905 l4959: cp 'R' ; Test 'RDR' scf ret nz call l4ad7 ; Get character cp 'D' scf ret nz cp 'R' scf ret nz ld a,0feh ; Map to 0FEH ex de,hl or a jp l4905 l496f: pop hl pop bc ld a,.drv+.nam+1 sub b ; Test empty space jp c,l4980 ex de,hl l4978: ld (hl),' ' ; Blank it inc hl dec a jp p,l4978 ex de,hl l4980: ld a,c ; Get delimiter ld b,0 sub '.' ; Check for dot ld (l4084),a call z,l4a2a ; Check line ex de,hl push de ld de,l412c+.drv+.nam ld a,b ; Get length cp .ext+1 ; Test length jp c,l4998 ld b,.ext ; Set max extension l4998: inc b l4999: dec b jp z,l49a5 call l4ad7 ; Get extension character ld (de),a ; Unpack it inc de jp l4999 l49a5: pop hl l49a6: ld a,c sub '/' ; Test possible option or a ld a,c ret nz ; Nope call l4ad7 ; Get character cp 'L' ; Test /L listing jp nz,l49be ld (l4089),a ; Set /L option l49b7: call l4ad7 ; Get character ld c,a ; Save it jp l49a6 l49be: cp 'N' ; Test /N option jp nz,l49c9 ld (l4090),a ; Set /N option jp l49b7 l49c9: cp 'O' ; Test /O octal listing jp nz,l49d4 ld (l408f),a ; Set /O option jp l49b7 l49d4: cp 'R' ; Test /R rel file jp nz,l49df ld (l408b),a ; Set /R option jp l49b7 l49df: cp 'C' ; Test /C cross reference jp nz,l49ed ld (l408c),a ; Set /C option ld (l4089),a ; Set /L option jp l49b7 l49ed: cp 'M' ; Test /M DS initialize jp nz,l49f8 ld (l4091),a ; Set /M option jp l49b7 l49f8: cp 'I' ; Test /I INTEL jp nz,l4a03 ld (l4088),a ; Set /I option jp l49b7 l4a03: cp 'X' ; Test /X suppress false listing jp nz,l4a10 ld a,TRUE ld (l408d),a ; Set /X option jp l49b7 l4a10: cp 'Z' ; Test /Z ZILOG jp nz,l4a1c xor a ld (l4088),a ; Clear /I option jp l49b7 l4a1c: cp 'P' ; Test /P extra stack page scf ret nz ld a,(l408a) inc a ; Advance /P count ld (l408a),a jp l49b7 ; ; Count symbolic characters in ^HL ; On exit Accu and reg C hold closing character ; Reg B holds length of characters ; ^HL points to closing character ; ^DE holds start of character ; l4a2a: ld b,0 ; Clear count push hl ; Save pointer l4a2d: call l4ad7 ; Get character cp 'Z'+1 ; Test range A..Z jp nc,l4a48 cp '0' ; Or 0..9 jp c,l4a48 cp 'A' jp nc,l4a44 cp '9'+1 jp nc,l4a48 l4a44: inc b ; Count characters jp l4a2d l4a48: ld c,a ; Save closing one pop de ; Get back start pointer ret ; ; Input command line ; l4a4b: push bc push de ld hl,CCP ; Point to CCP line ld a,(hl) ; Get length ld (hl),0 ; Reset it or a ; Test any in buffer ld b,a l4a55: jp z,l4a7a ; Buffer empty inc hl ld a,(hl) cp ' ' ; Skip leadinf blanks jp nz,l4a63 dec b jp l4a55 l4a63: ld de,l4647+1 ; Point to local buffer ld a,b dec hl inc b l4a69: ld (de),a ; Unpack command line inc de inc hl dec b jp z,l4a74 ld a,(hl) jp l4a69 l4a74: ld (l408e),a ; Set stop flag jp l4a9a l4a7a: xor a ld (l408e),a ; Reset stop flag ld a,(l4085) or a jp nz,l4a8d call l4b1b ; Give new line ld a,'*' call l4aee ; Indicate input requested l4a8d: ld c,.rdkbd ld de,l4647 call BDOS ; Read line from console ld a,lf call l4aee ; Close line l4a9a: pop de pop bc ld a,(l4647+1) ; Get length of line ld hl,l4647+2 ; Point to start push hl ld (l4699),hl ; Init command line add a,l ld l,a ; Point to end ld a,0 adc a,h ld h,a ld (hl),cr ; Close command line inc hl ld a,lf ld (hl),a pop hl ld a,(l4085) or a jp nz,l4ad6 push hl ld hl,l4647+2 ; Point to start again l4abe: ld a,(hl) ; Get character cp cr ; Test end of line jp z,l4ad5 sub 'a' ; Test lower case jp c,l4ad1 cp 'z'-'a'+1 jp nc,l4ad1 add a,'A' ; Convert to upper case ld (hl),a l4ad1: inc hl jp l4abe l4ad5: pop hl l4ad6: ret ; ; Test character in ^HL ; C set indicates end of file ; l4ad7: ld a,(hl) ; Get character inc hl cp ' ' ; Skip blanks jp z,l4ad7 cp lf ; And line feed jp z,l4ad7 cp cr ; Test end of line jp nz,l4b15 ; Nope inc hl ld (l4699),hl ; Save command line ret ; ; Put character on stack to console ; l4aed: pop af ; Get character ; ; Put character in Accu to console ; l4aee: push hl push de push bc push af ld c,.conout and NoMSB ; Less hi bit ld e,a call BDOS ; Put it pop af pop bc pop de pop hl or a ret ; ; Get character from CON for source file ; l4b00: push hl ld hl,(l4699) ; Get command line pointer dec hl ld a,(hl) ; Fetch character and NoMSB ; Less hi bit cp lf ; Test new line inc hl call z,l4a4b ; Input new line if so inc hl ld (l4699),hl ; Set new pointer dec hl l4b13: ld a,(hl) ; Get character pop hl l4b15: cp eof ; Test end of file scf ret z ; Yeap or a ret ; ; Give new line on console ; l4b1b: ld a,cr call l4aee ; Just put it ld a,lf jp l4aee ; ; Prepare list file ; l4b25: push af push bc push de push hl ld de,l4245 ; Get list buffer ld hl,0 ld (l4243),hl ; Clear buffer position ld hl,l40b4 ; Point to list file ld a,(l4089) ; Get /L option jp l4b4e ; ; Prepare object file ; l4b3b: push af push bc push de push hl ld de,l4143 ; Get object buffer ld hl,0 ld (l4141),hl ; Clear buffer position ld hl,l4093 ; Point to object file ld a,(l408b) ; Get /R option ; ; Prepare ^HL file for write ; ^DE points to disk buffer, Accu holds enable flag ; l4b4e: or a jp z,l4b7f ; Not enabled push hl ld c,.setdma call BDOS ; Set disk buffer pop hl ld a,(hl) or a ; Test device jp m,l4b7f ; Yeap, skip call l4ba1 ; Set up FCB push de ld c,.delete call BDOS ; Delete file pop de push de ld c,.make call BDOS ; Create file inc a ; Test success jp z,l46e3 ; Error pop hl ; ; Open file ^DE ; l4b73: call l4ba1 ; Set up FCB ld c,.open call BDOS ; Open file inc a ; Test success jp z,l46dd ; Error l4b7f: pop hl pop de pop bc pop af ret ; ; Prepare source file ; l4b84: push af push bc push de push hl ld hl,SRCbfl ld (l4445),hl ; Init source buffer position ld de,l4447 ld c,.setdma call BDOS ; Set disk buffer ld hl,l40d5 ; Point to source file ld a,(hl) or a ; Test CON/RDR jp m,l4b7f ; Yeap, skip it jp l4b73 ; Open file ; ; Set up FCB ^HL ; l4ba1: push hl push de ld de,_EX add hl,de ; Point to extend xor a ld d,_DIR-_EX l4baa: ld (hl),a ; Clear system bytes inc hl dec d jp nz,l4baa ld de,_CR-_DIR add hl,de ld (hl),a ; Clear current record pop hl pop de ret ; ; Close source file ; l4bb8: push af push de ld de,l40d5 ; Point to source file ld a,(de) or a ; Test CON/RDR jp m,l4bd8 ; Yeap push bc push hl push de ld de,l4447 ld c,.setdma call BDOS ; Set disk buffer pop de _LDBC ; ; Close file ^DE ; l4bcf: push bc push hl ld c,.close call BDOS ; Close file pop hl pop bc l4bd8: pop de pop af ret ; ; Put character to list device ; l4bdb: push af ld a,(l4089) ; Test /L option or a jp z,l48b0 ; Not set push de ld a,(l40b4) ; Get list device inc a jp z,l4bd8 ; CON jp m,l4c64 ; LST ld a,cr call l4c76 ; New line to print device ld a,lf call l4c76 ld a,eof call l4c76 push hl ld hl,(l4243) ; Get buffer position ld de,l4245 ; Get buffer push bc ld bc,l40b4 ; Point to list file call l4c4e ; Empty buffer ld de,l4245 ld c,.setdma call BDOS ; Set list buffer pop bc pop hl ld de,l40b4 ; Point to list file jp l4bcf ; Close it ; ; Close REL file ; l4c1b: push af ld a,(l408b) ; Test /R option or a jp z,l48b0 ; Not set push de ld a,(l4093) ; Get object device or a jp m,l4bd8 ; LST or CON ld a,eof call l4cdd ; Write end of file push hl ld hl,(l4141) ; Get buffer position ld de,l4143 ; Get buffer push bc ld bc,l4093 ; Point to object file call l4c4e ; Empty buffer ld de,l4143 ld c,.setdma call BDOS ; Set disk buffer pop bc pop hl ld de,l4093 ; Point to object file jp l4bcf ; Close it ; ; Empty disk buffer ^DE to FCB ^BC with record position in reg HL ; l4c4e: ld a,h ; Test any in buffer or l ret z ; Nope ld a,l and reclng-1 ; Mask pointer jp z,l4c59 add a,reclng ; Add carry l4c59: rla rla and 3 add hl,hl add a,h ; Calculate record count ld h,b ; Get FCB ld l,c jp l4cad ; Write to disk ; ; Close printer page ; l4c64: ld a,cr ; Close line call l4c76 ld a,lf call l4c76 ld a,ff call l4c76 ; Get new page pop de pop af ret ; ; Put character to print device ; l4c76: push af ; Save character ld a,(l4089) ; Test /L option or a jp z,l48b0 ; Not set ld a,(l40b4) ; Get list device inc a jp z,l4aed ; CON jp m,l4d55 ; LST ex (sp),hl push hl push de ld hl,(l4243) ; Get buffer position ld a,h cp HIGH LSTbfl ; Test buffer filled call z,l4ca5 ; Yeap inc hl ; Advance position ld (l4243),hl ld de,l4245-1 add hl,de pop de pop af push af and NoMSB ld (hl),a pop af pop hl ret l4ca5: ld de,l4245 ; Point to list buffer ld hl,l40b4 ; Point to list file ld a,LSTrec ; ; Write records from buffer ^DE to file ^HL; record count in Accu ; l4cad: push af push bc push de push hl ld c,.setdma call BDOS ; Set disk buffer pop de push de ld c,.wrseq call BDOS ; Write record or a ; Verify success jp nz,l4da1 ; Error pop de pop hl ld bc,reclng add hl,bc ; Advance buffer pointer ex de,hl pop bc pop af dec a ; Count down jp nz,l4cad ld hl,0 ; Return base position ret ; ; Write buffer to object file ; l4cd2: ld de,l4143 ; Point to object buffer ld a,RELrec ; Set length ld hl,l4093 ; Point to object file jp l4cad ; Write records ; ; Write byte in Accu to object file ; l4cdd: push af ld a,(l408b) ; Test /R option or a jp z,l48b0 ; Not set ld a,(l4093) ; Get object drive or a jp m,l4aed ; LST or CON ex (sp),hl push hl push de ld hl,(l4141) ; Get buffer position ld a,h dec a ; Test buffer filled call z,l4cd2 ; Yeap, empty it inc hl ; Advance buffer ld (l4141),hl ld de,l4143-1 add hl,de ; Position in buffer pop de pop af ld (hl),a ; Store byte pop hl ret ; ; Get character from source file ; C set indicates end of file ; l4d04: ld a,(l40d5) ; Point to source file inc a ; Test device jp z,l4b00 ; CON jp m,l4d90 ; RDR push hl push de ld hl,(l4445) ; Get source buffer position ld a,h cp HIGH SRCbfl ; Test buffer scanned call z,l4d25 ; Yeap inc hl ; Advance buffer position ld (l4445),hl ld de,l4447-1 add hl,de pop de jp l4b13 l4d25: ld de,l4447 ; Point to buffer ld a,SRCrec ; Get record count l4d2a: push af push de push bc ld c,.setdma call BDOS ; Set disk buffer ld de,l40d5 ; Point to source file ld c,.rdseq call BDOS ; Read record pop bc pop de dec a ; Test end of file jp z,l4d4e ; Yeap ld hl,reclng add hl,de ; Advance address ex de,hl pop af dec a jp nz,l4d2a l4d4a: ld hl,0 ; Return zero position ret l4d4e: pop af ld a,eof ld (de),a ; Set end of file jp l4d4a l4d55: pop af ; Get character push hl push de push bc push af ld c,.lstout ; Set BDOS code and NoMSB ld e,a ; Save character ld hl,l4092 ; Point to printer column cp ' ' ; Test printable jp nc,l4d73 ; Yeap sub cr ; Test start of line jp z,l4d71 ; Yeap inc a ; Test form feed jp z,l4d71 ; Yeap ld a,(hl) ; Get current column l4d71: dec a ; Get previous column ld (hl),a ; Save l4d73: inc (hl) ; Advance column ld a,e ; Get character cp tab ; Test tabulator jp nz,l4d88 ; Nope l4d7a: ld a,' ' call l4c76 ; Give blanks to printer ld a,(hl) ; Get position and COLTAB ; Test tab stop jp nz,l4d7a ; Nope jp l4d8b l4d88: call BDOS ; Put to printer l4d8b: pop af pop bc pop de pop hl ret ; ; Get character from RDR for source file ; l4d90: push hl push de push bc ld c,.rdrin call BDOS ; Get character pop bc pop de pop hl cp eof ; Test end of file scf ret z or a ret ; ; Process disk write error ; l4da1: ld hl,l4dc1 call l46cc ; Tesll disk full pop de ld a,(de) ; Get drive add a,'A'-1 ; Make ASCII cp 'A'-1 ; Test default drive jp nz,l4db2 ; Nope ld a,' ' ; Print blank if default l4db2: call l4aee ; Put to console ld hl,l4dc7 call l46cc call l4b1b ; Give new line jp OS ; End exit ; l4dc1: db 'DISK ',null l4dc7: db ' FULL',null l4dcd: ds fcblen l4dee: ; Include file record pointer db 0 l4def: ; Include file buffer address dw 0 l4df1: ; Include file buffer ds reclng ; ; Prepare include file from ^DE ; l4e71: push hl push de push bc ex de,hl ld hl,l4dcd ; Point to include file inc de ; Skip possible drive ld a,(de) ; Get next character dec de cp ':' ; Test drive delimiter ld a,0 jp nz,l4e8c ; Nope, set default disk ld a,(de) ; Get drive inc de sub 'A'-1 ; Make binary cp 'Z'+1-('A'-1) ; Verify correct range jp nc,l4ef0 ; Nope inc de l4e8c: ld (hl),a ; Save drive inc hl ld b,.nam ; Set length of name l4e90: ld a,(de) ; Get character inc de ld (l4084),a ; Save it cp '.' ; Test extension delimiter jp z,l4eb7 ; Yeap cp ' '+1 ; Test valid range jp c,l4eb7 ; Nope ld (hl),a ; Unpack name inc hl dec b jp nz,l4e90 l4ea5: ld a,(de) ; Get character inc de ld (l4084),a ; Save it cp '.' ; Test extension delimiter jp z,l4ebe ; Yeap cp ' '+1 ; Skip valid characters jp nc,l4ea5 jp l4ebe l4eb7: ld (hl),' ' ; Blank final name part inc hl dec b jp nz,l4eb7 l4ebe: ld b,.ext ; Set length of extension ld a,(l4084) ; Get last character cp '.' ; Test extension delimiter jp z,l4ecb ; Yeap, skip ld de,l0106 ; Set default .MAC l4ecb: ld a,(de) inc de ld (hl),a ; Unpack extension inc hl dec b jp nz,l4ecb ld (hl),b ; Clear extent ld de,l4df1 ld c,.setdma call BDOS ; Set include file buffer ld de,l4dcd ld c,.open call BDOS ; Open include file cp CPMerr jp z,l4ef0 xor a ld (l4dcd+_CR),a ; Clear current record ld (l4dee),a ; Clear record pointer l4ef0: pop bc pop de pop hl ret ; ; Get character from include file into Accu ; C set indicates end of file ; l4ef4: push hl push de push bc ld a,(l4dee) ; Get record pointer dec a jp p,l4f1b ; Still any in buffer ld de,l4df1 ld c,.setdma call BDOS ; Set include file buffer ld de,l4dcd ld c,.rdseq call BDOS ; Read record from include file add a,CPMerr ; Test end of file jp c,l4f30 ; Yeap ld hl,l4df1 ld (l4def),hl ; Reset include file buffer address ld a,reclng-1 l4f1b: ld (l4dee),a ; Update record pointer ld hl,(l4def) ; Get buffer address ld a,(hl) cp eof ; Test end of file jp nz,l4f2b ; Nope scf jp l4f30 l4f2b: inc hl ; Update address ld (l4def),hl ; save it or a l4f30: pop bc pop de pop hl ret ; ; Close include file ; l4f34: ret l4f35: db '0' ; ds 74,0 l4f80:: ;;** end