Title Terminal Initialization Program for the MD11 (23_Apr_84) ; ; Copyright 1984 ; Morrow Designs, Inc. ; San Leandro, Ca. ; John Zalabak ; .z80 Aseg org 0100h ;---------------------------------------------------------------------- ; Equates (21_Feb_84) ;-------------------- ; Rev equ 20h ;Bios/Bdos Equates Bios_Entry equ 0 ;Bios Entry Point Bdos_Entry equ 5 ;Bdos: Entry Vector Location Bdos_ConOut equ 2 ; Console Output Function Bdos_PString equ 9 ; Print a Sting on the Console Bdos_ConBuf_in equ 10 ; Read Console input buffer Bdos_Open_File equ 15 ; Open a File Bdos_Close_File equ 16 ; Close a File Bdos_Read_Seq equ 20 ; Read Sequential Bdos_Write_Seq equ 21 ; Write Sequential Bdos_Set_DMA equ 26 ; Set the DMA Address ;Non Printing Ascii Equates End_of_File equ 1Ah ;End of File Character ClrScr equ 1Ah ;Clear Screen Escape equ 1Bh ;Escape Cr equ 0Dh ;Carriage Return Lf equ 0Ah ;Line Feed Tab equ 09h ;Tab Space equ 20h ;Space ;Error Codes and Returned Status Open_Dat_Error equ 0FFh ;Can't open the Terminal.Dat File Open_Sys_Error equ 0FEh ;Can't open the Cpm3.Sys file Disk_Read_Error equ 0FDh ;Error occured in a disk read operation Unexpected_End equ 0FCh ;Unexpected End (Eol or Eof) Bad_Definition equ 0FBh ;Illegal Character Dict_Overflow equ 0FAh ;Dictionary Buffer has overflowed No_Titles equ 0F9h ;There are no terminal titles to build menu Not_in_Dict equ 0E0h ;Current Element is not in the dictionary ;Length defintions Record_Length equ 80h ;Length of one record Max_Dict_Length equ 10h ;Maximum Length of the dictionary buffer Max_Rec_Length equ 80h ; " " " a Record Max_Stack_Space equ 20h ; " " " the main stack ;Other Definitions Default_Dma equ 80h ;Start of the default dma buffer Status_EOF equ 1 ;End of file status Null equ 0FFh ;Null Key Definition page ;====================================================================== ; Main Line of Terminal Initialization (18_Apr_84) ;================================================= ; Init_Main: call Read_Dat_File ;Read the Terminal.Dat File or a ;If (there was an error) jr nz,ImErr ; Return (Error) call Get_Titles ;Build a table of title string pointers or a ;If (there were no titles found) jr nz,ImErr ; Return (Error) ImLp1: call Print_Menu ;Repeat Print the Menu call Get_Response ; Get the user's response or a jr nz,ImLp1 ;Until (there's a valid response) call Translate_Def ;Translate the Definition or a ;If (there was an error) jr nz,ImErr ; Return (Error) call Read_Sys_File ;Read the Cpm3.Sys File or a ;If (there was an error) jr nz,ImErr ; Return (Error) call Install_Def ;Install the Definitions jp Bios_Entry ;Return (Normal) ;Fatal Error Return ImErr: call Report_Errors ;Report the Error jp Bios_Entry ;Return (Error) page ;---------------------------------------------------------------------- ; Read the Terminal.Dat File (9_Apr_84) ;-------------------------------------- ; Read_Dat_File: ld de,FCB_Dat ;DE:= Pointer to Terminal.Dat FCB ld c,Bdos_Open_File ;C:= Open File Function call Bdos_Entry ;Open the File ld de,Memory_Image ;DE:= Starting Address of program cp 4 ;If (file was NOT successfully opened) jr c,BCLp1 ld a,Open_Dat_Error ; Can't open Terminal.Dat ret ; Return ;Read Until the End of the File BCLp1: push de ;Loop DE:= Current Load Address ld c,Bdos_Set_DMA ; C:= Set DMA Function call Bdos_Entry ; Set the current DMA address ld de,FCB_Dat ; DE:= Address of FCB ld c,Bdos_Read_Seq ; C:= Read Sequential Function call Bdos_Entry ; Read the next record pop de ld hl,Record_Length add hl,de ex de,hl ; DE:= Pointer to start next record or a jr z,BCLp1 ;Until (End of File or Error Encounterd) cp Status_Eof ;If (the end of the file encountered) ld a,0 ret z ; Return No Error ld a,Disk_Read_Error ret ;Return Disk Read Error page ;---------------------------------------------------------------------- ; Build a List of Terminal Title Lines (17_Apr_84) ;------------------------------------------------- ; 1) This routine builds a list of Terimal Title line addresses into ; the one dimensional array Title_Buffer. ; 2) Register Usage: ; D -> Flag for comments and definition lines ; E -> Adjusted Line length counter (minus leading white space) ; HL -> Memory Image Pointer ; Get_Titles: ld hl,Title_Buffer ld (Title_Pointer),hl ;Title_Buffer_Pointer:= Start buffer ld hl,Memory_Image ;Memory_Image_Pointer:= Start buffer GtLp1: ld de,0 ;Repeat Flag and line lenght:= 0 call Strip_White ; Remove the leading white space cp '*' ; If (Char eq Comment) jr z,GtSk1 cp ';' jr nz,GtLp2 GtSk1: ld d,a ; Set the Flag GtLp2: cp End_of_File ; Loop If (End of File eq True) jr nz,GtSk2 ld a,(Max_Titles) ; If (Titles were found) or a ld a,0 ; (Status=Ok) ret nz ; Return ld a,No_Titles ; Else (Status=Not_Ok) ret ; Return GtSk2: cp Cr ; If (End of the Line) jr z,GtBrk1 ; Break cp '=' ; Else If (char eq def) jr nz,GtSk3 ld d,a ; Set the Flag GtSk3: ld a,(hl) ; Get the next character inc hl ; Inc Memory Image Pointer inc e ; Inc Line Length jr GtLp2 GtBrk1: ld a,d ; If ( (line ne comment/def) and or a jr nz,GtSk4 ld a,e ; (it wasn't a blank line) ) or a jr z,GtSk4 ld a,(Max_Titles) inc a ld (Max_Titles),a ; Increment Title Count push hl ; (Save current pointer) inc e ; (adj line length for Cr) or a sbc hl,de ex de,hl ; DE:= Start of last line ld hl,(Title_Pointer) ld (hl),e inc hl ld (hl),d ; Save Start addr last line inc hl ld (Title_Pointer),hl ; Update Title Pointer pop hl ; (Restore current pointer) GtSk4: jr GtLp1 page ;====================================================================== ; Print the Menu (20_Apr_84) ;=========================== ; 1) This routine prints the menu in two columns. If the number of ; entries is odd then the left hand column will be the longest. ; 2) Register Usage: ; B -> Title Count ; DE -> String Pointer ; HL -> Pointer to Current Title ; Print_Menu: ld de,Menu_Heading ld c,Bdos_Pstring call Bdos_Entry ;Print the Menu Heading call Setup_Columns ;Set column starting titles and numbers ld a,(Max_Titles) ld b,a ;B:= Number of titles to print ;Print the Left Column Title PmLp1: ld a,(Left_Number) ;Loop ld c,a ; C:= Left Column Number inc a ld (Left_Number),a ld hl,(Left_Col) ; HL:= Pointer to Title Pointer ld e,(hl) inc hl ld d,(hl) inc hl ld (Left_Col),hl ; Update Left Column Title Pointer ex de,hl ; HL:= Pointer to start title String push bc call Print_Title ; Print the Title pop bc dec b ; If (All Titles Printed) ret z ; Return ;Print the Right Column Number ld a,(Right_Number) ld c,a ; C:= Right Column Number inc a ld (Right_Number),a ld hl,(Right_Col) ; HL:= Pointer to Title Pointer ld e,(hl) inc hl ld d,(hl) inc hl ld (Right_Col),hl ; Update Right Col Pointer ex de,hl ; HL:= Pointer to start title String push bc call Print_Title ; Print the Title ld c,Bdos_ConOut ; C:= Console Output Function ld e,Cr ; E:= Carriage Return call Bdos_Entry ; Print the Character ld c,Bdos_ConOut ; C:= Console Output Function ld e,Lf ; E:= Carriage Return call Bdos_Entry ; Print the Character pop bc dec b ; If (All Titles Printed) ret z ; Return jr PmLp1 ;---------------------------------------------------------------------- ; Setup the Columns for printing the menu (23_Apr_84) ;---------------------------------------------------- ; 1) This routine sets up both the column numbers and the title ; pointers for printing the menu. The menu format consists of ; two columns, each entry is preceeded by a choice number. ; 2) Register Usage: ; DE -> Used in address calcualtion ; HL -> General Purpose Pointer ; Setup_Columns: ld a,1 ld (Left_Number),a ;Left_Column_Number:= 1 ld de,Title_Buffer ld (Left_Col),de ;Left_Column_Pointer:= Start Title Buffer ld hl,(Title_Pointer) ;HL:= End of Title Buffer or a sbc hl,de ;HL:= Length of Title Buffer srl l ;HL:= 1/2 way through Title Buffer ld a,l srl a jr nc,ScSk1 ;If (the number of entries is odd) inc a ; Make Right Column Number Shorter inc hl ; Make Right Column Pointer Shorter ScSk1: add hl,de ld (Right_Col),hl ;Right_Column_Pointer:= Start Right Col inc a ld (Right_Number),a ;Right_Column_Number:= 1/4 buffer leng ret page ;---------------------------------------------------------------------- ; Print the Title (20_Apr_84) ;---------------------------- ; 1) Register Usage ; C -> Current Choice Number ; HL -> Pointer to the current Title ; Print_Title: push hl push bc ;(save the input parameters) ld b,6 ;B:= Number of Leading Spaces PtLp1: push bc ;Repeat ld c,Bdos_ConOut ; C:= Bdos Console Ouput Function ld e,Space ; E:= Space call Bdos_Entry ; Print a Space pop bc djnz PtLp1 ;Until (all leading spaces printed) pop bc ld l,c ld h,0 call Print_Number ;Print the Column Number ld c,Bdos_ConOut ld e,')' call Bdos_Entry ;Print a ')' ld c,Bdos_ConOut ld e,Space call Bdos_Entry ;Print a Space pop hl ld b,25 ;Column Count:= 25 PtLp2: ld a,(hl) ;While ( (Char ne Carriage Return) and cp Cr jr z,PtSk1 cp Lf ; and (Char ne Line Feed) ) jr z,PtSk1 push bc inc hl ; Increment the Title Pointer push hl ld c,Bdos_ConOut ; C:= Console Output Function ld e,a ; E:= Next character of Title call Bdos_Entry ; Print the Character pop hl pop bc djnz PtLp2 ; Decrement the column count PtSk1: ld a,b PtLp3: or a ;While (Column Count ne 0) ret z push af ld c,Bdos_ConOut ; C:= Console Output ld e,Space ; E:= Space call Bdos_Entry ; Print a Space pop af dec a ; Decrement the column count jr PtLp3 ;====================================================================== ; Get the Response from the user (10_Apr_84) ;=========================================== ; Get_Response: ld a,0 ret ;====================================================================== ; Translate the Definitions (10_Apr_84) ;====================================== ; Translate_Def: ret ;---------------------------------------------------------------------- ; Read the Cpm3.Sys File (10_Apr_84) ;----------------------------------- ; Read_Sys_File: ret ld de,FCB_Sys ;DE:= Pointer to Cpm3.Sys FCB ld c,Bdos_Open_File ;C:= Open File Function call Bdos_Entry ;Open the File ld de,Memory_Image ;DE:= Starting Address of program cp 4 ;If (file was NOT successfully opened) jr c,RSFLp1 ld a,Open_Dat_Error ; Can't open Terminal.Dat ret ; Return ;Read Until the End of the File RSFLp1: push de ;Loop DE:= Current Load Address ld c,Bdos_Set_DMA ; C:= Set DMA Function call Bdos_Entry ; Set the current DMA address ld de,FCB_Sys ; DE:= Address of FCB ld c,Bdos_Read_Seq ; C:= Read Sequential Function call Bdos_Entry ; Read the next record pop de ld hl,Record_Length add hl,de ex de,hl ; DE:= Pointer to start next record or a jr z,RSFLp1 ;Until (End of File or Error Encounterd) cp Status_Eof ;If (the end of the file encountered) ld a,0 ret z ; Return No Error ld a,Disk_Read_Error ret ;Return Disk Read Error page ;---------------------------------------------------------------------- ; Install the Definitions (10_Apr_84) ;------------------------------------ ; Install_Def: ret ;---------------------------------------------------------------------- ; Strip Leading White Space (11_Apr_84) ;-------------------------------------- ; Strip_White: ld a,(hl) ;While (Char eq Space or Tab) inc hl cp Space jr z,Strip_White ; Loop cp Tab jr z,Strip_White cp Lf jr z,Strip_White ret ;Return ;---------------------------------------------------------------------- ; Dictinonary Lookup (9_Apr_84) ;------------------------------ ; 1) This routine searches the dictionary for String matching ; the one in the dictionary buffer. ; 2) Register Usage: ; A -> Returned = 0 for NO Error ; B -> Counter for the length of the string ; HL -> Enter pointing to Start of Dictionary to search ; Dict_Lookup: ld a,(Dict_Length) ld c,a ;C:= current dictionary buffer length or a ;If (there's no name to look for) jr nz,SrcLp1 ld a,Not_in_Dict ; Set Returned Error Status ret ; Return SrcLp1: ld (Save_Pointer),hl ;Loop Save the pointer to the arg inc hl inc hl inc hl ; HL:= pointer to length byte ld a,(hl) ; A:= Length of Name or a ; If (its the End of the Dict.) jr nz,SrcSk2 ld a,Not_in_Dict ; Set Return Error Status ret ; Return SrcSk2: ld b,a ; B:= Length of dictionary string inc hl ; HL:= Pointer to Start of String cp c ; If (the Length Matches) jr nz,SrcNxt ld de,Dict_Buffer ; DE:= Start of Dict buf SrcLp2: ld a,(de) ; Repeat cp (hl) ; If (no match) jr nz,SrcNxt ; Break inc hl ; inc dict pointer inc de ; inc Temp pointer djnz SrcLp2 ; Until (Count eq 0) ld hl,(Save_Pointer) ; HL:= Pointer to arg. ld a,0 ; Flag:= Success ret ; Return SrcNxt: ld e,b ld d,0 ; DE:= Offset add hl,de ; HL:= Pointer to start next name jr SrcLp1 page ;====================================================================== ; Report Errors (29_Feb_84) ;========================== ; 1) Report Errors on the console. ; 2) Register Usage: ; A -> Has Error Code on entry ; B -> Counter ; C -> Holds copy of Error Code ; Report_Errors: push af ld a,(Line_Count) ;If (line number is NOT Zero) or a jr z,ReSk1 ld de,ErrOpn ld c,Bdos_PString call Bdos_Entry ; Print the Opening Message ld a,(Line_Count) ld l,a ld h,0 ; HL:= Line Number call Print_Number ; Print the line number ReSk1: pop af ld c,a ;C:= Error Code to Find ld b,Max_Error ld hl,Error_Table ;HL:= Start of the error table ReLp1: ld a,(hl) ;Repeat A:= Table's Error Code inc hl ld e,(hl) inc hl ld d,(hl) ; DE:= Pointer to String inc hl ; (HL equal to start next entry) cp c ; If (Code eq table) jr z,REprn ; Goto Print djnz RELp1 ;Until (the whole tables been checked) ld de,NoCode ;(set pointer to 'Unrecognized Error') REprn: ld c,Bdos_PString ; call Bdos_Entry ; Print the Message ret page ;---------------------------------------------------------------------- ; Print Line Number (12_Apr_84) ;------------------------------ ; 1) This routine prints the 16 bit number (passed in the HL) in ascii. ; 2) Register Usage: ; HL -> 16 bit number to be printed ; Print_Number: ld a,l ;If (The Number is Zero) or h jr nz,Dsk1 ld b,3 ; Set Leading space count to max DLp1: push bc ; Repeat ld c,Bdos_ConOut ; Set the function number ld e,Space call Bdos_Entry ; Print a Space pop bc djnz DLp1 ; Until (Leading space count eq 0) ld c,Bdos_ConOut ld e,'0' call Bdos_Entry ; Print the zero ret ; Return Dsk1: ld bc,0FFFFh push bc ;Put end flag on stack DLp2: ld bc,10 ;Repeat divisor:= 10 (base 10) call divide ; Divide push hl ; Save the remainder ld hl,9 or a sbc hl,de ex de,hl ; (Move quotient to dividend) jp c,DLp2 ;Until (quotient is less than 9) DLp3: ld a,l ;While (Result eq 0) or a jr nz,DLp4 ld e,Space ld c,Bdos_ConOut call Bdos_Entry ; Print a Space pop hl ; Get the next number jr DLp3 DLp4: add a,'0' ;Repeat ld e,a ; Convert number to ascii ld c,Bdos_ConOut call Bdos_Entry ; Print the number pop hl ; Get the next number ld a,l cp 0FFh jr nz,DLp4 ;Until (end of stack flag has been read) ret ;Return page ;---------------------------------------------------------------------- ; 16 bit Divide ;-------------- ; divide 16-bit number in [hl] by [bc] ; on exit, [de] is 16-bit quotient, [hl] is remainder ; divide: add hl,hl ;hi *2 ex de,hl ;[de] becomes lo ld hl,0 ;init hi ld a,16 ;16 bits divid0: adc hl,hl ;Repeat hi *2 or a ; clear borrow sbc hl,bc ; sbc hl,bc ;hi=hi-divisor ccf ; invert borrow for shift later jr c,divid1 ; if borrow { adc hl,bc ; Restore the value of the HL ccf divid1: ex de,hl ; get lo adc hl,hl ; lo *2 + remainder ex de,hl dec a ; count-- jr nz,divid0 ;Until (bit count eq 0) ret ;====================================================================== ; Dictionary Macro Definitions (9_Apr_84) ;======================================== ; ; Generate a Dictionary Entry (9_Apr_84) ;--------------------------------------- ; 1) This macro generates an entry in the function key dictionary. ; 2) Each entry in the dictionary has the following form ; 1 byte Length of the name string ; 3 bytes Key definitions (normal, shifted and contol) ; n bytes Name of function key ; DfDict macro Name, type, pntr local L1, L2 db type ;Type of the entry dw pntr ;Pointer to the default output string db l2 - l1 ;length of Name string l1: db '&Name' ;Name of function key l2: endm ; Terminate the Key Dictionary (28_Feb_84) ;----------------------------------------- ; DfEnd macro ds 4,0 ;4 bytes of zero to end the table endm page ;---------------------------------------------------------------------- ; Key Dictionary (9_Apr_84) ;-------------------------- ; 1) This Dictionary contains all of the Function Key Codes ; Main_Dictionary: DfDict LEVEL, 0, Level_Dflt DfDict CURSOR, 0, Cursor_Dflt DfDict HOME, 0, Home_Dflt DfDict CLEAR, 0, Clear_Dflt DfDict RIGHT, 0, Right_Dflt DfDict LEFT, 0, Left_Dflt DfDict UP, 0, Up_Dflt DfDict DOWN, 0, Down_Dflt DfDict CEOL, 0, CEol_Dflt DfDict CEOS, 0, CEos_Dflt DfDict INSLINE,0, InsLine_Dflt DfDict INSCHAR,0, InsChar_Dflt DfDict DELCHAR,0, DelChar_Dflt DfDict DELLINE,0, DelLine_Dflt DfDict HI, 0, Hi_Dflt DfDict LO, 0, Lo_Dflt DfEnd ;End of the table ;---------------------------------------------------------------------- ; Non_Printing Key Dictionary (9_Apr_84) ;--------------------------------------- ; 1) This Dictionary contains all of the Special Key names for non- ; printing keys. These names only can appear on the right side of ; the definition. ; Pnct_Dictionary: DfDict ESC, 0, 033 DfDict SP, 0, 20h DfEnd ;End of the table page ;---------------------------------------------------------------------- ; Default Definition Strings (9_Apr_84) ;-------------------------------------- ; Level_Dflt: db 0 Cursor_Dflt: db 0 Home_Dflt: db 0 Clear_Dflt: db 0 Right_Dflt: db 0 Left_Dflt: db 0 Up_Dflt: db 0 Down_Dflt: db 0 CEol_Dflt: db 0 CEos_Dflt: db 0 InsLine_Dflt: db 0 InsChar_Dflt: db 0 DelChar_Dflt: db 0 DelLine_Dflt: db 0 Hi_Dflt: db 0 Lo_Dflt: db 0 page ;---------------------------------------------------------------------- ; Error Code Tables and Message Strings (19_Apr_84) ;-------------------------------------------------- ; ;Error Message String Lookup Table ;--------------------------------- ; Error_Table: db Open_Dat_Error ;Cannot open the Termianl.Dat File dw ODEmsg db Open_Sys_Error ;Cannot open the Cpm3.Sys File dw OSEmsg db Disk_Read_Error ;Error occured in a disk read operation dw DREmsg db UnExpected_End ;Unexpected End (Eol or Eof) dw UEmsg db Bad_Definition ;Illegal Character in definition dw BDmsg db Dict_Overflow ;Dictionary Buffer has overflowed dw DOmsg db No_Titles ;No terminal titles to build menu dw NTmsg db Not_in_Dict ;Current Element not in the dictionary dw NDmsg End_Table: Max_Error equ ( (End_Table - Error_Table)/3 ) + 1 page ; Error Message Strings (19_Apr_84) ;---------------------------------- ; ODEmsg: db 'Cannot open the Terminal.Dat file $' OSEmsg: db 'Cannot open the Cpm3.Sys file $' DREmsg: db 'Error occured in a disk read operation $' UEmsg: db 'Unexpected End (Eol or Eof) $' BDmsg: db 'Illegal Character $' DOmsg: db 'Dictionary Buffer has overflowed $' NTmsg: db 'No terminal titles to build menu $' NDmsg: db 'Current Element not in the dictionary $' NoCode: db ' Unrecognized Error $' ErrOpn: db Cr,Lf, 'Error on line $' page ;---------------------------------------------------------------------- ; Local FCB's Area (9_Apr_84) ;---------------------------- ; FCB_Dat: db 0,'TERMINALDAT',0 ;Fcb name field ds 19,0 ;Blank file remainder of FCB FCB_Sys: db 0,'CPM3 SYS',0 ;Fcb name field ds 19,0 ;Blank file remainder of FCB page ;---------------------------------------------------------------------- ; General Parameter Area (11_Apr_84) ;----------------------------------- ; Save_Pointer: dw 0 ;Save location for pointer to dict argument Dict_Length: db 0 ;Length of the Dictionary buffer Dict_Buffer: ds 20h ;Dictionary buffer Line_Count: dw 0 ;Current Line Number Menu_Heading: db ClrScr,'MD-11 Terminal Initialization Program, Rev ' db ((Rev and 0F0h) shr 4) + '0', '.',(Rev and 0Fh) + '0' db Tab,Tab,Tab,' Copyright 1984' db Cr,Lf,'Morrow Designs Inc.' db Tab,Tab,Tab,Tab,Tab,Tab,'San Leandro, Ca' db Cr,Lf,Lf,Lf,Lf, '$' Left_Col: dw 0 ;Pointer to Left hand column Left_Number: db 0 ;Left Column Choice Number Right_Col: dw 0 ;Pointer to Right hand column Right_Number: db 0 ;Right Column Choice Number ds (0FFh and (Not ($ mod 100h) ) ) + 1, 0 Max_Titles: db 0 ;Total Number of Titles Title_Pointer: dw 0 ;Pointer into the title buffer Title_Buffer: ds 60h,0 ;Title Buffer Memory_Image: db 0 ;Label for start of buffer end