.comment \ zmp 1.5 overlay, version 1.0 computer: ampro lb+ terminal: wyse 50 (optional) - works with or without nzcom present. - displays baud rate, data bits, stop bits and parity in the wyse 50's host field (top line, above scrollable screen) if you set the equate hostline true. otherwise these are just shown on your screen when set. - provides a dtrexit equate which, when set true, will prompt you to see if you want DTR signal turned off when you exit ZMP. i have an old bell dataphone 1200 modem, and the only way i've found to keep it from answering my phone automatically when i don't want it to is to keep DTR off except when in a modem program. DTR is automatically turned on on entry to ZMP in any case. the prompt allows you to exit a terminal session temporarily to your o/s level for whatever reason, without disconnecting your session. - screen print function not currently implemented. - be sure to set ALL config equates (in praticular the disk/user for overlay files). al grabauskas 12/6/88 i'm reachable at: lillipute z-nodes 1&2 (312) 649-1730 (312) 664-1730 the advocate (312) 939-4411 \ ;----------------------------------------------------------------------------- ; ; Sample Overlay for ZMP (Z-Modem Program) ; ; Name ZMO-BLNK.Z80 ; ; Dated Sep 14, 1988 ; ; Written by - ; Ron Murray, c/o Z-Node 62, 061-9-450-0200, Perth, Western Australia. ; ; Modified to ZMP v1.2 standard rjm 15/9/88 ; Modified to ZMP v1.3 standard rjm 11/10/88 ; Modified to ZMP v1.4 standard rjm 20/11/88 ; 89/04/12 - Modified to ZMP v1.5 - George Conover ; ; ;----------------------------------------------------------------------------- ; ; ; System-dependent code overlay for ZMODEM ; ; ; ; Insert your own code as necessary in this file. Code contained herein ; has been written in Z80 code for use with M80 or SLR. Assemble as follows: ; ; SLR ZMO-xx01/h ; MLOAD ZMP.COM=ZMODEM.COM,ZMO-xx01.HEX ; or ; M80 =ZMO-xx01.Z80 ; RELHEX ZMO-xx01 ; MLOAD ZMP.COM=ZMODEM.COM,ZMO-xx01.HEX ; ; ; (Don't use L80 without changing the source for assembly as a ; cseg file.) ; ;----------------------------------------------------------------------------- ; ; ; Notes on modifying this file: ; ; C requires that functions do not change either index register (IX or IY). ; If your overlay requires either of these to be changed, ensure they are ; restored to the original values on return. ; Since collecting parameters from C functions can be tricky, only change ; the parts marked 'Insert your own code here'. Do NOT modify the jump ; table at the start. Do NOT modify the entry/exit sections of each ; function. Do NOT pass 'GO'. Do NOT collect $200. ; Apart from defining modem functions, this file also defines terminal ; characteristics. Examples provided are for ADM-3A (with a few of my own ; additions). Modify to suit your own terminal. An inline print routine ; is provided for printing strings in the usual way: usage is ; ; call print ; db 'required string',0 ; ;----------------------------------------------------------------------------- ; ; ; Don't forget to set your clock speed at the clkspd variable. ; ; ; If you find your overlay exceeds the maximum size (currently 0400h), ; you will have to contact me for another version. If too many people need ; to do it, we haven't allowed enough room. ; ; Ron Murray 15/8/88 ; ; ; ;--------------------------------------------------------------------------- false equ 0 true equ not false ;------------------------------------------------------------------------------ ; User-set variables: ; configuration equates for ampro overlay dtrexit equ true ; if true, the userout: routine will prompt ; you to see if you want to turn off DTR ; completely on exiting ZMP. DTR is automati- ; cally turned on when entering ZMP. turning ; DTR off prevents some modems from auto- ; answering the phone. the prompt allows you ; to leave a session temporarily to your o/s ; and not disconnect. hostline equ true ; controls whether your line parameters are ; displayed in the host field of a wyse ; terminal at all times in ZMP, or if they ; are simply echoed to the screen when set. clkspd equ 4 ; Processor clock speed in MHz debug equ false ; to allow debugging of overlay with Z8E etc. ; end configuration equates for ampro overlay ;Set the following two equates to the drive and user area which will contain ; ZMP's .OVR files, .CFG file, .FON file and .HLP file. Set both to zero ; (null) to locate them on the drive from which ZMP was invoked. overdrive equ 'F' ; Drive to find overlay files on ('A'-'P') overuser equ 15 ; User area to find files ;------------------------------------------------------------------------------ ; NOT user-set variables userdef equ 0145h ; origin of this overlay ; This address should not change with ; subsequent revisions. mspeed equ 03ch ; location of current baud rate. ovsize equ 0400h ; max size of this overlay ; ampro definitions ioint equ 57 ;BIOS call of initialization routine siob equ 52h ;Relative location in bios siob1 equ 53h ;*eag* siob3 equ 55h ;*eag* siob5 equ 57h ;*eag* ct1 equ 42h ;*eag* ; port definitions modctl equ 8ch ; modem control port b moddat equ 88h ; modem data port b ; bit definitions mdrcvb equ 01h ; Modem receive ready bit (dav) mdsndb equ 04h ; Modem send ready bit mdparer equ 010h ; parity error mdovrrn equ 020h ; overrun error mdfram equ 030h ; framing error mderrf equ mdparer+mdovrrn+mdfram ; *eag* mddtrof equ 068h ; turn off dtr, rts mddtron equ 0eah ; restore normal, 8 bits, rts on, etc. ; end ampro specific equates esc equ 1bh ctrlq equ 11h cr equ 0dh lf equ 0ah bdos equ 5 .z80 ; use z80 code aseg ; absolute if debug org 100h ; so you can debug it with cebug, zsid, etc else org userdef endif esc equ 1bh ctrlq equ 11h cr equ 0dh lf equ 0ah bdos equ 5 codebgn equ $ ;Jump table for the overlay: do NOT change this jump_tab: jp scrnpr ; screen print jp mrd ; modem read with timeout jp mchin ; get a character from modem jp mchout ; send a character to the modem jp mordy ; test for tx buffer empty jp mirdy ; test for character received jp sndbrk ; send break jp cursadd ; cursor addressing jp cls ; clear screen jp invon ; inverse video on jp invoff ; inverse video off jp hide ; hide cursor jp show ; show cursor jp savecu ; save cursor position jp rescu ; restore cursor position jp mint ; service modem interrupt jp invec ; initialise interrupt vectors jp dinvec ; de-initialise interrupt vectors jp mdmerr ; test uart flags for error jp dtron ; turn DTR on jp dtroff ; turn DTR OFF jp init ; initialise uart jp wait ; wait seconds jp mswait ; wait milliseconds jp userin ; user-defined entry routine jp userout ; user-defined exit routine jp getvars ; get system variables JP SETPORT ; Set port (0 or 1) ; Spare jumps for compatibility with future versions jp spare ; spare for later use jp spare ; spare for later use jp spare ; spare for later use jp spare ; spare for later use jp spare ; spare for later use jp spare ; spare for later use ; ; Main code starts here ; ;Screen print function scrnpr: ; <== Insert your own code here call print db 'This function not supported.',cr,lf,0 ; <== End of your own code spare: ret ; User-defined entry routine: leave empty if not needed ;------------------------------------------------------------------------------ ; this is a routine that locates the warm boot address whether nz-com is ; running or not and stores it at the word biospt. this allows access to ; ampro specific offsets in the bios. (note that this is bios base addr+3). ; ; note that this assumes the nz-com bios released with nz-src.lbr (vers. 1.4) ; if that isn't what you have you'll likely need to modify what's below. eyectof equ 5ah ; Offset to "NZ-COM" eyecatcher ; from virtual bios base. nzceye: db 'NZ-COM' ; Eyecatcher to match eyelen equ $-nzceye ; Length of eyecatcher ; end most likely user mods ---------------------------------------------- userin: push hl push de push bc push af ld hl,(1) ; This is some bios address.. ld l,eyectof ; Hl = ptr to "NZ-COM" eyecatcher ld de,nzceye ; Ptr to an internal copy of it ld b,eyelen ; Length nzckloop: ld a,(de) ; Get a char cp (hl) ; Compare to char at hl jr nz,nonzc ; No nz-com inc hl ; Bump ptr inc de ; Bump ptr dec b ; Decrement length jr nz,nzckloop ; Repeat if apropos ld a,(109h) ; get pointer to ENV descriptor ld l,a ld a,(10ah) ld h,a inc hl ; bump past jp opcode to console stat vector ld e,(hl) ; Get real console status vector inc hl ld d,(hl) ex de,hl ; Put it in hl dec hl ; Convert to warm boot vector dec hl dec hl jr biosret ; And return bios addr in biospt nonzc: ld hl,(1) ; Get original pointer biosret: ld (biospt),hl ; and save it call initall ; set up rest of the details call dtron ; make sure DTR is set pop af ; Restore regs and return pop bc pop de pop hl ret ; User-defined exit routine: leave empty if not needed userout: call print ; kill host message display on wyse db esc,'A31',cr,0 ; host msg field = dim underscore if dtrexit call print ; dtr off yet? db 'Kill DTR? (default no) ',0 call cyn ; get yes/no answer ret nz ; not a "yes" jp dtroff ; do it else ret endif ; if dtrexit ; ; Y/N input from console ; cyn: push bc ; save regs push de push hl ld c,1 call bdos ; print it or a,' ' ; make small case cp a,'y' ; yes? pop hl pop de pop bc ret ;Get a character from the modem: return in HL mchin: push bc ; <== Insert your own code here in a,(moddat) ; in modem data port ; <== End of your own code ld l,a ; put in HL ld h,0 or a ; set/clear Z pop bc ret ;Send a character to the modem mchout: ld hl,2 ; get the character add hl,sp ld a,(hl) ; <== Insert your own code here out (moddat),a ; out modem data port ; <== End of your own code ret ; done ;Test for output ready: return TRUE (1) in HL if ok mordy: ; <== Insert your own code here in a,(modctl) ; in modem control port and mdsndb ; bit to test for send ready jr z,monr ; modem not ready ld hl,1 ; indicate ready jr mordyret monr: ld hl,0 ; indicate not ready mordyret: ; <== End of your own code ld a,l ; set/clear Z or a ret ;Test for character at modem: return TRUE (1) in HL if so mirdy: ; <== Insert your own code here in a,(modctl) ; in modem control port and mdrcvb ; bit to test for receive ready jr z,minr ; modem not ready ld hl,1 ; indicate ready jr mirdyret minr: ld hl,0 ; indicate not ready mirdyret: ; <== End of your own code ld a,l ; set/clear Z or a ret ;Send a break to the modem: leave empty if your system can't do it sndbrk: ; <== Insert your own code here ld a,5 ; *eag* out (modctl),a ; send to the status port ld a,mddtrof ; turn off dtr, rts, send break out (modctl),a ; *eag* ; <== end of your own code ld hl,300 ; wait 300 mS call waithlms ; <== insert your own code here ; To restore ; <== End of your own code ret ;Test UART flags for error: return TRUE (1) in HL if error. mdmerr: ; <== Insert your own code here in a,(modctl) ; in modem control port and mderrf ; bits to test: parity, overrun, framing jr z,mnerr ; no error ld hl,1 ; indicate error jr merrret mnerr: ld hl,0 ; indicate no error merrret: ; <== End of your own code ld a,l ; set/clear Z or a ret ;Turn DTR ON dtron: ; <== Insert your own code here ld a,5 ; *eag* out (modctl),a ; *eag* ld a,mddtron ; restore normal, 8 bits, rts on, etc. out (modctl),a ; *eag* ; <== End of your own code ret ;Turn DTR OFF dtroff: ; <== Insert your own code here ld a,5 ; *eag* out (modctl),a ; send to the status port ld a,mddtrof ; turn off dtr, rts, send break out (modctl),a ; *eag* ; <== End of your own code ret ;Initialise the uart init: ld hl,2 ; get parameters add hl,sp ex de,hl call getparm ; in HL ld (brate),hl ; baud rate call getparm ld (parity),hl ; parity call getparm ld (data),hl ; data bits (BINARY 7 or 8) call getparm ld (stop),hl ; stop bits (BINARY 1 or 2) ; <== Insert your own code here ; using values below ;*eag* begin insertion initall: ; alternate entry point for userin ld de,(brate) ; Code to de ld hl,baudtb ; Offset into table add hl,de ld a,(hl) ; Fetch code or a ; 0? (means unsupported code) jp z,pbexit ; exit if so ld (bsave1),a ; Save it ld a,(brate) ; get brate ld (mspeed),a ; don't forget to load mspeed with the ; current brate value if the new rate is ; valid. ld hl,baudtx ; Offset into second table add hl,de ld a,(hl) ; Get second value ld (bsave2),a ; Save it also ld hl,(biospt) ; Get location of bios ld l,ct1 ; Add 42h to reach ct1 in i/o table ld a,47h ld (hl),a inc hl ; Move to next location ld a,(bsave1) ; Get first table value ld (hl),a ; Store it ld a,(bsave2) ; Get second table value ld b,a ; And save it ld l,siob1 ; Move ahead to siob+1 values ld a,(hl) ; Get current value and 3fh or b ; Or it with second value ld (hl),a ; Store it in work table inc hl inc hl ld a,(hl) ; Get last value and make or 80h ; Sure msb is set ld (hl),a ; Put it back in working table ld a,(data) ; 7 or 8 data bits sbc a,7 ; kill offset ld h,0 ld l,a ld de,bittbl ; Load lookup table add hl,de ; get bit pattern ld c,(hl) ; Save selection value ld hl,(biospt) ; Get bios address ld l,siob3 ; Move to siob+3 ld a,(hl) ; Wr5 info and 9fh ; Mask or c ; Add selection ld (hl),a ; Store it ld a,c ; Get selection rla ld c,a ; Shift selection left ld l,siob5 ; Move to siob+5 ld a,(hl) ; Wr3 info and 3fh ; Mask or c ld (hl),a ; Store it ld a,(parity) ; get parity cp 'N' jr z,parno cp 'E' jr z,parev cp 'O' jr z,parod jp pbexit parno: ld c,00h jr setpar parev: ld c,03h jr setpar parod: ld c,01h setpar: ld hl,(biospt) ; Get bios address ld l,siob1 ; Go to siob+1 ld a,(hl) and 0fch or c ld (hl),a ld a,(stop) ; stop bits sbc a,1 ; kill offset ld h,0 ld l,a ld de,stptbl ; bit patterns add hl,de ; ptr to bit pattern ld c,(hl) ; get result ld hl,(biospt) ; Get bios address ld l,53h ; Shift to bios+1 ld a,(hl) and 0f3h or c ld (hl),a ld hl,(brate) ; get baud code sla l ; *2 sla l ; *4 ld de,pbauds ; base of printable baud table add hl,de ; printable baud ld de,baudshw ; dest ld bc,4 ; len ldir ; move it ld a,(parity) ; display that ld (parshw),a ld a,(data) ; display that add a,'0' ; make ascii ld (bitshw),a ld a,(stop) ; display that add a,'0' ; make ascii ld (stopshw),a call print ; display stuff on wyse ; the next few lines set the host message field on the wyse-50 ; to the following string, which displays your currently set ; line parameters (baud, bits, parity and stop bits) in a ; permanent host field at the top of your terminal. if hostline ; equate is not set true, they will just be shown on the screen ; whenever they are set. if hostline db esc,'A3p' ; host msg field = dim underscore db esc,"F" ; set set message endif db ' Baud: ' baudshw: db ' ' ; printable baud rate db ' Bits: ' bitshw: db ' ' ; bits per char db ' Parity: ' parshw: db ' ' ; parity db ' Stop: ' stopshw: db ' ' ; stop bits db cr,lf,0 jp ioinit ; Do the initialization ;*eag* end insertion ; <== End of your own code ret ;*eag* begin insertion ioinit: ld a,ioint ; Offset into bios jump table ld hl,(biospt) ; Address of bios in hl ld l,a ; Add offset jp (hl) ; Go there with auto return ; routine to handle unsupported baud rates pbexit: call print db 'Unsupported.',cr,lf,0 ret ; table of baud rate divisors for supported rates baudtb: db 0,208,139 ; 110,300,450 db 208,0,104 ; 600,710,1200 db 52,26,13,0 ; 2400,4800,9600,19200 baudtx: db 0,80h,80h db 40h,0,40h db 40h,40h,40h,0 pbauds: db ' 110',' 300',' 450',' 600',' 710' db '1200','2400','4800','9600',' 19K' bsave1: db 0 ; Current setting from bsave2: db 0 ; Tables - uninitialized bittbl: db 20h,60h ; 7 or 8 data bits stptbl: db 04h,0ch ; 1 or 2 stop bits biospt: dw 0 ;*eag* end insertion ;-------------------------------------------------------------------------- stop: dw 1 ; stop bits parity: dw 'N' ; parity data: dw 8 ; data bits brate: dw 5 ; baud rate: ;-------------------------------------------------------------------------- ;Values of brate for each baud rate ; ; baud rate brate ; ; 110 0 ; 300 1 ; 450 2 ; 600 3 ; 710 4 ; 1200 5 ; 2400 6 ; 4800 7 ; 9600 8 ; 19200 9 ; 38400 10 ; 57600 11 ; 76800 12 ; ; ; Set the port. ZMP supplies either 0 or 1 as a parameter. ; setport: ld hl,2 ; get port number add hl,sp ex de,hl call getparm ; in HL (values are 0 and 1) ; <== Insert your own code here ; <== End of your own code ret ;**************************************************************************** ;Video terminal sequences: these are for ADM-3A: Modify as you wish ;Cursor addressing: cursadd: ld hl,2 ; get parameters add hl,sp ex de,hl call getparm ; in HL ld (row),hl ; row call getparm ld (col),hl ; column ; <== Insert your own code here ; using values in row and col call print db esc,'=',0 ; ADM-3A leadin ld a,(row) ; row first add a,' ' ; add offset call cout ld a,(col) ; sane for column add a,' ' call cout ; <== end of your own code ret row: ds 2 ; row col: ds 2 ; column ;clear screen: cls: call print db 01ah,0 ret ;inverse video on: invon: call print db esc,')',0 ret ;inverse video off: invoff: call print db esc,'(',0 ret ;turn off cursor: hide: call print db esc,'`0',0 ; wyse 50 cursor off ret ;turn on cursor: show: call print db esc,'`1',0 ; wyse 50 cursor on ret ;save cursor position: savecu: ret ;restore cursor position: rescu: ret ;**************************************************************************** ;Service modem interrupt: mint: ret ; my system doesn't need this ;Initialise interrupt vectors: invec: ret ; ditto ;De-initialise interrupt vectors: dinvec: ret ; ditto ;****************** End of user-defined code ******************************** ; Do not change anything below here. ;Modem character test for 100 ms mrd: push bc ; save bc ld bc,100 ; set limit mrd1: call mirdy ; char at modem? jr nz,mrd2 ; yes, exit ld hl,1 ; else wait 1ms call waithlms dec bc ; loop till done ld a,b or c jr nz,mrd1 ld hl,0 ; none there, result=0 xor a mrd2: pop bc ret ; Inline print routine: destroys A and HL print: ex (sp),hl ; get address of string ploop: ld a,(hl) ; get next inc hl ; bump pointer or a ; done if zero jr z,pdone call cout ; else print jr ploop ; and loop pdone: ex (sp),hl ; restore return address ret ; and quit ; ;Output a character in A to the console ; cout: push bc ; save regs push de push hl ld e,a ; character to E ld c,2 call bdos ; print it pop hl pop de pop bc ret ;Wait(seconds) wait: ld hl,2 add hl,sp ex de,hl ; get delay size call getparm ; fall thru to.. ;Wait seconds in HL waithls: push bc ; save bc push de ; de push ix ; and ix ld ix,0 ; then point ix to 0 ; so we don't upset memory-mapped i/o ;Calculate values for loop constants. Need to have two loops to avoid ; 16-bit overflow with clock speeds above 9 MHz. outerval equ (clkspd / 10) + 1 innerval equ (6667 / outerval) * clkspd wait10: ld b,outerval wait11: ld de,innerval wait12: bit 0,(ix) ; time-wasters bit 0,(ix) bit 0,(ix) ; 20 T-states each bit 0,(ix) bit 0,(ix) bit 0,(ix) dec de ld a,e ld a,d or e jr nz,wait12 ; 150 T-states per inner loop djnz wait11 ; decrement outer loop dec hl ; ok, decrement count in hl ld a,h or l jr nz,wait10 pop ix ; done -- restore ix pop de ; de pop bc ; and bc ret ;Wait milliseconds mswait: ld hl,2 add hl,sp ex de,hl ; get delay size call getparm ; fall thru to.. ;Wait milliseconds in HL waithlms: push de w1ms0: ld de,39 * clkspd w1ms1: dec de ld a,d or e jr nz,w1ms1 dec hl ld a,h or l jr nz,w1ms0 pop de ret ;Get next parameter from (de) into hl getparm: ex de,hl ; get address into hl ld e,(hl) ; get lo inc hl ld d,(hl) ; then hi inc hl ; bump for next ex de,hl ; result in hl, address still in de ret ;Get address of user-defined variables getvars: ld hl,uservars ret uservars: dw overdrive ; .OVR etc. drive/user dw overuser if ($ - codebgn) gt ovsize toobig: jp errval ; Overlay too large! endif end