Browse Source

Merge pull request #233 from b1ackmai1er/dev

Initial mecparts zmodem release
pull/246/head
Wayne Warthen 4 years ago
committed by GitHub
parent
commit
17e36df0a0
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      Source/Apps/Build.cmd
  2. 18
      Source/Apps/ZMODEM/Build.cmd
  3. 7
      Source/Apps/ZMODEM/Clean.cmd
  4. BIN
      Source/Apps/ZMODEM/zmconfig.ovr
  5. BIN
      Source/Apps/ZMODEM/zminit.ovr
  6. 862
      Source/Apps/ZMODEM/zmo-rw01.z80
  7. 573
      Source/Apps/ZMODEM/zmp-blnk.z80
  8. 256
      Source/Apps/ZMODEM/zmp-ovl.upd
  9. 24
      Source/Apps/ZMODEM/zmp.cfg
  10. 389
      Source/Apps/ZMODEM/zmp.doc
  11. 21
      Source/Apps/ZMODEM/zmp.fon
  12. 13
      Source/Apps/ZMODEM/zmp.for
  13. 20
      Source/Apps/ZMODEM/zmp.hlp
  14. 29
      Source/Apps/ZMODEM/zmp15+-.new
  15. BIN
      Source/Apps/ZMODEM/zmterm.ovr
  16. BIN
      Source/Apps/ZMODEM/zmxfer.ovr
  17. 9
      Source/HBIOS/uf.asm

1
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

18
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

7
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

BIN
Source/Apps/ZMODEM/zmconfig.ovr

Binary file not shown.

BIN
Source/Apps/ZMODEM/zminit.ovr

Binary file not shown.

862
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


573
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


256
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
===============================================================================


24
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


389
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 <X>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

21
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


13
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.


20
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


29
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.

BIN
Source/Apps/ZMODEM/zmterm.ovr

Binary file not shown.

BIN
Source/Apps/ZMODEM/zmxfer.ovr

Binary file not shown.

9
Source/HBIOS/uf.asm

@ -90,13 +90,13 @@ UF_OUT:
XOR A ; SIGNAL SUCCESS
RET
;
; INPUT STATUS - CAN WE SEND A CHARACTER
; INPUT STATUS - CAN WE RECEIVE A CHARACTER
;
UF_IST:
IN A,(FIFO_STATUS) ; IS THE QUEUE EMPTY?
RLCA
CPL
AND 00000001B
RLCA ; SET BIT 1 : 0 = DATA AVAIL. 1 = NO DATA AVAIL
CPL ; INVERT BIT 1 : 1 = DATA AVAIL. 0 = NO DATA AVAIL
AND 00000001B ; SET BYTE PENDING, 0 OR 1 AND STATUS
RET
;
; OUTPUT STATUS - CAN WE OUTPUT A CHARACTER
@ -137,6 +137,7 @@ UF_FLUSH:
UFBUFEMPTY:
LD (IY+0),E ; SAVE LOW WORD
LD (IY+1),D ; SAVE HI WORD
XOR A
RET ; NZ STATUS HERE INDICATES FAIL.
;
; USB-FIFO WILL APPEAR AS A SERIAL DEVICE AT DEFAULT SERIAL MODE

Loading…
Cancel
Save