Title Terminal Initialization Program for the MD11 (21_Jun_84) ; ; Copyright 1984 ; Morrow Designs, Inc. ; San Leandro, Ca. ; John Zalabak ; .z80 Aseg Org 0100h ;---------------------------------------------------------------------- ; Equates (15_Jun_84) ;-------------------- ; Rev equ 20h ;Bios/Bdos Equates Bios_Entry equ 0 ;Bios Entry Point Bdos_Entry equ 5 ;Bdos: Entry Vector Location Bdos_ConIn equ 1 ; Console Input Bdos_ConOut equ 2 ; Console Output Bdos_PString equ 9 ; Print a Sting on the Console Bdos_ConBuf_in equ 10 ; Read Console input buffer Bdos_Ret_Ver equ 12 ; Return CP/M version 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 Control_C equ 03h ;Control C (Force CPM Warm Boot) Tab equ 09h ;Tab Lf equ 0Ah ;Line Feed Cr equ 0Dh ;Carriage Return End_of_File equ 1Ah ;End of File Character Esc equ 1Bh ;Escape ;Length defintions Record_Length equ 80h ;Length of one record Max_Token_Len equ 10h ;Maximum Length of the Token buffer Max_Rec_Length equ 80h ; " " " a Record Max_Stack_Space equ 20h ; " " " the main stack Dca_Len equ 6 ; " " " a Dca String ;File Control Block Definitions Default_Fcb equ 5Ch ;Start of 1st FCB generated by CCP Default_Extent equ Default_Fcb+9 ;Offset to start of FCB's Extent page 60 ;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 ;No terminal titles to build menu Not_in_Dict equ 0F8h ;Current Element is not in dictionary No_Delimiter equ 0F7h ;Equal sign is missing in definition Bad_Type_Byte equ 0F6h ;Unknown Line Type Definition Bad_Level equ 0F5h ;Terminal Level Definition Out of Range Bad_Symbol equ 0F4h ;Bad Symbol in Definition Invalid_Number equ 0F3h ;Invalid Char in Literal Numeric String Number_Overflo equ 0F2h ;Literal Numeric String is too Long Number_Delimit equ 0F1h ;Missing Literal Numeric String Delimiter Dca_OverFlo equ 0F0h ;Direct Cursor Address String too Long Sys_Read_Err equ 0EFh ;Unable to Read System from the Disk Sys_Write_Err equ 0EEh ;Unable to Write System to the Disk ;Block Definitions (Masks) $Type_Cursor equ 10000000b ;Cursor Definition String $Type_Ascii equ 01000000b ;Ascii Cursor Position Format Flag $Type_Row equ 00100000b ;Row Definition $Type_Col equ 00010000b ;Column Definition $Type_Level equ 00001000b ;Level Defintion $Type_Char equ 00000100b ;Non Printing Character Definition $Type_Escape equ 00000010b ;Escape Table Definition $Type_Controì eqõ 00000001â ;Controì Tablå Definition ;Block Definitions (Bits) @Type_Cursor equ 7 ;Cursor Definition String @Type_Ascii equ 6 ;Ascii Cursor Position Format Flag @Type_Row equ 5 ;Row Definition @Type_Col equ 4 ;Column Definition @Type_Level equ 3 ;Level Defintion @Type_Char equ 2 ;Non Printing Character Definition @Type_Escape equ 1 ;Escape Table Definition @Type_Controì eqõ 0 ;Controì Tablå Definition ;Other Definitions Clear_Code equ 1Ah ;Escape Table Code for Clear Screen Default_Dma equ 80h ;Start of the default dma buffer Status_EOF equ 1 ;End of file status Null equ 0FFh ;Null Key Definition @Column_Flag equ 0 ;Row/Column Flag (see Order:) @Ascii_Flag equ 1 ;Binary/Ascii Flag (see Order:) Token_Number equ 1 ;Token Read was a Number Token_Literal equ 2 ; " " " " Literal page ; Cp/m 2.2 Bios Jump Table Offsets Bios_Address equ 1 ;Address of Bios (Warm Boot Vector Addr) WBoot_Offset equ 4 ;Warm Boot address (Gives base of Bios) RdBlk_Offset equ 37h ;Read a Block from the Floppy Disk WrBlk_Offset equ 3Ah ;Write a Block to the Floppy Disk RamDatX_Offset equ 40h ;RamDatX Area RamDatY_Offset equ 42h ;RamDatY Area Pool_Offset equ 46h ;Start Free Space Pool (same as Xltab) EtblPtr_Offset equ 48h ;Escape Lookup Table CtblPtr_Offset equ 4Ah ;Control Lookup Table EvctPtr_Offset equ 4Ch ;Escape Vector Table CvctPtr_Offset equ 4Eh ;Control Vector Table DcaPtr_Offset equ 50h ;Start of the Direct Cursor Addr Struct ; RamDatX Area Definitions HstDsk equ 0 ;Host Level Disk HstTrk equ 1 ; " " Track HstSec equ 2 ; " " Sector SecCnt equ 3 ;Sector Count (1 to n) Retry equ 4 ;Error Retry Count HstBuf equ 5 ;Host Buffer ErFlag equ 7 ;Error Flag DatXln equ 1Fh ;Length of RamDatX page ;====================================================================== ; Main Line of Terminal Initialization (18_Apr_84) ;================================================= ; Init_Main: call Read_Dat_File ;Read the Terminal Definition 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 ;Loop Print the Menu call Get_Response ; Get the user's response or a ; If (Response was Valid) jr nz,ImLp1 call Verify_Response ; Verify the response or a ; If (Repsonse was Yes) jr nz,ImLp1 ; call Translate_Def ; Translate Def or a ; If (Error True) jr nz,ImErr ; Return (Error) call Verify_Level ; If (Level is Ok) or a jr nz,ImLp1 ; Break call Read_Sys_File ;Read the Cpm3.Sys File or a ;If (there was an error) jr nz,ImErr ; Return (Error) call Build_Tables ;Build the Console Translation Table call Get_Version ;If (This is a Cp/m 2.2 system) jr z,ImSk1 call Install_Cpm2 ; Install Definitions for Cp/m 2 or a ; If (There was NO Error) jr z,ImOk ; Goto Normal Return jr ImErr ; Else Goto Error Return ImSk1: call Install_Cpm3 ;Else Install Definitions for Cp/m 3 or a ; If (There was NO Error) jr z,ImOk ; Goto Normal Return ImErr: call Report_Errors ;Report the Error ImOk: jp Bios_Entry ;Return page ;---------------------------------------------------------------------- ; Read the Terminal Definition File (15_Jun_84) ;---------------------------------------------- ; Read_Dat_File: ld a,(Default_Fcb+1) ;If (the default FCB has been filled in) cp ' ' jr z,BCsk2 ld bc,8 ; Length:= 8 (file_name_field) ld a,(Default_Extent) ; If (Extent is filled in) cp ' ' jr z,BCsk1 ld bc,11 ; Length:= 11 (whole name) BCsk1: ld de,FCB_Dat+1 ld hl,Default_Fcb+1 ldir ; Move the Default Fcb BCsk2: ld de,FCB_Dat ;DE:= Pointer to Terminal Def 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 Def File 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 (11_May_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 ;Loop Flag and line length:= 1 call Strip_White ; Remove the leading white space cp Cr ; If ( (1st Char is a Cr) Or jr z,GtSk1 cp ';' ; (1st Char is Comment) ) jr z,GtSk1 cp '*' jr nz,GtLp2 GtSk1: call Get_Next_Line ; Remove the Line jr GtLp1 ; Goto Start of Loop GtLp2: cp End_of_File ; Repeat jr nz,GtSk2 ; If (End of File eq True) ld (Temp_Buffer),hl ex de,hl ; DE:= Pointer to Eob ld hl,(Title_Pointer) ld (hl),e inc hl ld (hl),d ; Save Start addr last line inc hl 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 '=' ; Else If (char eq def) jr nz,GtSk3 ld d,a ; Set Non_Title Flag GtSk3: inc hl ; Inc Memory Image Pointer inc e ; Inc Line Length ld a,(hl) ; Get the next character cp Cr jr nz,GtLp2 ; Until (End of Line) ld a,d ; If (line eq definition) or a jr nz,GtSk4 ld a,(Max_Titles) inc a ld (Max_Titles),a ; Increment Title Count push hl ; (Save current pointer) 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 (30_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,0 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 ld (Right_Number),a ;Right_Column_Number:= 1/4 buffer leng ret page ;---------------------------------------------------------------------- ; Print the Title (30_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,' ' ; E:= Space call Bdos_Entry ; Print a Space pop bc djnz PtLp1 ;Until (all leading spaces printed) pop bc ld a,'A' add a,c ;Add Ascii Offset to Column Offset ld e,a ld c,Bdos_ConOut call Bdos_Entry ;Print the Column Letter ld c,Bdos_ConOut ld e,')' call Bdos_Entry ;Print a ')' ld c,Bdos_ConOut ld e,' ' 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,' ' ; E:= Space call Bdos_Entry ; Print a Space pop af dec a ; Decrement the column count jr PtLp3 page ;====================================================================== ; Get the Response from the user (11_May_84) ;=========================================== ; 1) This routine gets the response from the user. If the response is ; valid then the accm is returned equal to zero (else its returned ; non-zero). ; 2) The HL register pair is returned pointing to the base of the title ; line. ; 3) Register Usage: ; DE -> Offset to the start of the title line ; HL -> Returned Pointing to the start of the title line. ; Get_Response: ld de,Response_Msg ld c,Bdos_PString call Bdos_Entry ;Print the prompt string GrLp1: ld c,Bdos_ConIn call Bdos_Entry ;Get the User's Response and 5Fh ;(force response to upper case) cp Control_C ;If (Response eq Force Warm Boot) jp z,Bios_Entry ; Goto Warm Boot sub 'A' ;Adjust the Response ld e,a cp 0 ;If ( (Response lt 0) or ret c ld a,(Max_Titles) dec a cp e ; (Response gt Max_Titles) ) ret c ; Return sla e ld d,0 ;DE:= Offset to title line ld hl,Title_Buffer add hl,de ;HL:= Pointer to title ld e,(hl) inc hl ld d,(hl) inc hl ld (Start_Def),de ;Save the Start of the Definition ld e,(hl) inc hl ld d,(hl) ld (End_Def),de ;Save the End of the Defintion ld a,0 ;Returned_Status:= Title Found ret ;Return page ;====================================================================== ; Verify the User's Response (18_Jun_84) ;======================================= ; 1) This routine verifies the user's response by presenting the ; the title of the chosen terminal and then demanding a Y/N ; validation from the user. ; Verify_Response: ld de,VRmsg1 ld c,Bdos_PString call Bdos_Entry ;Print 'Is ' ld hl,(Start_Def) ;HL:= Pointer to start of the title ld b,25 ;B:= Max Title Length ld c,Bdos_ConOut ;C:= Console Output Function VrLp1: ld a,(hl) ;While ( (Char ne Carriage Return) and cp Cr jr z,VrSk1 cp Lf ; and (Char ne Line Feed) ) jr z,VrSk1 inc hl ; Increment the Title Pointer push bc push hl ld e,a ; E:= Next character of Title call Bdos_Entry ; Print the Character pop hl pop bc djnz VrLp1 ; Decrement the column count VrSk1: ld de,VrMsg2 ld c,Bdos_PString call Bdos_Entry ; Print ' the correct choice?' call Yes_or_No ; Get the Response ret ; (Flag set in Yes_or_No) page ;====================================================================== ; Translate the Definitions (15_Jun_84) ;====================================== ; 1) This routine is the main line of the definition parser. First the ; title line is removed. Then successive lines are read and decoded ; until either an end of file mark or the start of the next ; definition is encountered. ; 2) Comment lines within the definition are ignored. ; 3) A count is kept of the number of lines within the definition. This ; is used in error reporting. ; Translate_Def: ld hl,(Start_Def) ;HL:= Pointer to start title line call Get_Next_Line ;Remove the current Line ld a,0 ;If (End of File Read) ret c ; Return TdLp1: ld a,(Line_Count) ;Loop inc a ld (Line_Count),a ; Increment the def line number call Strip_White ; Strip white space cp Cr ; If ( (Char eq Cr) Or jr z,TdSk0 cp ';' ; (Char eq Comment) ) jr z,TdSk0 cp '*' jr nz,TdSk1 TdSk0: call Get_Next_Line ; Remove the Line jr TdLp1 TdSk1: push hl ; If (End of definition) ld de,(End_Def) xor a ; (Status:= Ok) sbc hl,de pop hl ret nc ; Return call Get_Token ; (move line def into Token_Buf) ret c ; If (Error or Eof) Return calì Strip_Whitå » Movå tï thå Equaì Sign cp '=' ld a,No_Delimiter ; If (equal sign missing) ret nz ; Return (error) push hl ld hl,Main_Dictionary call Dict_Lookup ; Lookup the Code ex de,hl pop hl or a ; If (Code in Main Dict) jr nz,TdSk3 call Proc_String ; Process the String or a ; If (Error) ret nz ; Return jr TdLp1 TdSk3: push hl ; Else ld hl,Aux_Dictionary ; Lookup Aux Dict call Dict_Lookup ex de,hl pop hl or a ; If (Code not found) ret nz ; Return (error) call Set_DE_to_Def ; DE:= Pointer to Data ld a,(de) ; A:= Line Type bit @Type_Cursor,a ; If (Line_Type is Cursor) jr z,Tdsk4 call Proc_Cursor ; Process cursor definition or a ; If (error true) ret nz ; Return jr TdLp1 TdSk4: bit @Type_Level,a ; Else If (Line_Type is Level) jr z,TdSk5 call Proc_Level ; Process Level Definition or a ; If (Error true) ret nz ; Return jr TdLp1 TdSk5: ld a,Bad_Type_Byte ; Else Type is invalid ret ; Return page ;---------------------------------------------------------------------- ; Process a Cursor Definition (14_Jun_84) ;---------------------------------------- ; Proc_Cursor: inc hl ;Move past the equal sign PClp1: call Get_Token ;Repeat Move Token Into Token_Buffer ret c ; If (Error) Exit or a ; If (End of Line) jr nz,PCsk1 inc hl ; HL:= Moved past Eol Character ret ; Return PCsk1: call Check_Aux ; Lookup String in Aux Dict or a ; If (String is in the dict) jr nz,PCsk5 call Set_DE_to_Def ; DE:= Pointer to Data ld a,(de) ; A:= Line Type bit @Type_Row,a ; If (Symbol eq Row) jr z,PCsk2 call Proc_Row_Col ; If (Error) ret c ; Return jr PClp1 PCsk2: bit @Type_Col,a ; If (Symbol eq Column) jr z,PCsk3 call Proc_Row_Col ; If (Error) ret c ; Return jr PClp1 PCsk3: bit @Type_Ascii,a ; If (Symbol is Ascii) jr z,PCsk4 ld a,(Order) set @Ascii_Flag,a ; Set Ascii Flag ld (Order),a jr PClp1 PCsk4: inc de ; Else ld a,(de) ; A:= Symbol Val call Store_Dca ; Store Symbol ret c ; If (Error) Exit jr PCLp1 PCsk5: ld a,(Token_Type) ; Else If (Token Type eq Number) cp Token_Number jr nz,PCsk6 push hl call RadN_to_Binary ; Convert to Binary ld a,l ; A:= Number pop hl call Store_Dca ; Save the Number ret c ; If (Error) then Exit jr PCLp1 PCsk6: ld de,Token_Buffer ; DE:= Pointer to Token Buffer ld a,(Token_Length) ld b,a ; B:= Length of Token Buffer PClp2: call Check_Control ; Else Repeat Process Control Char PCsto: call Store_Dca ; Store in Dca Buffer ret c ; If (Error) Exit inc de ; Inc Token_Buffer pointer djnz PCLp2 ; Until (Token_Buffer emptied) jr PCLp1 page ;---------------------------------------------------------------------- ; Save The Direct Cursor Address Character (14_Jun_84) ;----------------------------------------------------- ; 1) This routine stores one byte in the current dca string after ; checking for Dca OverFlo. ; 2) If there was an Error (Dca Length too Long) then the carry is ; returned set else its returned cleared. ; 3) Register Usage: ; A -> Character to store ; DE -> Temp Storage and Pointer Calculation ; HL -> Pointer to Save Location ; Store_Dca: push hl push de lä d,á ;Savå thå Characteò iî D ld a,(Dca_Length) ld e,a inc a ;Increment the Dca Length cp Dca_Len ;If (Length gt Max) jr c,SDsk1 pop de pop hl ld a,Dca_OverFlo ; A:= Error Code scf ; Flag:= Error ret ; Return SDsk1: ld (Dca_Length),a ;Update Dca Length ld a,(Dca_Level) cp 0 ;If (Dca_Level eq 0) jr nz,SDsk2 ld hl,DcaStrt ; HL:= Dca Start String jr SDsk4 SDsk2: cp 1 ;Else If (Dca_Level eq 1) jr nz,SDsk3 ld hl,DcaMid ; HL:= Dca Mid String jr SDsk4 SDsk3: ld hl,DcaEnd ;Else HL:= Dca End String SDsk4: ld a,d ld d,0 add hl,de ;HL:= Pointer to Storage Location ld (hl),a ;Save the Character inc hl ld (hl),0FFh ;ReTerminate the String pop de pop hl or a ;Flag:= No Error (Carry Cleared) ret page ;---------------------------------------------------------------------- ; Process Row/Column Cursor Offsets (14_Jun_84) ;---------------------------------------------- ; 1) This routine processes both Row and Column Offsets and sets the ; Column before Row flag if appropriate. ; 2) If an error Occurs then the carry is returned set else its cleared. ; 3) Register Usage: ; C -> Temporary Storage for Type_* ; DE -> Altered in Subroutine Calls ; HL -> Incremented past Offset Value ; Proc_Row_Col: ld c,a ;C:= Row/Column Flag ld a,(Dca_Level) inc a ld (Dca_Level),a ;Inc Dca Level (Start -> Mid -> End) ld a,0 ld (Dca_Length),a ;Reset Current Dca Length to 0 bit @Type_Col,c ;If ( (Offset eq Column) And jr z,PRsk1 cp 1 ; (Dca_Level eq Mid) ) jr nz,PRsk1 ld a,(Order) set @Column_Flag,a ld (Order),a ; Set Column before Row Flag PRsk1: call Fill_Numb_Buf ;Fill the Number Buffer ret c ;If (Error) Then Exit push hl call RadN_to_Binary ;Convert the Number to Binary ld a,(Dca_Level) ld h,a ;(save Dca_Level temporairly in H) ld a,l sub 20h ;Adjust offset Relative to Standard dec h ;If (this is the first offset) pop hl ; (restore HL) jr nz,PRsk3 ld (Offset1),a ; Save Offset1 or a ; Clear Carry ret ; Return PRsk3: ld (Offset2),a ;Else Save Offset2 or a ; Clear Carry ret ; Return page ;---------------------------------------------------------------------- ; Process a Level Definition (4_Jun_84) ;-------------------------------------- ; 1) This routine reads, translates and verifies a LEVEL definition. ; Proc_Level: inc hl call Strip_White ;A:= Ascii Terminal Level cp '0' ;If (Terminal Level within limits) jr c,PLbad cp '4' jr nc,PLbad and 0Fh ; A:= Absolute Terminal Level ld (Terminal_Level),a ; Update the terminal level call Get_Next_Line ; Strip the remainder of the line ld a,0 ret ; Return PLbad: ld a,Bad_Level ;Else Returned_Status:= Bad Terminal Level ret ; Return page ;---------------------------------------------------------------------- ; Process a String Definition (15_Jun_84) ;---------------------------------------- ; 1) This routine does the processing for a teminal translation string. ; The type (e.g. Clear screen) has already been looked up before this ; routine is entered. First a check is made for the equal sign. Then ; a pointer to the start of the translation string is saved in the ; the block definition. Finally the body of the definition (if ; there is one) is translated and terminated by a byte of 0FFh. ; 2) Register Usage: ; A -> General Purpose ; DE -> On entry is a Pointer to a pointer to the string def. ; HL -> Pointer to into the Terminal.dat source file. ; Proc_String: inc hl ;(move past the equal sign) push hl ;(save the text pointer) call Set_DE_to_Def ;DE:= Pointer to Data (line title) ex de,hl inc hl inc hl ;(move HL to start of pointer in block def) ld de,(Temp_Buffer) ld (hl),e inc hl ld (hl),d ;Setup the pointer in the block def. pop hl ;(restore text pointer) PSlp1: call Get_Token ;While (there is another token) ret c ; If (Error) Exit or a jr z,PSdone call Check_Aux ; Lookup String in Aux Dict or a ; If (String is in the dict) jr nz,PSsk1 call Set_DE_to_Def ; DE:= Pointer to Data ld a,(de) ; A:= Line Type bit @Type_Char,a ; If (Symbol isn't Char) ld a,Bad_Symbol ret z ; Return (error) inc de ; Else ld a,(de) ; Get the Char call Store_Temp_Buf ; Store it jr PSLp1 PSsk1: ld a,(Token_Type) ; Else If (Token Type eq Number) cp Token_Number jr nz,PSsk2 push hl call RadN_to_Binary ; Convert to Binary ld a,l ; A:= Number pop hl call Store_Temp_Buf ; Save the Number ret c ; If (Error) then Exit jr PSLp1 PSsk2: ld a,(Token_Length) ; Else ld b,a ; B:= Length of Token Buffer ld de,Token_Buffer ; DE:= Pointer to Token Buffer PSlp2: call Check_Control ; Repeat Process Control Chars call Store_Temp_Buf ; Store Character inc de ; Inc Token_Buffer pointer djnz PSLp2 ; Until (Token_Buffer emptied) jr PSLp1 PSdone: ld a,0FFh ;A:= Terminator call Store_Temp_Buf ;Terminate the string inc hl ;HL:= Moved past End of Line Character ld a,0 ret ;Return ;---------------------------------------------------------------------- ; Check The Aux Dictionary (11_Jun_84) ;------------------------------------- ; 1) This routine checks the Aux Dictionary for the String contained ; in the Token Buffer. ; 2) Register Usage: ; DE -> If Found then its returned pointing to the Definition ; HL -> Preserved ; Check_Aux: push hl ld hl,Aux_Dictionary ;Lookup String in Aux Dict call Dict_Lookup ex de,hl ;Move the Defintion Pointer into DE pop hl ret ;---------------------------------------------------------------------- ; Check if the current Character is a control Character (15_Jun_84) ;------------------------------------------------------------------ ; 1) This routine checks if the current character is a control char. If ; it isn't then the accm is returned UnToutched; Else, the control ; character is converted and returned in the accm. ; 2) Register Usage: ; A -> Returned equal to Char or Converted Control Char ; B -> Token Buffer Length Count ; DE -> Pointer to Current Position in Token Buffer ; Check_Control: ld a,(de) cp '^' ;If (Char ne Control Char) ret nz ; Return djnz CCsk1 ;If (Token_Length - 1 eq 0) inc b ; Restore Token Length ret ; Return CCsk1: inc de ; Increment Token_Buffer_Pointer ld a,(de) ; Get Character sub 40h ; Convert to cntrl ret page ;---------------------------------------------------------------------- ; Check for a Literal Numeric Definition (14_Jun_84) ;--------------------------------------------------- ; 1) This routine checks for a literal numeric definition. If the token ; buffer isn't the start of a literal numeric definition (token_buffer ; equal to a Single Quote) then the current character is returned ; with the carry cleared. If this is a numeric defintion then the ; number is moved into the number buffer and the accm is returned ; equal to zero. If there was an error in moving the number into the ; number buffer then the carry is returned set else its returned clear. ; Check_Number: ld a,(de) cp "'" ;If (Char ne Single Quote) jr z,CNsk1 or a ; Clear error Flag ret ; Return (Not a Number) CNsk1: dec b ;If (there are No chars in Token Buf) jr z,CNsk2 inc b ; Restore the Counter or a ; Clear Error Flag ret ; Return (Not a Number) CNsk2: call Fill_Numb_Buf ;Fill the Number Buffer ld a,0 ;Flag:= Its a Number ret ;Return (carry set/cleared in Fill rtn) page ;---------------------------------------------------------------------- ; Fill the Number Buffer (13_Jun_84) ;----------------------------------- ; 1) This routine fills the Number Buffer. If the number buffer overflows ; then the carry is returned set else its returned cleared. ; 2) Register Usage: ; B -> [Preserved] Maximum for length of Number Buffer ; C -> [Preserved] Current Length of the Number Buffer ; DE -> [Preserved] Pointer into the Number Buffer ; HL -> Pointer into the Terminal.Dat File ; Fill_Numb_Buf: push bc push de ld b,6 ld c,0 ld de,Number_Buffer ;DE:= Start of the Number Buffer FNlp1: ld a,(hl) ;Loop cp "'" ; If ( (Char eq Single Quote) Or jr z,FNdone call White_Space? ; (Char eq White Space) Or jr z,FNdone call End_Line? ; (Char eq Eof/Eol) ) jr z,FNdone FNsk1: call Valid_Number ; If (This isn't a Valid Number) jr nc,FNsk2 pop de pop bc scf ; Flag:= Error ld a,Invalid_Number ; A:= Error Code ret ; Return (Error) FNsk2: ld (de),a ; Number_Buffer:= Current Char inc hl ; Inc Number_Buffer Pointer inc de ; Inc Token_Buffer_Pointer inc c ; Inc Buffer Length djnz FNlp1 ; If (Number Buffer Overflowed) pop de pop bc scf ; Flag:= Error ld a,Number_OverFlo ; A:= Error Code ret ; Return FNdone: ld a,c ld (Number_Length),a ;(Save the Number Length) pop de pop bc ld b,1 ;B:= 1 for Proc_String/Proc_Cursor Loop or a ;Flag:= No Error (clears the carry) ret ;Return page ;---------------------------------------------------------------------- ; Check for a Valid Ascii/Ascii-Hex Number (11_Jun_84) ;----------------------------------------------------- ; 1) This routine check if the character in the accm is a number. If it ; is then its converted to a zero based binary number and the carry ; is returned Cleared. Else the number is returned in the accm and ; the carry is returned Set. ; 2) Register Usage: ; A -> Returned w/Number relative to base 0 if valid number ; Valid_Number: cp '0' ;If (Number Lt 0) jr c,VNno ; Quit cp '9' + 1 ;If (Number le 9) jr c,VNyes ; Convert and Exit and 5Fh ;(Force to Upper Case) cp 'A' ;If ( (Number Lt A) Or jr c,VNno cp 'F' + 1 ; (Number Gt F) ) jr nc,VNno ; Quit sub 7 ;Shift Alpha-Number down VNyes: sub '0' ;Shift Number base to 0 or a ;Flag:= its a Number ret ;Return VNno: scf ;Flag:= Not a Number ret ;Return ;---------------------------------------------------------------------- ; Store a Byte in the Temp Buffer (4_Jun_84) ;------------------------------------------- ; 1) This routine stores one byte in the Temp_Buffer located at the ; end of the Terminal.dat file (its setup in Get_Titles). ; Store_Temp_Buf: push hl ld hl,(Temp_Buffer) ;HL:= Pointer into temp_buffer ld (hl),a ;Save the character inc hl ld (Temp_Buffer),hl ;(increment the pointer) pop hl ret ;Return page ;---------------------------------------------------------------------- ; Get the Next Line (14_Jun_84) ;------------------------------ ; 1) This routine reads characters until a new-line or and end-of-file ; is read. If the end of file character is read then the carry is ; returned set else its cleared. ; 2) Register Usage: ; A -> Current character ; HL -> Pointer into the source file. ; Get_Next_Line: ld a,(hl) ;Loop Get Character cp End_of_File ; If (Char eq End of File) jr nz,GLsk1 scf ; Flag:= End of File ret ; Return GLsk1: inc hl ; Pointer:= Pointer + 1 cp Cr ; If (Char eq end_of Line) jr nz,Get_Next_Line or a ; Flag:= Not End of File ret page ;---------------------------------------------------------------------- ; Get the Next Token (15_Jun_84) ;------------------------------- ; 1) This routine moves the next token into the Token Buffer, Updates ; the Token Length and Token Type. ; 2) Register Usage: ; A -> Returned equal to the number of characters in buffer ; C -> Counter for Token_Buffer Length ; DE -> Pointer into the dictionary buffer ; HL -> Pointer to the current position in the source file ; Get_Token: call Strip_White ;Remove Leading White Space ld de,Token_Buffer ;DE:= Start of Dict buf ld c,0 ;C:= Counter ; Check For a Number ;------------------- ; ld a,(hl) cp 30h ;If (Char eq Number) jr c,GwSk1 cp 3Ah jr nc,GwSk1 ld a,Token_Number ld (Token_Type),a ld a,0 ld a,(Token_Length) call Fill_Numb_Buf ; Fill the Number Buffer ret ; Return ; Check for a Quoted String ;-------------------------- ; GwSk1: cp "'" ;If (Char eq Single Quote) jr nz,GwLp2 inc hl ; If (Next char eq Quote too) ld a,(hl) cp "'" jr nz,GwLp1 ld (de),a ; Save Quote in Token Buf inc c ; Count it jr GwSk2 GwLp1: ld (de),a ; Else Repeat inc de ; Inc Token Buffer Pointer inc hl ; Inc Source Pointer inc c ; Inc Counter ld a,(hl) call End_Line? ; If (Char eq Eof/Eol) jr z,GwSk2 ; Break cp "'" jr nz,GwLp1 ; Until (Char eq Quote) GwSk2: inc hl ; Pointer:= Next char past Quote ld a,Token_Literal ld (Token_Type),a ld a,c ld (Token_Length),a or a ret ; Read Literal String ;-------------------- ; GwLp2: cp 30h ;Loop If (Char eq Number) jr c,GwSk3 cp 3Ah jr c,GwDone ; Break GwSk3: call White_Space? ; If (Char eq White Space) jr z,GwDone ; Break call End_Line? ; If (Char eq Eof/Eol) jr z,GwDone ; Break cp "'" ; If (Char eq Quote) jr z,Gwdone ; Break ld (de),a ; Token_Buffer:= Current Character inc de ; Token_Pointer:= Token_Pointer+1 inc hl ; Buf_Pointer:= Buf_Pointer + 1 ld a,(hl) inc c ; Counter:= Counter + 1 jr GwLp2 GwDone: ld a,Token_Literal ld (Token_Type),a ;Token Type:= Literal Defintion ld a,c ld (Token_Length),a ;Save the Length or a ret ;Return page ;---------------------------------------------------------------------- ; Strip Leading White Space (11_Jun_84) ;-------------------------------------- ; 1) This routine removes leading white-space (comma, tab and line-feed) ; 2) Register Usage ; A -> Holds the last character read on return ; HL -> Pointer into the source file. (returned pointing at the ; current character). ; Strip_White: ld a,(hl) ;While (Char ne Space, Tab or Lf) call White_Space? ret nz inc hl ; Increment the Text Pointer jr Strip_White ;---------------------------------------------------------------------- ; Check for White Space (11_Jun_84) ;---------------------------------- ; 1) This routine Checks if the contents of the Accm is a Space, Tab ; Comma or Line Feed. If there is a match for any of these characters ; then the Z-Flag is returned set else its cleared. ; White_Space?: cp ' ' ;If (Char eq Space, Tab, Lf or Comma) ret z cp Tab ret z cp Lf ret z cp ',' ret ; Return with the Zero Flag Set ;---------------------------------------------------------------------- ; Check for End_of_Line or End_of_File (11_Jun_84) ;------------------------------------------------- ; 1) This routine checks if the Accm is equal to either an End of Line ; or an End of File Mark. If the Accm is equal to either of these ; characters then the Z-Flag is returned Set else its Cleared. ; End_Line?: cp Cr ;If (Char eq end_of Line/File) ret z cp End_of_File ret ; Return with the Zero Flag Set page ;---------------------------------------------------------------------- ; Dictinonary Lookup (1_Mar_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 ; DE -> Pointer into the Token Buffer ; HL -> Enter pointing to Start of Dictionary to search ; Dict_Lookup: ld a,(Token_Length) ld c,a ;C:= current token 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 ; 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,Token_Buffer ; DE:= Start of Token buf SrcLp2: ld a,(de) ; Repeat cp 'a' ; If ( (Number ge a) And jr c,ScrSk3 cp 'z' + 1 ; (Number Le z) ) jr nc,ScrSk3 and 5Fh ; (force upper case) ScrSk3: cp (hl) ; If (no match) jr nz,SrcNxt ; Break inc hl ; inc dict pointer inc de ; inc Token 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 ;---------------------------------------------------------------------- ; Set DE register pair to Start of Block Definition (25_May_84) ;-------------------------------------------------------------- ; 1) On entry, the DE pair is pointing to the argument field of a ; dictionary entry. The Argument field of a dictionary entry points ; to an arbitrary length block definition. This routine moves the ; DE pair so that it points to the start of the data in the block ; defintion. ; 2) Register Usage: ; DE -> Enter Pointing to Pointer in Dictionary ; Exit Pointing to Block Definition ; HL -> Preserved ; Set_DE_to_Def: push hl ;(save the Text pointer) ex de,hl ld e,(hl) inc hl ld d,(hl) ;DE:= Pointer to Type pop hl ;(restore text pointer) ret ;Return page ;====================================================================== ; Verify the Terminal Level (18_Jun_84) ;====================================== ; 1) This routine prints the Description of the Current Level and ; then prompts the user for verification. ; Verify_Level: ld a,(Terminal_Level) or a ;If (Terminal Level eq 0) jr nz,VLsk1 ld c,Bdos_PString ld de,Level_0_Msg call Bdos_Entry ; Print the Level 0 Message jr VLvrf VLsk1: add a,'0' ;Else ld (LevelN),a ; Set the Level Number in Message sub '1' sla a ld e,a ld d,0 ; DE:= (Terminal Level - 1) * 2 ld hl,Level_Table add hl,de ld e,(hl) inc hl ld d,(hl) ; Get a pointer to the Terminal push de ld c,Bdos_PString ld de,Level_n_Msg call Bdos_Entry ; Print the Body of Terminal Message ld c,Bdos_PString pop de call Bdos_Entry ; Print Terminal VLvrf: ld c,Bdos_PString ld de,VlMsg1 call Bdos_Entry ;Print 'Is the current level Ok? (Y/N)' call Yes_or_No ;Get the User's response ret ;Return (Response set in Yes_or_No) ;====================================================================== ; 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 ;====================================================================== ; Build The Console Tranlsation Tables (21_Jun_84) ;================================================= ; 1) This routine builds the Console Translation Tables into Memory. ; Build_Tables: call Setup_Image ;Setup the Character Table ld hl,(Escape_Vector) ;HL:= Start of Table ld a,(Esc_Tbl_Leng) ;A:= Table Length call Move_Down ;Move Translation Strings ld hl,(Control_Vector) ;HL:= Start of Table ld a,(Cnt_Tbl_Leng) ;A:= Table Length call Move_Down ;Move Translation Strings call Fix_CLR ;Fix the Clear Screen Entry if present ret ;---------------------------------------------------------------------- ; Setup the Character Table Image (18_Jun_84) ;-------------------------------------------- ; 1) This routine sets up an image of the Character Table at the ; beginning of free memory space (Memory_Image). ; Setup_Image: ld de,Memory_Image ld (Esc_Tbl_Pntr),de ld c,$Type_Escape ;C:= Pattern Mask call Build_Trans ;Build Escape Char Translation Table ld (Esc_Tbl_Leng),a ;Save the Escape Table Length ld (Cnt_Tbl_Pntr),de ld c,$Type_Control ;C:= Pattern Mask call Build_Trans ;Build Control Char Translation Table ld (Cnt_Tbl_Leng),a ;Save the Control Table Length ld (Escape_Vector),de ld c,$Type_Escape call Build_Vector ;Build Escape Vector Table ld (Control_Vector),de ld c,$Type_Control call Build_Vector ;Build Control Vector Table ld (Save_Pointer),de ;Save a pointer to the next free space ret page ;---------------------------------------------------------------------- ; Build a Translation Table (20_Jun_84) ;-------------------------------------- ; 1) This routine is used to build the Escape and Control Lookup Tables. ; 2) Register Usage: ; A -> General Purpose - Returned equal to the Table Length ; A' -> Holds the Character (from Get_Type_X) ; B -> Count equal to table length (not including terminator) ; C -> Mask set by calling program ($Type_Control/$Type_Escape) ; DE -> Pointer into table (returned = next free space) ; HL -> Pointer into Dictionary Definitions ; Build_Trans: ld hl,Start_Dict_Def ;HL:= Pointer into the dictionary ld b,0 ;B:= Counter (Table Length) BTlp1: push bc call Get_Type_X ;While (There's an escape char) pop bc jr z,BTsk1 inc b ; Counter:= Counter + 1 ex af,af' ld (de),a ; Save the Character ex af,af' inc de ; Inc Table Pointer jr BTlp1 BTsk1: ld a,0FFh ld (de),a ;Terminate the Lookup Table inc de ;Leave DE pointing to next free space ld a,b ;A:= Table Length ret ;Return ;---------------------------------------------------------------------- ; Build a Vector Table (20_Jun_84) ;--------------------------------- ; 1) This routine is used to build the Escape and Control Vector Tables. ; Build_Vector: ld hl,Start_Dict_Def BVlp3: call Get_Type_X ;While (There's an Escape Char) ret z call Move_Def ; Move the Vector into the table jr BVlp3 page ;---------------------------------------------------------------------- ; Get Next Occurance of Type X in Main Dict Defs (18_Jun_84) ;----------------------------------------------------------- ; 1) Register Usage: ; AF' -> The Translation char if the entry was found ; B -> Temporary storage of the Type Mask from the Dict Def ; C -> Type Mask ; DE -> Counter ; HL -> Pointer into the Dictionary Definitions ; Get_Type_X: ld a,(hl) ;While (Not at the end of the Table) or a ret z ld b,a ; B:= Type Mask inc hl ex af,af' ld a,(hl) ; AF':= Id Byte ex af,af' inc hl ld a,(hl) inc hl or (hl) inc hl jr z,Get_Type_X ; If (Entry has been defined) ld a,c and b ret nz ; Return jr Get_Type_X ;---------------------------------------------------------------------- ; Move a Translation Definition (18_Jun_84) ;------------------------------------------ ; 1) This routine moves the pointer to a translation string into the ; vector table. ; 2) Register Usage: ; DE -> Pointer into a Vector Table ; HL -> Points to Hi-Byte of Dict Def + 1 ; Move_Def: push hl dec hl dec hl ;HL:= Pointer to Lo-Byte of Dict Def ld a,(hl) ex de,hl ld (hl),a ;Move Lo_Byte into Pointer Table inc hl ex de,hl inc hl ld a,(hl) ex de,hl ld (hl),a ;Move Hi_Byte into Pointer Table inc hl ex de,hl pop hl ret page ;---------------------------------------------------------------------- ; Move a Translation String Down (21_Jun_84) ;------------------------------------------- ; 1) This routine moves the Translation Strings for the given Table ; (i.e. Control or Escape) down to the top of the newly built image ; of the character table. ; 2) The Vectors to the Translation Strings are made into offsets ; relative to the start of the Console Translation Structure Base (ie ; (Esc_Tbl_Pntr)). ; 3) Register Usage: ; A -> Equal to the Table Length on Entry ; B -> Counter (number of entries in the table) ; DE -> Pointer to the Old Location of the Translation String ; HL -> Pointer to New Location of the Translation String ; Move_Down: or a ;If (Table Length eq 0) ret z ; Return ld b,a ;B:= Table Length MDlp1: ld e,(hl) ;Repeat inc hl ld d,(hl) ; DE:= Pointer Source push de push hl ld hl,(Save_Pointer) ; HL:= Destination of String ld de,(Esc_Tbl_Pntr) ; DE:= Base of Translate Struct or a sbc hl,de ex de,hl ; DE:= Offset from Structure Base pop hl ld (hl),d dec hl ld (hl),e ; Update Vector Table inc hl pop de inc hl push hl ; (Save pointer to next vector) ld hl,(Save_Pointer) ; HL:= Pointer to Destination MDlp2: ld a,(de) ; Loop ld (hl),a ; Move a Byte inc hl ; Inc destination pointer inc de ; Inc source pointer cp 0FFh ; Until (Byte eq Terminator) jr nz,MDlp2 ld (Save_Pointer),hl pop hl djnz MDlp1 ;Until (Count eq 0) ret ;Return ;---------------------------------------------------------------------- ; Fix the CLR Screen Entry in the Escape Table (18_Jun_84) ;--------------------------------------------------------- ; 1) This routine patches the Clear Screen Code Entry in the Escape ; Table (if it is present). This is needed because Adm31's use ; both 1Ah's and '*''s to clear the screen; So, there has to be ; entries in both the Escape and the Control Tables for this code. ; 2) Register Usage: ; A -> General Purpose ; HL -> Pointer into Escape Table ; Fix_CLR: ld hl,(Esc_Tbl_Pntr) ;HL:= Pointer to Start of Escape Table FClp1: ld a,(hl) ;While (Not at the end of the table) cp 0FFh ret z cp Clear_Code ; If (its the Clear Code) jr nz,FCsk1 ld (hl),'*' ; Replace it ret ; Return FCsk1: inc hl ; Inc Table Pointer jr FClp1 page ;====================================================================== ; Check the CP/M version (16_Apr_84) ;=================================== ; 1) This routine checks the CP/M version. It returns with the ; Z flag = 1 if CP/M 3. ; Get_Version: ld c,Bdos_Ret_Ver ;Return version Bdos call call Bdos_Entry ld a,0F0h and l cp 30h ret ;====================================================================== ; Install Definitions in a CP/M 2.2 System (21_Jun_84) ;===================================================== ; Install_Cpm2: call Read_Cpm2_Bios ;Read the Bios into Memory or a ;If (There was an Error) ld a,Sys_Read_Err ; (A:= Error Code) ret nz ; Return ;&&& call Write_Cpm2_Bios ;Write the Bios back onto Disk or a ;If (There was an Error) ld a,Sys_Write_Err ; (A:= Error Code) ret nz ; Return ld a,0 ret page ;---------------------------------------------------------------------- ; Read the Cp/m 2.2 Bios (21_Jun_84) ;----------------------------------- ; 1) This routine reads the Bios from the system tracks into the ; next free memory space (next free space pointer set in Build_Tables) ; Read_Cpm2_Bios: call Setup_IX ;Set IX to RamdatX and Save the Original ld de,RdBlk_Offset ;DE:= Offset to the RdBlk Address call Get_Bios_Pntr ex de,hl ;HL:= Vector to Read a Block Routine call IR_HL ;Execute the read a block routine ld a,(ix+ErFlag) push af call Restore_IX ;Restore the Original System IX Areq pop af ret ;Return IR_HL: jp (hl) ;---------------------------------------------------------------------- ; Write the Cp/m 2.2 Bios (21_Jun_84) ;------------------------------------ ; 1) This routine writes the Bios back to the system tracks. ; Write_Cpm2_Bios: call Setup_IX ;Set IX to RamdatX and Save the Original ld de,WrBlk_Offset ;DE:= Offset to the WrBlk Address call Get_Bios_Pntr ex de,hl ;HL:= Vector to Read a Block Routine call IW_HL ;Execute the Write a Block routine ld a,(ix+ErFlag) push af call Restore_IX ;Restore the Original System IX Areq pop af ret ;Return IW_HL: jp (hl) page ;---------------------------------------------------------------------- ; Setup IX to Point to System RamDatX (20_Jun_84) ;------------------------------------------------ ; 1) This routine Sets the IX register to point to the system RamDatX. ; 2) The original system RamDatX is saved ; Setup_IX: ld de,RamDatX_Offset ;DE:= Offset to the RamDatX Pointer call Get_Bios_Pntr push de ex de,hl ld de,Save_IX_Area ld bc,DatXln ldir ;Save the Original System IX Area pop ix ;IX:= RamDatX ld (ix+HstDsk),0 ;Drive:= 0 ld (ix+HstTrk),1 ;Starting_Track:= 1 ld (ix+HstSec),2 ;Starting_Sector:= 2 ld (ix+SecCnt),4 ;Number_of_Sectors_to_Read:= 4 ld (ix+Retry),10 ;Retries:= 10 ld hl,(Save_Pointer) ld (ix+HstBuf),l ld (ix+HstBuf+1),h ;Disk_Buffer:= Next Free Space in Memory ld (ix+ErFlag),0 ;Error_Flag:= Reset ret ;---------------------------------------------------------------------- ; Restore the Original System IX Area (21_Jun_84) ;------------------------------------------------ ; Restore_IX: push ix pop de ;DE:= Start of System IX ld hl,Save_IX_Area ;HL:= Start of System IX Save Area ld bc,DatXln ;BC:= Length of IX Area ldir ;Restore the Original System RamDatX ret ;Return page ;---------------------------------------------------------------------- ; Get One of the Bios Pointers (20_Jun_84) ;----------------------------------------- ; Get_Bios_Pntr: ld hl,(Bios_Entry+1) ;HL:= Pointer to Warm Boot Entry ld l,0 ;HL:= Pointer to Base of Bios call Get_DE_Indr_HL ;DE:= Contents of Addr Pointed to by HL ret ;Return ;---------------------------------------------------------------------- ; Load the DE register Pair Indirectly Through the HL (20_Jun_84) ;---------------------------------------------------------------- ; Get_DE_Indr_HL: add hl,de ;HL:= Pointer to RamDatY Pointer ld e,(hl) inc hl ld d,(hl) ;DE:= Contents of Addr Pointed to by HL ret ;Return page ;====================================================================== ; Install Definitions in a CP/M 3.0 System (21_Jun_84) ;===================================================== ; Install_Cpm3: ld c,Bdos_PString ld de,ICmsg1 call Bdos_Entry ld a,0 ret ;Not Installed Message ICmsg1: db Cr,Lf,'Cannot Install a Cp/m 3.0 System',Cr,Lf,'$' page ;---------------------------------------------------------------------- ; Get a Yes/No Response from the User (18_Jun_84) ;------------------------------------------------ ; Yes_or_No: ld c,Bdos_ConIn ;Loop call Bdos_Entry ; Get the User's Response and 5Fh ; (force response to upper case) cp Control_C ; If (Response eq Force Warm Boot) jp z,Bios_Entry ; Goto Warm Boot cp 'Y' ; If (Response is Yes) jr nz,YNsk1 ld a,0 ret ; Return (Ok) YNsk1: cp 'N' ; Else If (Response is No) jr nz,Yes_or_No ld a,0FFh ret ; Return (Not Ok) page ;====================================================================== ; Report Errors (4_Jun_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 de,CrLf ;DE:= Pointer to Cr/Lf String ld c,Bdos_PString ;C:= Print String Function call Bdos_Entry ;Print Carriage Return Line Feed 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 numbeint the Opening Message 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,' ' 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,(Output_Radix) ;Repeat divisor:= Current Radix 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,' ' 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) ld e,' ' ld c,Bdos_ConOut call Bdos_Entry ;Print a Space ret ;Return page ;---------------------------------------------------------------------- ; Convert from the Current Radix to Binary (13_Jun_84) ;----------------------------------------------------- ; 2) Register Usage: ; BC -> [Preserved] Counter ; DE -> Multiplier (Current Radix) ; HL -> Multiplicand ; RadN_to_Binary: ld hl,0 ld a,(Number_Length) ;If (Buffer is Null) or a ret z ; Return ld e,a ld d,0 ;DE:= Length of Number Buffer ld hl,Number_Buffer ;HL:= Start of Number Buffer add hl,de dec hl ;HL:= End of Number Buffer (Adj 0-Base) ld e,(hl) ld d,0 ex de,hl ;HL:= Last Result dec a ;If (Buffer Length is 1) ret z ; Return push bc ;(Preserve the BC register pair) ld (Temp_Result),hl ex de,hl ;HL:= Pointer to Next Number push hl ld b,a ;B:= Counter ld de,(Input_Radix) TSlp1: pop hl ;Repeat dec hl ld a,(hl) push hl ld l,a ld h,0 ; HL:= Next Digit call Multiply push de ld de,(Temp_Result) add hl,de ld (Temp_Result),hl ; Update Result pop de push hl ld hl,(Input_Radix) call Multiply ; Increment Multiplier ex de,hl pop hl ; (restore result) djnz TSlp1 ;Until (Count eq zero) pop de pop bc ret ;---------------------------------------------------------------------- ; 16 bit Multiply ;---------------- ; 1) This routine multiplies the contents of the HL register by the ; contents of the DE register leaving the result in the HL register. ; 2) Register Usage: ; BC -> [Preserved] Temp Storage ; DE -> [Preserved] Multiplier ; HL -> Multiplicand/Result ; Multiply: push bc push de ;(Save Registers) ld c,l ld b,h ld hl,00000h MuLp1: ld a,b ;While (Count ne zero) or c jr nz,MuSk1 pop de pop bc ; (Restore Registers) ret ; (Return) MuSk1: ld a,b rra ld b,a ld a,c rra ld c,a jr nc,MuSk2 add hl,de MuSk2: ex de,hl add hl,hl ex de,hl jr MuLp1 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 page .sall ;Suppress Macro Listings ;====================================================================== ; Dictionary Macro Definitions (1_Mar_84) ;======================================== ; ; Generate a Dictionary Entry (1_Mar_84) ;--------------------------------------- ; 1) This macro generates an entry in the function key dictionary. ; 2) Each entry in the dictionary has the following form ; 1 byte Type of Entry ; 2 bytes Pointer to definition string ; n bytes Name of function key ; DfDict macro Name, pntr local L1, L2 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 (21_May_84) ;--------------------------- ; 1) This Dictionary contains all of the Title Codes ; Main_Dictionary: DfDict HOME, Def_Home ; Level 1 Definitions DfDict CLR, Def_Clear DfDict LEFT, Def_Left DfDict RIGHT, Def_Right DfDict UP, Def_Up DfDict DOWN, Def_Down DfDict HI, Def_Hi ; Level 2 Definitions DfDict LO, Def_Lo DfDict CEOL, Def_CEol DfDict CEOS, Def_CEos DfDict INSLINE, Def_InsLine ; Level 3 Definitions DfDict INSCHAR, Def_InsChar DfDict DELCHAR, Def_DelChar DfDict DELLINE, Def_DelLine DfEnd ;---------------------------------------------------------------------- ; Main Dictionary Definitions ;---------------------------- ; Start_Dict_Def: ; Level 1 Definitions Def_Clear: db $Type_Control or $Type_Escape db Clear_Code dw 0 Def_Home: db $Type_Control db 1Eh dw 0 Def_Left: db $Type_Control db 8 dw 0 Def_Right: db $Type_Control db 0Ch dw 0 Def_Up: db $Type_Control db 0Bh dw 0 Def_Down: db $Type_Control db 0Ah dw 0 ; Level 2 Definitions Def_Hi: db $Type_Escape db '(' dw 0 Def_Lo: db $Type_Escape db ')' dw 0 Def_CEol: db $Type_Escape db 'T' dw 0 Def_CEos: db $Type_Escape db 'Y' dw 0 ; Level 3 Definitions Def_InsChar: db $Type_Escape db 'Q' dw 0 Def_InsLine: db $Type_Escape db 'W' dw 0 Def_DelChar: db $Type_Escape db 'E' dw 0 Def_DelLine: db $Type_Escape db 'R' dw 0 End_Dict_Def: db 0 ;Terminator for the Compact Routine page ;---------------------------------------------------------------------- ; Aux Dictionary (4_Jun_84) ;-------------------------- ; 1) This dictionary contains everything but the title codes. ; Aux_Dictionary: DfDict CURSOR, Def_Cursor DfDict ASCII, Def_Ascii DfDict R+, Def_Row DfDict C+, Def_Column DfDict ESC, Def_Escape DfDict SP, Def_Space DfDict LEVEL, Def_Level DfEnd ;End of the table ;---------------------------------------------------------------------- ; Aux Definitions ;---------------- ; Def_Cursor: db $Type_Cursor ;Type:= Cursor Definition db 0 Def_Ascii: db $Type_Ascii ;Type:= Ascii Cursor Position Format db 0 Def_Row: db $Type_Row ;Type:= Row Offset db 0 Def_Column: db $Type_Col ;Type:= Column offset db 0 Def_Escape: db $Type_Char ;Type:= Non Printing Character db Esc ;Escape Character Def_Space: db $Type_Char ;Type:= Non Printing Character db ' ' ;Space Def_Levelº dâ $Type_Level ;Type:= Level Definition db 0 page ;---------------------------------------------------------------------- ; Error Code Tables and Message Strings (21_Jun_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 db No_Delimiter ;Equal Sign is missing in definition dw NEmsg db Bad_Type_Byte ;Line Definition Type is UnKnown dw BBmsg db Bad_Level ;Terminal Level Definition Out of Range dw BLmsg db Bad_Symbol ;Bad Symbol in definition dw BSmsg db Invalid_Number ;Invalid Char in Numeric String dw BNmsg db Number_Overflo ;Literal Numeric String is too Long dw NOmsg db Number_Delimit ;Missing Literal Numeric String Delimiter dw NLmsg db Dca_OverFlo ;Direct Cursor Address String too Long dw DCmsg db Sys_Read_Err ;Unable to read System from the Disk dw SRmsg db Sys_Write_Err ;Unable to Write System to the Disk dw SWmsg End_Table: Max_Error equ ( (End_Table - Error_Table)/3 ) + 1 page ; Error Message Strings (21_Jun_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 $' NEmsg: db 'Missing Delimiter $' BBmsg: db 'Line Definition Type is Unknown $' BLmsg: db 'Terminal Level Definition Out of Range $' BSmsg: db 'Bad Symbol in Definition Line $' BNmsg: db 'Invalid Char in Literal Numeric String $' NOmsg: db 'Literal Numeric String is too Long $' NLmsg: db 'Missing Literal Numeric String Delimiter $' DCmsg: db 'Direct Cursor Address String too Long $' SRmsg: db 'Unable to read System from the Disk $' SWmsg: db 'Unable to Write System to the Disk $' NoCode: db 'Unrecognized Error $' ErrOpn: db Cr,Lf, 'Error on line $' page ;---------------------------------------------------------------------- ; Other Text Strings (10_May_84) ;------------------------------- ; Menu_Heading: db Cr,Lf,Lf,Lf,Lf,Lf,Lf,Lf,Lf,Lf,Lf,Lf,Lf db Cr,Lf,Lf,Lf,Lf,Lf,Lf,Lf,Lf,Lf,Lf,Lf,Lf db 'MD-11 Terminal Initialization Program, Rev ' db ((Rev and 0F0h) shr 4) + '0', '.',(Rev and 0Fh) + '0' db ' Copyright 1984' db Cr,Lf,'Morrow Designs Inc.' db Tab,Tab,Tab,Tab,Tab,Tab,'San Leandro, Ca' db Cr,Lf,Lf,Lf, '$' Response_Msg: db Cr,Lf,Lf db Tab,' Please enter the Letter of Your Choice $' CrLf: db Cr,Lf,'$' VrMsg1: db Cr,Lf,Lf db Tab,' Is $' VrMsg2: db ' the correct choice? (Y/N) $' VlMsg1: db Cr, Lf,Lf,Lf,Lf db Tab,' Is the current level Ok? (Y/N) $' Level_0_Msg: db Cr,Lf,Lf,Lf,Lf, Lf,Lf,Lf,Lf, Lf,Lf,Lf,Lf, Lf,Lf,Lf,Lf db Tab,'The CP/M SYSTEM diskette will not be installed for your' db Cr,Lf db Tab,'terminal. You must install some of the application programs' db Cr,Lf db Tab,'(i.e. WordStar and LogiCalc) yourself. In addition, the' db Cr,Lf db Tab,'Micro-Menus will not appear as they should on the screen.' db Cr,Lf db Tab,'Before confirming this selection, check to see if your' db Cr,Lf db Tab,'terminal can emulate any of those on the selection Menu. If' db Cr,Lf db Tab,'it can, you will find it more convenient to use your system.' db Cr,Lf,'$' Level_n_Msg: db Cr,Lf,Lf,Lf,Lf, Lf,Lf,Lf,Lf, Lf,Lf,Lf,Lf, Lf,Lf,Lf,Lf, Lf,Lf db Tab,'You have a Level ' LevelN: db '1 terminal. All programs supplied by Morrow' db Cr,Lf db Tab,'Designs are pre-installed for your terminal. Any programs' db Cr,Lf db Tab,'not supplied by Morrow Designs must be installed for' db Cr,Lf,'$' Level1: db Tab,'an ADM-3A terminal. $' Level2: db Tab,'a SOROC IQ-120 terminal. $' Level3: db Tab,'an ADM-31 terminal. $' page ;====================================================================== ; Local Data Area (15_Jun_84) ;---------------------------- ; ; Local Fcb's ;------------ ; 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 ; Title Processing Storage ;------------------------- ; Max_Titles: db 0 ;Total Number of Titles Title_Pointer: dw 0 ;Pointer into the title buffer Title_Buffer: ds 60h,0 ;Title Buffer 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 ; Line Processing Storage ;------------------------ ; Line_Count: dw 0 ;Current Line Number Start_Def: dw 0 ;Start of the current definition End_Def: dw 0 ;End of the current definition Temp_Buffer: dw 0 ;Pointer to end of Memory_Image Token_Type: db 0 ;Type of Token Token_Length: db 0 ;Length of the Dictionary buffer Token_Buffer: ds 20h ;Dictionary buffer Number_Buffer: ds 6,0 ;Buffer for Literal Numeric Strings Number_Length: db 0 ;Length of the Number Buffer Temp_Result: dw 0 ;Temporary Result used in Radix Conversion page ; Other Storage ;-------------- ; Save_Pointer: dw 0 ;Save Location for a Word Esc_Tbl_Leng: db 0 ;Length of Escape Char Translate Table Cnt_Tbl_Leng: db 0 ;Length of Control Char Translate Table Dca_Level: db 0 ;Current Dca Level (Start, Mid or End) Dca_Length: db 0 ;Current Dca String Length Output_Radix: dw 10 Input_Radix: dw 10 Save_IX_Area: ds DatXln,0 ;Storage for system RamDatX Level_Table: dw Level1 ;Lookup Table For Terminal Types dw Level2 dw Level3 ; Character Table Storage ;------------------------ ; Terminal_Level: db 0 ;Terminal definition level DcaStrt: ds Dca_Len,0FFh ;Dca Prefix String DcaMid: ds Dca_Len,0FFh ;Dca Seperator String DcaEnd: ds Dca_Len,0FFh ;Dca Terminator String Esc_Lvl: db 0 ;Escape processing level Offset1: db 0 ;First Character Offset Offset2: db 0 ;Second Character Offset Order: db 0 ;Flag Byte (0-Row/Col, 1-Bin/Asc) Esc_Tbl_Pntr: dw 0 ;Pointer to Start Escape Lookup Table Cnt_Tbl_Pntr: dw 0 ; " " " Control Lookup Table Escape_Vector: dw 0 ;Vector to start of the Escape Table Control_Vector: dw 0 ;Vector to start of the Control Table Memory_Image: db 0 ;Label for start of buffer end