From 43914c45c183eb7f17e6aab409f327b3255706c5 Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Mon, 23 Aug 2021 22:58:06 +0800 Subject: [PATCH] Initial mecparts zmodem release No linux makefile --- Source/Apps/Build.cmd | 1 + Source/Apps/ZMODEM/Build.cmd | 18 + Source/Apps/ZMODEM/Clean.cmd | 7 + Source/Apps/ZMODEM/zmconfig.ovr | Bin 0 -> 12288 bytes Source/Apps/ZMODEM/zminit.ovr | Bin 0 -> 5120 bytes Source/Apps/ZMODEM/zmo-rw01.z80 | 862 ++++++++++++++++++++++++++++++++ Source/Apps/ZMODEM/zmp-blnk.z80 | 573 +++++++++++++++++++++ Source/Apps/ZMODEM/zmp-ovl.upd | 256 ++++++++++ Source/Apps/ZMODEM/zmp.cfg | 24 + Source/Apps/ZMODEM/zmp.doc | 389 ++++++++++++++ Source/Apps/ZMODEM/zmp.fon | 21 + Source/Apps/ZMODEM/zmp.for | 13 + Source/Apps/ZMODEM/zmp.hlp | 20 + Source/Apps/ZMODEM/zmp15+-.new | 29 ++ Source/Apps/ZMODEM/zmterm.ovr | Bin 0 -> 16256 bytes Source/Apps/ZMODEM/zmxfer.ovr | Bin 0 -> 19072 bytes Source/HBIOS/uf.asm | 9 +- 17 files changed, 2218 insertions(+), 4 deletions(-) create mode 100644 Source/Apps/ZMODEM/Build.cmd create mode 100644 Source/Apps/ZMODEM/Clean.cmd create mode 100644 Source/Apps/ZMODEM/zmconfig.ovr create mode 100644 Source/Apps/ZMODEM/zminit.ovr create mode 100644 Source/Apps/ZMODEM/zmo-rw01.z80 create mode 100644 Source/Apps/ZMODEM/zmp-blnk.z80 create mode 100644 Source/Apps/ZMODEM/zmp-ovl.upd create mode 100644 Source/Apps/ZMODEM/zmp.cfg create mode 100644 Source/Apps/ZMODEM/zmp.doc create mode 100644 Source/Apps/ZMODEM/zmp.fon create mode 100644 Source/Apps/ZMODEM/zmp.for create mode 100644 Source/Apps/ZMODEM/zmp.hlp create mode 100644 Source/Apps/ZMODEM/zmp15+-.new create mode 100644 Source/Apps/ZMODEM/zmterm.ovr create mode 100644 Source/Apps/ZMODEM/zmxfer.ovr diff --git a/Source/Apps/Build.cmd b/Source/Apps/Build.cmd index 48a858ae..87038f2e 100644 --- a/Source/Apps/Build.cmd +++ b/Source/Apps/Build.cmd @@ -35,6 +35,7 @@ pushd Tune && call Build || exit /b & popd pushd FAT && call Build || exit /b & popd pushd I2C && call Build || exit /b & popd pushd ramtest && call Build || exit /b & popd +pushd zmodem && call Build || exit /b & popd copy *.com %APPBIN%\ || exit /b diff --git a/Source/Apps/ZMODEM/Build.cmd b/Source/Apps/ZMODEM/Build.cmd new file mode 100644 index 00000000..7063e7f3 --- /dev/null +++ b/Source/Apps/ZMODEM/Build.cmd @@ -0,0 +1,18 @@ +@echo off +setlocal + +set TOOLS=..\..\..\Tools + +set PATH=%TOOLS%\zx;%PATH% + +set ZXBINDIR=%TOOLS%\cpm\bin\ +set ZXLIBDIR=%TOOLS%\cpm\lib\ +set ZXINCDIR=%TOOLS%\cpm\include\ + +zx Z80ASM -ZMO-RW01/H || exit /b +zx MLOAD25 -ZMP.COM=ZMPX.COM,ZMO-RW01 || exit /b + +copy /Y zmp.com ..\..\..\Binary\Apps\ || exit /b +copy /Y *.ovr ..\..\..\Binary\Apps\ || exit /b +copy /Y *.hlp ..\..\..\Binary\Apps\ || exit /b +copy /Y zmp.doc ..\..\..\Doc\ || exit /b \ No newline at end of file diff --git a/Source/Apps/ZMODEM/Clean.cmd b/Source/Apps/ZMODEM/Clean.cmd new file mode 100644 index 00000000..161b365c --- /dev/null +++ b/Source/Apps/ZMODEM/Clean.cmd @@ -0,0 +1,7 @@ +@echo off +setlocal + +if exist zmp.com del zmp.com +if exist *.hex del *.hex +if exist *.lst del *.lst +if exist *.zip del *.zip diff --git a/Source/Apps/ZMODEM/zmconfig.ovr b/Source/Apps/ZMODEM/zmconfig.ovr new file mode 100644 index 0000000000000000000000000000000000000000..556170c11072e28fcfc927d40b06f2ac8d0992b7 GIT binary patch literal 12288 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 U`^PEP_jbO;DN=QMS(*9#7Y>k2LjV8( literal 0 HcmV?d00001 diff --git a/Source/Apps/ZMODEM/zmo-rw01.z80 b/Source/Apps/ZMODEM/zmo-rw01.z80 new file mode 100644 index 00000000..b2b8af4b --- /dev/null +++ b/Source/Apps/ZMODEM/zmo-rw01.z80 @@ -0,0 +1,862 @@ +;----------------------------------------------------------------------------- +; +; Overlay for ZMP (Z-Modem Program) +; +; Name ZMO-RW01.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 +; Modified to ZMP v1.5 standard rjm 25/3/89 +; +; ZMO-RW01.Z80 ROMWBW version using HBIOS and https://github.com/mecparts/zmp version of zmodem +; Databits, stop bit, parity setting not supported. +; All i/o is through the hbios. +; Timing delay calcuations based on hbios reported cpu speed. +; Console is assumed to be current hbios CIO console +; Only 1 port is supported by this version of zmp. +; Port setting supports 2 port, port A is CIO 1, port B is CIO 2 +; This overlay is compatible with Ron Murray's original ZMP15 which support two ports. +; Teraterm users may need to change the ZmodemWinSize value to 1024 in teraterm.ini file. +; +;----------------------------------------------------------------------------- +; +; +; 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: + +;clkspd equ 10 ; Processor clock speed in MHz +debug equ false ; to allow debugging of overlay with Z8E etc. + +;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 0 ; Drive to find overlay files on ('A'-'P') +overuser equ 0 ; User area to find files +; +; Initial ROMWBW CIO device +; +initdev equ 1 ; Second CIO device on system +; +; Initial baud rate code +; +initbr equ 10 ; Refer to "baudtbl" table below - brate column +; +;------------------------------------------------------------------------------ + + +; 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 + + .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 +; +; Get the cpu speed reported by romwbw hbios and calculate +; the three required loop counter values for timing. +; +; outerva (outv) +; innerval (inv) +; millisv (msv) + +userin: + ld a,-1 ; force re-init + ld (mspeed),a + + push bc + ld bc,0f8f0h ; get clock speed in l + rst 08 +; +; outerval equ (clkspd / 10) + 1 +; + push hl ; save clock speed + ld h,0 + ld c,10 + call div_hl_c ; result in hl + ld a,l + inc a + ld (outv),a +; +; innerval equ (6667 / outerval) * clkspd +; + ld c,a + ld hl,6667 + call div_hl_c ; result in hl +; + ex de,hl + pop hl ; recall clock + ld a,l ; save + push af ; clock speed + + call mult_a_de + ld (inv),hl + +; +; ld de,39 * clkspd +; + pop af ; recall clock speed + ld de,39 + call mult_a_de + ld (msv),hl +; + pop bc + ret + +outv: ds 1 ; outer value +inv: ds 2 ; inner value +msv: ds 2 ; millisec value +; +; maths helpers +; +mult_a_de: ; https://wikiti.brandonw.net/index.php?title=Z80_Routines:Math:Multiplication + ld c, 0 + ld h, c + ld l, h + add a, a ; optimised 1st iteration + jr nc,$+4 + ld h,d + ld l,e + ld b,7 +_loop2: + add hl,hl + rla + jr nc,$+4 + add hl,de + adc a,c + djnz _loop2 ; result in ahl + ret +; +div_hl_c: ; https://wikiti.brandonw.net/index.php?title=Z80_Routines:Math:Division + xor a + ld b,16 +_loop1: + add hl, hl + rla + jr c,$+5 + cp c + jr c,$+4 + sub c + inc l + djnz _loop1 ; result in hl + ret + +; User-defined exit routine: leave empty if not needed +userout: + + ret + + +;Get a character from the modem: return in HL +mchin: + push bc + ; <== Insert your own code here + push de + ld b,00h + ld hl,port + ld c,(hl) + rst 08 + + ld a,e + pop de + ; <== 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 + ld e,a + ld b,01h + ld hl,port + ld c,(hl) + rst 08 + ; <== End of your own code + ret ; done + +;Test for output ready: return TRUE (1) in HL if ok +mordy: + ; <== Insert your own code here + ld b,03h + ld hl,port + ld c,(hl) + rst 08 + ld h,0 + or a + jr z,modrdy1 + ld a,1 +modrdy1: + ld l,a + ; <== 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 + push bc + ld b,02h + ld hl,port + ld c,(hl) + rst 08 + or a + jr z,mirdy1 + ld a,1 +mirdy1: + ld l,a + ld h,0 + pop bc + + ; <== 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 hl,300 ; wait 300 mS + call waithlms + + ; <== End of your own code + ret +; +;Test UART flags for error: return TRUE (1) in HL if error. +mdmerr: + ; <== Insert your own code here + ld hl,0 + + ; <== End of your own code + ld a,l ; set/clear Z + or a + ret + + + +;Turn DTR ON +dtron: + ; <== Insert your own code here + + ; <== End of your own code + ret + + + +;Turn DTR OFF +dtroff: + ; <== Insert your own code here + + + ; <== 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 + call print + db cr,lf,cr,lf,'Initializing CIO device ...',cr,lf,0 + + ld a,(port) ; get device type + ld c,a + ld b,06h + rst 08 + or a ; check if valid + jr nz,initerr + + ld a,(brate) ; get baud rate to set + ld c,a + ld b,0 + ld hl,baudtbl + add hl,bc + ld a,(hl) ; convert to encoded hbios + cp a,-1 + jr z,initerr + + push af + ld a,(port) ; get line characteristics + ld c,a + ld b,05h + rst 08 + ld a,d ; mask out exisitng + and 11100000b ; replace with rate + ld d,a + pop af + or d + ld d,a + + ld b,04h ; set new + ld a,(port) ; speed + ld c,a + rst 08 + or a + jr nz,initerr + + call print + db 'CIO device initialized: ',0 + ld a,(port) + add a,'0'-1 + call cout + call print + db cr,lf,0 + + ld a,(brate) + ld (mspeed),a ; don't forget to load mspeed with the + ; current brate value if the new rate is + ; valid. See table of values below. + ; <== End of your own code + ret +initerr: + call print + db 'Unable to initialize CIO device: ',0 + ld a,(port) + add a,'0'-1 + call cout + call print + db cr,lf,0 + + ret + +;-------------------------------------------------------------------------- +stop: dw 1 ; stop bits +parity: dw 'N' ; parity +data: dw 8 ; data bits +brate: dw initbr ; baud rate: +;-------------------------------------------------------------------------- +;Values of brate for each baud rate +; +; hb encode baud rate brate +; +baudtbl: + db -1 ; 110 0 not supported + db 2 ; 300 1 + db 17 ; 450 2 + db 3 ; 600 3 + db -1 ; 710 4 not supported + db 4 ; 1200 5 + db 5 ; 2400 6 + db 6 ; 4800 7 + db 7 ; 9600 8 + db 8 ; 19200 9 + db 9 ; 38400 10 + db 24 ; 57600 11 + db 10 ; 76800 12 + +; +; Set the port. ZMP supplies either 0 or 1 as a parameter. You're on your +; own here -- your system is bound to be different from any other! You may +; implement a software switch on all the modem-dependent routines, or perhaps +; you can have one or two centralised routines for accessing the UARTs and +; modify the code from this routine to select one or the other. (Who said +; there was anything wrong with self-modifying code?). If you have only one +; UART port, or if you don't want to go through all the hassles, just have +; this routine returning with no changes made. Note that ZMP calls this +; routine with both values for the port on initialisation. +; +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 + + inc l ; l = cio 1 or cio 2 + push hl + ld b,06h ; test if a valid cio + ld c,l + rst 08 + pop hl + or a + ld a,l + ld (port),a + jr nz,seterr + push hl + call print + db 'Setting CIO device: ',0 + pop hl + + ld a,l + add a,'0'-1 + call cout + call print + db cr,lf,0 + ret +seterr: + push hl + call print + db 'Unable to set CIO device: ',0 + pop hl + ld a,l + add a,'0'-1 + call cout + call print + db cr,lf,0 + ; <== End of your own code + ret + +port: db initdev ; zmp port 0 = cio 1, zmp port 1 = cio 2 + +;**************************************************************************** +;Video terminal sequences: these are for VT-100: Modify as you wish +;Cursor addressing: +cursadd: + ld hl,2 ; get parameters + add hl,sp + ex de,hl + call getparm ; in HL + inc hl + ld (row),hl ; row + call getparm + inc hl + ld (col),hl ; column + ; <== Insert your own code here + ; using values in row and col + call print + db esc,'[',0 + ld a,(row) ; row first + call cursconv + ld a,';' + call cout + ld a,(col) ; same for column + call cursconv + ld a,'H' + call cout + ; <== end of your own code + ret + +cursconv: + ld b,a + xor a +ca1: + add a,1 + daa + djnz ca1 + ld (num),a + and 0f0h + jr z,ca2 + srl a + srl a + srl a + srl a + or '0' + call cout +ca2: + ld a,(num) + and 0fh + or '0' + call cout + ret + +row: ds 2 ; row +col: ds 2 ; column +num: ds 1 + +;Clear screen: +cls: + call print + db esc,"[H",esc,"[2J",0 + ret + +;Inverse video on: +invon: + call print + db esc,"[7m",0 + ret + +;Inverse video off: +invoff: + call print + db esc,"[m",0 + ret + +;Turn off cursor: +hide: + call print + db esc,'[?25l',0 + ret + +;Turn on cursor: +show: + call print + db esc,'.3',0 + ret + +;Save cursor position: +savecu: + call print + db esc,'[7',0 + ret + +;Restore cursor position: +rescu: + call print + db esc,'[8',0 + 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 +; Display A in hex +prthexbyte: + push af + push de + call hexascii + ld a,d + call cout + ld a,e + call cout + pop de + pop af + ret + +hexascii: + ld d,a + call hexconv + ld e,a + ld a,d + rlca + rlca + rlca + rlca + call hexconv + ld d,a + ret + +hexconv: + and 0fh + add a,90h + daa + adc a,40h + daa + ret + +;****************** 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 + ld b,01h + ld c,80h + ld e,a + rst 08 + 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 a,(outv) ; was ld b,outerval + ld b,a +wait11: + ld de,(inv) ; was 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,(msv) ; was 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 + \ No newline at end of file diff --git a/Source/Apps/ZMODEM/zmp-blnk.z80 b/Source/Apps/ZMODEM/zmp-blnk.z80 new file mode 100644 index 00000000..9cd1ba0b --- /dev/null +++ b/Source/Apps/ZMODEM/zmp-blnk.z80 @@ -0,0 +1,573 @@ +;----------------------------------------------------------------------------- +; +; 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 +; Modified to ZMP v1.5 standard rjm 25/3/89 +; +; +;----------------------------------------------------------------------------- +; +; +; 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: + +clkspd equ 4 ; Processor clock speed in MHz +debug equ false ; to allow debugging of overlay with Z8E etc. + +;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 'A' ; Drive to find overlay files on ('A'-'P') +overuser equ 0 ; 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 + + .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 +userin: + ret + +; User-defined exit routine: leave empty if not needed +userout: + ret + + +;Get a character from the modem: return in HL +mchin: + push bc + ; <== Insert your own code here + + + ; <== 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 + + + ; <== End of your own code + ret ; done + +;Test for output ready: return TRUE (1) in HL if ok +mordy: + ; <== Insert your own code here + + ; <== 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 + + + ; <== 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 hl,300 ; wait 300 mS + call waithlms + + ; <== End of your own code + ret +; +;Test UART flags for error: return TRUE (1) in HL if error. +mdmerr: + ; <== Insert your own code here + + ; <== End of your own code + ld a,l ; set/clear Z + or a + ret + + + +;Turn DTR ON +dtron: + ; <== Insert your own code here + + ; <== End of your own code + ret + + + +;Turn DTR OFF +dtroff: + ; <== Insert your own code here + + + ; <== 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 + ld (mspeed),a ; don't forget to load mspeed with the + ; current brate value if the new rate is + ; valid. See table of values below. + ; <== End of your own code + ret +;-------------------------------------------------------------------------- + +stop: dw 1 ; stop bits +parity: dw 'N' ; parity +data: dw 8 ; data bits +brate: dw 7 ; 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. You're on your +; own here -- your system is bound to be different from any other! You may +; implement a software switch on all the modem-dependent routines, or perhaps +; you can have one or two centralised routines for accessing the UARTs and +; modify the code from this routine to select one or the other. (Who said +; there was anything wrong with self-modifying code?). If you have only one +; UART port, or if you don't want to go through all the hassles, just have +; this routine returning with no changes made. Note that ZMP calls this +; routine with both values for the port on initialisation. +; +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 + +port: ds 1 + + +;**************************************************************************** +;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 1ah,0 + ret + +;Inverse video on: +invon: + call print + db esc,'G4',0 + ret + +;Inverse video off: +invoff: + call print + db esc,'G0',0 + ret + +;Turn off cursor: +hide: + call print + db esc,'.1',0 + ret + +;Turn on cursor: +show: + call print + db esc,'.3',0 + 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 + \ No newline at end of file diff --git a/Source/Apps/ZMODEM/zmp-ovl.upd b/Source/Apps/ZMODEM/zmp-ovl.upd new file mode 100644 index 00000000..b2da16ec --- /dev/null +++ b/Source/Apps/ZMODEM/zmp-ovl.upd @@ -0,0 +1,256 @@ + ZMP Overlay Update Information + + This file contains information on updating ZMP overlays designed for +previous versions to the current version. Newer versions appear first in +this file. + +Updates to ZMP14 Overlays for use with ZMP15. +--------------------------------------------- + + The changes required here are associated with ZMP15's ability to access +either of two UART ports, if available on the specific machine. One entry +needs to be added to the jump table, and an extra routine needs to be added +to set which port is in use. Lines which must be added to the overlay have +an asterisk at the beginning. + +1. Add an entry to the jump table. + + Add the following instruction at the end of the jump table, after the +'jp getvars' instruction and before the spare jumps: + +* jp setport ; Set the modem port being used + +2. Add the setport routine. + + The following routine should be added into the code. A good place is +immediately following the UART init code. + +*; +*; Set the port. ZMP supplies either 0 or 1 as a parameter. You're on your +*; own here -- your system is bound to be different from any other! You may +*; implement a software switch on all the modem-dependent routines, or perhaps +*; you can have one or two centralised routines for accessing the UARTs and +*; modify the code from this routine to select one or the other. (Who said +*; there was anything wrong with self-modifying code?). If you have only one +*; UART port, or if you don't want to go through all the hassles, just have +*; this routine returning with no changes made. Note that ZMP calls this +*; routine twice -- once for each port value -- on initialisation. +*; +*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 +* +*port: ds 1 +* + +End of changes ZMP14 --> ZMP15. + + -- Ron Murray + 25/3/89 + +=============================================================================== + +Updates to ZMP13 Overlays for use with ZMP14. +--------------------------------------------- + + Some changes need to be made to accommodate the user-specification +of drive/user area for the .OVR files. Changes need to be made in three +places in your overlay (asterisks at the start of lines indicate which lines +should be added): + +1. Specify the required drive/user area. + + Add the following section after the mspeed equate: + +*;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 'A' ; Drive to find overlay files on ('A'-'P') +*overuser equ 0 ; User area to find files + +2. Add to the jump table + + Add the following instruction at the end of the jump table, after the +'jp userout' instruction and before the spare jumps: + +* jp getvars ; get system variables + + +3. Add code at the end to get the system variables: + + Add the following code just in front of the overlay size test: + +*;Get address of user-defined variables +* +*getvars: +* ld hl,uservars +* ret +* +*uservars: +* dw overdrive ; .OVR etc. drive/user +* dw overuser +* + +End of ZMP14 overlay modifications. + + -- Ron Murray, 20/11/88 + +=============================================================================== + +Updates to ZMP12 Overlays for use with ZMP13. +--------------------------------------------- + + There have been very few changes made to the overlay structure in ZMP13. +Some shuffling of module orders has allowed the origin to be set at 0145 hex, +and here it should stay (unless I fiddle with the startup code -- MOST +unlikely!). So, set your 'userdef' equate to 0145h and you should be able to +leave it there. + There is also a bug fix which should be installed in all overlays. + +1. Fix a bug in the wait routines + + Two routines in the user overlays are misnamed. You would expect wait1s +to pause for one second, and wait1ms to pause for one millisecond, wouldn't +you? Well they don't. Blame it on a lack of sleep on my part. They actually +pause for a number of seconds (milliseconds) in hl. I suggest renaming them +to waithls amd waithlms. The main consequence of this has been the pause in +the middle of the 'send break' routine: there was originally a ld hl, 1 before +the call to wait1s, but it got lost somewhere along the way. In any case, one +second is probably too long for this, and I suggest you change it to + + ld hl, 300 ; wait 300 mS + call waithlms + + There are two faults in the waithls (formerly wait1s) routine. The first +is a misplaced jr instruction that caused waits of more than 1 second to be +much longer than intended. The other concerns z80 machines with a clock speed +greater than 9 MHz: these will cause 16-bit overflow in the ld de,6667 +instruction. (It had never occurred to me that anyone would have a z80 running +at this speed!). Both these faults can be solved by replacing the whole +waithls routine with the following: + +;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 + +; End of changes to waithls routine + + The remaining changes concern baud rates. Firstly, ZMP13 will reject a +selected baud rate if the machine is not capable of it. It does this by +determining if the value in mspeed (location 3c hex) has changed. Thus if +you modify your overlay to only change 003ch (mspeed) if the new baud rate +is valid, then incorrect baud rates cannot be selected. No code is given for +this as all overlays are different. Note that the only penalty for not making +this change is that all baud rates are accepted, whether valid or not. Older +overlays always set mspeed to the new value. + In response to numerous requests (well, actually, two), ZMP13 will accept +speeds of 38400, 57600 and 76800 baud. This means that it accepts the numbers +for these -- mspeed values are 10, 11 and 12 respectively. If you think that +you can get your machine to actually work at these speeds, then go ahead. But +don't blame me if it doesn't work. (Personally, I doubt if successful +transfers in both directions with a 4 MHz machine can be done at much over +4800 baud. But don't let me stop you.) + + -- Ron Murray + 11/10/88 + + +End of changes ZMP12 --> ZMP13 +=============================================================================== + +Updates to ZMP11 Overlays for ZMP12. +------------------------------------ + + Some additions to the jump table have been made to allow for user-defined +routines to be executed on entry/exit from ZMP. Modify your overlay as +follows: + +1. Adding to the jump table + + Add the following code to the end of the jump table after the line: + + jp mswait ; wait milliseconds (Last entry of old table) + +==> Insert this stuff + jp userin ; user-defined entry routine + jp userout ; user-defined exit routine + +;Spare jumps for compatibility with future versions + jp spare ; spares for later use + jp spare ; spares for later use + jp spare ; spares for later use + jp spare ; spares for later use + jp spare ; spares for later use +==> End of inserted jump codes + +2. Adding the 'spare' code + + The following code can be added anywhere. A good idea is to put the +'spare:' label in front of an existing ret instruction. + +spare: + ret + +3. Adding the user routines + + Add the following code to your overlay. Anywhere will do. The code +you put in here depends on what you want to do. + +;User-defined entry routine: leave empty if not used +userin: + ret + +;User-defined exit routine: leave empty if not used +userout: + ret + +End of changes ZMP11 --> ZMP12 +=============================================================================== + + \ No newline at end of file diff --git a/Source/Apps/ZMODEM/zmp.cfg b/Source/Apps/ZMODEM/zmp.cfg new file mode 100644 index 00000000..1f2b0ffb --- /dev/null +++ b/Source/Apps/ZMODEM/zmp.cfg @@ -0,0 +1,24 @@ +1 1 0 0 0 360 + + + + + + + + + + +AT! +ATV1Q0DT +! +CONNECT +BUSY +NO CARRIER +NO ANSWER +ERROR +~+++~~ATH! +15 30 +5 N 8 1 +1400 512 F 5 50 + diff --git a/Source/Apps/ZMODEM/zmp.doc b/Source/Apps/ZMODEM/zmp.doc new file mode 100644 index 00000000..aeb5383e --- /dev/null +++ b/Source/Apps/ZMODEM/zmp.doc @@ -0,0 +1,389 @@ + ** ZMP Documentation ** + +1. Introduction. + + ZMP is a communications/file transfer program for CP/M which +performs Xmodem, Xmodem-1k (often erroneously called Ymodem), +true Ymodem and Zmodem file transfer protocols. Although tested +with Z80DOS, ZRDOS and CP/M 2.2, there seems to be no reason why +it shouldn't work with CP/M 3 as well. The only requirements are +a Z80 processor (sorry about that!), a computer running CP/M in +one of its various guises, with at least 45k of TPA (but the more +the better!), and a modem. + When you try to pack this many features into one program, +you end up with a pretty large file. The big problem occurs when +file transfers are attempted: unless you have at least 4-8k of +buffer size, you might as well use xmodem protocol. The approach +taken in ZMP is to use overlays for various functions, accepting +the time taken to load these from disk. Thus performance will +vary depending on your disk setup: if you have a hard disk and a +fast processor you will likely not notice the difference. If, on +the other hand, you are running a Commodore 128 with CP/M on a +1571 drive, there is no physical reason why ZMP won't work, but +you might consider investing in a book to read while the overlays +load. (A suitable book to read might be a computer catalogue!). + The curious amongst you may notice that the beginning of the +ZMPX.COM file has the magic 'Z3ENV' string, but don't let this +fool you into thinking that you don't need to add terminal +characteristics into the overlay if you have a ZCPR3 system. It +has proved possible to persuade this particular C compiler to +access ZCPR3's environment descriptor, but not for ZMP. Yet. +Perhaps later. In the meantime, the startup code is there for it. + In order to produce a program which would work with most +CP/M systems, the Zmodem protocol performed by ZMP is fairly +simple. The transmit section uses 'Full Streaming with Reverse +Interrupt', as Chuck Forsberg calls it in his description of the +Zmodem protocol. The receive section uses 'Segmented Streaming'. +This means that, if your system can do serial I/O and disk I/O at +the same time, ZMP does not take advantage of the faster transfer +rate which this capability provides. Since, however, I can't +write and listen at the same time, and neither can my computer, +and neither can the vast majority of CP/M computers, it seemed +the best approach to take. Segmented Streaming means that the +receive program tells the transmit program how big its buffer is. +The transmit program then sends just that much data, then waits +for an acknowledge from the receiver. We have encountered some +Zmodem programs which send too much data in this case: errors +will appear if this happens, but the protocol should recover and +the file will be received intact (we hope!). + The string which ZMP passes to the receiving program to +interrupt in case of errors is likewise simple. Basically it +causes the receiving program to send a control-C character and +then wait for one second. The receiver will then send its ZRPOS +string, by which time ZMP, as the transmitter, should be ready to +receive it. + + +2. Customisation. + + ZMP must be customised to suit your system. This involves +overlaying the un-installed copy of ZMP.COM (contained in this +library as ZMPX.COM) with a user-written installation overlay. +Some hints on writing this are given below; there is a blank +overlay file in this library, or you may be able to obtain one +for your computer from the same place you got this library. +This value is set at 0145 hex, and should stay there permanently. +See the notes in this document, and also the ZMP-OVL.UPD file, +for more details on how to set up your overlay. + Once the installation overlay is written, assemble it with +M80 (or SLR or whatever), use RELHEX to create a .HEX file, and +use MLOAD to overlay it over the ZMPX.COM file to produce your +very own ZMP.COM. + +3. Operation. + + The following files must be on the same disk and user area, +which must be specified in your customisation overlay: + + ZMCONFIG.OVR -- the configuration overlay + ZMINIT.OVR -- the initialisation overlay + ZMTERM.OVR -- the terminal overlay + ZMXFER.OVR -- the file transfer overlay + ZMP.HLP -- the help file (recommended). + + Start the program with ZMP. The screen should clear, then a +title message is printed, then ZMP enters terminal mode. You may +type escape-H for help at this point. When you first run the +program, the first thing you need to do is to enter the +configuration overlay (type escape-C) and set all the defaults +and others to suit your system as required. If you don't know +whether to change something or not, it's probably better to leave +it alone. When you exit the configuration program, answer 'Y' to +the 'Make changes permanent' question. ZMP.FON and ZMP.CFG will +be produced on your disk, in the same drive/user area as the +above files. + + Operation of the program is controlled by escape sequences +entered in terminal mode. Escape-H gives you a list of options. +Most of these are self-explanatory, but they will be summarized +here. + +B - Send Break to modem. + If your overlay has been set up to send a break command + to your UART, this command will perform this function. (Some + remote systems may require a break sent to them to interrupt + Zmodem transfers). + +C - Configure system. + This function is designed to set system defaults, save + phone numbers etc. Changing baud rates etc. for a particular + call are better handled with the escape-L option. If you + answer Y or y to the 'make changes permanent?' question, the + new configuration will be saved in a ZMP.CFG file, and the + phone numbers in a ZMP.FON file for later use. The .CFG file + is read, if it exists, when ZMP is first started. + +D - Get disk Directory. + Gets a directory of the current drive and user area. + Change to another with the escape-F command, described + below. The directory will be sorted and will include + filesizes unless you have so many files on the current + drive/user area that there is insufficient memory available + to sort them. In this case an unsorted directory, without + file sizes, will be printed. + +F - Disk/File operations. + This command is used to change the current drive/user + area, to reset a disk in the current drive, and to view, + erase, print or rename files. There are also options to give + a directory of the current drive/user area, and to supply a + new filename for the capture file. This filename may specify + a different drive/user area than the current one. If capture + mode is on, the status line printed when terminal mode is + entered will state the capture file name. + +H - Get Help. + Prints the ZMP.HLP file. You may then either type CR to + return to terminal mode, or enter the required function key. + +I - Initiate phone call. + Reads the ZMP.FON file, if any, and prints it. You have + four seconds after typing ESC I, during which you may enter + the letter corresponding to the required number, in which + case ZMP will dial it without printing a list. Otherwise the + full phone list will be printed, and you will be asked which + number you want. Enter the identifying letter of the number + you wish to call. You can also enter numbers not in the + list. Multiple numbers can be called by entering them separ- + ated with commas. Dialling will then commence, and will + continue until one of the numbers answers, or until you + abort the process with the escape key. Note that the baud + rate used for the call is that in the .FON file for that + number, or the current one if a new number is entered. This + function works best if the strings in the .CFG file have + been set up for your modem, and the initialisation string + sent to the modem sets it into verbose mode for status + messages (ATV1). + +K - Display Keyboard macros. + The configuration option allows up to ten macro keys to + be defined, and these are recalled by typing escape followed + by the numbers 0 to 9. This function prints the current + assignments. + +L - Change Line settings. + This function allows temporary changes of baud rate, + stop bits, and data bits. There is also an option to operate + terminal mode in full duplex (locally typed characters are + sent but not displayed on the screen), half duplex (locally + typed characters are sent and also displayed on the screen), + or echo mode (as for half duplex, but received characters + are echoed to the remote system as well as being displayed). + Don't have two computers talking to each other in echo mode + unless you're bored. There are also options to allow/dis- + allow control characters above CR to be displayed in term- + inal mode, to strip the parity bit in terminal mode, and to + re-initialise the currently selected UART and modem at the + current baud rate. + Like IMP, ZMP uses location 003C hex to store a value + corresponding to the present baud rate. Then, if you leave + ZMP and later re-enter, it checks location 003C. If it + contains a legal value, then that baud rate is set for you, + otherwise it sets the default baud rate as selected in the + .CFG file. + +M - Toggle capture mode in Memory. + Received characters will be saved in a buffer and saved + in a file named 'ZMP.LOG' when the buffer fills or when the + command is entered again. A control-S/control-Q sequence is + sent to the remote computer while the buffer is being saved + in an attempt to stop it sending more data. + +P - Toggle Printer. + This is similar to the 'M' command, except incoming + characters are sent to the printer. This functions best if + your system performs the BIOS 'List Status' function + correctly. + +Q - Quit the program. + Obvious. You will be asked if this is really what you + want. Any entry other than N or n will exit to CP/M. + +R - Receive a file. + You will be asked which protocol you wish to use. The + default is ZMODEM. The modem option will allow either + 128-byte blocks (standard XMODEM) or 1k blocks (XMODEM-1k), + since this is decided by the transmit end. If an attempt is + made to receive a file which has the same name as a file on + the current drive/user area, the current one will be renamed + to .BAK and the new one will then be received normally. + (However, see below for the transfer resumption feature in + ZMP v1.5 and above). + Note that the byte count on the screen is not kept up- + to-date on Zmodem receive. This is because the data arrives + non-stop and there is simply no time available with non- + interrupt driven computers to update the screen. An update + is performed if errors occur, and when the computer pauses + to write to the disk. + Starting with version 1.4, Zmodem file receive will + commence automatically upon receipt of the sender's ZRQINIT + string. Thus all you need to do is have the sender initiate + the transfer, select the drive and user area you wish + the file(s) to be received on, and wait.. + ZMP v1.5 adds the ability to resume an interrupted + Zmodem transfer. If a Zmodem receive attempt fails (either + because of manual cancellation or massive errors), you will + be asked if you wish to save the portion of the file already + received. If not, it will be erased. If so, and a subsequent + Zmodem receive attempt would result in a file of the same + name, you are asked if you wish to resume the transfer. If + you do, transfer will start at the end of the file. + Otherwise the old file will be renamed to .BAK as before. + Since this feature is a function of the receiver, it should + work with any Zmodem implementation which conforms + reasonably closely to Chuck Forsberg's standard. It has been + tested with ZMP and RZMP, and I would like to hear of any + programs with which it doesn't work. No attempt is made to + determine if the files are the same up to the commencement + point: the Zmodem protocol provides two ways in which this + may be determined (file date and CRC), but neither has yet + been implemented in ZMP. + +S - Send a file. + Operation is similar to the receive function. + Additional options available are ASCII send and the + capability of distinguishing between normal Xmodem and + Xmodem-1k. In Ymodem and Zmodem modes, wildcard filenames + and multiple filenames are allowed. Multiple filenames + should be entered separated by spaces. In all cases, files + on different drives/user areas may be specified by supplying + a zcpr3-style du: prefix (e.g. C7:NEATPROG.WOW). + Byte count information is displayed in Zmodem mode on + transmit. This causes noticeable breaks between packets, but + it is felt that this is outweighed by the usefulness of the + information. ZMP's Zmodem mode is capable of CRC-32 opera- + tion, although CRC-16 mode is used if the receiver is incap- + able of CRC-32. Some other terminal programs, however, do + strange things when faced with a receiving program which + claims it can do CRC-32 (we have encountered one for the + Amiga which exhibits this problem). If this happens, the + esc-L menu and the configuration overlay have an option to + disable CRC-32. + +X - Hangup. + This function causes the modem to disconnect from the + phone line, by momentarily dropping DTR. + +Y - Print screen. + Allows the current screen to be dumped to printer. Note + that this must be supported in the overlay: most terminals + are incapable of this function. The standard overlay prints + 'This function not supported.'. If you can make it work on + your system, good luck! + +Z - Clear screen. + Allows the screen to be cleared. Useful if it fills + with rubbish. + + +4. Other information. + +a) ZMP at higher baud rates. + When I first produced ZMP, I was more interested in + producing a universal Zmodem program than anything else. + Originally (several C compilers ago!) I had difficulty get- + ting it to work even at 300 baud, and so little thought was + given to accommodate higher transmission speeds. In partic- + ular, there is a "designed-in" bug/feature which would prob- + ably preclude ZMP working at much over 4800 baud. The prob- + lem is in the user overlay, in the mrd: routine. The requ- + irement here is to have a routine which returns either when + a character is available at the modem (in which case we + return TRUE), or 100 mS has elapsed (in which case we return + FALSE). The catch is that I used 100 x 1 mS waits, between + which we test for a character. A little calculation will + show that a 9600 baud character will take a little over 1 mS + to transfer, and 19200 baud characters take half this time. + Thus we are practically guaranteed to miss characters at + 19200 baud, and even 9600 baud characters leave little + processing timeto spare. Two possible ways to overcome this + are: + + i) Make the wait time shorter. Thus we could wait 1000 x + 100 uS periods instead. This, however, makes the actual + wait time more unpredictable, since subroutine + call/return times are comparable to the wait time. It + also just puts off the evil day. + + ii) Use a hardware timer to determine whether 100 mS has + elapsed. This is the preferred approach. Thus the mrd: + routine would loop continuously, exiting when either + there was a character at the modem or when the hardware + timer expired. An embryo CP/M-68K version of ZMP using + this approach has proved capable of reliable transfers + at 19,200 baud (although one must admit that it IS + running a 68010 at 10 MHz!). + + I would like to hear from anyone who has had any + success with either of these two approaches. + +5. Acknowledgements. + + ZMP was developed from Hal Maney's Heath-specific HMODEM II. +I would like to thank Hal for writing HMODEM: CP/M users have +been without ZMODEM capability for far too long. As requested in +the source file, acknowledgement is given to him therein. +Appreciations also go to the authors of the Hi-Tech C compiler, +which proved to be capable of producing fast and compact code for +Z80 machines. + ZMP in its various incarnations is refined by suggestions +from you, the user. In particular, I would like to thank Mike +Allen, Richard Kopplin and Fred Haines for their invaluable +suggestions. I may sometimes be a little slow at implementation, +but I usually get there eventually! Fred Haines has also kindly +offered to be the U.S. collection point for bug reports, +suggestions etc. His address appears at the bottom of this +document, and he'll forward them to me via what he calls 'U.S. +Snail'. I will try and respond using what I call 'Australia +Pest'. + I would also like to thank Lindsay Allen, sysop of Z-Node +62. His name was removed from the original zmp11 title screen at +his own request, since I had done most of the work in modifying +Hmodem to work on other machines. Without Lindsay's encouragement +at difficult times, suggestions as to how to go about +recalcitrant procedures, and experience in file transfers, ZMP +would not have been produced. Thank you. + + +6. Finally... + The files contained in this library are placed in the public +domain. Just don't sell it, claim you wrote it, or do anything +similar that might annoy me. Above all, don't bother trying to +sue me if it doesn't work, or you tripped over the disk, or +anything similar. I haven't distributed the source files partly +due to the size of them, partly due to the fact that compilation +is messy (several modifications were needed to "standard" library +functions!), and partly due to the fact that there's still work +to do on them. Besides, I feel a certain fatherly feeling towards +ZMP, having spent most of my spare time for the last four months +working on it. So here's the deal: I will continue to support ZMP +(and RZMP) until I get sick of it. This could take an unknown +amount of time! At that point, I will release the sources into +the RCP/M community, and you may make of them what you will. + ZMP has a remote system relative, called RZMP. This allows +Zmodem transfers to and from remote systems. It should be +available from the same place from which you obtained ZMP. + I have also produced an extremely cut-down version of ZMP +which runs under CP/M-68K, currently running quite well as a +single .68K file (no overlays!) on a system with 128k bytes of +memory. If there is enough interest from CP/M-68k users (are +there any??), I could be persuaded to upgrade this version to the +point where it could be released. + Comments and suggestions are welcome. Bug reports are not so +welcome, but we'd like them anyway! Send either to: + + Z-Node 62 + Perth, Western Australia + (061+) 09-450-0200 + (Soon to be on FidoNet) + + U.S. users may send reports/comments to: + + Fred Haines, + 733 North King's Road, Apt. 356 + Los Angeles, California 90069 + + -- Ron Murray + 26th March, 1989 +te systems. It should be +available from the same place fr diff --git a/Source/Apps/ZMODEM/zmp.fon b/Source/Apps/ZMODEM/zmp.fon new file mode 100644 index 00000000..3266618f --- /dev/null +++ b/Source/Apps/ZMODEM/zmp.fon @@ -0,0 +1,21 @@ +Virtual Altair altair 8 N 8 1 0 +_________________ _________________ 9 N 8 1 0 +_________________ _________________ 9 N 8 1 0 +_________________ _________________ 9 N 8 1 0 +_________________ _________________ 9 N 8 1 0 +_________________ _________________ 9 N 8 1 0 +_________________ _________________ 9 N 8 1 0 +heatwave heatwave 8 N 8 1 0 +_________________ _________________ 9 N 8 1 0 +_________________ _________________ 9 N 8 1 0 +_________________ _________________ 9 N 8 1 0 +Level 29 bbs.fozztexx.com 8 N 8 1 0 +_________________ _________________ 9 N 8 1 0 +_________________ _________________ 9 N 8 1 0 +_________________ _________________ 9 N 8 1 0 +Particles BBS particles 8 N 8 1 0 +_________________ _________________ 9 N 8 1 0 +_________________ _________________ 9 N 8 1 0 +_________________ _________________ 9 N 8 1 0 +_________________ _________________ 9 N 8 1 0 + diff --git a/Source/Apps/ZMODEM/zmp.for b/Source/Apps/ZMODEM/zmp.for new file mode 100644 index 00000000..18f92615 --- /dev/null +++ b/Source/Apps/ZMODEM/zmp.for @@ -0,0 +1,13 @@ + ZMP is a communications/file transfer program for CP/M which +performs Xmodem, Xmodem-1k (often erroneously called Ymodem), +true Ymodem and Zmodem file transfer protocols. + + This library contains an un-installed ZMP.COM (called +ZMPX.COM) and five .OVR files. There is also a file called +ZMP-OVL.UPD which describes the changes which need to be made to +the user-written overlay to allow it to operate with this version +of ZMP. YOU need to read this one!! + + Details of changes made to this version are in the ZMPxx.NEW +file. + \ No newline at end of file diff --git a/Source/Apps/ZMODEM/zmp.hlp b/Source/Apps/ZMODEM/zmp.hlp new file mode 100644 index 00000000..641ab610 --- /dev/null +++ b/Source/Apps/ZMODEM/zmp.hlp @@ -0,0 +1,20 @@ +Commands: Precede with ESC: + +B Send break to modem +C Configure system +D Get disk directory +F File operations, change/reset disk +H Get instructions +I Initiate phone call (dial) +K Display keyboard macros +L Change line parameters (baud rate, full/half duplex/echo, UART settings) +M Toggle memory capture mode +P Toggle printer +Q Quit +R Receive a file +S Send a file +X Hangup +Y Print screen +Z Clear local screen + + \ No newline at end of file diff --git a/Source/Apps/ZMODEM/zmp15+-.new b/Source/Apps/ZMODEM/zmp15+-.new new file mode 100644 index 00000000..0e027d6b --- /dev/null +++ b/Source/Apps/ZMODEM/zmp15+-.new @@ -0,0 +1,29 @@ + Version 1.5+/- of ZMP now compiles and links with v3.09 of +Hi Tech C and fixes a few things that had niggled at me for +awhile (some, a few decades): + +* Datestamps transferred in Y/Zmodem transfers. +* Fixed long filename conversions on Y/Zmodem transfers. +* Fixed issues displaying baud rate and send times when the + baud rate is > 19.2K. +* Removed superfluous CR sent to the remote end when a + connection was established, which was a pita when connecting to + a Linux box. +* In keyboard macros, ! translates to a CR now, not CR/LF. +* \ escapes ! and ~ so those literal characters can be used in + keyboard macros. +* Long distance access code has been removed. +* Quick dialing letters limited to A-T. + + This version, based on the version of the source code in +ZMP-SRC.LBR, is missing a few things that made it into the later +version in ZMP15.LBR. So, to quote the original author, + +"As always, ensure that you erase your .CFG file and make a +new one with the config option. There have again been changes to +the format of this file." + +June 7, 2021 + +This ROMWBW version is an extract of https://github.com/mecparts/zmp/bin +as at Aug 23rd, 2021. diff --git a/Source/Apps/ZMODEM/zmterm.ovr b/Source/Apps/ZMODEM/zmterm.ovr new file mode 100644 index 0000000000000000000000000000000000000000..ef5b3324280878252c2998a291dedcb7bcb27b13 GIT binary patch literal 16256 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 A0RR91 literal 0 HcmV?d00001 diff --git a/Source/Apps/ZMODEM/zmxfer.ovr b/Source/Apps/ZMODEM/zmxfer.ovr new file mode 100644 index 0000000000000000000000000000000000000000..ff48846575dbcaef44b573baf317ef576ccd2e67 GIT binary patch literal 19072 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