aseg org 0100h .z80 ;******************************************************** ;* * ;* * ;* SHELL V4.4 Barrie Hall 5/3/1982 * ;* --------------------------------- * ;* This program simulates CPM submit. * ;* * ;* Bugs, comments, abuse to: * ;* Barrie Hall * ;* 3 Maycock St * ;* East Denistone * ;* 2112 NSW, Australia * ;* ph: 802200 a.h * ;* OR * ;* leave a message on Software Tools * ;* RCPM on Sydney (02)997-1836 * ;* * ;* * ;* The first form will load the named command file into * ;* characters to CP/M one at a time. If a $<1..9> is * ;* encoutered, a string will be substituted. * ;* This string comes from the command line, it is the * ;* nth space bounded string typed. * ;* * ;* 0A>sh par1 par2 ... parN * ;* * ;* 0A>sh ;typed with a blank command line * ;* * ;* will invoke the INTERACTIVE mode. Shell will prompt * ;* with a single ">" and wait for you to type a command * ;* lines. The lines are transfered to the command * ;* Buffer after each , to exit, type a "@", the * ;* command lines are now passed to CP/M, one char at a * ;* time. * ;* * ;* 0A>sh * ;* >type hmm.txt * ;* >type hello.asm * ;* >stat :dsk * ;* >@ * ;*------------------------------------------------------* ;* Now the system executes those commands * ;*------------------------------------------------------* ;* * ;* Advantages over CP/M submit/xsub * ;* -------------------------------- * ;* SHELL will work with ANY program using CONSOLE input.* ;* * ;* SHELL is memory based, not disk based, so it runs * ;* much more quickly, with no disk accesss to fetch * ;* commands. * ;* * ;* SHELL has an interactive mode for sequences you dont * ;* want to write a submit file for, but still want to * ;* execute in a "BATCH MODE", like lots of printing * ;* or compilation. * ;* * ;* Errors,panic exit * ;* ----------------- * ;* If SHELL cant find your SUBMIT file, it will tell * ;* you, and exit. * ;* * ;* If your submit file trys to use parameters that you * ;* didn't type, it will exit with a warm boot, With NO * ;* message... * ;* * ;* If you hit a key while SHELL has control of the * ;* keyboard calls, it will exit with a warm boot. * ;* * ;* Converting SUBMIT files to SHELL files * ;* -------------------------------------- * ;* Simple, just delete the XSUB command if its there...* ;* * ;* * ;* Installation-operation * ;* ---------------------- * ;* This prog runs hidden from CP/M, SO you have to find * ;* about 220 bytes + Buffer size of memory above your * ;* BIOS, or between your BIOS and CP/M, if you have * ;* some there. * ;* * ;* Be SURE you know what you are doing here, but if your* ;* BIOS finishes before the end of memory (including * ;* sector buffers ,etc) the memory above it is probably * ;* ok to use. * ;* * ;* A lot of systems use a memory mapped video board, * ;* there is usually some unused memory above this. * ;* * ;* Equate the first location of this memory to DEST. * ;* * ;* SECTORS defines how big a command buffer you want, * ;* 1/2k is more than enough for 99% of submit files, * ;* 1/4k is probably ok. * ;* * ;* Shell intercepts BIOS keyboard calls, CP/M thinks its* ;* coming from the keyboard, so SHELL will work with ANY* ;* program that uses keyboard input normally. * ;* * ;* Any calls to BIOS keyboard status will return 00, * ;* (no chars), so if a program hangs under SHELL, thats * ;* why. (I havent found any yet) * ;* * ;* Use M80 to assemble this program, I don't know about * ;* ZASM. SHELL uses M80's ".phase" op, which allows you * ;* to assemble code to run at a location different from * ;* the load address. Once SHELL has loaded a command * ;* file from disk or interactively. It will block move * ;* 220 bytes of runtime stuff to your high mem and then * ;* hook into the BIOS jump table. When it runs out of * ;* chars, it does a normal RETURN, (NOT WARM BOOT), so * ;* you can stay in the last program loaded. * ;* * ;* If you hit ANY KEY while SHELL is in control, SHELL * ;* will remove its hooks and warm boot the system. * ;* * ;* Improvements * ;* ------------ * ;* It is very easy to add some SIMPLE control structures* ;* like a LOOP--ENDLOOP with a constant number iter- * ;* ations and a variable parameter number so we could * ;* do this: * ;* * ;* #loop 5 * ;* cc1 $n * ;* #end * ;* :this would compile five programs named on * ;* the command line after sh . I plan to do this * ;* when I get some time, BUT MAYBE you could do it for * ;* yourself???? * ;* * ;* Barrie Hall , August 1982 * ;* * ;******************************************************** ; ; History - most recent first. ; --------------------------- ; Doco added to front: 4/8/1982 bjh ; ; ;update: 22/7/82 expands 1-9 parameters in the command lin ;bjh ; ;update: 21/7/82 ,only Warm Boots when a key has ; been hit, otherwise, returns to sender ; ; update: 18/7/82 to ret to ccp instead of warm boot ; bjh. ; ;------------------------------------------------------- dest equ 0f800h ;my spare memory sectors equ 2 ;1/2k of commands??? fdos equ 0005h fcb equ 005ch fcbcr equ fcb+32 cmdbuf equ 80h ;cpm command line tail true equ 0 false equ not true ;a lie??? ;main program ;fcb is default fcb at 5c ; work out how big our tpa is ; get fdos addr from 6 and 7 ; ; This program runs hidden from cpm ; at f800h so we must do a block move ; before execution ; bmove:: ld hl,start ld de,dest ld bc,len-dest ldir ;moved the runtime stuff up high ;*************************************************** ;* We must check for a filename on the command line ;* If there is one, skip it and get the parameters ;* from the command line and put them in the ;* parameter buffers 1-9. ;* If there is NO file name, enter interactive mode. ;**************************************************** parse:: ld hl,cmdbuf ld a,(hl) cp 0 jp z,inter ;interactive mode ;move the command tail to a safe place ld hl,cmdbuf ld de,param ld c,a inc c ld b,0 ldir ;move it stfil:: xor a ld (fcbcr),a ;clear current rec field getfil:: ld de,fcb call open ld de,opmess cp 0ffh jp z,error ; file is open, now read it in ld hl,buff ;hl is buff pointer ld b,sectors ;read B sectors maximum rloop:: ld d,h ld e,l call setdma ;update dma for read ld de,fcb call read cp 0 jr nz,endfil ld de,128 ;sector size add hl,de djnz rloop ;next sector ;file read in ; ; the rest of prog ;NOW we have the command file in memory ;lets hook into the bios, first we have ;to compute the address of the jump table ;at the front of the bios. ; endfil:: ghook:: ld hl,(01h) ;address of warm boot ld bc,0004h ;offset to consts: add hl,bc ld a,(hl) ld (kbst),a inc hl ld a,(hl) ld (kbst+1),a inc hl inc hl ld (hokad),hl ;save for later ld a,(hl) ;save real conin add ld (kb),a inc hl ld a,(hl) ld (kb+1),a dec hl ld (hl),low hook inc hl ld (hl),high hook ld de,logon ld a,false ld (pflag),a ld hl,buff ld (point),hl ;the hooks are in so return to cpm and stand back??? error:: call pmess ret inter:: ;interactive mode ;this mode is invoked when there is no file name ;on the command line.. ;we must print a prompt and read a LINE of input ;from CPM and then transfer it to the SHELL buffer ;when we get a blank line,execute the line by ;installing the shell hooks... ld hl,buff ld (point),hl ;set up pointer into cmd prmt:: ld e,'>' call cout ld de,interbuf ld a,40h ;longest line ld (de),a call lchin call crlf ld de,(point) ld hl,interbuf+1 ;chars in the interbuff ld a,(hl) cp 00 ;blank line??? jr z,blank ;do it ld c,a inc hl ld a,(hl) ;first char of line cp '@' ;exit condition jr z,exec ;go and do it... ld b,0 ldir ;move a line into final buff blank:: ld a,0dh ;carraige ret ld (de),a inc de ld (point),de ;for next line jr prmt ;next line... exec:: ld hl,(point) ld (hl),1ah ;EOF inc hl ld (hl),1ah ;EOF - just in case... jr endfil ;cpm routines crlf: ld e,0ah call cout ld e,0dh call cout ret ; cout: push bc push de push hl ld c,2 jr cpm ; chin: push bc push de push hl ld c,1 jr cpm ; lchin:: push bc push de push hl ld c,10 jr cpm pmess:: push bc push de push hl ld c,9 jr cpm open:: push bc push de push hl ld c,15 ;open cp/m file code jr cpm read:: push bc push de push hl ld c,20 ;read cp/m file code. jr cpm setdma:: push bc push de push hl ld c,26 ;set dma address code. jr cpm cpm:: call fdos ;go to cp/m pop hl ;restore all registers pushed pop de pop bc ret ;back to the main program logon:: db '(Shell v4.4 installed)',0ah,0dh,'$' opmess:: db 'Shell: Cant find command file',0dh,0ah,'$' interbuf:: ds 40h ;---------------------------------------------------------- ;this part lives in high memory somewhere start equ $ .phase dest ;your spare memory ;******************************************************** ;* * ;* This part of the program mimics CP/M CONIN routine * ;* * ;******************************************************** ;We handle the parameters by checking for a '$' sign ;and then jumping to a routine which 1. Finds if that ;parameter was given on the command line. 2. Sets up ;a flag which tells this prog to get a char from the ;parameter exp rather than the the main text submit.. ; If this flag is set, the next call to the kb routine ;will vector to EXPAR, which returns a char from the ;the parameter being expanded... hook:: push hl push bc push de ld a,(pflag) ;are we doing a parameter cp true jr z,expar ;get a char from it instaed ld hl,(point) ;get pointer to command text hooka:: ld a,(hl) inc hl cp 1ah ;eof call z,rhook ;remove hooks and leave cp 0ah ;piss off line feeds jr z,hooka ;check for $n paramter cp '$' call z,subs ld (point),hl ;save pointer to text pret:: ;back here if we did a par char push af ; ;now check kb status routine and get out ;if a key has been pushed ; ld hl,rtlab push hl ;return address ld hl,(kbst) jp (hl) ;computed gosub rtlab:: cp 0 jr nz,panic ;key pushed,get out pop af pop de pop bc pop hl ret ;get out ,remove hook panic:: call rhook jp 0 ;warm boot rhook:: ld hl,(hokad) ld a,(kb) ld (hl),a inc hl ld a,(kb+1) ld (hl),a ld a,0dh ;we return with a return to prog ;hooks removed, return to what ever called us ret ;return to prog by ret..Hooks in CBIOS removed... ;----------------------------------------------------------- ; Expand the parameter, this code returns the next ; char from the parameter we are expanding.. expar:: ld a,(cnt) dec a jr z,finpar ;no more chars ld (cnt),a ld hl,(ppp) ;get parameter pointer ld a,(hl) inc hl cp ' ' ;exit if space ;if it is a space, we have come to the end of the ;current parameter expansion, clear the flag ;and return a space in A. ;This code will not be used again until there is ;another $n in the main submit text.. jr z,finpar ;clear flag etc.. ld (ppp),hl jr pret ;go back to main finpar:: ld a,false ld (pflag),a ld a,' ' jr pret ;The following code is called when a $ is encountered in ;the main submit file, it points (ppp) at the beginning ;of the relevant string from the command line which ;we moved to PARAM buffer. ; This code MUST return the first character of the new ;expansion.. subs:: push hl ld a,(hl) ;get paramter number.. sub '0' ld l,a push hl ;save parameter num ;and point at the correct one ;parameter ranges from $1 to $9 ;GETS returns DE pointing to the next string in the ;the command line copy at PARAM, B equal to the ;number of chars in the string, or 00 if no string ;available... ld hl,param ld a,(hl) ld (cnt),a inc hl ld (cmdpt),hl ;start GETS at front of buff pop hl ;get back parameter number call gets ;skip filename fnd:: call gets xor a cp b jr z,perror ;parameter error dec l jr nz,fnd ld a,b ld (cnt),a ;length of parameter cp 1 ;only one char in this par?? jr z,nexp ;return it and be done!! inc de ;points at first char in par ld (ppp),de ;save pointer to param ld a,true ;set par flag ld (pflag),a dec de nexp:: ld a,(de) ;first char of parameter pop hl inc hl ret perror:: jr panic ;warm boot, parameter error ;------------------------------------------------------ ;routine returns pointer to a ;space bounded string in DE ;and its length in B or if out of chars B=0. ;stuffs up BC,DE,AF saves HL gets:: push hl ld b,0 ld hl,(cmdpt) ld a,(cnt) ld c,a ;get chars left sllp:: ld a,(hl) inc hl cp ' ' ;but if that wasnt a space jr nz,thro dec c jr z,exlop jr sllp thro:: ld d,h ld e,l dec de ;correction inc b ;1 char already dec c jr z,exlop lenlop:: ld a,(hl) inc hl inc b ;another char dec c jr z,exlop cp ' ' jr nz,lenlop ;measure the string dec b ;correction ld (cmdpt),hl ;save our place on line ld a,c ld (cnt),a ;save count pop hl ret exlop:: ld a,1 ld (cnt),a ;zero out count pop hl ret ;-------------------------------------------------------- len:: ;label for bmove ppp:: ds 2 pflag:: ds 1 cmdpt:: ds 2 cnt:: ds 1 kbst:: ds 2 point: ds 2 hokad:: ds 2 kb:: ds 2 buff:: ds sectors*128 ;command buffer param:: ds 40h ;space for cpm command line ; and end to it all...... end