title PCW utilities name ('PCW') ; The utility sampler for PCW machines ; This program combines the seven AMSTRAD utilities ; Combined by W.Cirsovius, April 1991 ; Call it: PCW -utility {options} ; Utility and options are defined as: ; LANGUAGE option ; PALETTE option1 option2 ; SET24X80 ON or OFF ; SETKEYS file ; PAPER {option {option..}} ; SETLST file ; SETSIO {option {option..}} ; FALSE equ 0 TRUE equ NOT FALSE ; GERMAN equ TRUE ; Select German messages ;GERMAN equ FALSE ; Select English messages ; OS equ 0000h BDOS equ 0005h FCB equ 005ch CCPcmd equ 0080h _Conout equ 2 _Lstout equ 5 _Condir equ 6 _String equ 9 _vers equ 12 _Open equ 15 _RdSeq equ 20 _SetDMA equ 26 _Parse equ 152 RecLng equ 128 _OSErr equ 0ffh FN equ 11 CPM31 equ 031h _DevTbl equ 20 _Userf equ 30 _PCW equ 1 SA.INIT equ 00b6h SA.BAUD equ 00b9h SA.PARA equ 00bch KM.EXP equ 00d4h KM.KEY equ 00d7h CD.VERS equ 00e3h nul equ 00h tab equ 09h cr equ 0dh lf equ 0ah esc equ 1bh eot equ '$' eof equ 'Z'-'@' eos equ -1 LoMask equ 00001111b Mask equ 00111111b LowBits equ 00000011b ALL equ 11111111b ASCmask equ 00011111b COMRAM equ 0c000h DevLen equ 8 XON.XOF equ 00010000b MSB equ 7 _IG equ 0 _AN equ 1 _HX equ 2 _NM equ 3 _EX equ 4 _EO equ 5 _SG equ 6 _Def equ 2 _Gap equ 3 _Lines equ 4 _Pitch equ 5 _Defeat equ 6 _Sheet equ 7 Ln.Gap equ 1 SHL _Lines + 1 SHL _Gap ; ; %%%%%%%%%%%%%%%%%%%%%%%%% ; %%% START THE UTILITY %%% ; %%%%%%%%%%%%%%%%%%%%%%%%% ; PCW: ld sp,(BDOS+1) ; Get local stack call GetVersion ; Get machine version call PrepCCPLine ; Prepare command line call SelectOption ; Select an option call JPr ; Process option jp OS ; .. bye, bye ; ; Select an option ; SelectOption: call GetAttr ; Get attribute jr nz,InvSel ; .. should not be end bit _SG,a ; Test - call Get jr z,SelectOption ; .. nope, try it ld hl,$MCMD.TAB call FindStr ; Get option ld a,l or h ret nz ; .. ok InvSel: ld de,$INV.SEL call String ; Invalid jp OS $INV.SEL: IF GERMAN db 'Falsches Programm ausgew{hlt' ELSE db 'Invalid utility selected' ENDIF $CRLF: db cr,lf,eot $MCMD.TAB: db 'LANGUAGE',eos dw Language db 'PALETTE',eos dw Palette db 'SET24X80',eos dw Set24x80 db 'SETKEYS',eos dw Setkeys db 'PAPER',eos dw Paper db 'SETLST',eos dw Setlst db 'SETSIO',eos dw SetSIO db eos,0,0 ; ; Execute via register ; ENTRY Reg HL points to address ; JPr: jp (hl) ; ; Find string from table ; ENTRY Reg HL points to table ; EXIT Reg L holds 1st operand ; Reg H holds 2nd operand or -1 if not found ; FindStr: push de push bc push af call ChrGet ; Get valid character ld d,b ; Save attribute dec hl ; .. fix list jr FS.go FS..unget: inc e FS.unget: dec e call nz,UnGet ; Unget character jr nz,FS.unget FS.skip: ld a,(hl) ; Get character inc hl inc a jr nz,FS.skip ; .. skip item inc hl FS.go: ld e,0 ; Init counter jr FS.cmp FS.loop: call CmpChr ; Compare character jr nz,FS..unget ; .. not found call Get ; Get character from file inc e FS.cmp: call GetChr ; Get character and attribute inc hl ld a,(hl) cp eos ; Test end of string jr nz,FS.loop ; .. nope inc e dec e ; Test total end jr z,FS.end ; .. yeap ld a,b xor d ; Test same attribute and 00101011b ; Test result jr z,FS..unget ; .. still searching FS.end: inc hl ld e,(hl) ; Get operands inc hl ld d,(hl) ex de,hl ; .. into right reg pop af pop bc pop de ret ; ; Compare characters ; ENTRY Accu and reg C hold characters ; EXIT Zero set if same ; CmpChr: sub c ; Compare ret z ; .. found cp -' ' ; Test blank ???? ret nz ; .. nope ld a,b or 11111101b ; Fix attribute inc a ; .. fix result ret ; ; Decode from table ; ENTRY Reg HL points to table ; Entry: Command key, execution address ; Closed by -1, execution address ; EXIT Reg HL holds execution address ; Decode: push de push bc push af call ChrGet ; Get character jr Dec.go ; .. start Dec.loop: inc hl ; Skip address inc hl Dec.go: ld a,(hl) ; Get character inc hl cp eos ; Test end of table jr z,Dec.ex call CmpChr ; Find character jr nz,Dec.loop Dec.skip: call Get ; Skip alphanumeric characters call GetChr bit _AN,b jr nz,Dec.skip Dec.ex: ld e,(hl) ; Fetch address inc hl ld d,(hl) ex de,hl pop af pop bc pop de ret ; ; Get version of machine ; GetVersion: ld c,_vers call BDOS ; Get OS version cp CPM31 ; Test CP/M+ jr nz,InvalEnv ; .. should be ld hl,(OS+1) ld de,3*(_Userf-1) add hl,de ld (Userf+1),hl ; Set USERF vector ld de,3*(_DevTbl-_Userf) add hl,de ld (DevTbl+1),hl call GetType ; Get machine type cp _PCW ; Should be PCW ret z ; ; Tell invalid environment ; InvalEnv: push de ld de,$INVENV call String ; Print error pop de ret $INVENV: IF GERMAN db 'Programm l{uft nicht an dieser Maschine' ELSE db 'This program will not run in this environment' ENDIF db cr,lf,eot ; ; Tell file not found ; OpenErr: push de ld de,$CANNOT call String ; Print error pop de ret $CANNOT: IF GERMAN db 'Datei nicht vorhanden' ELSE db 'Cannot open file' ENDIF db cr,lf,eot ; ; Process error ; ENTRY Reg DE points to error message ; ProcErr: push bc push af call String ; Print error call GetAttr ; Test EOL or EOF jr nz,PE.ex ; .. yeap ld de,$IGNORE call String ; Tell ignoring jr PE.go PE.loop: ld a,c call Conout ; Print character PE.go: call GetChr ; Get character and attribute call GetAttr ; Test EOL or EOF call Get ; Get character jr z,PE.loop ; .. there is more to print ld de,$CRLF call String ; .. close line PE.ex: pop af pop bc ret $IGNORE: IF GERMAN db 'Rest der Zeile wird ignoriert: ',eot ELSE db 'Ignoring rest of line: ',eot ENDIF ; ; Execute BIOS function 30 : USERF ; Userf: jp $-$ ; ; Get type of machine ; EXIT Accu holds type of machine ; GetType: call Userf ; .. get type dw CD.VERS ret ; ; Execute BIOS function 20 : DEVTBL ; EXIT Reg HL points to device table ; DevTbl: jp $-$ ; ; Set SIO ; ENTRY Accu holds mode ; Reg D holds stop bits ; Reg E holds parity ; Reg H holds receiver data bits ; Reg L holds transmitter data bits ; InitSIO: call Userf dw SA.INIT ; .. init SIO ret ; ; Get current SIO settings ; EXIT Accu holds mode ; Reg B holds receiver baud rate ; Reg C holds transmitter baud rate ; Reg D holds stop bits ; Reg E holds parity ; Reg H holds receiver data bits ; Reg L holds transmitter data bits ; GetSIO: call Userf dw SA.PARA ; .. get SIO ret ; ; Set baud rate for SIO ; ENTRY Reg H holds receiver baud rate ; Reg L holds transmitter baud rate ; SetBAUD: call Userf dw SA.BAUD ; .. set baud rates ret ; ; Store key translation ; ENTRY Reg C holds number of key to be set ; Reg D holds key state ; Reg B holds new value for the key ; StoreKey: call Userf ; .. set translation dw KM.KEY ret ; ; Store token string ; ENTRY Reg B holds token number ; Reg C holds length of string ; Reg HL points to string in COMMON memory ; EXIT Carry set indicates success ; StoreToken: call Userf ; .. set translation dw KM.EXP ret ; ; Print character on console via BDOS ; ENTRY Accu holds character ; Condir: push hl push de push bc push af ld e,a ld c,_Condir call BDOS ; .. print pop af pop bc pop de pop hl ret ; ; Print blabk on console ; Blank: push af ld a,' ' call Conout ; Print blank pop af ret ; ; Print character on console ; ENTRY Accu holds character ; Conout: push hl push de push bc push af ld e,a ld c,_Conout call BDOS ; .. print pop af pop bc pop de pop hl ret ; ; Print string from table ; ENTRY Accu holds value ; Reg DE points to table ; Table starts with number of entries ; Each strings ends with value ; TableStr: push hl push de push bc push af ld c,a ; Get value ex de,hl ld b,(hl) ; Get entry inc hl ld e,l ; Copy string ld d,h inc b ; Test special end of table jr z,TS.swap TS.skip: ld a,(de) ; Find end of sub-string inc de cp eot jr nz,TS.skip ld a,(de) ; Get next value inc de cp c ; .. compare jr z,TS.string TS.swap: dec b ; Count down jr nz,TS.skip ex de,hl TS.string: call String ; .. print string pop af pop bc pop de pop hl ret ; ; Print string on console ; ENTRY Reg DE points to string closed by '$' ; String: push hl push de push bc push af ld c,_String call BDOS ; .. print pop af pop bc pop de pop hl ret ; ; Print character on printer ; ENTRY Accu holds character ; Lstout: push hl push de push bc push af ld e,a ld c,_Lstout call BDOS ; .. print pop af pop bc pop de pop hl ret ; ; Parse file ; ENTRY Reg HL points to file string ; Parse: ld (PB),hl ; .. set file ld de,PB ld c,_Parse call BDOS ; .. get file ld a,l or h ; Verify end ret z ld de,$ILL.LIN call String ; Give error jp OS ; .. and stop PB: dw 0,FCB $ILL.LIN: IF GERMAN db 'Ung}ltiger Dateiname' ELSE db 'Invalid file name' ENDIF db cr,lf,eot ; ; Verify no wild card in file ; NoWild: ld hl,FCB+1 ld bc,FN ld a,'?' cpir ; Find it ret nz ; .. ok ld de,$WCARD call String ; Give error jp OS ; .. and stop $WCARD: IF GERMAN db '? und * sind nicht erlaubt im Dateinamen' ELSE db 'Invalid wild card in file name' ENDIF db cr,lf,eot ; ; Prepare definition file ; GetFile:: ld hl,(CmdPtr) ; Get current line call Parse ; Parse file call NoWild ; Verify no wild card xor a ld (RecPtr),a ; Clear pointer ld hl,Buff1 ; Init buffer ld (BufPtr),hl ld de,FCB ld c,_Open call BDOS ; Find file cp _OSErr ; Test file here jp nc,OpenErr ; .. nope call ChgVec ; Change GET and UNGET call Get ; .. and get from file ret ; ; Prepare CCP command line ; PrepCCPLine: ld hl,CCPcmd ld a,(hl) ; Fetch length of input ld c,a inc a ld (CCPlen),a ; .. save it inc hl ld (CmdPtr),hl ; Init buffer ld b,0 add hl,bc ; Point to end of line ld (hl),nul ; Close line dec a ; Test any jp z,Help ; .. nope ld hl,CmdGet ld (Get+1),hl ; Set vectors ld hl,CmdUnGet ld (UnGet+1),hl ; ; Get character from command line ; Store character and attribute ; CmdGet: push hl push de push bc push af ld hl,(CmdPtr) ; Get current pointer ld c,(hl) ; .. get character ex de,hl call PutChr ; .. save it ld a,c cp nul ; Test end of line jr z,CmdGet.eof ld a,(CCPlen) dec a ; Fix pointers ld (CCPlen),a ex de,hl inc hl ld (CmdPtr),hl CmdGet.eof: pop af pop bc pop de pop hl ret ; ; Get character from file ; Put result into memory ; FGet: push hl push de push bc push af ld a,(RecPtr) ; Get pointer or a jr nz,Get.Buff ; .. not empty ld hl,(BufPtr) ; Get pointer ld de,Buff1 ; Test position sbc hl,de jr nz,Get.mem ; .. not at start ld de,Buff1 call RdRec ; Read record ld a,RecLng ld (RecPtr),a ; Set buffer filled jr Get.Buff Get.mem: ld a,l cp RecLng ; Test at start of 2nd buffer jr z,Get.at2nd ; .. yeap ld bc,RecLng ld de,Buff1 ld hl,Buff2 ldir ; Unpack record Get.at2nd: ld de,Buff2 call RdRec ; Get record ld a,RecLng ld (RecPtr),a ; Set buffer filled ld hl,Buff2 ld (BufPtr),hl ; Set other buffer Get.Buff: ld hl,(BufPtr) ; Get buffer ld c,(hl) ; .. fetch character ex de,hl call PutChr ; Save character and attribute ld a,c cp eof ; Test end of file jr z,FGet.eof ; .. yeap ld a,(RecPtr) dec a ; Fix pointers if not ld (RecPtr),a ex de,hl inc hl ld (BufPtr),hl FGet.eof: pop af pop bc pop de pop hl ret ; ; Read record from file ; ENTRY Reg DE holds buffer ; RdRec: push de ld c,_SetDMA call BDOS ; Set disk buffer ld de,FCB ld c,_RdSeq call BDOS ; Read record pop hl ; Get back buffer or a ; Test more ret z ; .. yeap ld (hl),eof ; Set end of file ret ; ; Unget current character to file ; FUnGet: push hl push de push bc push af ld a,(Char) ; Get character cp eof ; Test end of file ld hl,(BufPtr) jr z,UG.dummy ; .. yeap, skip ld hl,RecPtr inc (hl) ; Fix pointers if not ld hl,(BufPtr) dec hl ld (BufPtr),hl jr UG.dummy ; ; Unget current character from command line ; CmdUnGet: push hl push de push bc push af ld a,(Char) ; Get character cp nul ; Test end of line ld hl,(CmdPtr) jr z,UG.dummy ; .. yeap, skip ld hl,CCPlen inc (hl) ; Fix pointers if not ld hl,(CmdPtr) dec hl ld (CmdPtr),hl UG.dummy: dec hl ld c,(hl) call PutChr ; Save character and attribute pop af pop bc pop de pop hl ret ; ; Change to file vectors ; ChgVec: ld hl,FGet ld (Get+1),hl ; Set vectors ld hl,FUnGet ld (UnGet+1),hl ret ; ; The GET vector ; Get: jp $-$ ; Get character ; ; The UNGET vector ; UnGet: jp $-$ ; Unget character ; ; Get valid definition character from file ; ChrGet: jr .ChrGet ; .. skip reading from file CG.loop: call Get ; Get character from file .ChrGet: call GetChr ; Get character and attribute bit _EO,b ; Test end of file or line ret nz ; .. exit bit _IG,b ; Test valid character jr nz,CG.loop ; .. nope ret ; ; Get current character and attribute ; EXIT Reg C holds character ; Reg B holds attribute ; GetChr: ld bc,(Char) ; Get character and attribute ret ; ; Get EOL or EOF state of current character ; EXIT Accu holds attribute ; Zero set if not EOL or EOF ; GetAttr: ld a,(Attr) ; Get attribute and 1 SHL _EO ; .. test bit ld a,(Attr) ; .. get back ret ; ; Test current character end of file ; EXIT Zero set if not EOF ; EOF?: ld a,(Char) ; Get character sub eof ; Fix for end of file cp 1 sbc a,a ret ; ; Put character and attribute into memory ; ENTRY Reg C holds character ; PutChr: bit MSB,c ; Test 80..FF ld b,01h jr nz,.PutCmdChr ; .. yeap, set standard ld b,0 ld hl,AttrTable add hl,bc ld b,(hl) ; Fetch attribute .PutCmdChr: ld (Char),bc ; Save character and attribute ret ; ; Fix for end of line ; FixNL: call GetAttr ; Get attributes call nz,Get ; .. read next if EOL or EOF ret ; ; Fix to end of line ; FixtoNL: push af FN.loop: call GetAttr ; Test EOL or EOF call Get ; Get character from file jr z,FN.loop ; .. get more till end pop af ret ; ; Get new key value ; EXIT Accu holds value ; Zero flag set on error ; GetNew: push bc call ChrGet ; Get valid character pop bc call STRING? ; Test string ret z ; .. should be call GetStrVal ; Get value jp z,UnGet ; Unget character on error push af call STRING? ; .. fix for end pop af ret ; ; Build token ; ENTRY Reg HL points to location in COMMON memory ; EXIT Zero set indicates error ; BuildToken: push hl call ChrGet ; Get valid character call STRING? ; Test string jr z,BT.ex ; .. should be ld c,0 ; Clear count jr BT.go BT.loop: ld (hl),a ; Store character inc hl ; .. bump pointer inc c ; .. and count BT.go: call GetStrVal ; Get string value jr nz,BT.loop call STRING? ; Fix for end or 1 BT.ex: pop hl ret ; ; Test current character a string indicator ; EXIT Zero set if not string indicator ; STRING?: push bc call GetChr ; Get character and attribute ld a,c sub '"' ; Test string cp 1 sbc a,a call nz,Get ; Get character from file if so pop bc ret ; ; Get string value ; EXIT Accu holds value ; Zero flag set on end ; GetStrVal: push hl push de push bc jr GSV.go GSV.loop: call Get ; Get character from file GSV.go: call GetChr ; Get character and attribute ld a,b or NOT (1 SHL _EO) ; Check for EOL or EOF inc a jr z,GSV.ex ; .. yeap ld a,c cp ' ' jr c,GSV.loop ; .. skip control cp '"' ; Test empty string jr z,GSV.ex cp '^' call Get ; Get next character from file call z,GetStrByte ; Process prefix call z,UnGet ; Unget character GSV.ex: pop bc pop de pop hl ret ; ; Get byte from string ; EXIT Accu holds byte ; Zero flag set on invalid control ; GetStrByte: call GetChr ; Get character and attribute ld a,c cp '^' ; Test control prefix jr z,GSB.skp cp '"' ; .. test string prefix jr z,GSB.skp cp '@' ; Test control jr c,GSB.Numb? and ASCmask ; .. mask what we got GSB.skp: call Get ; Get character from file jr GSB.ex GSB.Numb?: cp '''' ; Test numeric value jr z,GSB.Numb ; .. yeap xor a ; Set error ret GSB.Numb: call Get ; Get character from file call GetNum ; Get number call z,GetKeyWrd ; .. nope, try key word jp z,UnGet ; Unget character if invalid call GetChr ; Get character and attribute ld a,c cp '''' call z,Get ; Get character from file ld a,l ; Get byte GSB.ex: ld b,0 inc b ; Fix success ret ; ; Get control keyword ; EXIT Reg L holds code on success ; Zero flag set on error ; GetKeyWrd: ld hl,$KEYWRD call FindStr ; Find keyword ld a,h inc a ; .. fix for result ret ; ; Keywords of control strings ; On success reg L holds control code ; reg H holds 0 ; Otherwise reg L holds 0 ; reg H holds -1 ; $KEYWRD: db 'NUL',eos,'@'-'@',0 db 'SOH',eos,'A'-'@',0 db 'STX',eos,'B'-'@',0 db 'ETX',eos,'C'-'@',0 db 'EOT',eos,'D'-'@',0 db 'ENQ',eos,'E'-'@',0 db 'ACK',eos,'F'-'@',0 db 'BEL',eos,'G'-'@',0 db 'BS',eos,'H'-'@',0 db 'HT',eos,'I'-'@',0 db 'LF',eos,'J'-'@',0 db 'VT',eos,'K'-'@',0 db 'FF',eos,'L'-'@',0 db 'CR',eos,'M'-'@',0 db 'SO',eos,'N'-'@',0 db 'SI',eos,'O'-'@',0 db 'DLE',eos,'P'-'@',0 db 'DC1',eos,'Q'-'@',0 db 'DC2',eos,'R'-'@',0 db 'DC3',eos,'S'-'@',0 db 'DC4',eos,'T'-'@',0 db 'NAK',eos,'U'-'@',0 db 'SYN',eos,'V'-'@',0 db 'ETB',eos,'W'-'@',0 db 'CAN',eos,'X'-'@',0 db 'EM',eos,'Y'-'@',0 db 'SUB',eos,'Z'-'@',0 db 'ESC',eos,'['-'@',0 db 'FS',eos,'\'-'@',0 db 'GS',eos,']'-'@',0 db 'RS',eos,'^'-'@',0 db 'US',eos,'_'-'@',0 db 'SP',eos,' ',0 db 'DEL',eos,7fh,0 db 'XON',eos,'Q'-'@',0 db 'XOFF',eos,'S'-'@',0 db eos,0,eos ; ; Get number from input ; EXIT Zero set if no number ; Reg HL holds number ; GetNum: push bc call ChrGet ; Get valid character bit _NM,b ; Test number jr z,GN.hex ; .. nope call GetDec jr GN.ex GN.hex: bit _EX,b ; Test hex prefix jr z,GN.ex ; .. nope call GetHex ; .. get it GN.ex: pop bc ret ; ; Get decimal number ; EXIT Reg HL holds number ; GetDec: push de push bc call ChrGet ; Get valid character bit _NM,b ; Test number jr z,GD.ex ; .. no ld hl,0 ; Init result jr GD.go GD.loop: ld e,l ; Copy number ld d,h add hl,hl ; * 2 add hl,hl ; * 4 add hl,de ; * 5 add hl,hl ; * 10 GD.go: ld a,c sub '0' ; Strip off offset add a,l ld l,a ; .. add to old number adc a,h sub l ld h,a call Get ; Get character from file call GetChr ; .. and attribute bit _NM,b ; Test still number jr nz,GD.loop ; .. yeap or 1 ; .. set success GD.ex: pop bc pop de ret ; ; Get hex number ; EXIT Reg HL holds number ; GetHex: push bc call ChrGet ; Get valid character bit _EX,b ; Test expansion prefix jr z,GH.ex ; .. nope call Get ; Get character from file call GetChr ; .. and attribute bit _HX,b ; Test hex call z,UnGet ; Unget character if not jr z,GH.ex ; .. and exit ld hl,0 ; Init result jr GH.go GH.loop: add hl,hl ; * 2 add hl,hl ; * 4 add hl,hl ; * 8 add hl,hl ; * 16 GH.go: ld a,c ; Get character and LoMask ; Mask lower part bit _NM,b ; Test 0..9 jr nz,GH.dec ; .. yeap add a,9 ; Fix for hex GH.dec: or l ld l,a ; Put into result call Get ; Get character from file call GetChr ; .. and attribute bit _HX,b ; Test still hex jr nz,GH.loop ; .. yeap or 1 ; Set success GH.ex: pop bc ret ; ; $$$$$$$$$$$$$$$$$$$$$$$$ ; $$$ PROCESS LANGUAGE $$$ ; $$$$$$$$$$$$$$$$$$$$$$$$ ; Language:: call GetNum ; Get number jr z,IllNum ld a,esc call Condir ; Give escape ld a,'2' call Condir ; .. give prefix ld a,l add a,' ' ; Add offset jp Condir ; .. define language IllNum: ld de,$BAD.NUM jp ProcErr ; Tell invalid number $BAD.NUM: IF GERMAN db 'Fehlerhafte Zahl' ELSE db 'Bad number' ENDIF db cr,lf,eot ; ; $$$$$$$$$$$$$$$$$$$$$$$ ; $$$ PROCESS PALETTE $$$ ; $$$$$$$$$$$$$$$$$$$$$$$ ; Palette:: call GetNum ; Get 1st number jr z,TstSet ; .. none call SetBackGround ; Set background color call GetNum ; Get 2nd number jr z,TstEnd ; .. nope call SetForeGround ; Define colour jr TstEnd TstSet: call FixNL ; Test end of line jr z,TstEnd ; .. nope ld de,$NO.COLOR ld c,_String jp BDOS $NO.COLOR: IF GERMAN db 'Keine Farbe' ELSE db 'No colour' ENDIF db cr,lf,eot TstEnd: call FixNL ; Test end of line ret nz ; .. yeap ld de,$BAD.COLOR jp ProcErr $BAD.COLOR: IF GERMAN db 'Falsche Farbe' ELSE db 'Bad colour' ENDIF db cr,lf,eot ; ; Set backgound colour ; ENTRY Reg L holds 0 or 1 ; SetBackGround: push de ld e,'c' call SetESCAPE ; .. set it pop de ret ; ; Set foreground colour ; ENTRY Reg L holds 0 or 1 ; SetForeGround: push de ld e,'b' call SetESCAPE ; .. set it pop de ret ; ; Set ESCape sequence ; ENTRY Reg E holds ESCape character ; Reg L holds color ; SetESCAPE: push af ld a,esc call Condir ; Give ESCape ld a,e call Condir ; .. set character ld a,l and Mask ; Mask color add a,' ' call Condir ; .. set it pop af ret ; ; $$$$$$$$$$$$$$$$$$$$$$$$ ; $$$ PROCESS SET24X80 $$$ ; $$$$$$$$$$$$$$$$$$$$$$$$ ; Set24x80:: ld hl,$S.ON.OFF call FindStr ; Find ON or OFF ld a,l ; Test result or a jr nz,SetScr ; .. well done call FixNL ; Test end of line jr z,SetERR ; .. nope, should be ld l,'x' ; Set default ON SetScr: ld a,esc call Condir ; Give ESCape ld a,l jp Condir ; .. and character SetERR: ld de,$SET.ERR jp ProcErr ; $SET.ERR: IF GERMAN db 'Entweder ON oder OFF' ELSE db 'Must be ON or OFF' ENDIF db cr,lf,eot $S.ON.OFF: db 'ON',eos,'x',0 db 'OFF',eos,'y',0 db eos,0,0 ; ; $$$$$$$$$$$$$$$$$$$$$$$ ; $$$ PROCESS SETKEYS $$$ ; $$$$$$$$$$$$$$$$$$$$$$$ ; Setkeys:: call GetFile ; Open file ld hl,(BDOS+1) ; Get top of memory dec h ld (HI.RAM),hl ; .. save dec hl ld a,h cp HIGH COMRAM ; Test range jp c,InvalEnv ; .. less memory PK.loop: call GetNum ; Get number jr z,PK.noNum ; .. nope, must be expansion call GetNumKey ; Get translation jr PK.Close PK.noNum: ld hl,$EXPND call FindStr ; Find expansion inc l ; .. test found call nz,GetNum ; .. yeap, get number ld de,$BADNUM ; Load message call nz,GetToken ; Get token if ok PK.Close: call nz,FixtoNL ; Fix to end of line call z,FixNL ; Fix next character call z,ProcErr ; .. process error call EOF? ; Test end of file jr z,PK.loop ; .. nope ret ; ; Expansion string ; On success reg L holds 0 ; reg H holds 0 ; Otherwise reg L holds -1 ; reg H holds -1 ; $EXPND: db 'E',eos,0,0 db eos,eos,eos $BADNUM: IF GERMAN db 'Falsche Tastennummer oder Expansion' ELSE db 'Bad key number or expansion token' ENDIF db cr,lf,eot ; ; Get key translation ; ENTRY Reg L holds key number ; EXIT Zero set on invalid translation ; Reg DE holds error message ; GetNumKey: ld c,l ; Save key number call GetState ; Get shift state ld h,a ; .. save call GetNew ; Get value ld b,a ; Set new value ld de,$ILLKEY ret z ld d,h ; Set state call StoreKey ; .. store it or ALL ; Set success ret $ILLKEY: IF GERMAN db 'Falsches ]bersetzungszeichen' ELSE db 'Bad shift or translation character' ENDIF db cr,lf,eot ; ; Get shift state ; EXIT Accu holds selected state ; GetState: push hl xor a ; Clear entry state GS.loop: ld hl,$CTRL call FindStr ; Find control prexix or l ; .. insert it inc h ; Test ready jr nz,GS.loop ; .. nope pop hl or a ; Test any state ret nz ; .. yeap ld a,00000001b ; Return normal ret ; ; Control string prefix ; On success reg L holds shift state ; reg H holds 0 ; Otherwise reg L holds 0 ; reg H holds -1 ; $CTRL: db 'C',eos,00010000b,0 db 'E',eos,00010000b,0 db 'N',eos,00000001b,0 db 'S',eos,00000010b,0 db 'A',eos,00000100b,0 db 'SA',eos,00001000b,0 db eos,0,eos ; ; Process token ; EXIT Zero set on error ; GetToken: ld d,l ; Save token ld hl,(HI.RAM) ; Get high memory call BuildToken ; .. build token ld b,d ; Get token number ld de,$BADEXPN ret z ; .. error string call StoreToken ; Store token ld de,$BADSTR sbc a,a ; Fix zero (CY ->> no ZERO) ret $BADEXPN: IF GERMAN db 'Fehler in Expansion' ELSE db 'Bad expansion string' ENDIF db cr,lf,eot $BADSTR: IF GERMAN db 'Zeichen zu lang oder falsche Auswahl' ELSE db 'String too long or token number invalid' ENDIF db cr,lf,eot ; ; $$$$$$$$$$$$$$$$$$$$$ ; $$$ PROCESS PAPER $$$ ; $$$$$$$$$$$$$$$$$$$$$ ; Paper:: xor a ld (Defeat),a ; .. clear defeat ld (OptSel),a ; Clear any option call ExexOptions ; Execute command line jr z,CmdErr ld a,(OptSel) ; Get option and Ln.Gap ; Map line and gap set cp Ln.Gap ; Test either jp nz,SetPrinter ; .. init printer if so ld hl,(LinLen) ; Get length of line ld a,(RealLen) ; Test length set inc a jr nz,PP.noFix ; .. ON ld b,h ; .. copy length PP.FixIt: add a,l ; Fix length djnz PP.FixIt ld l,a PP.noFix: ld a,(Gap) ; Get gap cp l ; Compare against line length jp c,SetPrinter ; .. go init if OK ld de,$GAP.LT.LEN ; .. else tell error CmdErr: call ProcErr ; Process error ld de,$NO.CHNG jp String ; Tell nothing changed ; $NO.CHNG: IF GERMAN db 'Keine Einstellung des Druckers vorgenommen' ELSE db 'No change has been made to the printer ' db 'settings.' ENDIF db cr,lf,eot $GAP.LT.LEN: IF GERMAN db 'Zwischenraum mu~ kleiner als L{nge sein' ELSE db 'Gap Length must be less than Form Length.' ENDIF db cr,lf,eot ; ; Execute command options ; EXIT Zero set on error ; ExexOptions: call ChrGet ; Get character call FixNL ; Test end of line ret nz ; .. yeap ld hl,$PCMD.TAB call Decode ; .. decode command call JPr jr nz,ExexOptions ; Loop till error ret ; ; Main command table ; $PCMD.TAB: db 'A' dw SetA4.5 db 'C' dw SetContinous db 'D' dw SetDefaults db 'F' dw SetForm db 'G' dw SetGap db 'L' dw SetLine db 'P' dw SetPaper db 'S' dw SetSingle db eos dw SetNumber ; ; Option : A4 or A5 ; SetA4.5: call ChkRange ; Check range 4 or 5 db 4,5+1 dw $BAD.A4..5 ld de,$BAD.A4..5 ret z ; .. error cp 4 ; .. test A4 ld a,70 ; .. select lines jr z,..A4 ld a,50 ..A4: or a call StLines ; Store lines ld a,3 call StGap ; Set gap of three jr SetSheet ; Set sheet ; $BAD.A4..5: IF GERMAN db 'Falscher Parameter f}r "A4" oder "A5".' ELSE db 'Badly formed "A4" or "A5" parameter.' ENDIF db cr,lf,eot ; ; Option : SINGLE SHEET ; SetSingle: call GetSxxx ; Skip SHEET SetSheet: ld a,-1 ; Set single sheet jr StSheet ; ; Option : CONTINOUS STATIONARY ; SetContinous: call GetSxxx ; Skip STATIONARY StConSheet: xor a ; Set continous sheet StSheet: ld hl,Sheet ld (hl),a ; Set flag inc hl set _Sheet,(hl) ; .. set sheet bit set _Defeat,(hl) ; .. set defeat off inc hl inc (hl) dec (hl) ret nz inc hl ld (hl),a or 1 ret ; ; Option : DEFAULTS ; SetDefaults: ld hl,OptSel set _Def,(hl) ; Indicate bit or (hl) ; .. set success ret ; ; Option : FORM LENGTH ; SetForm: call GetLxxx ; Skip LENGTH call ChkRange ; Check range 6..99 db 6,99+1 dw $ILL.FORM ret z ; .. error or a jr StLines ; Store lines ; $ILL.FORM: IF GERMAN db 'L{nge mu~ liegen zwischen 6 und 99 Zeilen.' ELSE db 'Form Length must be between 6 and 99 lines.' ENDIF db cr,lf,eot ; ; Option : GAP LENGTH ; SetGap: call GetLxxx ; Skip LENGTH call ChkRange ; Check range 0..99 db 0,99+1 dw $ILL.GAP ret z ; .. error jr StGap ; .. set gap ; $ILL.GAP: IF GERMAN db 'Zwischenraum darf h|chstens 99 sein.' ELSE db 'Gap Length must be 99 lines or less.' ENDIF db cr,lf,eot ; ; Store lines ; ENTRY Accu holds line length ; Carry set indicates PAPER OUT DEFEAT OFF ; StLines: ld (LinLen),a ; Store lines sbc a,a ld (RealLen),a ; Set real length set call SetPitch ; Set default pitch of 6 ld hl,OptSel set _Lines,(hl) ; Indicate lines attached ld a,(hl) ; Get state and 1 SHL _Gap ; Test gap set ret nz ; .. yes, else set gap 0 ; ; Store gap ; ENTRY Accu holds gap ; StGap: ld (Gap),a ; Store gap ld hl,OptSel set _Gap,(hl) ; Indicate set cp 1 ; Test any ret c ; .. nope jr SetPitch ; Set default pitch of 6 ; ; Option : LINE PITCH ; SetLine: ld hl,$PITCH call Decode ; .. throw away PITCH call ChkRange ; Check range 6..8 db 6,8+1 dw $ILL.PITCH ret z ; .. error cp 7 ; Verify 6 or 8 ret z ; .. error jr StPitch ; Store pitch ; $ILL.PITCH: IF GERMAN db 'Zeilenabstand mu~ 6 oder 8 Zeilen ' db 'pro Zoll sein' ELSE db 'Line Pitch must be 6 or 8 lines per inch.' ENDIF db cr,lf,eot $PITCH: db 'P',0,0 db eos ; ; Set default pitch of 6 ; SetPitch: ld a,(OptSel) and 1 SHL _Pitch ; Test pitch selected ret nz ; .. don't change ld a,6 ; .. set 6 StPitch: ld (Pitch),a ld hl,OptSel set _Pitch,(hl) ; Set pitch selected or (hl) ; .. force non zero ret ; ; Option : PAPER OUT DEFEAT ON/OFF ; SetPaper: call Get.ON.OFF ; Try ON/OFF ret nz ; .. got it ld hl,$OUT call Decode ; Throw away OUT call Get.ON.OFF ; Now ON/OFF ? ret nz ; .. yeap ld hl,$DEFEAT call Decode ; Throw away DEFEAT Get.ON.OFF: ld hl,$P.ON.OFF call FindStr ; Find ON or OFF ld de,$ILL.DEFEAT dec l ret z ; .. error, neither ld (Defeat),hl ; Set code ld hl,OptSel set _Defeat,(hl) ; Set defeat ret ; $P.ON.OFF: db 'ON',eos,0,-1 db 'OFF',eos,0,0 db eos,1,0 $ILL.DEFEAT: IF GERMAN db 'Papierende ignorieren mu~ ON oder OFF sein.' ELSE db 'Paper Out Defeat on/off badly formed.' ENDIF db cr,lf,eot $OUT: db 'O',0,0 db eos $DEFEAT: db 'D',0,0 db eos ; ; Option : ; SetNumber: call ChkRange ; Check range 1..17 db 1,17+1 dw $INV.FORM ret z scf call StLines xor a call StGap ; Set no gap jp StConSheet ; Set continous sheet ; $INV.FORM: IF GERMAN db 'L{nger mu~ liegen zwischen 1 und 17 pro Zoll' ELSE db 'Form length must be between 1 and 17 inches.' ENDIF db cr,lf,eot ; ; Find and skip secondary option SHEET or STATIONARY ; GetLxxx: ld hl,$Lxxx jp Decode ; .. throw away ; $Lxxx: db 'L',0,0 db eos ; ; Find and skip secondary option SHEET or STATIONARY ; GetSxxx: ld hl,$Sxxx jp Decode ; .. throw away ; $Sxxx: db 'S',0,0 db eos ; ; Check range ; Call follows: Lower limit ; Upper limit ; Address of error message ; EXIT Zero set on invalid parameter ; Reg DE holds address of error message ; ChkRange: call GetNum ; Get number ex (sp),hl ; .. save ld c,(hl) ; Get lower limit inc hl ld b,(hl) ; .. and upper limit inc hl ld e,(hl) ; .. and address inc hl ld d,(hl) inc hl ex (sp),hl ; Bring back the stack jr z,CR.err ; .. no number ld a,h or a ; HI should be zero jr nz,CR.inval ld a,l cp c ; .. compare LO jr c,CR.inval cp b ; .. and HI ret c CR.inval: xor a ; Set error ret CR.err: ld de,$BAD.PAR ret ; $BAD.PAR: IF GERMAN db 'Falscher Parameter' ELSE db 'Badly formed parameter.' ENDIF db cr,lf,eot ; ; Init printer ; SetPrinter: ld a,(OptSel) ; Get what we sampled ld c,a sla c call c,DefSheet sla c call c,DefDefeat sla c call c,DefPitch sla c call c,DefLine sla c call c,DefGap sla c ret nc ; .. no more, exit ld a,'d' call ESCout ; Set default ld de,$DEF.SET jp String ; .. and tell it ; $DEF.SET: IF GERMAN db 'Grundeinstellung ausgef}hrt' ELSE db 'Defaults set' ENDIF db cr,lf,eot ; ; Print escape prefixed character on printer ; ENTRY Accu holds character ; ESCout: push af ; Save character ld a,esc call Lstout ; .. give prefix pop af ; .. and selection jp Lstout ; ; Define pitch ; DefPitch: ld a,'8' ld hl,Pitch sub (hl) call ESCout ; Set pitch ld de,$LIN.PITCH call String ; Give statistic ld a,(Pitch) call PrASCII ; .. give count ld de,$LIN.INCH call String jp NL ; .. close line ; $LIN.PITCH: IF GERMAN db 'Zeilenabstand ',eot ELSE db 'Line Pitch ',eot ENDIF $LIN.INCH: IF GERMAN db ' (Zeilen pro Zoll)',eot ELSE db ' (lines per inch)',eot ENDIF ; ; Give new line to console ; NL: ld de,$CRLF jp String ; .. do it ; ; Print decimal number ; ENTRY Accu holds number ; PrDec: ld b,-1 ; Set init PD.loop: inc b sub 10 ; Subtract tens jr nc,PD.loop add a,10 ; Make real again push af ld a,b ; Test tens or a jr nz,PD.0..9 ; .. yeap ld a,' '-'0' ; .. give blank PD.0..9: call PrASCII pop af PrASCII: add a,'0' ; Add offset jp Conout ; .. print ; ; Define length of line ; DefLine: ld a,'C' call ESCout ; Give length of line ld a,(RealLen) ; Test real length set inc a push af call z,Lstout ; .. yeap, set it ld a,(LinLen) ; Get length of line call Lstout ; .. to printer ld de,$FORM.LEN call String ; Give statistic call PrDec ; .. tell line count ld de,$INCHES pop af call z,String call nz,TellLines ; Tell lines jp NL ; $FORM.LEN: IF GERMAN db 'Forml{nge ',eot ELSE db 'Form Length ',eot ENDIF $INCHES: IF GERMAN db ' (Zoll)',eot ELSE db ' (inches)',eot ENDIF ; ; Give simple string ; TellLines: ld de,$LINES jp String ; $LINES: IF GERMAN db ' (Zeilen)',eot ELSE db ' (lines)',eot ENDIF ; ; Define gap ; DefGap: ld a,(Gap) or a push af ld a,'O' call z,ESCout ; Set gap ld a,'N' call nz,ESCout pop af call nz,Lstout ld de,$GAP.LEN call String call PrDec ; Give gap count call TellLines ; Tell lines jp NL ; $GAP.LEN: IF GERMAN db 'L{nge des Zwischenraums ',eot ELSE db 'Gap Length ',eot ENDIF ; ; Define defeat ; DefDefeat: ld a,'9' ld hl,OnFlag add a,(hl) call ESCout ; .. give defeat ld de,$OUT.DEF call String ; Tell it ld a,(OnFlag) ; Check state or a ld de,$DEF.OFF ; Tell it call z,String ld de,$DEF.ON call nz,String jp NL ; IF GERMAN $OUT.DEF: db 'Papierende ignorieren ',eot ELSE $OUT.DEF: db 'Paper Out Defeat ',eot ENDIF $DEF.OFF: db 'Off',eot $DEF.ON: db 'On',eot ; ; Define sheet ; DefSheet: ld a,(Sheet) or a ld a,'c' call z,ESCout ; Give continous ld a,'$' call nz,ESCout ; .. or single sheet ld de,$CONT.SHEET call z,String ; Tell state ld de,$SNGL.SHEET call nz,String jp NL ; IF GERMAN $CONT.SHEET: db 'Kontinuierliche Ausgabe',eot $SNGL.SHEET: db 'Einzelblatt',eot ELSE $CONT.SHEET: db 'Continuous Stationery',eot $SNGL.SHEET: db 'Single Sheet',eot ENDIF ; ; $$$$$$$$$$$$$$$$$$$$$$ ; $$$ PROCESS SETLST $$$ ; $$$$$$$$$$$$$$$$$$$$$$ ; Setlst:: call GetFile ; Open file jr LstLoop LstDef: call Lstout ; Put to printer LstLoop: call GetStrVal ; Get string value jr nz,LstDef ; .. put to printer call FixNL ; Test end of line ld de,$BAD.VAL call z,ProcErr ; .. error if not call EOF? ; Test end of file jr z,LstLoop ; .. nope ret $BAD.VAL: IF GERMAN db 'Falscher Wert' ELSE db 'Bad value' ENDIF db cr,lf,eot ; ; $$$$$$$$$$$$$$$$$$$$$$ ; $$$ PROCESS SETSIO $$$ ; $$$$$$$$$$$$$$$$$$$$$$ ; SetSIO:: call SIOfitted ; Find SIO ld de,$NO.SIO jp nz,ProcErr ; .. not there call ExecOptions ; Do commands call z,ProcErr ; .. error ld de,$NO.SCHNG jp z,String ; Tell no set up call ProgramSIO ; Program the SIO jp TellState ; .. and tell state ; IF GERMAN $NO.SCHNG: db 'Serielle Schnittstelle nicht ge{ndert' db cr,lf,eot $NO.SIO: db 'Serielle Schnittstelle nicht eingebaut' db cr,lf,eot ELSE $NO.SCHNG: db 'SIO left unchanged',cr,lf,eot $NO.SIO: db 'SIO not found',cr,lf,eot ENDIF ; ; Find SIO fitted ; EXIT Zero set if found ; SIOfitted: call FndSIO ; Find SIO in BIOS table ret nz ; .. not here ld a,(hl) ; Get control and XON.XOF ; Isolate XON/XOFF bit add a,-XON.XOF sbc a,a ; Map bit to FF or 00 ld (SIOx),a call GetSIO ; Get SIO data cpl ; Isolate handshake inc a rra push af sbc a,a ld (HandShk),a ; Set it pop af ; Isolate interrupt rra sbc a,a ld (Intrpt),a ; Set it ld (BdRate),bc ; Save baud rate ld (Parity),de ; Save parity and stop bits ld (TData),hl ; Save data bits xor a ret ; ; Transfer data to SIO ; ProgramSIO: call FndSIO ; Find SIO address ld a,(SIOx) ; Get old XON/XOFF and XON.XOF xor (hl) and XON.XOF xor (hl) ld (hl),a ; .. set into table ld hl,(HandShk) ; Get handshake ld a,l rra ld a,h ; .. and interrupt rla and LowBits cpl inc a ; .. here is the mode ld bc,(BdRate) ; Get baud rate ld de,(Parity) ; Get parity and stop bits ld hl,(TData) ; Get data bits push bc call InitSIO ; Set all pop hl jp SetBAUD ; .. baud rate, too ; ; Find SIO fitted ; EXIT Zero set if found ; Reg HL points to control code of table ; FndSIO: push de push bc call DevTbl ; Get device table ld de,$SIO ; Set search item SIO.loop: ld a,(hl) ; Test end of table (0 is end) cp 1 jr c,No.SIO ; .. no SIO found call CmpStr ; Find in table ld bc,DevLen add hl,bc ; .. point to next jr nz,SIO.loop ; .. not found, try next dec hl ; .. fix address dec hl No.SIO: pop bc pop de ret ; $SIO: db 'SIO ' ; ; Compare two strings ; ENTRY Regs DE and HL point to strings ; EXIT Zero set if same strings ; CmpStr: push hl push de ld b,DevLen-2 ; Set length less control CS.loop: ld a,(de) cp (hl) ; .. compare jr nz,CS.no ; .. no match inc de inc hl djnz CS.loop ; .. loop on CS.no: pop de pop hl ret ; ; Execute command options ; EXIT Zero set on error ; ExecOptions: xor a ld (DefStop),a ; Set default stop bits ExecLoop: ld hl,$CMD.TAB call Decode ; Decode from table call JPr ; .. execute jr nz,ExecLoop ; .. loop if no error jp FixNL ; Set line to end ; ; Main command table ; $CMD.TAB: db 'R' dw SetRecBaud db 'T' dw SetTrmBaud db 'B' dw SetBits db 'S' dw SetStop db 'P' dw SetParity db 'X' dw SetXON db 'H' dw SetHandShake db 'I' dw SetInterrupt db eos dw SetBaudRates ; ; No option, get baud rate for both channels ; SetBaudRates: ld bc,RBx ; Point to reciever baud rate call DecBaudRate ; Get it jr nz,SetBoth ; .. then set transmitter ld de,$BAD.OPTION ; .. remember invalid option ret ; $BAD.OPTION: IF GERMAN db 'Falsche Option' ELSE db 'Bad option' ENDIF db cr,lf,eot ; ; Option TX : Set transmitter baud rate ; SetTrmBaud: ld bc,TBx ; Point to transmit baud rate call DecBaudRate ; Get it ret z ; .. error jr SetDefStop ; Set default stop bits ; ; Option RX : Set receiver baud rate ; SetRecBaud: ld bc,RBx ; Point to receiver baud rate call DecBaudRate ; Get it ret z ; .. error jr SetDefStop ; Set default stop bits ; ; Copy baud rate ; SetBoth: ld a,(bc) ; .. get current receiver dec bc ld (bc),a ; .. copy to transmitter ; ; Set default stop bits ; SetDefStop: ld a,(DefStop) ; Test any selection or a ret nz ; .. yeap, so leave ld a,(bc) ; Get current rate cp 4 ; .. look for 134.5 ccf sbc a,a ; .. build bits inc a ; 50, 75 and 110 get 2 bits add a,a ; .. other get 1 bit ld (StopBit),a ; Save stop bits or 1 ; .. force non zero ret ; ; Decode baud rate ; ENTRY Reg BC points to rate to be set ; DecBaudRate: ld hl,$BAUD.TAB ld de,$BAD.BAUD jp SetOption ; Get and set baud rate ; $BAUD.TAB: db '50',eos,1,0 db '75',eos,2,0 db '110',eos,3,0 db '134.5',eos,4,0 db '134',eos,4,0 db '150',eos,5,0 db '300',eos,6,0 db '600',eos,7,0 db '1200',eos,8,0 db '1800',eos,9,0 db '2400',eos,10,0 db '3600',eos,11,0 db '4800',eos,12,0 db '7200',eos,13,0 db '9600',eos,14,0 db '19200',eos,15,0 db eos,0,eos ; $BAD.BAUD: IF GERMAN db 'Falsche Baudrate' ELSE db 'Bad baud rate' ENDIF db cr,lf,eot ; ; Option BITS : Set bit length ; SetBits: ld hl,$BIT.SEL call Decode ; Decode from table jp (hl) ; $BIT.SEL: db 'R' dw SetRecBits db 'T' dw SetTrmBits db eos dw SetDataBits ; ; Set both same length ; SetDataBits: call SetRecBits ; Get receiver bits ret z ; .. error dec bc ld (bc),a ; .. set transmitter the same ret ; ; Option BITS RECEIVE : Set receive bits ; SetRecBits: ld bc,RData ; Point to receive length jr SetTheBits ; ; Option BITS TRANSMIT : Set receive bits ; SetTrmBits: ld bc,TData ; Point to transmit length SetTheBits: ld hl,$DATA.TAB ld de,$BAD.BITS jp SetOption ; Get and set data length ; $DATA.TAB: db '5',eos,5,0 db '6',eos,6,0 db '7',eos,7,0 db '8',eos,8,0 db eos,0,eos ; $BAD.BITS: IF GERMAN db 'Falsche Bitl{nge' ELSE db 'Bad bits' ENDIF db cr,lf,eot ; ; Option STOP : Set stop bits ; SetStop: ld hl,$STOP.TAB ld de,$BAD.STOP ld bc,StopBit ; Point to stop bits call SetOption ; Get and set stop bits ret z ; .. invalid ld a,-1 ld (DefStop),a ; Set no default stop bits ret ; $STOP.TAB: db '1.5',eos,1,0 db '1',eos,0,0 db '2',eos,2,0 db eos,0,eos ; $BAD.STOP: IF GERMAN db 'Falsche Anzahl Stopbits' ELSE db 'Bad stop bits' ENDIF db cr,lf,eot ; ; Option PARITY : Set parity ; SetParity: ld hl,$PARI.TAB ld de,$BAD.PARITY ld bc,Parity ; Point to parity jr SetOption ; Get and set parity ; $PARI.TAB: db 'NONE',eos,0,0 db 'ODD',eos,1,0 db 'EVEN',eos,2,0 db eos,0,eos ; $BAD.PARITY: IF GERMAN db 'Falsche Parit{t' ELSE db 'Bad parity' ENDIF db cr,lf,eot ; ; Option XON : Set XON/XOFF protocol ; SetXON: ld bc,SIOx ; Point to XON/XOFF jr Set.ON.OFF ; .. set it ; ; Option HANDSHAKE : Set handshake ; SetHandShake: ld bc,HandShk ; Point to handshake jr Set.ON.OFF ; .. set it ; ; Option INTERRUPT : Set interrupt mode ; SetInterrupt: ld bc,Intrpt ; Point to interrupt Set.ON.OFF: ld hl,$ON.TAB ld de,$BAD.ON jr SetOption ; Get and set mode ; $ON.TAB: db eos,0,eos db 'ON',eos,eos,0 db 'OFF',eos,0,0 db eos,0,eos ; $BAD.ON: IF GERMAN db 'Entweder ON oder OFF' ELSE db 'Bad on/off' ENDIF db cr,lf,eot ; ; Find item from table and store it ; ENTRY Reg BC points to item to be set ; Reg HL points to table ; Reg DE holds error message ; EXIT Zero flag set on error ; SetOption: call FindStr ; Find item inc h ; Test success ret z ; .. nope ld a,l ld (bc),a ; Store value ret ; ; Tell how SIO initilaized ; TellState: call TellRate ; Tell baud rate call TellData ; .. data length call TellStop ; .. stop bits call TellParity ; .. parity call Tell.XON ; .. XON/XOFF call TellHandShake ; .. handshake call TellInterrupt ; .. inerrupt ld de,$CR.LF jp String ; Close statistic $CR.LF: db cr,lf,eot ; ; Tell baud rate ; TellRate: ld hl,(BdRate) ; Get baud rate ld a,h cp l ; Test both same jr z,SameRates ; .. yeap ld de,$RX call String call SameRates ; Give receiver ld a,l ld de,$TX call String ; .. then transmitter SameRates: call Blank ; Print blank ld de,$BAUD.SETS jp TableStr ; $RX: db ' Rx',eot $TX: db ' Tx',eot ; $BAUD.SETS: db 15,'?',eot db 1,'50',eot db 2,'75',eot db 3,'110',eot db 4,'134.5',eot db 5,'150',eot db 6,'300',eot db 7,'600',eot db 8,'1200',eot db 9,'1800',eot db 10,'2400',eot db 11,'3600',eot db 12,'4800',eot db 13,'7200',eot db 14,'9600',eot db 15,'19200',eot ; ; Tell data length ; TellData: ld de,$BITS call String ld hl,(TData) ; Get bit length ld a,h cp l ; Test same length jr z,SameData ld de,$RD call String ; Tell receiver call SameData ld a,l ld de,$TD call String ; .. and transmitter SameData: ld de,$DATA.SETS jp TableStr ; .. tell length ; $BITS: db ' Bits ',eot $RD: db 'rx ',eot $TD: db ' Bits tx ',eot ; $DATA.SETS: db 4,'?',eot db 5,'5',eot db 6,'6',eot db 7,'7',eot db 8,'8',eot ; ; Tell stop bits ; TellStop: ld de,$STOP call String ld a,(StopBit) ; Get stop bits ld de,$STOP.SETS jp TableStr ; .. tell it ; $STOP: db ' Stop ',eot ; $STOP.SETS: db 3,'?',eot db 0,'1',eot db 1,'1.5',eot db 2,'2',eot ; ; Tell parity ; TellParity: ld de,$PARITY call String ld a,(Parity) ; Get parity ld de,$PARITY.SETS jp TableStr ; .. tell it ; $PARITY: IF GERMAN db ' Parit{t ',eot ELSE db ' Parity ',eot ENDIF ; $PARITY.SETS: db 3,'?',eot db 0,'none',eot db 1,'odd',eot db 2,'even',eot ; ; Tell XON/XOFF ; Tell.XON: ld de,$XON ld a,(SIOx) ; Get XON/XOFF jr TellOnOff ; .. tell it ; $XON: db ' Xon',eot ; ; Tell handshake ; TellHandShake: ld de,$HAND.SHAKE ld a,(HandShk) ; Get handshake jr TellOnOff ; .. tell it ; $HAND.SHAKE: db ' Handshake',eot ; ; Tell interrupt ; TellInterrupt: ld de,$INTERRUPT ld a,(Intrpt) ; Get interrupt jr TellOnOff ; .. tell it ; $INTERRUPT: db ' Interrupt',eot ; ; Tell ON or OFF ; TellOnOff: call String ld de,$ON.OFF jp TableStr ; Tell state ; $ON.OFF: db 2,' ?',eot IF GERMAN db 0,' aus',eot db -1,' an',eot ELSE db 0,' off',eot db -1,' on',eot ENDIF ; ; Give little help ; Help: ld de,$HELP call String ; .. tell it jp OS $HELP: IF GERMAN db 'Programmsammlung f}r PCW Maschinen',cr,lf,lf db 'Dieses Programm kombiniert die sieben AMSTRAD' db ' Routinen',cr,lf,lf db 'Aufruf mit: PCW -Routine (Option(en))',cr,lf db 'Die Routinen und Optionen sind definiert als:' db cr,lf,lf db 'LANGUAGE',tab,'Option',cr,lf db 'PALETTE',tab,tab,'Option1 Option2',cr,lf db 'SET24X80',tab,'ON oder OFF',cr,lf db 'SETKEYS',tab,tab,'Datei',cr,lf db 'PAPER',tab,tab,'(Option (Option..))',cr,lf db 'SETLST',tab,tab,'Datei',cr,lf db 'SETSIO',tab,tab,'(Option (Option..))',cr,lf ELSE db 'The utility sampler for PCW machines',cr,lf,lf db 'This program combines the seven AMSTRAD ' db 'utilities',cr,lf,lf db 'Call it: PCW -utility {options}',cr,lf db 'Utility and options are defined as:',cr,lf,lf db 'LANGUAGE',tab,'option',cr,lf db 'PALETTE',tab,tab,'option1 option2',cr,lf db 'SET24X80',tab,'ON or OFF',cr,lf db 'SETKEYS',tab,tab,'file',cr,lf db 'PAPER',tab,tab,'{option {option..}}',cr,lf db 'SETLST',tab,tab,'file',cr,lf db 'SETSIO',tab,tab,'{option {option..}}',cr,lf ENDIF db eot ; ; Attribute table of all ASCII characters ; Bit definitions: ; ; 7 6 5 4 3 2 1 0 ; +----+----+----+----+----+----+----+----+ ; | xx | SG | EO | EX | NM | HX | AN | IG | ; +----+----+----+----+----+----+----+----+ ; ; xx N.C. ; SG Minus sign ; EO EOL or EOF ; EX Extension string ; NM Numeric 0..9 ; HX Hex range A..F ; AN Alphanumeric prefix ; IG Ignore for definition ; AttrTable: ; ; Control characters ; db 21h,01h,01h,01h,01h,01h,01h ; 00..06 db 01h,01h,01h,01h,01h,01h,21h ; 07..0D db 01h,01h,01h,01h,01h,01h,01h ; 0E..14 db 01h,01h,01h,01h,01h,21h,01h ; 15..1B db 01h,01h,01h,01h ; 1C..1F ; ; ASCII characters ; db 01h,01h,00h,10h,01h,01h,10h ; !"#$%& db 01h,01h,01h,01h,01h,01h,40h ; '()*+,- db 00h,01h,0ch,0ch,0ch,0ch,0ch ; ./01234 db 0ch,0ch,0ch,0ch,0ch,01h,01h ; 56789:; db 01h,01h,01h,01h,01h,06h,06h ; <=>?@AB db 06h,06h,06h,06h,02h,02h,02h ; CDEFGHI db 02h,02h,02h,02h,02h,02h,02h ; JKLMNOP db 02h,02h,02h,02h,02h,02h,02h ; QRSTUVW db 02h,02h,02h,01h,01h,01h,01h ; XYZ[\]^ db 01h,01h,06h,06h,06h,06h,06h ; _`abcde db 06h,02h,02h,02h,02h,02h,02h ; fghijkl db 02h,02h,02h,02h,02h,02h,02h ; mnopqrs db 02h,02h,02h,02h,02h,02h,02h ; tuvwxyz db 01h,01h,01h,01h,01h ; {|}~DEL Char: ds 1 Attr: ds 1 CCPlen: ds 1 CmdPtr: ds 2 RecPtr: ds 1 BufPtr: ds 2 Buff1: ds RecLng Buff2: ds RecLng Defeat: ds 1 OptSel: ds 1 LinLen: ds 1 RealLen: ds 1 Gap: ds 1 Pitch: ds 1 OnFlag: ds 1 Sheet: ds 1 HandShk: ds 1 Intrpt: ds 1 BdRate: ds 2 TBx: ds 1 RBx: ds 1 Parity: ds 1 StopBit: ds 1 TData: ds 1 RData: ds 1 SIOx: ds 1 DefStop: ds 1 HI.RAM: ds 2 end