home *** CD-ROM | disk | FTP | other *** search
- 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 <filename> 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 <CR> , 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 <file>. 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
-