Title Program Loader for the MD-1/2/3 using CP/M 2 (12_Sept_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. a Pointer to the Desired Entry ; Print_Position Print the Drive Position Message ; Get_Bios_Pntr Get One of the Bios Pointers ; Get_Response Get the User's Response ; Install_Ims Put the Ims string into the IMS buffer ; -- General Parameters ; -- Program Load List ; -- Prompt Strings ; -- Error Messages page 64 ;---------------------------------------------------------------------- ; External Definitions (10_Sept_84) ;---------------------------------- ; 1) This variables are defined in the 'List' files ; External LodLst External LodLen ;---------------------------------------------------------------------- ; Equates (10_Sept_84) ;--------------------- ; ; IDs and Rev Numbers ;-------------------- ; CpmVer equ 20h ;Cpm Version Number Ccl equ 30h ;Cbios Compatibility Level Prev equ 11h ;Program revision number PID equ 'Ok' ;Program ID ; Address Definitions ;-------------------- ; Bios_Entry equ 0 ;Address of the Start of the BIOS + 3 warmbt equ 01h ;Address of the Bios Warm boot entry Number_Drives equ 04h ;Number of Physical Drives Bdos_Entry 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 ;---------------------- ; Bdos_ConOut equ 2 ;Console Output a Character Bdos_DirIO equ 6 ;Direct console control Bdos_PString equ 9 ;Print a string Bdos_GetRev equ 0Ch ;Get revision number of cpm system Bdos_SFirst equ 11h ;Search for first occurance of file x Bdos_SetDMA equ 1Ah ;Set the DMA Address InWait equ 0FFh ;Direct console input ; Offsets ;-------- ; Ccl_Offset equ 3C ump Table Mtab_Offset equ 44h ;Mtab Pointer from Start of Jump Table ; 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 Install_Ims) ClrScr equ 1Ah ;Clear Screen Esc equ 1Bh ;Escape Bright equ '(' ;Start High Lighting Dim equ ')' ;Start Low Lighting ; Other Definitions ;------------------ ; Null equ 0FFh ;Null Key filespec prompt @Double_Sided equ 5 ;Double Sided Bit in Mtab's DskDef0 page ;---------------------------------------------------------------------- ; Main Line of the Floppy Disk Loader for Cpm 2.2 (10_Sept_84) ;------------------------------------------------------------- ; Main_Line: ld hl,(PIDadd) ;HL:= Contents of 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 Check_Ccl ; Check CP/M rev and compatibility or a ; If (Rev levels aren't high enough) jr nz,Mdone ; Quit call Clear_Screen ; Clear the Console Screen ld de,Prmpt1 ld c,Bdos_PString call Bdos_Entry ; Print the initial prompt call Get_Response ; Get the user response or a ; If (Response eq Stop) jr nz,MDone ; Quit 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 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 Look_for_File ;Get the user to load the next disk ad 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 Bios_Entry ;Goto the Bios Warm Boot Entry page ;====================================================================== ; Check the Cbios Compatibility Level (18_Jun_84) ;================================================ ; ;Check the Cpm Version Number Check_Ccl: ld c,Bdos_GetRev ;C:= Bdos get cpm version number call Bdos_Entry ;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 ne expected version) jr nz,CclErr ; Goto Error return ;Check the Cbios Compatibility Level ld hl,(Bios_Entry+1) ;HL:= Bios warm boot entry address ld de,Ccl_Offset ;DE:= offset to Cbios compatiblity level add hl,de ;HL:= Pointer to Cbios compatibility ld a,(hl) ;If (crnt compatibility ne Cbios Ccl) and 0F0h ; (Mask off minor revision number) cp Ccl jp nz,CclErr ; Goto Error return Cclok: ld a,0 ;A:= Successful Completion status ret ;Return CclErr: ld de,Err1 ; DE:= revision error message ld c,Bdos_PString ; C:= Print string function call Bdos_Entry ; Print Input Drive number string ld a,0FFh ; A:= error return status ret page ;====================================================================== ; Clear the Console Screen (20_Jul_84) ;===================================== ; 1) This Routine Simply outputs a Carriage Return followed by 50 Line ; Feeds to the Console. ; 2) NONE of the Register Pairs are altered. ; Clear_Screen: push bc push de push hl ld c,Bdos_ConOut ;C:= Bdos Console Output Function Number ld e,Cr ;E:= Carriage Feed pop bc djnz CsSk1 ;Until (Character Counter - 1 eq 0) pop hl pop de pop bc ret ;Return page ;====================================================================== ; Prompt for Key file then Check search for it (10_Sept_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. ; Look_for_File: ld bc,Key_Offset ;Loop BC:= Offset to Prompt string call Get_Base ; HL:= Pointer Prompt string table base ld a,(hl) ; If (File Name string is Null) cp Null ld a,0 ret z ; Return (No Error) inc hl ; HL:= Source (Start of FCB) ld de,Local_Fcb ; DE:= Destination (Local FCB) ld bc,13 ; BC:= Length of Transfer ldir ; Transfer FCB for the Key File push hl ; (save pointer to prompt string) ld de,Prmpt2 ld c,Bdos_PString call Bdos_Entry ; Print 'please insert diskette.. pop de ; DE:= Pointer to prompt string ld c,Bdos_PString call Bdos_Entry ; Print title of diskette call Print_Position ; Print the Remainder of the Prompt call Get_Response ; Get response from console or a ; If (response eq Stop) ret nz ; Return ld c,Bdos_SetDMA ld de,Local_Buffer call Bdos_Entry ; Set the DMA Address ld c,Bdos_SFirst ld de,Local_Fcb call Bdos_Entry ; Find Key File On Selected Drive cp 0FFh ; If (key file was found) ld a,0 ret nz ; Return (Ok) ld de,Err2 ld c,Bdos_PString call Bdos_Entry ; Print Error Message jr Look_for_File page ;---------------------------------------------------------------------- ; Return a Pointer to the Desired Entry (5_Feb_84) ;------------------------- 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 ; Get_Base: 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 ;---------------------------------------------------------------------- ; Print the Drive Position Message (10_Sept_84) ;---------------------------------------------- ; 1) This Routine Prints: ; 'diskette into your' and then ; - Nothing for a Single Drive System ; - Right Hand for a Single Sided Double Drive System ; - Upper for a Double Sided Double Drive System ; 'disk drive' ; Print_Position: ld de,GpM1 ;DE:= Pointer to First Part of Message ld c,Bdos_PString ;C:= Bdos Print String Function call Bdos_Entry ;Print 'diskette into your' ld de,RamDatY_Offset call Get_Bios_Pntr ;DE:= Pointer to Start of RamDatY dec de dec de ;DE:= Pointer to Vnum ld a,(de) ;Update Vnum or a ;If (there's more than one drive) jr z,GpSk3 ld de,Mtab_Offset call Get_Bios_Pntr ld a,(de) bit @Double_Sided,a ; I ht Hand or Upper GpSk3: ld de,GpM2 ;DE:= Pointer to Final Part of Message ld c,Bdos_PString ;C:= Bdos Print String Function call Bdos_Entry ;Print 'disk drive' ret ;Return page ;---------------------------------------------------------------------- ; Get One of the Bios Pointers (10_Sept_84) ;------------------------------------------ ; 1) This routine picks up one of the Vectors from the Bios Jump Table. ; 2) On Entry the DE register pair holds the offset to the desired entry ; 3) On Return the DE register pair holds the vector. ; 4) Register Usage: ; DE -> Enter:= Offset to Vector; Exit:= Vector ; HL -> Pointer to base of Bios (Cold Start Entry) ; Get_Bios_Pntr: ld hl,(Bios_Entry+1) ;HL:= Pointer to Warm Boot Entry ld l,0 ;HL:= Pointer to Base of Bios 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 ;---------------------------------------------------------------------- ; Get the User's Response (10_Sept_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 Carriage Return to continue or a Control_C ; to 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 ; Get_Response: ld de,Prmpt4 ld c,Bdos_PString call Bdos_Entry ;print the response prompt AskLp1º lä c,Bdos_DirIO ;Loop ld e,InWait ; (Set funct to wait for input) call Bdos_Entry ; Get a character from console and 5Fh ; (force to upper case) cp CntrlC ; If (Response eq Stop) jr nz,AskSk1 ld a,0FFh ;Print Carriage Return Line Feed pop af ;A:= Response (0-Continue or 0FFh-Stop) ret ;Return page ;====================================================================== ; Put the Ims string into the IMS buffer (18_Jun_84) ;=================================================== ; 1) This routine puts the current iteration's ims string into the ; ims buffer. ; Install_Ims: ld bc,Ims_Offset ;BC:= Offset to IMS sting call Get_Base ;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 hl,(Bios_Entry+1) ;Get warm boot address ld bc,Inject_Offset ;offset to inject IMS routine add hl,bc ;add offset to HL call jphl ;call (HL) ld a,0 ;If (the ims string was accepted) ret nc ; Return (no error) ld de,Err3 ;Else ld c,Bdos_PString call Bdos_Entry ; Print error (ims string won't fit) ld a,0FFh ret ; Return (ERROR) jphl: jp (hl) page ;---------------------------------------------------------------------- ; Prompt Strings (11_Sept_84) ;---------------------------- ; Prmpt1: db Esc,Dim,Lf,Lf,Lf,Tab db ' Micro Decision Distribution Diskette' db Cr,Lf,Lf,Tab db 'This is your ' db Esc,Bright db 'DISTRIBUTION ' db Esc,Dim db 'diskette. It is used to create a CP/M' db Cr,Lf,Tab db 'working diskette f on it will be erased.' db Cr,Lf,Lf,Tab db 'It is very important that you keep these two diskettes straight.' db Cr,Lf,Lf,'$' Prmpt2: db Esc, Dim, Cr,Lf db 'Please insert your ' db Esc, Bright, Cr,Lf,'$' GpM1: db Esc, Dim, Cr,Lf db 'diskette into your $' GpMup: db 'upper $' GpMrt: db 'right hand $' GpM2: db 'disk drive. $' Prmpt4: db Cr,Lf,Lf,Lf db 'Press ' db Esc,Bright db '[RETURN] ' db Esc,Dim db 'when you are ready to proceed $' CrLf: db Cr,Lf,'$' page ;---------------------------------------------------------------------- ; Error Messages (18_Jun_84) ;-------------------------- ; Err1: db Cr,Lf,'Wrong Version of CP/M' db Cr,Lf,'This version of FDL Requires CP/M vers 2.2 Cbios rev ' db Ccl shr 4 + 30h,'.x$' Err2: db Cr,Lf,'ERROR: This is NOT the proper disk$' Err3: db Cr,Lf,'ERROR: There is insufficient space in the ims buffer$' page ;---------------------------------------------------------------------- ; General Parameters (5_Feb_84) ;------------------------------ ; Local_Fcb: ds 32,0 Local_Buffer: ds 128,0 end ;---------------------------------------------------------------------- ; Text Message ;------------- ; Micro Decision Distribution Diskette This is your DISTRIBUTION diskette. It is used to create a CP/M working diskette for your Micro Decision. You will need another diskette to become your WORKING diskette. This diskette need not be blank, but any information currently on it will be erased. It is very important that you keep these two diskettes straight.'