Title Program Loader for the MD-11 using CP/M 3 (10_Feb_84) ; ; Copyright 1984 ; Morrow Designs, Inc ; San Leandro, Ca. .z80 aseg org 0100h ; This program allows you to batch command strings to the ; Ims facility. Additionally, you have the option to check for the ; existance of a file before the ims string is submitted which allows ; you to do validity checks. ; There are two major data structures that are used to drive this ; program. The first is a parameter block kept in page zero while the ; program is running. It consists of an ID word followed by the current ; iteration (0 to n) followed by the maximum number of iterations. ; The second data structure is a two dimensional array. The first ; dimension is set by the iteration counter. ; Index: (5_Feb_84) ;------------------ ; ; Main - Main Line ; CclChk - Check the Cbios Compatibility Level ; ChkErr - Check for errors in Previous transfers ; GetDsk - Check for the existance of the key file ; PutIMS - Put the Ims string into the IMS buffer ; GetBas - Return a Pointer to the Desired Entry ; GetRsp - Get the User's Response ; GetBuf - Move system memory into the local buffer ; PutBuf - Put the Local Buffer into System Memory ; DoCold - Call the Bios Cold Boot Entry Point ; -- - General Parameters ; -- - Program Load List ; -- - Prompt Strings ; -- - Error Messages page 64 ;---------------------------------------------------------------------- ; Equates (10_Feb_84) ;------------------- ; ; IDs and Rev Numbers ;-------------------- ; CpmVer equ 30h ;Cpm Version Number ccl equ 0 ;Cbios Compatibility Level Prev equ 11h ;Program revision number PID equ 'Ok' ;Program ID ; Drive Designations for Key filespec prompt strings ;--------------------------------------------------- ; X_Drive equ 0 ;Current Drive A_Drive equ 1 ;Drive A: B_Drive equ 2 ;Drive B: C_Drive equ 3 ;Drive C: Null equ 0FFh ;Null Key filespec prompt ; Address Definitions ;-------------------- ; Wboot equ 0 ;Address of the Start of the BIOS + 3 warmbt equ 01h ;Address of the Bios Warm boot entry bdos equ 05h ;Address of the start of the BDOS IBuf equ 80h ;tail buffer location PIDadd equ 40h ;Address of the ID word LodOff equ 42h ;Current Program Load offset LodMax equ 43h ;Maximum number of load files ErrFlag equ 44h ;Error Flag ; Bdos Function Numbers ;---------------------- ; conin equ 1 ;Console Input a Character ConOut equ 2 ;Console Output a Character DirIO equ 6 ;Direct console control print equ 9 ;Print a string GetRev equ 0Ch ;Get the revision number of this cpm system sfirst equ 11h ;Search for the first occurance of file x delete equ 13h ;Delete a file(s) setdma equ 1Ah ;Set the DMA Address InWait equ 0FDh ;Direct console input (waits until char ready) InjIMS equ 11 ;Extended Function - Inject IMS String ; Offsets ;-------- ; CclOff equ 7 ;Offset to Clevel from start of char. struct. KeyOff equ 0 ;Key File Offset ImsOff equ 2 ;Ims Sting Offset ; Non Printing Ascii Character Equates ;------------------------------------- ; CntrlC equ 3 ;Control C Code (Warm Boot) bell equ 7 ;Bell Code tab equ 9 ;Tab lf equ 0Ah ;Line Feed cr equ 0Dh ;Carriage Return PCr equ 8Dh ;Pause carriage return (see PutIMS) ClrScr equ 1Ah ;Clear Screen Esc equ 1Bh ;Escape Bright equ '(' ;Start High Lighting Dim equ ')' ;Start Low Lighting page ;---------------------------------------------------------------------- ; MAIN - Main Line (10_Feb_84) ;---------------------------- ; Main: ld hl,(PIDadd) ;HL:= Contents of the ID word location ld de,PID ;DE:= Program ID word or a ;(Clear carry) sbc hl,de ;If (ID hasn't been written) jr z,MSkp1 call CclChk ; Check CP/M rev and compatibility level or a ; If (Rev levels aren't high enough) jr nz,Mdone ; Quit ld de,Prmpt1 ld c,Print call Bdos ; Print the initial prompt ld de,PID ld (PIDadd),de ; Write the ID ld a,0 ld (LodOff),a ; Reset the Load Offset ld (ErrFlag),a ; Reset the Error flag ld a,(LodLen) ld (LodMax),a ; Set the Maximum number of load files MSkp1: ld a,(ErrFlag) ;see if previous copy O.K. or a jr z,CopyOk ld a,(LodOff) ;decrement Load Offset if Error dec a ld (LodOff),a CopyOk: call GetDsk ;Get the user to load the next disk or a ;If (the user wants to stop) jr nz,MDone ; Quit MSkp2: ld a,(LodOff) ;If (This is NOT the first iteration) or a jr z,MSkp3 call ChkErr ; Check for errors on previous transfer or a ; If (temp files were found) jr nz,MDone ; Quit MSkp3: call PutIms ;Install the Ims String or a ;If (There wasn't room for the Ims String) jp nz,MDone ; Quit ld a,(LodOff) inc a ld (LodOff),a ;Load Offset:= Load Offset + 1 ld b,a ld a,(LodMax) ;(A:= Last Load File Number) cp b ;If (this is the last file) jr nz,MSkp4 MDone: ld de,0 ld (PIDadd),de ; Reset the ID word MSkp4: jp Wboot ;Goto the Bios Warm Boot Entry page ;---------------------------------------------------------------------- ; CCLCHK - Check the Cbios Compatibility Level (4_Jan_84) ;-------------------------------------------------------- ; ;Check the Cpm Version Number CclChk: ld c,GetRev ;C:= Bdos get cpm version number call Bdos ;Get version number in L ld a,l ;A:= Cpm Version 14, 22 or 31 and 0F0h ;Mask off the minor revision number cp CpmVer ;If (version doesn't match expected version) jr nz,CclErr ; Goto Error return ;Check the Cbios Compatibility Level ld a,6 ;A:= Function_6 (Return Character table) ld de,LocBuf ;DE:= Pointer to the local buffer call DoCold ;Move the character table into the local buffer ld hl,CclOff ;HL:= offset to Cbios compatiblity level add hl,de ;HL:= Pointer to Cbios compatibility level ld a,(hl) ;If (current compatibility levle ne Cbios Ccl) cp Ccl jp nz,CclErr ; Goto Error return Cclok: ld a,0 ;A:= Successful Completion return status ret ;Return CclErr: ld de,Err1 ; DE:= revision error message ld c,Print ; C:= Print string function number call Bdos ; Print the Input Drive number string ld a,0FFh ; A:= error return status ret page ;---------------------------------------------------------------------- ; CHKERR - Check for errors in Previous transfers (5_Feb_84) ;----------------------------------------------------------- ; ChkErr: ld hl,Fcb ;HL:= Pointer to drive number in Fcb ld (hl),B_Drive inc hl ;HL:= Pointer to start of name field in Fcb ld b,8 ;B:= Length of fcb name field CElp1: ld (hl),'?' ;Repeat Fcb:= ? inc hl ; Pointer:= Pointer + 1 djnz CElp1 ;Until (name field has been filled with ?'s) ld b,3 ;B:=Length of fcb extent field CElp2: ld (hl),'$' ;Repeat Fcb:= $ inc hl ; Pointer:= Pointer + 1 djnz CElp2 ;Until (extent field has been filled with $'s) ld (hl),0 ;Extent:= 0 ld c,setdma ld de,LocBuf call bdos ;Set the DMA Address ld c,sfirst ld de,Fcb call bdos ;Search for the first occurance of ???????.$$$ cp 0FFh ;If (there were no temp files found) ld a,0 ; (ok return status) ret z ; return (NO error) ld de,Err3 ld c,Print call Bdos ;Print the error message ld a,0FFh ;(Error returned status) ret ;Return page ;---------------------------------------------------------------------- ; GETDSK - Prompt for Key file then Check search for it (7_Feb_84) ;----------------------------------------------------------------- ; 1) This routine checks for the existance of a particular file on ; a particular disk. ; 2) If the File Name String is Null (0) then the file check is ; NOT preformed. ; GetDsk: ld bc,KeyOff ;Loop BC:= Offset to the Prompt string call GetBas ; HL:= Pointer to base of Prompt string table ld a,(hl) ; If (The File Name string is Null) cp Null ld a,0 ret z ; Return (No Error) inc hl ; HL:= Source (Start of FCB) ld de,Fcb ; DE:= Destination (Local FCB) ld bc,13 ; BC:= Length of Transfer ldir ; Transfer the FCB for the Key File push hl ; (save pointer to prompt string start) ld de,Prmpt2 ld c,Print call Bdos ; Print 'please insert the diskette... pop de ; DE:= Pointer to prompt string start ld c,Print call Bdos ; Print title of diskette ld de,Prmpt3 ld c,Print call Bdos ; Print remainder of prompt call GetRsp ; Get response from console (Continue/Stop) or a ; If (response eq Stop) ret nz ; Return ld c,setdma ld de,LocBuf call bdos ; Set the DMA Address ld c,SFirst ld de,Fcb call Bdos ; Find the Key File On the Selected Drive cp 0FFh ; If (the key file was found) ld a,0 ret nz ; Return (NO Error) ld de,Err2 ld c,Print call Bdos ; Print Error Message jr GetDsk page ;---------------------------------------------------------------------- ; PUTIMS - Put the Ims string into the IMS buffer (5_Feb_84) ;----------------------------------------------------------- ; 1) This routine puts the current iteration's ims string into the ; ims buffer. ; PutIMS: ld bc,ImsOff ;BC:= Offset to IMS sting call GetBas ;HL:= Pointer to the ims string push hl ;(save pointer on stack) ;Translate special characters in the Ims String ImsLp2: inc hl ;Repeat (move HL past the length byte) ld a,';' ; If (char eq Standard_Cr) cp (hl) jr nz,ImsSk2 ld (hl),Cr ; substitute Cr jr ImsSk3 ImsSk2: ld a,'|' ; Else If (char eq Pause_Cr) cp (hl) jr nz,ImsSk3 ld (hl),PCr ; substitute pause Cr ImsSk3: djnz ImsLp2 ;Until (all of buffer is processed) pop de ;DE:= pointer to start of processed buffer ;Inject the Ims string into the Ims buffer ld a,InjIMS ;A:= extended function call: inject ims call DoCold ;do extended function ld a,0 ;If (the ims string was accepted) ret nc ; Return (no error) ld de,Err4 ;Else ld c,Print call Bdos ; Print error (ims string won't fit) ld a,0FFh ret ; Return (ERROR) page ;---------------------------------------------------------------------- ; GETBAS - Return a Pointer to the Desired Entry (5_Feb_84) ;---------------------------------------------------------- ; 1) This routine uses the LodOff Value along with the Entry offset ; (passed in the BC pair) to form a pointer into the Load List. ; 2) The Load List is a two dimensional (n by 2 word) array. The First ; dimension of the array is the set by the current iteration number ; of the Loader Program (LodOff). The second dimension of the array ; allows access to the current Key file (and it prompt string) and ; the Ims Stings pointers. ; 3) Pointer offsets (passed in the BC pair): ; 0 = Key File Name ; 2 = Ims String Text ; 4) Register Usage: ; A -> General Purpose ; BC -> Pointer Offset or second dimension (0=Prompt,2=Key,4=Ims) ; DE -> used as Offset in calculating the first dimension ; HL -> Pointer to Desired Entry's Pointer ; GetBas: ld a,(LodOff) sla a sla a ld e,a ld d,0 ;DE:= Offset - LodOff * 4 ld hl,LodLst ;HL:= Base of Load List add hl,de ;HL:= Pointer to Base of First Dimenstion add hl,bc ;HL:= Pointer to Second Dimension ld e,(hl) inc hl ld d,(hl) ;(retrieve the pointer from the table) ex de,hl ;HL:= Pointer to base of desired string ret ;Return page ;---------------------------------------------------------------------- ; GETRSP - Get the User's Response (7_Feb_84) ;-------------------------------------------- ; 1) This routine prints a prompt string and then waits for a valid ; response from the console device. ; 2) A valid response is a C (or c) for continue and S (or s) or ; control_C for stop. ; 3) Register Usage: ; AF -> Returned 0 for continue or 0FFh for Stop ; BC -> Bdos function number in the C register ; DE -> On Entry Points to the string to print ; GetRsp: ld de,Prmpt4 ld c,Print call bdos ;print the response prompt AskLpº lä c,DirIO ;Loop ld e,InWait ; (Set funct to wait for input) call Bdos ; Get a character from the console and 5Fh ; (force to upper case) cp 'C' ; If (Response eq Continue) jr nz,AskSk1 ld e,a ; (Save the character for echo) ld a,0 ; (Continue code) jr AskSk3 ; Return (Continue) AskSk1: cp 'S' ; Else If (Response eq Stop) jr nz,AskSk2 ; Break ld e,a ; (Save the character for echo) ld a,0FFh ; (Stop code) jr AskSk3 AskSk2: cp CntrlC ; Else IF (Response eq Control_C) jr z,AskSk4 ; Break jr AskLp AskSk3: push af ;Print the Final Carriage Return Line Feed ld c,ConOut ;C:= Console Output Funct (char in E already) call Bdos ;Print the Response AskSk4: ld de,CrLf ld c,Print call Bdos pop af ret ;Return page ;---------------------------------------------------------------------- ; GETBUF - Move system memory into the local buffer (4_Jan_84) ;------------------------------------------------------------- ; 1) This routine forces the destination to be the local buffer, calls ; the cold start (extended bios functions) entry point, and then saves ; the registers after swapping hl and de. ; GetBuf: ld de,LocBuf ;DE:= Pointer to Local Buffer call DoCold ;Move System Memory into the local buffer ld (saveBC),bc ;Save the returned registers ex de,hl ;HL:= Pointer to first xlt ld (saveDE),de ld (saveHL),hl ret ;Return ;---------------------------------------------------------------------- ; PUTBUF - Put the Local Buffer into System Memory (4_Jan_84) ;------------------------------------------------------------ ; 1) This is the inverse of GetBuf; It replaces the system's memory ; with the contents of the local buffer. ; 2) GetBuf MUST be called before entering this routine. ; PutBuf: ld a,1 ;Function_1:= Write to system memory ld bc,(SaveBC) ld de,(SaveDE) ld hl,(SaveHL) ;Restore the Returned Registers call DoCold ;Write the Mtabs back into system memory ret ;---------------------------------------------------------------------- ; DOCOLD - Call the Bios Cold Boot Entry Point (4_Jan_84) ;-------------------------------------------------------- ; 1) The Cold Boot Entry point to the bios (1st entry in the bios ; jump table) is located by looking at locations 1 & 2 which ; point to the warm boot address (the desired address + 3). ; DoCold: push hl ;Save the HL Register Pair ld hl,(Wboot+1) ;HL:= Warm Boot Address ld l,0 ;HL:= Cold Boot Address ex (sp),hl ;Restore the HL Register Pair ret ;Goto The Cold Boot entry page ;---------------------------------------------------------------------- ; General Parameters (5_Feb_84) ;------------------------------ ; Fcb: ds 32,0 SaveBC: dw 0 ;Save Location for the BC register pair SaveDE: dw 0 ; " " " " DE " " SaveHL: dw 0 ; " " " " HL " " LocBuf: ds 128,0 ;---------------------------------------------------------------------- ; Program Load List (5_Feb_84) ;----------------------------- ; LodLen: db (LodEnd - LodLst)/4 LodLst: dw Key1, Ims1 dw Key2, Ims2 dw Key3, Ims3 dw Key4, Ims4 dw Key5, Ims5 dw Key6, Ims6 dw Key7, Ims7 LodEnd: page ; Key file Names and Prompt Strings ;---------------------------------- ; 1) Entry Format: ; -FCB filespec followed by the prompt string. ; -or a Null (0FFh) for No File Check ; Key1: db NOT Null, B_Drive,'HELP HLP',0 db 'CP/M 3 Distribution Diskette Master II$' Key2: db NOT Null, B_Drive,'CORRECT COM',0 db 'Software Distribution Diskette - 1 (Correct-It)$' Key3: db NOT Null, B_Drive,'MBASIC COM',0 db 'Software Distribution Diskette - 2 (MBasic)$' Key4: db NOT Null, B_Drive,'LC COM',0 db 'Software Distribution Diskette - 3 (LogiCalc)$' Key5: db NOT Null, B_Drive,'PEARLED COM',0 db 'Personal Pearl Distribution Diskette (Disk 1 of 2)$' Key6: db NOT Null, B_Drive,'PSORT COM',0 db 'Personal Pearl Distribution Diskette (Disk 2 of 2)$' Key7: db NOT Null, B_Drive,'NWU COM',0 db 'New Word Distribution Diskette$' page ; Ims Strings ;------------ ; Entry Format: ; -Valid Ims Sting in the same format as the IMS command ; carriage return = ; ; warm boot pause = | ; Ims1: db (Ims2 - Ims1) - 1 db 'hdlpip A:=B:*.*;hdl2;' Ims2: db (Ims3 - Ims2) - 1 db 'hdlpip A:=B:*.*;hdl2;' Ims3: db (Ims4 - Ims3) - 1 db 'hdlpip A:=B:*.*;hdl2;' Ims4: db (Ims5 - Ims4) - 1 db 'hdlpip A:=B:*.*;hdl2;' Ims5: db (Ims6 - Ims5) - 1 db 'hdlpip A:=B:*.*;hdl2;' Ims6: db (Ims7 - Ims6) - 1 db 'hdlpip A:=B:*.*;hdl2;' Ims7: db (ImsN - Ims7) - 1 db 'hdlpip A:=B:*.*;era profile.sub;ren profile.sub=prof2.sub;pilot init;' ImsN: page ;---------------------------------------------------------------------- ; Prompt Strings (5_Feb_84) ;-------------------------- ; Prmpt1: db ClrScr, Esc, Bright, 'MD-11 Master Disk Program Loader Rev ' db ((PRev and 0F0h) shr 4) + '0', '.', (PRev 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,'$' Prmpt2: db Esc, Dim, cr,lf db 'Please insert the diskette labeled:' db Esc, Bright, cr,lf,'$' Prmpt3: db Esc, Dim, cr,lf db 'into your floppy disk drive. $' Prmpt4: db Esc, Dim, Bell, cr,lf, cr,lf, 'Press ' db Esc, Bright,'C' db Esc, Dim, ' to continue or ' db Esc, Bright,'S' db Esc, Dim, ' to Stop: ' db Esc, Bright, '$' CrLf: db cr,lf,'$' page ;---------------------------------------------------------------------- ; Error Messages (5_Feb_84) ;-------------------------- ; Err1: db cr,lf,'Wrong Version of Cbios' db cr,lf,'This version of Foreign Requires CP/M vers 3.0 Cbios rev ' db ccl shr 4 + 30h,'$' Err2: db cr,lf,'ERROR: This is NOT the proper disk$' Err3: db cr,lf,'ERROR: There was an Error made in the previous file transfer$' Err4: db cr,lf,'ERROR: There is insufficient space in the ims buffer$' end