diff --git a/Source/Apps/Build.cmd b/Source/Apps/Build.cmd index da042c4c..cd71ed07 100644 --- a/Source/Apps/Build.cmd +++ b/Source/Apps/Build.cmd @@ -32,6 +32,7 @@ pushd Tune && call Build || exit /b & popd pushd FAT && call Build || exit /b & popd pushd Test && call Build || exit /b & popd pushd ZMP && call Build || exit /b & popd +pushd ZMD && call Build || exit /b & popd copy *.com %APPBIN%\ || exit /b diff --git a/Source/Apps/Clean.cmd b/Source/Apps/Clean.cmd index 8e9810e6..22259b3a 100644 --- a/Source/Apps/Clean.cmd +++ b/Source/Apps/Clean.cmd @@ -13,3 +13,4 @@ pushd Tune && call Clean || exit /b 1 & popd pushd FAT && call Clean || exit /b 1 & popd pushd Test && call Clean || exit /b 1 & popd pushd ZMP && call Clean || exit /b 1 & popd +pushd ZMD && call Clean || exit /b 1 & popd diff --git a/Source/Apps/Makefile b/Source/Apps/Makefile index 7ca650ad..ea2decb0 100644 --- a/Source/Apps/Makefile +++ b/Source/Apps/Makefile @@ -1,7 +1,7 @@ OBJECTS = sysgen.com survey.com \ syscopy.com assign.com format.com talk.com mode.com rtc.com \ timer.com rtchb.com -SUBDIRS = XM FDU FAT Tune Test ZMP +SUBDIRS = XM FDU FAT Tune Test ZMP ZMD DEST = ../../Binary/Apps TOOLS =../../Tools diff --git a/Source/Apps/ZMD/-29sep88 b/Source/Apps/ZMD/-29sep88 new file mode 100644 index 00000000..e69de29b diff --git a/Source/Apps/ZMD/-notice.doc b/Source/Apps/ZMD/-notice.doc new file mode 100644 index 00000000..79faa5ad --- /dev/null +++ b/Source/Apps/ZMD/-notice.doc @@ -0,0 +1,24 @@ + + ----------------------------------------------------------------------- + Copyright (c) 1987, 1988 by Robert W. Kramer III, ALL RIGHTS RESERVED + Release 1.50 1569 40th St. + 09/29/88 Rock Island, Il. 61201 + Voice: (309) 786-6711, 24hr + RI RCPM-RDOS (128 Meg) Data: (309) 786-6227, 24hr, 300/1200/2400 + ----------------------------------------------------------------------- + + + USER AGREEMENT: + --------------- + + ZMD is free to use, providing program signon messages (my name, program + name, release date and copyright notices) remain intact as released. + You may modify any .Z80 file as you wish so long as your modified copy + is used for your own personal non-profit use and is NOT passed on to + any other party. + + You are encouraged to distribute ZMD releases to any interested party + providing all files remain in their ORIGINAL UNMODIFIED RELEASE FORM + as distributed from RI RCPM-RDOS. + + \ No newline at end of file diff --git a/Source/Apps/ZMD/-zmd.for b/Source/Apps/ZMD/-zmd.for new file mode 100644 index 00000000..151dceae --- /dev/null +++ b/Source/Apps/ZMD/-zmd.for @@ -0,0 +1,10 @@ +----- +ZMD150.LBR - CP/M Communications + 09/29/88 - This release is super clean, super fast - and smaller. + Some major problems in the way Ymodem Batch protocol was implemented + on CP/M systems has been fixed, virtually eliminating all delays + between files. CPM3 systems can now run all ZMD programs with no + problems. Some other bug fixes, modifications and enhancements. + This is probably the last release of ZMD until ZMD with ZMODEM is + released. Bob Kramer - RI RCPM-RDOS (128 Mb) - (309) 786-6711 + \ No newline at end of file diff --git a/Source/Apps/ZMD/Build.cmd b/Source/Apps/ZMD/Build.cmd new file mode 100644 index 00000000..fdc64135 --- /dev/null +++ b/Source/Apps/ZMD/Build.cmd @@ -0,0 +1,37 @@ +@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 -zmd/fm +zx l80 -zmd,zmd/n/e + +zx z80asm -zmap/fm +zx l80 -zmap,zmap/n/e + +zx z80asm -znews/fm +zx l80 -znews,znews/n/e + +zx z80asm -znewp/fm +zx l80 -znewp,znewp/n/e + +zx z80asm -zfors/fm +zx l80 -zfors,zfors/n/e + +zx z80asm -zforp/fm +zx l80 -zforp,zforp/n/e + +zx z80asm -zmdel/fm +zx l80 -zmdel,zmdel/n/e + +zx z80asm -zmdhb/fh +zx mload25 zmd=zmd.com,zmdhb + +copy /Y zmd.com ..\..\..\Binary\Apps\ || exit /b + diff --git a/Source/Apps/ZMD/Clean.cmd b/Source/Apps/ZMD/Clean.cmd new file mode 100644 index 00000000..04e795a6 --- /dev/null +++ b/Source/Apps/ZMD/Clean.cmd @@ -0,0 +1,10 @@ +@echo off +setlocal + +ren zmdsubs.rel zmdsubs.rel.sav +if exist *.rel del *.rel +ren zmdsubs.rel.sav zmdsubs.rel +if exist *.hex del *.hex +if exist *.prn del *.prn +if exist *.lst del *.lst +if exist *.com del *.com diff --git a/Source/Apps/ZMD/Makefile b/Source/Apps/ZMD/Makefile new file mode 100644 index 00000000..af10bc44 --- /dev/null +++ b/Source/Apps/ZMD/Makefile @@ -0,0 +1,10 @@ +OBJECTS = zmd.com +DEST = ../../../Binary/Apps +TOOLS = ../../../Tools +OTHERS = *.hex zmd.rel + +include $(TOOLS)/Makefile.inc + +zmd.com: zmd.rel zmdhb.hex + $(ZXCC) $(CPM)/l80 -zmd,zmd/n/e + $(ZXCC) $(CPM)/MLOAD25 zmd=zmd.com,zmdhb diff --git a/Source/Apps/ZMD/autoinst.doc b/Source/Apps/ZMD/autoinst.doc new file mode 100644 index 00000000..b5209d59 --- /dev/null +++ b/Source/Apps/ZMD/autoinst.doc @@ -0,0 +1,36 @@ + + ----------------------------------------------------------------------- + Copyright (c) 1987, 1988 by Robert W. Kramer III, ALL RIGHTS RESERVED + Release 1.50 1569 40th St. + 09/29/88 Rock Island, Il. 61201 + Voice: (309) 786-6711, 24hr + RI RCPM-RDOS (128 Meg) Data: (309) 786-6227, 24hr, 300/1200/2400 + ----------------------------------------------------------------------- + + + ZMD AUTO-INSTALL FEATURE + ------------------------ + + ZINSTL can automatically install the new release of ZMD (and utilities) + with the use of the '!' option. ZINSTL ! will read all switch/toggle + configurations and port/modem/rtc overlays from your already installed + version of ZMD where you can then use them to install this new release. + + Follow these steps: + + 1) Extract all files from ZMDnnn.LBR + 2) Rename your already configured ZMD.COM to ZMD149.COM + 3) Run ZINSTL (Release 1.50) with the '!' option: ZINSTL ! + 4) Answer any questions ZINSTL may ask + 5) Use the 'J' option to save configurations + 6) Rename ZMD150.COM to ZMD.COM + + + NOTE: This will not work with any other version of ZMD except for 1.49 + and 1.50. Running ZINSTL without the ! option will cause it to run just + like you've all been used to. In the future, if the new release header + file ZMDHDR.Z80 becomes incompatible with that of the previous release + this feature will be disabled. + + + \ No newline at end of file diff --git a/Source/Apps/ZMD/equates.ins b/Source/Apps/ZMD/equates.ins new file mode 100644 index 00000000..f38310c6 --- /dev/null +++ b/Source/Apps/ZMD/equates.ins @@ -0,0 +1,88 @@ +; +; Version identification +; +VERS EQU 1 ; Release +MODLEV EQU 5 ; Major modification level +REV EQU 0 ; Minor revision number + +VMONTH EQU 09 ; Version month +VDAY EQU 29 ; Version day +VYEAR EQU 88 ; Version year +; +;========================================================================== +; +NO EQU 0 +YES EQU 0FFH +; +;-------------------------------------------------------------------------- +; Define ASCII characters used +;-------------------------------------------------------------------------- + +SOH EQU 1 ; ^A - start of header +STX EQU 2 ; ^B - start of 1k header +CTRLC EQU 3 ; ^C - abort/break character +EOT EQU 4 ; ^D - end of transmission +ACK EQU 6 ; ^F - acknowledge +BELL EQU 7 ; ^G - bell +BS EQU 8 ; ^H - backspace +TAB EQU 9 ; ^I - horizontal tab +LF EQU 10 ; ^J - line feed +CTRLK EQU 11 ; ^K - abort character +CR EQU 13 ; ^M - carriage return +PAUSE EQU 19 ; ^S - pause request +NAK EQU 21 ; ^U - negative acknowledge +CANCEL EQU 24 ; ^X - cancel +EOF EQU 26 ; ^Z - end of file +CRC EQU 67 ; C - CRC request character +KSND EQU 75 ; K - 1k block request character +DEL EQU 127 ; Delete/Rubout +; +; +; Define standard CP/M BDOS equates +; +DIRCON EQU 6 ; Direct console output +PRINT EQU 9 ; Print string function +GETVER EQU 12 ; Get CP/M version +SELDSK EQU 14 ; Select drive +OPEN EQU 15 ; Open file +CLOSE EQU 16 ; Close file +SRCHF EQU 17 ; Search for first occurence +SRCHN EQU 18 ; Search for next occurence +DELETE EQU 19 ; Delete file +READ EQU 20 ; Read record +WRITE EQU 21 ; Write record +MAKE EQU 22 ; Make new file +RENAME EQU 23 ; Rename a file +CURDRV EQU 25 ; Get current drive +SETDMA EQU 26 ; Set DMA +SETFILE EQU 30 ; Set file attributes +SETUSR EQU 32 ; Set user area to receive file +RRDM EQU 33 ; Read random +WRDM EQU 34 ; Write random +FILSIZ EQU 35 ; Compute file size +SETRRD EQU 36 ; Set random record + +BDOS EQU 0005H ; Address for BDOS jump vectors +TBUF EQU 0080H ; Default DMA address +FCB EQU 005CH ; System FCB +FCB1 EQU 006CH ; Secondary FCB area +FCBEXT EQU FCB+12 ; File extent +FCBRNO EQU FCB+32 ; Record number +RANDOM EQU FCB+33 ; Random record field +RLEN EQU 128 ; Record length +ITEMSZ EQU 16 ; Number of data bytes in each filename entry +; +; +TAGFIL EQU 7 +DWNTAG EQU 6 +NOSYS EQU 5 +NOLBS EQU 4 +NOCOMS EQU 3 +NOCOMR EQU 2 +RESERV1 EQU 1 +ZCPR EQU 0 +; +; +; +;-------------------------------------------------------------------------- + \ No newline at end of file diff --git a/Source/Apps/ZMD/mkcoms.sub b/Source/Apps/ZMD/mkcoms.sub new file mode 100644 index 00000000..2486776a --- /dev/null +++ b/Source/Apps/ZMD/mkcoms.sub @@ -0,0 +1,44 @@ +; +; +; MKCOMS.SUB - 09/29/88 - Assemble/Link ZMD and utilities +; +; To use this file with M80, you'll have to edit all 'z80asm ' +; to 'm80 ='. Older versions of M80 which truncate labels to 6 +; bytes will not assemble the programs properly. +; +; --> MICROSOFT MACRO-80 v3.43 has been tested and proven to +; assemble them without error. +; +; +z80asm zmd/m +l80 zmd,zmd/n/e +era zmd.rel +; +z80asm zmap/m +l80 zmap,zmap/n/e +era zmap.rel +; +z80asm znews/m +l80 znews,znews/n/e +era znews.rel +; +z80asm znewp/m +l80 znewp,znewp/n/e +era znewp.rel +; +z80asm zfors/m +l80 zfors,zfors/n/e +era zfors.rel +; +z80asm zforp/m +l80 zforp,zforp/n/e +era zforp.rel +; +z80asm zmdel/m +l80 zmdel,zmdel/n/e +era zmdel.rel +; +; +; Done... +; + \ No newline at end of file diff --git a/Source/Apps/ZMD/zforp.z80 b/Source/Apps/ZMD/zforp.z80 new file mode 100644 index 00000000..be6414c0 --- /dev/null +++ b/Source/Apps/ZMD/zforp.z80 @@ -0,0 +1,420 @@ +; + + TITLE ZFORP.Z80 - 09/29/88 - ZMD Public Description Utility +; Copyrighted (c) 1987, 1988 +; Robert W. Kramer III + + PAGE +;- -; +; Update History ; +; ; +; Date Release Comments ; +; -------- ------- ---------------------------------------------- ; +; ; +; 09/29/88 v1.50 - No change(s) made to this file. ; +; 03/18/88 v1.49 - No change(s) made to this file ; +; 03/13/88 v1.48 - Redefined buffer table at end of programs. STACK; +; and filename buffers now EQUated with offsets ; +; from the last switch/toggle in program instead ; +; of with DS directive. ; +; - Some systems which do NOT have an interrupt ; +; driven keyboard may have noticed problems when ; +; an invalid key was entered in the ZNEWP, ZFORP ; +; and ZMDEL programs. In ZNEWP and ZFORP, if a ; +; CR was entered to pause the output, output was ; +; limited to one line at a time per key pressed. ; +; If an invalid key was hit, output would have ; +; remained in a paused state until one of the ; +; abort keys were pressed. This was difficult to ; +; find since my keyboard is interrupt driven and ; +; I could not duplicate the problem on my own ; +; system. ; +; 02/25/88 v1.47 - No change(s) made to this file ; +; 01/27/88 v1.46 - Some changes were made to ZMDSUBS that are not ; +; directly related to this file ; +; - Fixed typo in help guide reflecting '/' as the ; +; flag to force LF in search routine ; +; 01/17/88 v1.45 - First public release ; +; 12/24/87 v1.01 - Some trivial bugs fixed ; +; 11/10/87 v1.00 - Initial version ; +;- -; + +;-------------------------------------------------------------------------; +; EXTERNAL Declarations: | +;-------------------------------------------------------------------------; + + + EXTRN CKABRT,CMDBUF,DBUF,ERXIT,EXIT,ILPRTB,LINCNT,NOFILE + EXTRN NOFOR,OLDDRV,OLDUSR,PRINTV,RECAR1,RECDR1,RENFCB + EXTRN RSDMA,SHONM4,STACK,TYPE,UCASE,NOFOR + +; +;-------------------------------------------------------------------------; +; Program Starts Here | +;-------------------------------------------------------------------------; + + + .Z80 + ASEG + ORG 100H ; Program starts + JP BEGIN ; Jump around configuration table + INCLUDE ZMDHDR.Z80 ; Include the ZMD header overlay + .REQUEST ZMDSUBS ; Include the ZMD subroutines + +; +; +; Save CP/M stack, initialize new one for this program +; +BEGIN: LD (STACK),SP ; Save return address to CCP + LD SP,STACK ; Initialize new one for this program + +; +; Get current drive/user and save for later +; + LD A,255 + CALL RECAR1 + LD (OLDUSR),A ; Save current user area + LD C,CURDRV + CALL BDOS + LD (OLDDRV),A ; Save current drive + +; +; Tell em who we are +; + LD HL,PUBFOR + CALL PRINTV + +; +; See if descriptions enabled +; + LD A,(DESCRIB) + OR A + JP NZ,BEGIN1 + LD A,(MSGDESC) + OR A + JP Z,NOFOR + +BEGIN1: CALL ILPRTB + DB '(S to Pause - C K or X Abort - ? for Help)' + DB CR,LF,LF,0 + LD A,8 + LD (LINCNT),A + +; +; See if user wants file displayed 'nonstop' ($N) +; + LD A,(TBUF) ; Number of bytes in command tail + OR A ; Were there any? + LD (SHOWALL),A ; Tell rest of program + JP Z,OPNFIL ; Just go display the file if not + + LD A,(FCB+1) ; Get first character on command line + CP '$' ; Must specify '$' first for pause disabling + JP NZ,CKHLP ; Nope, continue normal + + LD A,(FCB+2) ; Get second character on command line + CP 'N' ; 'N' for nonstop display? + JP NZ,CKHLP ; No + + XOR A + LD (SHOWALL),A ; Disable string search + LD (PAGLEN),A ; Else disable page pauses + JP OPNFIL + +; +; See if requesting help +; +CKHLP: LD A,(TBUF+2) ; Get character after space + CP '?' ; ?? + JP NZ,SAVTAIL ; No, save command tail for comparison + + LD A,(TBUF+3) ; Any more chracters? + OR A + JP Z,HELP ; No, so must want HELP + +; +; Move command line buffer to internal buffer +; +SAVTAIL:LD HL,TBUF ; Point to command line buffer + LD B,(HL) ; Character count is first byte into 'B' + LD DE,CMDBUF ; Destination is internal buffer + INC HL ; Increment to ' ', next INC gets first chr + LD A,(HL) ; Get this character + CP ' ' ; Is it a space? + JR Z,SVTAIL1 ; Yes, leave things alone + DEC HL ; No, decrement pointer + +SVTAIL1:INC HL ; Increment to next character + LD A,(HL) ; Into A + LD (DE),A ; Store in internal buffer + INC DE ; Increment pointer + DJNZ SVTAIL1 ; One less character on command line + +; +; Open FOR file +; +OPNFIL: LD A,(USER) ; Get user area to find FOR file + CALL RECAR1 ; Log into it + LD A,(DRIVE) ; Get drive to find FOR file + CALL RECDR1 ; Log into it + + LD HL,FILE ; Initialize internal FCB1 + LD DE,FORNAM ; With FOR filename + CALL RENFCB + + LD DE,FILE ; Internal FCB1 contains filename + LD C,OPEN ; Now attempt open + CALL BDOS + INC A ; Open successful? + LD HL,FORNAM ; Point to FOR filename for 'not found' + JP Z,NOFILE ; No, inform user and abort + +; +; Read a 128 byte record into DBUF at end of program +; + XOR A + LD (FILE+12),A ; Start with first extent + LD (FILE+32),A ; And first record + LD DE,DBUF ; Destination buffer + +; +RDRECD: PUSH DE ; Save current data buffer address + CALL RSDMA ; Reset DMA + + LD C,READ ; Read next record + LD DE,FILE ; From FOR file + CALL BDOS + POP DE ; Get current DBUF address back + OR A ; Read successful? + JP NZ,RERROR ; No, go check EOF + LD HL,TBUF ; 128 byte buffer in page 0 + +WRDLP: LD A,(LINEND) ; At end of line? + OR A + JP Z,WDLP1 ; No + + XOR A + LD (LINEND),A ; Else we aren't anymore + + LD A,(HL) ; Get the character + AND 7FH ; Strip parity + CP '-' ; Start of next description? + JP NZ,WDLP1 ; No + + LD A,3 + LD (DE),A ; Stuff a break for beginning of last descrip + JP SEARCH + +WDLP1: LD A,(HL) ; Get character + AND 7FH ; Strip high bit + CP DEL ; Rubout? + JP Z,NEXT ; Yes, ignore and get next character + CP EOF ; EOF - End of file marker? + JP Z,ENDFIL ; Yes, all done + LD B,A ; Save character for now + LD A,(SHOWALL) ; Looking for specified string? + OR A + LD A,B ; Get our character back now + JP NZ,WDLP2 ; Yes, just write to memory + CALL TYPE ; Output to console + EX AF,AF' ; Save flags (NZ=displaying to console) + LD A,0 ; A=0 disables pausing while checking abort + EX AF,AF' ; Save it for now, get character back + JP WDLP3 ; And see if at end of line + +WDLP2: LD (DE),A ; Else writing to memory + INC DE ; Next buffer position + EX AF,AF' ; Save flags (Z=writing to memory) + LD A,1 ; A=1 enables puasing while checking abort + EX AF,AF' ; Save it for now, get character back + +WDLP3: CP LF ; Are we at end of line? + JP NZ,NEXT ; No get next character + + LD A,(SHOWALL) ; Get string search toggle + LD (LINEND),A ; If set, at end of line, and writng to memory + EX AF,AF' ; AF'=1 enable pauses, disable if 0 + CALL CKABRT ; Check for user abort (and pauses if A=1) + +NEXT: INC L ; One more byte + JP Z,RDRECD ; If no more get next record + JP WRDLP ; Else get next character + +; +; Search for a match with search string +; +SEARCH: PUSH HL ; Save HL + LD HL,CMDBUF ; Point to buffer containing command tail + +SEARC1: LD (CMDPTR),HL ; Save command tail buffer pointer + LD HL,DBUF ; Disk buffer with FOR text + +SEARC2: LD DE,(CMDPTR) ; Get command tail buffer pointer again + PUSH HL ; Save it (command tail pointer still in DE) + +SEARC3: LD A,(DE) ; Get a character + CP '\' ; Force LF? + JP NZ,SEARC4 ; No + LD A,LF ; Else LF value in A for comparison + +SEARC4: INC DE ; Increment to next command tail character + OR A ; Anything there? + JP Z,SEARC8 ; No + CP '|' ; String seperator? + JP Z,SEARC8 ; Yes + LD B,A ; Save character for compare + LD A,(HL) ; Get a FOR text character in A + CALL UCASE ; Convert it to uppercase + +SEARC5: LD C,A ; Put FOR text character in C for now + INC HL ; And increment to next one + LD A,B ; Get comparison character back (from CMDBUF) + CP '?' ; Accept any character? + JP Z,SEARC3 ; Yes, call it a match + CP C ; Else are they the same? + JP Z,SEARC3 ; Yes, call it a match + POP HL ; Else get FOR buffer address back + INC HL ; Increment to next character + LD B,0 ; Initialize count to 0 + LD A,(HL) ; Get next character from FOR buffer + CP CTRLC ; Beginning of description entry? + JP Z,SEARC6 ; Yes + CP 4 ; End of file? + JP NZ,SEARC2 ; No + INC B ; Else, show we hit end of buffer + +SEARC6: LD HL,(CMDPTR) ; Get command tail pointer back + +SEARC7: LD A,(HL) ; Get character from saved command tail + INC HL ; Point to next one + CP '|' ; Searching for multiple strings? + JP Z,SEARC1 ; Yes, go search next one + OR A ; Else are we all done? + JP NZ,SEARC7 ; No, keep looking + LD A,B ; Else see if at end of buffer + OR A + JP NZ,ENDFL1 ; Yes + LD DE,DBUF+1 + POP HL ; Get record count back + JP NEXT ; Go get next + +SEARC8: POP HL + LD A,CR + CALL TYPE ; Output CR for end of line + LD HL,DBUF + +SEARC9: LD A,(HL) ; Get character + CP CTRLC ; Start of description? + JP Z,SEARC10 ; Yes, go get next character + CP 4 ; End of file? + JP Z,ENDFL1 ; Yes + CALL TYPE ; Output character to console + CP LF ; At end of line? + LD A,0 ; Disable page pauses + CALL Z,CKABRT ; Check for aborts + INC HL ; Next character + JP SEARC9 ; Loop until a ^C or ^D + +SEARC10:POP HL + LD DE,DBUF+1 + JP NEXT ; Go get next byte + +; +; The following routine displays the help guide to the user +; +HELP: CALL PRTABT + DB CR,LF + DB 'Usage examples:' + DB CR,LF + DB CR,LF,' FOR Show entire file' + DB CR,LF,' FOR $N Show entire file without paging' + DB CR,LF,' FOR ZMD All descriptions containing string ''ZMD''' + DB CR,LF,' FOR ZMD|LU ''|'' seperates multiple strings to search' + DB CR,LF,' FOR \ZMD ''\'' forces line feed and looks at filenames' + DB CR,LF,' FOR ZM? ''?'' matches any character in this position' + DB CR,LF,0 + + LD A,(INCLDU) + OR A + JP Z,HELP1 + CALL PRTABT + DB ' FOR (B0:) Descriptions for files received on B0:',0 + +HELP1: CALL PRTABT + DB CR,LF,0 + LD A,(DSTAMP) + OR A + JP Z,HELP4 + LD A,(EDATE) + OR A + JP Z,HELP2 + CALL PRTABT + DB ' FOR ??/12',0 + JP HELP3 + +HELP2: CALL PRTABT + DB ' FOR 12/??',0 + +HELP3: CALL PRTABT + DB ' Show files received in month of December',0 + +HELP4: CALL ERXIT + DB CR,LF,LF,LF,LF,'$' + +; +; Inline print routine checks for user abort on each line feed +; +PRTABT: POP HL ; Get address following CALL + +AM1: LD A,(HL) ; Character in A + OR A ; Null terminator? + JP Z,AM2 ; Yes, all done + CALL TYPE ; Else output to console + CP LF ; Was it a LF? + LD A,0 ; Enable page pauses + CALL Z,CKABRT ; Check for user abort, or pause request + INC HL ; Point to next character + JP AM1 ; Loop until a null + +AM2: PUSH HL ; Current address in HL=return address + RET + +; +; +RERROR: CP 1 + JP Z,ENDFIL + CALL ERXIT + DB '-- Source file read error$' +; +ENDFIL: LD A,(SHOWALL) + OR A + JP Z,ENDFL1 + LD A,4 + LD (DE),A + JP SEARCH + +ENDFL1: LD C,CLOSE + LD DE,FILE + CALL BDOS + CALL ERXIT + DB CR + DB '-----' + DB CR,LF + DB '-- End of file --$' + + +; +; These next are dummy routines to satisfy external ZMDSUBS requests. +; They do nothing, but leave alone +; +DONE:: JP EXIT +TIME:: RET + + +LINEND: DB 0 +SHOWALL:DB 0 +CMDPTR: DW 0 + + + END + \ No newline at end of file diff --git a/Source/Apps/ZMD/zfors.z80 b/Source/Apps/ZMD/zfors.z80 new file mode 100644 index 00000000..3461842c --- /dev/null +++ b/Source/Apps/ZMD/zfors.z80 @@ -0,0 +1,233 @@ +; + + TITLE ZFORS.Z80 - 09/29/88 - ZMD Sysop Description Utility +; Copyrighted (c) 1987, 1988 +; Robert W. Kramer III + + PAGE +;- -; +; Update History ; +; ; +; Date Release Comments ; +; -------- ------- ---------------------------------------------- ; +; ; +; 09/29/88 v1.50 - Added trivial routines to display the user's ; +; prompt selections to screen. ; +; 03/13/88 v1.49 - No changes made to this file ; +; 03/13/88 v1.48 - Had a small problem with TPA fix which has been ; +; corrected. CHKTPA was calculating the total ; +; number of bytes available for DBUF, but wasn't ; +; clearing register L (forcing an even amount of ; +; sectors before initializing OUTSIZ buffer limit ; +; comparison word). This may have introduced ; +; minimal garbage to your FOR file if your FOR ; +; file is large enough to fill available TPA with ; +; ZMD, ZFORS or to the log file if running ZMDEL. ; +; - Rewrote OUTCHR routine in ZMDSUBS. ; +; - Redefined buffer table at end of programs. STACK; +; and filename buffers now EQUated with offsets ; +; from the last switch/toggle in program instead ; +; of with DS directive. ; +; - Some systems which do NOT have an interrupt ; +; driven keyboard may have noticed problems when ; +; an invalid key was entered in the ZNEWP, ZFORP ; +; and ZMDEL programs. In ZNEWP and ZFORP, if a ; +; CR was entered to pause the output, output was ; +; limited to one line at a time per key pressed. ; +; If an invalid key was hit, output would have ; +; remained in a paused state until one of the ; +; abort keys were pressed. This was difficult to ; +; find since my keyboard is interrupt driven and ; +; I could not duplicate the problem on my own ; +; system. ; +; 02/25/88 v1.47 - No change(s) made to this file +; 01/27/88 v1.46 - Set MODE to 255 so ZMDSUBS knows we might be ; +; running in local mode and not to worry if BYE ; +; is running or not when CHKENV checks to see ; +; which clock features are valid. ; +; 01/17/88 v1.45 - First public release ; +; 12/06/87 v1.02 - Fixed numerous trivial bugs. ; +;- -; + +;-------------------------------------------------------------------------; +; EXTERNAL Declarations: | +;-------------------------------------------------------------------------; + + + EXTRN CLRLIN,DECOUT,DSCFLG,ERXIT,EXIT,FILCNT,GETDAT + EXTRN GETDSC,GETFN,GETKIND,ILPRTB,INPUT,NEWNAM,OLDDRV + EXTRN OLDUSR,OPNFOR,PRINTV,RECAR1,SHOCAT,STACK,TYPE + EXTRN UCASE,NOFOR,MODE + +; +;-------------------------------------------------------------------------; +; Program Starts Here | +;-------------------------------------------------------------------------; + + + .Z80 + ASEG + ORG 100H ; Program starts + JP BEGIN ; Jump around configuration table + INCLUDE ZMDHDR.Z80 ; Include the ZMD header overlay + .REQUEST ZMDSUBS ; Include the ZMD subroutines + +; +; +; Save CP/M stack, initialize new one for this program +; +BEGIN: LD (STACK),SP ; Save return address to CCP + LD SP,STACK ; Initialize new one for this program + +; +; Save current drive/user +; + LD A,255 ; Get current user + CALL RECAR1 + LD (OLDUSR),A ; Store it + LD C,CURDRV ; Get current drive + CALL BDOS + LD (OLDDRV),A ; Store it + +; +; Disable sleepy caller timeout and set description routines for up to +; 50 new entries +; + XOR A + LD (DESWAIT),A ; Disable sleepy caller timer + LD A,50 + LD (FILCNT),A ; Allow up to 50 descriptions + + LD A,255 + LD (MODE),A ; Tell ZMDSUBS we're a sysop utility + +; +; Display program name and version +; +BEGIN1: LD HL,SYSFOR ; Point to name of this program + CALL PRINTV ; Display it + + LD A,(DESCRIB) ; Regular FOR descriptions? + OR A + JP NZ,MAKDESC ; Yes, skip next + + LD A,(MSGDESC) ; BBS message base descriptions? + OR A + JP Z,NOFOR ; No, descriptions disabled + LD A,1 + LD (DSCFLG),A ; Set flag to show message base descriptions + LD A,(PRUSR) ; Get the private user + LD (USER),A ; FOR destination + LD A,(PRDRV) ; Get the private drive + LD (DRIVE),A ; FOR destination + JP MAKFN ; Skip date stuff + +; +; Get the date of the upload if suppose to. +; +MAKDESC:LD A,(DSTAMP) ; Datestamping description header? + OR A + JP Z,MAKFN ; No, go get filename + CALL ILPRTB + DB 'Date of upload: ',0 + CALL GETDAT ; Get the date + +; +; Get the filename (no spaces with '.' filename seperator) +; +MAKFN: CALL ILPRTB + DB CR,LF + DB ' Name of file: ',0 + CALL GETFN ; Get filename + CALL CLRLIN ; Clear current line + LD A,B ; Get filename bytes remaining count in A + CP 11 ; Anything entered? + JP NZ,GOTNM1 ; Yes, skip this + +; +; No filename was entered, check for save or abort, else continue +; + CALL ILPRTB + DB 'Save, Continue, Abort: ',0 + CALL INPUT ; Get character + CALL UCASE ; Convert to uppercase + CP 'S' ; Save changes? + JP Z,OPNFOR ; Yes, write current buffer to FOR file + + CP 'A' ; Abort program? + JP NZ,BEGIN1 ; No, get next character + CALL ILPRTB + DB CR + DB 'Abort with NO changes? ',0 + CALL INPUT + CALL UCASE + CP 'Y' + JP NZ,BEGIN1 + JP EXIT ; Then abort + +; +; Display file descriptor/upload areas and get choice +; +GOTNM1: CALL GETKIND ; Get file category for description header + +; +; Show the drive/user +; + LD A,(MSGDESC) ; Using BBS message base for descriptions? + OR A + JP NZ,SHOWDU ; Yes, show drive/user of uploaded file + LD A,(INCLDU) ; Include du in description header? + OR A + JP Z,SHOWFN ; No, then skip this stuff + +SHOWDU: LD A,(DRV) ; Get upload drive + CALL TYPE ; Output to console + LD A,(USR) ; Get upload user area + LD H,0 + LD L,A ; In A + CALL DECOUT ; Decimal output routine + LD A,':' ; Output colon + CALL TYPE + +; +; Show the filename +; +SHOWFN: LD HL,NEWNAM + +SHONM1: LD A,(HL) + CP LF + JP Z,SHOWCT + CALL TYPE + INC HL + JP SHONM1 + +; +; Show the file descriptor/upload area +; +SHOWCT: LD A,(ASKIND) ; Supposed to be showing file descriptor? + OR A + JP Z,MKENTRY ; No, get the description + CALL ILPRTB + DB ' - ',0 + CALL SHOCAT ; If so, show it + +; +; Get up to 7 lines for description +; +MKENTRY:CALL GETDSC ; Get up to 7 lines for description + JP NZ,BEGIN1 ; If none entered, or incorrect, skip next + + LD IY,FILCNT ; Else point to maximum entries left + DEC (IY) ; One less to go + JP BEGIN1 ; Get next one + +; +; These next are dummy routines to satisfy ZMDSUBS external requests. +; They do nothing, but leave them alone. +; +DONE:: JP EXIT ; Exit routine can take care of us +TIME:: RET + + + END + \ No newline at end of file diff --git a/Source/Apps/ZMD/zmap.z80 b/Source/Apps/ZMD/zmap.z80 new file mode 100644 index 00000000..4af048d8 --- /dev/null +++ b/Source/Apps/ZMD/zmap.z80 @@ -0,0 +1,268 @@ +; + + TITLE ZMAP.Z80 - 09/29/88 - ZMD System MAP Utility +; Copyrighted (c) 1988 +; Robert W. Kramer III + + PAGE +;- -; +; Update History ; +; ; +; Date Release Comments ; +; -------- ------- ---------------------------------------------- ; +; ; +; 09/29/88 v1.50 - Initial release ; +;- -; + +;-------------------------------------------------------------------------; +; EXTERNAL Declarations: | +;-------------------------------------------------------------------------; + + + EXTRN EXIT,ILPRTB,OLDDRV,OLDUSR,PRINTV,RECAR1,STACK,TYPE + EXTRN KIND,CATADR,SHONM4,WHLCHK,DECOUT + +; +;-------------------------------------------------------------------------; +; Program Starts Here | +;-------------------------------------------------------------------------; + + + .Z80 + ASEG + ORG 100H ; Program starts + JP BEGIN ; Jump around configuration table + INCLUDE ZMDHDR.Z80 ; Include the ZMD header overlay + .REQUEST ZMDSUBS ; Include the ZMD subroutines + +; +; +; Save CP/M stack, initialize new one for this program +; +BEGIN: LD (STACK),SP ; Save return address to CCP + LD SP,STACK ; Initialize new one for this program + +; +; Save current drive/user +; + LD A,255 ; Get current user + CALL RECAR1 + LD (OLDUSR),A ; Store it + LD C,CURDRV ; Get current drive + CALL BDOS + LD (OLDDRV),A ; Store it + +; +; +; Display program name and version +; +BEGIN1: LD HL,MAPNAM ; Point to name of this program + CALL PRINTV ; Display it + + LD A,(ASKAREA) + OR A + JP Z,NOTDEF ; Upload areas not enabled, Abort + + CALL WHLCHK + JP Z,BEGIN2 + LD A,1 + LD (SPECIAL),A + +BEGIN2: CALL HBORD + + LD A,'A' + LD (KIND),A + + LD A,(MAXTYP) + RRA + PUSH AF + + LD A,(MAXTYP) + SUB A,'A' + RRA + LD C,A + + POP AF + JP NC,NOTODD + LD A,1 + LD (ISODD),A + +NOTODD: INC C + LD A,'A' + ADD A,C + LD C,A ; C contains letter of 2nd column descriptors + + LD A,(MAXTYP) + SUB A,'@' + LD B,A ; B contains binary number of descriptors + + LD DE,DESTBL ; DE contains address to 26 byte table + LD A,C + EX AF,AF' + LD A,'A' ; Initialize first entry + +SETLP: LD (DE),A + INC DE + INC A + EX AF,AF' + DJNZ SETLP + LD A,0 + LD (DE),A ; Stuff terminator for display routines + +; +; Main program loop +; +LOOP: LD A,(COLM) + OR A + JP NZ,DOCOL2 + + CALL ILPRTB + DB ' | ',0 + JP ATEND + +DOCOL2: CALL ILPRTB + DB ' || ',0 + +ATEND: CALL SHOWFD + CALL SHOWDU + LD A,(COLM) + OR A + JP Z,ATEND1 + CALL ILPRTB + DB ' |' + DB CR,LF,0 + XOR A + JP ATEND2 + +ATEND1: LD A,1 + +ATEND2: LD (COLM),A + + LD HL,(TBLSAV) + INC HL + LD (TBLSAV),HL + LD A,(HL) + LD (KIND),A + OR A + JP NZ,LOOP + + LD A,(ISODD) + OR A + JP Z,ISDN1 + +ISDONE: CALL ILPRTB + DB ' || ',0 + LD A,(SPECIAL) + OR A + JP Z,IS1 + CALL ILPRTB + DB ' ',0 + +IS1: CALL ILPRTB + DB ' |',CR,LF,0 + +ISDN1: CALL HBORD + CALL ILPRTB + DB CR,LF + DB ' Use FOR/NEW to view recent upload description/log listings.' + DB 0 + JP EXIT +; +; +SHOWDU: LD A,(KIND) + SUB 'A' + RLA + RLA + LD D,0 + LD E,A + LD IY,TYPTBL + ADD IY,DE + LD A,(IY) + CALL TYPE + + LD A,(IY+1) + CALL SHODU1 + + CALL ILPRTB + DB ' ',0 + + LD A,(SPECIAL) + OR A + RET Z + + LD A,(IY+2) + CALL TYPE + + LD A,(IY+3) + +SHODU1: CP 10 + PUSH AF + + LD H,0 + LD L,A + CALL DECOUT + CALL ILPRTB + DB ':',0 + + POP AF + RET C + + CALL ILPRTB + DB ' ',0 + RET + +; +; +SHOWFD: CALL CATADR + INC DE + INC DE + LD B,23 + +SHOFD1: LD A,(DE) + CALL TYPE + INC DE + DJNZ SHOFD1 + CALL ILPRTB + DB ' ',0 + RET + +; +; Show horizontal border for top and bottom +; +HBORD: CALL ILPRTB + DB ' ================================================================',0 + LD A,(SPECIAL) + OR A + JP Z,HBORD1 + CALL ILPRTB + DB '==========',0 + +HBORD1: CALL ILPRTB + DB CR,LF,0 + RET + +NOTDEF: CALL ILPRTB + DB CR,LF + DB 'ZMD Upload Routing feature not enabled, ',0 + LD HL,MAPNAM + CALL SHONM4 + CALL ILPRTB + DB 'aborting...',0 + JP EXIT +; +; These next are dummy routines to satisfy ZMDSUBS external requests. +; They do nothing, but leave them alone. +; +DONE:: JP EXIT ; Exit routine can take care of us +TIME:: RET + +TBLSAV: DW DESTBL +DESTBL: DB 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +ISODD: DB 0 +COUNT: DB 0 +COLM: DB 0 +SPECIAL:DB 0 + + + END + \ No newline at end of file diff --git a/Source/Apps/ZMD/zmd.pdf b/Source/Apps/ZMD/zmd.pdf new file mode 100644 index 00000000..464b212e Binary files /dev/null and b/Source/Apps/ZMD/zmd.pdf differ diff --git a/Source/Apps/ZMD/zmd.ws b/Source/Apps/ZMD/zmd.ws new file mode 100644 index 00000000..26359638 --- /dev/null +++ b/Source/Apps/ZMD/zmd.ws @@ -0,0 +1,1144 @@ +. MARGINS: RIGHT=65; LEFT= +.op +.he** 09/29/88 ** ZMD Reference Manual - Version 1.50 +.foCopyright (c) 1987, 1988 Robert W. Kramer III ALL RIGHTS RESERVED + + + + + + + + + + + + + + + + + + + + + ZMD File Transfer Program for the Z80 RCP/M + + External Reference Specification + + ZMD - Version 1.50 +.PA Š.pn 1 +.he** 09/29/88 ** ZMD Reference Manual - Version 1.50 Page # + +     CONTENTS + +     1.° Introductioî tï ZMD..........................® 4 + +     2.° Applicablå Files.............................® 5 + +     3.° Installation.................................® 8 + +      3.± Locaì CRÔ Cleaò Screeî Sequences.............. 8 + +      3.² Input/Output.................................. 8 +      3.2.± Modeí......................................... 8 +      3.2.² Microprocessoò Speed.......................... 9 +      3.2.³ Modeí Speeä Indicatoò Byte.................... 9 +      3.2.´ Disë Writå Locë Flag.......................... 9 +      3.2.µ Sleepù Calleò Timeout......................... 9 +      3.2.¶ Minimuí Speeä foò 1ë Blocks................... 9 +      3.2.· File Transfer Buffer Queue.................... 10 +      3.2.¸ Pagå Pausing.................................. 10 +         3.2.9 Automatic Calculation of Disk Buffer Size..... 10 + +      3.³ Timekeeping................................... 11 +      3.3.± MBYE/BYEµ Clocë Support....................... 11 +      3.3.² ZMÄ Internaì Clock/Datå Readeò Code........... 11 +      3.3.³ Restrictinç Downloadó tï Timå Left............ 12 +      3.3.´ Maximuí Timå Allowed.......................... 12 +      3.3.µ Displaù Timå oî Systeí messages............... 12 +      3.3.6 Logon Hour/Minute Addresses................... 12 + +      3.´ Accesó Restrictions........................... 13 +      3.4.± ZCMD/ZCPR..................................... 13 +      3.4.² WHEEÌ Byte.................................... 13 +      3.4.³ Maximuí Drive/User............................ 13 +      3.4.´ BYE/BBÓ Prograí Accesó Flaç Byte.............. 13 + + 3.µ Uploaä Configuration.........................® 14 +      3.5.± Preformatteä BBÓ Messagå Uploads.............. 14 +      3.5.² Hidinç Ne÷ Uploadó Untiì Approveä bù Sysop.... 14 +      3.5.³ Uploaä Routinç tï Multiplå Drive/Users........ 14 +      3.5.4 Uploadinç tï Specifieä Drive/User............. 14 +      3.5.5 Receivinç Privatå Uploads..................... 15 +      3.5.¶ Creditinç Uploaä Timå tï Timå Left............ 15 +      3.5.· Receivinç .COÍ Fileó Securely................. 15 + +      3.¶ Uploaä Descriptions........................... 16 +      3.6.± Forwardinç Descriptionó tï BBÓ Messagå Base... 16 +      3.6.² Forwardinç Descriptionó tï FOÒ Texô File...... 16 +      3.6.³ Desriptioî Filå Filename/Drive/User........... 16 +      3.6.´ Uploaä Descriptioî Headeò Information......... 17 +      3.6.µ Includinç Filå Descriptors.................... 17 +      3.6.¶ Includinç Uploaä Drive/Useò Area.............. 17 +      3.6.· Datestampinç thå Descriptioî Header........... 17 +      3.6.¸ Overridinç Descriptioî Requests............... 17 +      3.6.¹ Automatiã Worä Wrap........................... 18 Š +      3.· Downloaä Configurations....................... 19 +      3.7.± Restrictinç .LBÒ anä Singlå F± Taggeä Files... 19 +      3.7.² Disallo÷ Sendinç .COÍ Files................... 19 +      3.7.³ Disallo÷ Sendinç .??£ Files................... 19 +      3.7.´ Disallo÷ Sendinç F² Taggeä $SYSteí Files...... 20 +      3.7.µ Sendinç F³ Taggeä Fileó Regardlesó oæ Access.. 20 +      3.7.¶ Speciaì Sysoð Downloadó tï Selecteä Caller.... 20 + +      3.¸ Logkeeping.................................... 21 +      3.8.± Makinç ZMD.LOÇ File..........................® 21 +      3.8.² Europeaî Datå Formaô (DD/MM/YY)............... 21 +      3.8.³ Transfeò Loç Drive/User/Filename.............. 21 +      3.8.´ LASTCALÒ Filå Information..................... 21 +      3.8.µ Countinç Filå Transferó foò BBÓ Software...... 21 + +.pa Š +     APPENDICES + + +     APPENDIØ A.............................................. 23 + +      A.± Modem Interface............................... 23 + A.1.1 Creating Modem I/O Overlays................... 23 + A.1.2 Installing Modem I/O Overlays................. 23 + + +     APPENDIØ B.............................................. 25 + +      B.± RTà Clock/Datå Readeò Codå.................... 25 + + +     APPENDIØ C.............................................. 26 + +      C.± Filå Descriptors/Categories................... 26 + + +     APPENDIØ D.............................................. 27 + +      D.± Uploaä Routinç Table.......................... 27 +.pa Š +     1.° Introductioî tï ZMD + +     ZMÄ  ió  á  Remotå CP/Í Filå  Transfeò  Prograí  writteî  iî +     MICROSOFÔ  MACRO-8° languagå usinç ZILOÇ Z8°  assembler®  Iô +     wilì  ruî  oî anù Z8° microprocessoò usinç CP/Í ² oò  ³  anä +     provideó  fulì supporô foò systemó runninç ZCMÄ oò ZCPÒ  CCÐ +     replacement® ZMÄ caî bå configureä tï ruî undeò mosô populaò +     remotå  consolå  programs¬  buô ió  primarilù  targeteä  foò +     BYE5+¬  MBYÅ anä BYE3¬ oò aó aî entirelù stanä alonå prograí +     usinç  modem/porô overlayó foò modeí I/O®  Fulì supporô  ió +     provideä foò mosô oæ thå populaò BBÓ softwarå sucè aó  PBBS¬ +     MBBS¬  RBBS¬ Metal¬ Oxgate¬ ZBBÓ anä others® Communicationó +     programó sucè aó MODEM7¬ MEX¬ MEX+¬ PROCOMM¬ ProYam¬ QMODEM¬ +     IMÐ anä otheró arå alì alsï fullù compatible. + +     Thió  manuaì  ió  noô intendeä tï bå specifiã iî  detaiì  tï +     thå internaì characteristicó oæ ZMÄ anä utilities®  Iô  waó +     writteî  aó á guidå tï helð thå implementeò decidå whicè  oæ +     thå  optionó anä featureó wilì bå useä oî hió  system® + +     Aî  internaì referencå manuaì coverinç thå ZMDSUBS.REÌ  filå +     anä  user'ó  manuaì  haó  beeî  iî  thå  making®  Additionaì +     modem/porô overlayó wilì bå addeä tï thå ZMDOVLn.LBÒ filå aó +     theù  arå  created®  Á ZMDCLOCK.LBÒ ió beinç considereä  foò +     organizinç  approveä RTà inserts®  Therå arå  manù  planneä +     features®  Iæ  yoõ havå anù ideaó foò changeó oò additions¬ +     feeì freå tï contacô me. + +  Robert W. Kramer III RI RCPM-RDOS (128mb) +  1569 40th St. 300/1200/240° - 24hrs +  Rock Island, Il 61201 Data: (309) 786-6227 +      Voiceº (309© 786-671± + +     Features: + +      ï  Menõ driveî instalì prograí with intelligence +      o Automatic installation of new releases +      ï  User definable modeí/port I/Ï routineó +      ï  µ seconäs to gather 255 filenames in batch mode! +      o Multiple drive/users fully supported in Batch send +      o Overlayable .COM file installation +      o Upload routing to multiple drive/user areas +      o Time and Datestamping in upload description header +      o 100% MBYE/BYE3/BYE5 compatible + o Truly capable of standalone operation +      o Automatic batch enable (eliminates the 'SB' command) +      o Automatic 'k' block detection of host +      o Fully CP/M 2.n and CP/M 3.n compatible +      o ARC/ARK/LBR member extraction support +      o Automatic BYEBDOS - I/O overlay detection +      ï  Fasteò erroò checkinç resultinç iî quicker transfers + o No delays between files in batch transfers +.pa Š +     2.0 Applicable Files + +     Filenamå Kâ Purpose +     ZMDHDR .Z80 Thió  filå  containó  alì  thå  prograí +                          switcheó  anä valueó lookeä aô  bù  alì +                          thå ZMÄ programs®  Iô ió noô needeä iæ +                          usinç  thå installatioî prograí ZINSTÌ. + +     ZMDSUBS.REL‚ Contains the common subroutines for all + ZMÄ  anä  supporô utilities®  Thió  ió +                          useä  wheî  linkinç á  newlù  assembleä +                          versioî oæ onå oæ thå programs® Sourcå +                          codå ió noô releaseä foò thió file® + +     ZINSTL .COM Thió  ió  thå instalì prograí  useä  tï +      configurå thå ZMD anä utilitù programs® +                          Wheî firsô ran¬  ZINSTÌ readó thå firsô +                          1°  recordó  oæ ZMD.COÍ oî thå  currenô +                          drive/user®  Iæ noô found¬ promptó foò +                          á ne÷ drive/useò tï loç intï anä  trieó +                          again®  Á  fasô  anä easù tï uså  menõ +                          driveî  displaù  showinç  alì   currenô +                          prograí settings®  Afteò editinç anù oæ +                          thå switches/values¬ á selectioî oæ 'J§ +                          iî thå maiî menõ wilì writå thå currenô +                          configuratioî   (firsô  11  recordó  oæ +                          ZINSTL©  bacë  tï ZMD anä ALÌ  oæ  it'ó +                          utilities® Uså iô oî thå flù tï changå +                          switcheó  anä  valueó  quicklù  withouô +                          havinç  tï  reassemblå  anything®  Thió +                          takeó  onlù secondó anä allowó yoõ  thå +                          versatilitù oæ changinç addresses¬ filå +                          descriptors/categories¬ upload/downloaä +                          drive/useò  areas¬  timå  restrictions¬ +                          etc®  Anythinç founä iî thå ZMDHDR.Z8° +                          configuratioî headeò caî bå editeä froí +                          withiî  ZINSTL®  Sourcå  codå  ió  noô +                          provideä foò thió program®  Iæ yoõ makå +                          anù  modificationó  tï  thå  ZMDHDR.Z8° +                          configuratioî  file¬   ZINSTÌ  wilì  NÏ +                          longeò  bå  ablå tï instalì  youò  .COÍ +                          fileó properly. + +     ZMD  .COM‚  Maiî filå  transfeò  program®  Leavå + ZMD .Z80  thió onå onlinå foò publiã uså (Usuallù +                          A0:)® Iô provideó fulì systeí securitù +                          whilå   presentinç   á  useò   freindlù +                          interfacå  tï  uploadó  anä  downloads® +                          YMODEÍ 1ë anä YMODEÍ 1ë  Batch¬  XMODEÍ +                          12¸  bytå  CRC¬  anä  XMODEÍ  12¸  bytå +                          checksuí  arå supporteä witè  automatiã +                          protocoì detect. +.pa Š +     Filenamå Kâ CRà Purpose + ZMAP .COM Publiã upload/downloaä matriø displaù +     ZMAP .Z80          program®  Alsï  completelù  installablå +                          witè thå ZINSTÌ program®  Privatå areaó +                          are shown only if WHEEL byte is on. + +     ZFORS .COM Sysoð descriptioî filå utility® Thió +     ZFORS .Z80 onå    allowó   thå   Sysoð   tï    adä +                          descriptionó  tï thå FOÒ texô filå  (oò +                          BBÓ  messagå base)®  Thió prograí wilì +                          noô   ruî   unlesó   descriptionó   arå +                          enabled. + +     ZNEWÓ .COM‚ Sysoð filå transfeò loç utility® Thió +     ZNEWS .Z80 onå  allowó  thå Sysoð  tï  appenä  thå +                          ZMD.LOÇ  filå witè á ne÷ uploaä  entry® +                          Thió  procedurå  currentlù  supportó  ± +                          entry per program run. + +     ZMDEÌ .COM‚ Sysoð filå transfeò loç purgå utility® +     ZMDEL .Z80 Cleanó  thå ZMD.LOÇ filå oæ alì entrieó +                          excepô foò "R¢ uploadeä entries®  Thió +                          keepó  thå  loç filå  aô  á  reasonablå +                          size. + +     ZNEWР .COM‚ Publiã filå transfeò loç utilitù allowó +     ZNEWP .Z80 calleró  tï quicklù vie÷ statisticó  oæ +                          recenô  uploadó sucè aó thå drive/user¬ +                          filå sizå iî kilobytes¬  datå oæ uploaä +                          (iæ  clock/datå optionó  arå  enabled)¬ +                          etc®  Thió  prograí ió usuallù  placeä +                          on A0:. + +     ZFORР .COM‚ Publiã uploaä descriptioî search anä +     ZFORP .Z80 displaù  utility®  Useró  caî vie÷  thå +                          descriptionó   onlinå  oæ   thå   fileó +                          recentlù   uploaded®   Strinç   searcè +                          capabilitieó  arå  supporteä  tï  allo÷ +                          'picking§ thå descriptionó desired®  Á +                          calleò    caî    quicklù    vie÷    alì +                          descriptionó pertaininç tï 'IBM'¬ 'Z80§ +                          oò anù strinç thaô wilì fiô oî thå hosô +                          system'ó   commanä   line®   Multiplå +                          strinç searcè ió alsï supported¬  aó ió +                          datå  searcheó (iæ enabled©  anä  fileó +                          locateä  iî  á specifiã drive/useò  (iæ +                          thaô  featurå  ió  enabled)®   Á  nicå +                          companion for ZMD. + + +.pa Š + + + + + + + + + + + + + + +     ------------------------------------------------------------ +     NOTEº  Tï  prevenô possiblå discrepencieó withiî thå ZMDSUBÓ +     subroutineó file¬  alì programó havå beeî designeä tï  aborô +     witè  erroò iæ thå program'ó maiî featurå ió disabled®  Foò +     example¬  ZFORÓ  wilì  noô ruî unlesó iô haó beeî  installeä +     witè descriptionó enabled® ZMÄ caî noô bå disabled¬ howeveò +     wilì  aborô  witè erroò iæ thå modeí I/Ï  routineó  arå  noô +     found® Pleaså dï noô trù tï disable thió prograí function. +     ------------------------------------------------------------ +.pa Š +     3.0 Installation + +     3.1 Local CRT Clear Screen Sequences + +     CLRSCRΠ seô  tï  YEÓ enableó ZMÄ anä alì utilitù  fileó  tï +     cleaò  youò screeî locallù durinç batcè filå  transferó  anä +     menõ displays®  Iæ youò terminaì requireó á ^Ú (1AH)¬  leavå +     CLRSTR‚ alone® Otherwiså yoõ wilì havå tï includå youò cleaò +     screeî sequencå aô labeì CLRSTR® Uð tï ¶ byteó arå allowed. +     This CLS sequence is terminated with a '$'. + +     STOPº Iæ runninç ZMÄ anä utilitieó aó á stanä alonå packagå +     anä  youò  locaì  consolå outpuô vectoò  addresó  cannoô  bå +     calculateä  usinç standarä CP/Í conventionó (i.e®  youò BIOÓ +     JР tablå haó beeî altered)¬  yoõ wilì neeä tï providå  thå +     addresó yourselæ aô labeì CONOUÔ iî youò port/modeí overlay® +     Thió ió cruciaì tï ZMÄ eveî wheî noô usinç thå cleaò  screeî +     featurå  aó thå recorä counô ió displayeä locallù durinç thå +     filå transfeò anä anù outpuô oæ thió naturå tï thå modeí  aô +     thió timå woulä causå seriouó problems. + + +     3.2 Input/Output + +     3.2.1 Modem + +     ZMÄ provideó fulì supporô foò thå Extendeä BDOÓ calló seô uð +     bù  somå  Remotå Consolå Programó sucè aó BYEµ  oò  MBYE44+® +     Iî ordeò tï uså thió method¬ simplù skið thå overlaù procesó +     outlineä iî APPENDIØ A® Iæ nï overlaù ió included¬ ZMÄ wilì +     uså  BYE'ó modeí I/Ï routineó alreadù  established®  Iæ  aî +     attempô  tï seô thå currenô useò areá tï 24± returnó á valuå +     oæ  7· iî registeò A¬  thå followinç calló tï BDOÓ  musô  bå +     handled by your BYE program: + +      BDOS +      Call Function +      ---- --------------------- +      61 Check receive ready +      62 Check send ready +      63 Send a character +      64 Receive a character +      65 Check carrier +      66 Console status +      67 Console input +      68 Local console output  + +     Iæ  youò BYÅ prograí doeó noô seô uð it'ó modeí I/Ï routineó +     foò  publiã  accesó bù outsidå programs¬  yoõ wilì  havå  tï +     follo÷  thå  overlaù  procedurå outlineä iî  APPENDIØ  Á  oî +     Modem Interface‚ tï instalì youò modeí routines. + +     NOTE:‚  Thió  featurå ió fullù automatic®  Nï  matteò  whicè +     methoä  yoõ use¬  ZMÄ wilì know® Š +     3.2.2 Microprocessor Speed + +     MHÚ  ió  defineä tï represenô youò  system'ó  microprocessoò +     speed® Thió allowó ZMD tï accuratelù timå delayó anä sleepù +     calleò timeouts® Musô bå integeò valuå iî thå rangå oæ 1-9. + + +     3.2.3 Modem Speed Indicator Byte + +     MSPEEÄ  shoulä  contaiî  thå  addresó oæ  youò  modeí  speeä +     indicatoò  byte®  Thió ió needeä sï thaô ZMÄ caî  calculatå +     thå  amounô  oæ timå needeä foò transferó anä  foò  transfeò +     speeä  insertioî iî thå loç filå entry®  Youò  BYÅ  prograí +     shoulä  stufæ  thió integeò valuå somewherå  iî  memory®  Aî +     integeò valuå oæ 1-¹ musô corresponä aó illustrated: + +          Value Bps Value Bps +      ----- ------- ----- ------- +      1 300 7 4800 +      5 1200 8 9600 +      6 2400 9 19200 + + +     3.2.4 Disk Write Lock Flag +      +     WRTLOà ió  thå higè memorù bytå togglå useä  foò  disablinç +     BYE'ó  abilitù  tï hanç uð wheî thå caller'ó timå ió  uð  oò +     carrieò ió lost®  Thió allowó currenô disë writå operationó +     tï  bå completeä first®  Checë youò BBÓ documentatioî - manù +     moderî systemó don'ô neeä this®  Iæ unsure¬ seô thió tï NO® +     Codå  tï seô anä reseô thió togglå assumeó iô tï bå  locateä +     LOCOFÆ byteó froí thå JÐ COLDBOOÔ vectoò aô thå beginninç oæ +     thå BYÅ BIOÓ jumð table® (YEÓ foò MBBÓ anä PBBS). +      + +     3.2.5 Sleepy Caller Timeout + +     DESWAIÔ  ió  thå numbeò oæ minuteó oæ inactivitù  durinç  aî +     uploaä  descriptioî oò anù prompô beforå abortinç thå  inpuô +     routine®  (0-255¬  ° disableó thió feature)®  Iæ á timeouô +     occuró durinç descriptioî entry¬  thå currenô disë buffeò ió +     writteî tï disë anä thå prograí exitó tï CP/Í givinç controì +     back to your BYE program (if WRTLOC is YES). + + +     3.2.6 Minimum Speed for 1k Blocks + +     MINKSPD‚ ió thå minimuí modeí speeä alloweä tï transfeò fileó +     usinç 1ë blocks®  Iæ oî á networë sucè aó Pà Pursuit¬  anä +     arå ablå tï receivå incominç calls¬ seô thió bytå tï 1® Thå +     delayó  theså networkó uså tï senä datá bacë anä fortè  makå +     1ë packetó advantageouó tï eveî 30° bpó users®  Iæ noô oî á +     networë sucè aó Pà Pursuit¬ it'ó á matteò oæ preference¬ Seå + illustratioî iî figurå 3.2.³ foò lisô oæ modeí speeä values. Š +     3.2.7 File Transfer Buffer Queue + +     BUFSIÚ  allowó yoõ tï changå thå numbeò oæ 1ë blockó  beforå +     writinç  buffeò tï disk®  Normaì disë systemó caî  transfeò +     16ë  froí computeò tï disë iî 2-3-´ secondó  oò  less®  Somå +     verù  slo÷  5-1/4¢ floppù systemó (sucè aó Nortè  Star©  maù +     takå uð tï 20-3° secondó tï transfeò 16k®  Thió woulä causå +     severaì timeoutó aô 1° secondó each®  Iæ yoõ experiencå anù +     timeouts¬ trù changinç thió tï somethinç smaller¬ perhapó 8ë +     oò eveî 4k. +      + +     3.2.8 Page Pausing + +     PAGLEΠ ió seô tï thå numbeò oæ lineó tï displaù iî  betweeî +     [moreÝ  pauseó  anä menõ displays®  (Seô tï  °  tï  disablå +     page pauses. + + +     3.2.9 Automatic Calculation of Disk Buffer Size + +     STDBUF‚ enableä telló ZMÄ programó tï calculatå thå amounô oæ +     memorù  availablå  foò  routineó  usinç  DBUÆ  disë  buffer® +     OUTSIÚ  wilì adjusô accordinç tï thå contentó oæ locatioî  ¶ +     anä 7® Iæ BYÅ ió running¬ thió valuå ió useä aó is¬ elså iæ +     BYÅ  ió NOT‚ running¬  0806È ió subtracteä froí thió  addresó +     locatioî ¶ anä 7®  Iî eitheò case¬ thå enä oæ prograí valuå +     determineä aô timå oæ assemblù ió subtracteä froí thå resulô +     oæ  thå abovå tï situations®  Leftoveò byteó iî Ì arå  theî +     discardeä tï leavå aî eveî pagå boundary. + + +     ------------------------------------------------------------ +     NOTEº  MOSÔ  ALÌ systemó wilì benefiô witè STDBUÆ  enabled¬ +     sincå  maximuí  numbeò oæ uploadó alloweä iî  batcè  receivå +     modå  ió directlù relateä tï thå amounô oæ memorù available® +     However¬ Iæ youò systeí useó memorù locateä belo÷ thå CCÐ oò +     BYÅ program¬  yoõ wilì neeä tï disablå this¬  iî whicè  caså +     OUTSIÚ  wilì bå seô tï 16ë nï matteò what®  Iæ youò  systeí +     hangó   oò   behaveó  strangelù  durinç   descriptioî   filå +     read/writå operations¬ disablå thió - trù iô enableä first. +     ------------------------------------------------------------ + +.pa Š +     3.3 Timekeeping + +     3.3.1 BYE Clock Support + +     CLOCK‚  enableä  wilì  allo÷ ZMÄ anä  utilitieó  tï  looë  aô +     clocë  anä datå informatioî retrieveä bù BYÅ  (BYE5¬  MBYEnî +     anä MBYE44« witè extendeä BDOÓ enabled© froí youò systeí anä +     storeä  iî  higè  memory®  Thå addresó oæ thió  higè  memorù +     buffeò ió calculateä aó thå addresó aô (JÐ COLBOOT+25)®  Iæ +     yoõ seô thió tï YES¬ thå followinç informatioî ió retrieved: + + +      Location Contents Range +      +------------------+-----------------------+-------+ +      | (JP COLDBOOT+24) | Maximum time allowed  | 0-255 | +     | (JP COLDBOOT+25) | LSB of RTCBUF address | ----- | +     | (JP COLDBOOT+26) | MSB of RTCBUF address | ----- | +     +------------------+-----------------------+-------+ + + +------------------+-----------------------+-------+ +     | (RTCBUF+0) | Current hour | 0-23 | +     | (RTCBUF+1) | Current minute | 0-59 | +     | (RTCBUF+2) | Current seconds | 0-59 | +     | (RTCBUF+3) | Current century | 19 | +     | (RTCBUF+4) | Current year | 0-99 | +     | (RTCBUF+5) | Current month | 1-12 | +     | (RTCBUF+6) | Current day | 1-31 | +     | (RTCBUF+7©  | LSB oæ TOS | 0-255 | +     | (RTCBUF+8©  | MSB oæ TOS | ----- | + +------------------+-----------------------+-------+ + + Clock/datå  readeò codå insertó arå noô supporteä undeò thió +     configuration® ZMÄ programó supporô alì clock/datå featureó +     witè  thió switcè enableä anä clock/datå readeò codå  ió  iî +     BYE® + + +     3.3.2 ZMD Internal Clock/Date Reader Code + +     RTC‚  shoulä bå enableä iæ yoõ cannoô takå advantagå oæ BYE'ó +     RTCBUÆ  explaineä abovå anä yoõ wisè tï includå youò  systeí +     specifiã  clocë anä datå readeò codå aô labeì RTCTIÍ iî  thå +     ZMDHDR.Z8°  configuratioî table®  Bå surå tï initializå alì +     byteó  witè binarù valueó (seå Range‚ columî iî  tablå  3.3.± +     foò  minimuí anä maximuí values)®  BCDBIÎ maù bå  requesteä +     froí  ZMDSUBS.REÌ tï converô binarù codå decimaì valuå iî  Á +     registeò  tï  binarù valuå iî Á register®  Deletå alì  ';<=§ +     lineó  afteò youò codå ió installed®  Thió concepô ió  noô +     valiä  iæ CLOCË switcè ió enableä anä BYÅ ió  runninç  witè +     clocë anä datå readeò codå installed. + +     NOTEº  Makå  surå yoõ dï noô overruî thå modeí I/Ï  patcè +     area when you insert your clock code. +.pa Š +     3.3.3 Restricting Downloads to Time Left + +     TIMEON‚ switcè enableä telló ZMÄ tï restricô downloadó tï thå +     calleró  timå  lefô  oî system®  Iæ CLOCË  ió  enableä  anä +     MBYE/BYEµ  ió running¬  BYE'ó maximuí timå alloweä bytå (JÐ +     COLDBOOT+24©  ió useä foò comparison®  Iæ CLOCË ió  NÏ  (oò +     MBYE/BYE5©  anä RTà ió yes¬  MAXTOÓ shoulä bå pokeä bù  youò +     RTà insert®  Iæ CLOCË anä RTà arå botè NO¬  MAXMIÎ wilì bå +     useä  aó  á defaulô anä incrementeä oò decrementeä  aó  filå +     transferó occur. + + +     3.3.4 Maximum Minutes Allowed + +     MAXMIN‚  shoulä  bå seô tï youò likinç iæ CLOCË anä  RTà arå +     botè NO¬ anä TIMEOÎ ió YES® Thió valuå wilì bå thå default® +     Thió ió decremented/incrementeä eacè timå á filå transfeò ió +     madå  anä  thå  calleò  ió loggeä ofæ  wheî  iô  reacheó  0® + + +     3.3.5 Display Time on System Messages + +     DSPTIM‚ ió seô YEÓ tï havå timå oî systeí messageó  displayeä +     aô thå starô anä exiô oæ ZMD® Iæ CLOCË ió YES¬ anä MBYE/BYÅ +     ió  running¬  TOÓ ió gotteî froí BYE'ó TOÎ worä (iî RTCBUF)® +     Iæ  CLOCË ió NO¬  oò MBYE/BYEµ ió noô running¬  thå  currenô +     minuteó  alloweä  ió subtracteä froí thå originaì  valuå  oæ +     MAXMIÎ aô prograí startup®  Thå resulô ió displayeä aó timå +     on® Thió value ió actuallù á tallù: +      +      Original MAXMIN + upload time - download time = time on + + +     3.3.6 Logon Hour/Minute Addresses + +      LHOUR‚  ió thå addresó oæ thå caller'ó logoî  houò  bytå +     seô  bù  youò  BYÅ oò BBÓ prograí wheî thå calleò  logó  on® +     LHOUR+² ió thå logoî minute® Botè valueó containeä iî theså +     addresseó  shoulä bå iî binary®  Thió shoulä onlù bå seô iæ +     RTà anä eitheò TIMEOÎ oò DSPTOÓ arå seô YES® (Noô useä witè +     CLOCK). +.pa Š +     3.4 Access Restrictions + +     3.4.1 ZCMD/ZCPR + +     ZCPÒ (biô ° iî ACCMAP© shoulä bå seô tï YEÓ iæ yoõ intenä oî +     monitorinç  WHEEÌ bytå statuó oò neeä tï restricô  receivinç +     SYS¬  RCP¬  NDÒ filå types® Iæ thió biô ió seô NO¬ WHEEÌ ió +     alwayó 0. + + +     3.4.2 WHEEL Byte + +     WHEEÌ bytå togglå ió foò verù speciaì users® Iæ ZCPÒ ió seô +     tï YES¬  ZMÄ wilì monitoò thå bytå locateä aô thió address® +     Iæ it'ó 0¬ time¬ drive/user/filenamå anä accesó restrictionó +     remaiî iî force® Iæ thió bytå ió non-zero¬ alì restrictionó +     are bypassed. + + +     3.4.3 Maximum Drive/User + +     USEMAØ  shoulä  bå seô tï YEÓ iæ yoõ wanô tï uså ZCPR'ó  lo÷ +     memorù  byteó tï keeð tracë oæ maximuí drivå anä user®  ZMÄ +     wilì  uså  thå valueó aô locationó DRIVMAØ  anä  USRMAØ  foò +     maximuí  drive/user®  Iæ USEMAØ ió NO¬  hardcodå MAXDRÖ anä +     MAXUSÒ tï youò owî requirements. + + +     3.4.4 BYE/BBS Program Access Flag Byte + +     ACCESÓ  iæ  enabled¬  telló ZMÄ thaô youò BYE/BBÓ  softwarå +     supporô  aî  accesó  flagó  register®  Thió  flaç  registeò +     (AFBYTE©  ió ± datá bytå iî lengtè anä containó ¸ flaç  bitó +     correspdondinç  tï commoî BBÓ restrictions®  ZMÄ caî  checë +     thió  registeò  beforå  allowinç thå 'RM§ optioî  tï  uploaä +     preformatteä messagå fileó tï youò BBS'ó messagå base¬ oò tï +     uså  thå  'RW§ optioî foò 'privilegeä user§  uploaä  withouô +     beinç requireä tï givå uploaä descriptions®  Iæ enabled¬ seô +     ACCOFÆ  tï  reflecô thå numbeò oæ byteó froí JÐ COLDBOOÔ  tï +     AFBYTÅ  flagó byte®  ZMÄ inspectó AFBYTÅ foò  thå  followinç +     flaç data: + + + Bit: 7 6 5 4 3 2 1 0 + | | | | | | | | +  Privileged user ---* | | | | | | | + Uploaä -----ª ü ü ü ü ü ü ª Oæ theså bits¬ onlù 3¬ + Downloaä -------ª ü ü ü ü ü 5¬ ¶ anä · arå useä bù + CP/Í ---------« ü ü ü ü ZMD®  Biô numberó arå + Writå -----------ª ü ü ü poweró oæ 2¬  witè biô + Reaä -------------« ü ü ° beinç  thå  leasô + BBÓ ---------------« ü significanô biô oæ thå + System -----------------+ byte. +.pa Š +     3.5 Upload Configurations + +     3.5.1 Preformatted BBS Message Uploads + +     MSGFIÌ  switcè  enableó ZMÄ tï accepô  preformatteä  messagå +     filå  uploads®  Fileó uploadeä witè thå 'RM§ optioî wilì  bå +     forwardeä  tï  thå  drive/useò defineä aô PRDRÖ  anä  PRUSR® +     Thió uploaä ió theî appendeä tï youò BBÓ messagå base®  Youò +     BBÓ  softwarå  anä  BYÅ prograí musô supporô  thió  feature® +     MBBÓ, QBBS and PBBS all support this feature. PMSG/HMSG is + now available on RI RCPM-RDOS. + + +     3.5.2 Hiding New Uploads Until Approved by Sysop + +     HIDEIÔ allowó Sysopó tï keeð alì ne÷ regulaò uploadó  hiddeî +     froí  publiã viewinç untiì revieweä anä cleared®  Thió way¬ +     ne÷  uploadó  wilì  noô appeaò iî á  DIRectorù  listinç  anä +     cannoô bå vieweä oò eveî downloadeä bù ZMD® Thió featurå ió +     disableä wheî thå WHEEÌ bytå ió OÎ oò Privatå uploaä modå ió +     enabled®  Fileó  thaô  havå beeî hiddeî wilì sho÷ uð  iî  á +     DIRectorù listinç wheî thå WHEEÌ bytå ió seô anä á $Ó optioî +     ió  useä  tï sho÷ SYSTEÍ files®  Referencå wilì bå madå  tï +     theså  fileó iî thå loç anä FOÒ texô filå listingó iæ  thoså +     featureó  arå enabled®  Yoõ caî uså POWEÒ oò NSWEEÐ tï  seô +     hiddeî fileó tï $DIR. + + +     3.5.3 Upload Routing to Multiple Drive/Users + +     ASKAREÁ  switcè seô YEÓ enableó uploaä routinç  tï  multiplå +     drive/useò areas®  Witè thió enableä á calleò ió  displayeä +     á lisô oæ uploaä categorieó tï chooså from®  Wheî hå enteró +     hió selection¬  ZMÄ wilì calculatå thå offseô tï thå  uploaä +     drive/useò  iî TYPTBÌ anä seô thå uploaä areá baseä oî  hió +     selection®  Thió ió donå aô thå samå timå foò botè  Regulaò +     anä Privatå uploads)®  Uploaä routinç ió disableä wheî thå +     WHEEÌ bytå ió set¬ iî whicè case¬ normaì uploadó wilì gï tï +     thå  currenô drive/useò areá anä privatå uploadó wilì gï  tï +     thå drive/useò equateä aô PRDRÖ anä PRUSR. + + +     3.5.4 Uploading to Specified Drive/User + +     SETAREÁ  enableä  forceó alì ne÷ uploadó tï  thå  drive/useò +     defineä aô DRV‚ anä USR®  Iæ thå WHEEÌ bytå ió set¬  regulaò +     uploadó wilì gï tï thå currenô oò specifieä drive/user® Alì +     privatå  fileó uploadeä witè thå 'RP§ optioî wilì bå senô tï +     PRDRÖ anä PRUSÒ regardlesó oæ WHEEÌ status. + +.pa Š +     3.5.5 Receiving Private Uploads + +     PRDRÖ anä PRUSÒ arå thå drive/useò areá wherå ALÌ fileó senô +     tï  thå Sysoð witè thå 'RP§ optioî wilì gï  (unlesó  ASKAREÁ +     ió YES)® Thió permitó experimentaì files¬ replacemenô and/oò +     proprietarù  programó tï bå senô tï aî areá onlù  accessiblå +     bù  thå  Sysop®  Thió ió alsï thå drivå anä useò areá  wherå +     messagå  fileó  arå  uploaded¬  iæ MSGFIÌ ió  seô  YES®  Iæ +     ASKAREÁ ió YES¬ 'RP§ uploadó wilì gï herå onlù iæ thå WHEEÌ +     ió set®  Iæ MSGDESà ió YES¬  thió ió thå drivå anä useò areá +     thå FOÒ texô filå wilì bå placeä beforå appendinç iô tï  thå +     BBÓ system'ó messagå base. + + +     3.5.6 Crediting Upload Time to Time Left + +     CREDIÔ  enableä  causeó ZMÄ tï crediô calleró foò  thå  timå +     theù  spenä uploadinç non-privatå fileó eacè  session®  Foò +     example¬  á  calleò whï spendó 3° minuteó sendinç aî  uploaä +     getó  3° minuteó addeä tï hió TLOS®  (Yoõ musô  seô  eitheò +     CLOCK¬ RTà oò TIMEOÎ tï YEÓ tï uså thió feature). + + +     3.5.7 Receiving .COM Files Securely + +     NOCOMÒ  telló ZMÄ tï renamå .COÍ fileó tï .OBÊ anä  .PRÌ  tï +     .OBР oî  receive®  Thió featurå ió alsï disableä wheî  thå +     WHEEÌ bytå ió set. + +.pa Š +     3.6 Upload Descriptions + +     Thió sectioî haó tï dï witè uploaä descriptions®  Iæ yoõ dï +     noô intenä oî implementinç uploaä descriptions¬  seô DESCRI +     anä  MSGDESà tï  NO®  Thå resô oæ  theså  valueó  arå  theî +     ignored®  Iæ  usinç descriptions¬  seô ONLÙ onå oæ theså tï +     YES¬ noô both. + + +     3.6.1 Forwarding Descriptions to BBS Message Base + +     MSGDESà shoulä bå seô YEÓ iæ youò youò BBÓ systeí  supportó +     messagå  uploads¬  anä yoõ prefeò uploaä descriptionó tï  bå +     placeä iî youò BBÓ messagå baså (seô DESCRI NO)® MBBÓ useró +     neeä  tï instalì MFMSG.COÍ witè thå MBBSINIÔ program®  Theî +     seô  youò BYÅ prograí tï kno÷ abouô messagå filå uploadó  bù +     settinç thå MSGFIÌ optioî iî BYE/MBYÅ tï YES®  Iæ seô  YES¬ +     ZMÄ  wilì  producå  á  FOÒ texô  filå  wheî  writinç  uploaä +     descriptions®  Thió  FOÒ filå wilì gï tï thå drivå anä  useò +     areá  equateä aô PRDRÖ anä PRUSÒ jusô beforå beinç  appendeä +     tï youò BBÓ system'ó messagå base. + + +     3.6.2 Forwarding Description to FOR Text File + +     DESCRI  switcè shoulä bå YEÓ iæ yoõ wanô descriptionó tï bå +     appendeä tï thå currenô FOÒ filå wherå theù caî bå vieweä bù +     calleró   witè  thå  ZFORР utility®   Sysoð  caî  adä   ne÷ +     descriptionó  witè thå ZFORÓ utility®  Uploadó senô tï  thå +     Sysoð privatå uploaä areá wilì noô requirå descriptions¬ noò +     wilì  fileó uploadeä witè thå 'RW§ optioî - useò musô  bå  á +     privilegeä  useò  (biô · iî ACCESÓ bytå set© oò  havå  WHEEÌ +     accesó anä PUPOPÔ musô bå seô YEÓ tï uså thå 'RW§ option. + + +     3.6.3 Description Filename + +     FORNAM/DRIVE/USEÒ  ió thå drive/useò anä filenamå oæ thå FOÒ +     descriptioî  texô  file®  Thió filenamå musô  bå  1±  byteó +     paddeä witè spaces® Iæ usinç witè DESCRI seô YES¬ yoõ musô +     indicatå  whaô  drive/useò  yoõ wanô thå 'FOR§  filå  tï  bå +     placed®  Drive/useò areá ió automaticallù changeä tï  PRDRÖ +     anä  PRUSÒ  iæ descriptionó arå tï bå forwardeä tï  thå  BBÓ +     messagå baså + +.pa Š +     3.6.4 Upload Description Header Information + +     Iæ  youò configuratioî includeó DESCRI seô tï  YES¬  you'lì +     havå  tï telì ZMÄ whaô informatioî yoõ wanô includeä iî  thå +     firsô linå oæ eacè description® Codå ió includeä iî alì ZMÄ +     programó  tï  placå  alì  (any© informatioî  iî  thå  uploaä +     descriptioî header® Thå followinç diagraí illustrateó á fulì +     implementatioî oæ DESCRIB: + + +  ----- +  ZMD150.LBR - Communications (C3:) Rcvd: 09/29/88 + / / / + _______/ _______/ _____/ + ASKIND INCLDU DSTAMP + + + +     3.6.5 Including File Descriptors + +     ASKINÄ  switcè  enableä causeó ZMÄ programó tï asë  foò  thå +     categorù  oæ  thå  upload(s© anä writå iô  intï  thå  uploaä +     descriptioî header®  Iæ yoõ seô thió tï YES¬  makå surå yoõ +     seô  MAXTYÐ tï thå highesô letteò choicå yoõ wisè tï supporô +     anä ediô thå texô aô KNDTBÌ uð tï anä includinç youò  MAXTYÐ +     setting® (Useä onlù witè DESCRIB). + + +     3.6.6 Including Upload Drive/User Area + +     INCLDÕ  enableä  wilì  includå thå drive/useò  areá  oæ  thå +     uploadeä filå intï thå uploaä descriptioî header® (Useä onlù +     witè DESCRIB). + + +     3.6.7 Datestamping the Description Header + +     DSTAMÐ enableä wilì includå thå datå thå uploaä waó receiveä +     intï thå uploaä descriptioî header®  (NÏ iæ nï clock© (Useä +     onlù witè DESCRIB). + + +     3.6.8 Overriding Description requests + +     PUPOPÔ  allowó descriptionó tï bå disableä wheî "RW¢ ió useä +     oî thå ZMÄ commanä linå (i.e® ZMÄ R× FILE.EXT)® Thió commanä +     maù  onlù bå useä bù thoså considereä "priviledged¢ useró oî +     youò  systeí oò WHEEÌ users®  Uploadó oæ thió typå wilì  bå +     taggeä iî thå ZMD.LOÇ filå aó private¬  sï aó noô tï displaù +     witè thå NE× command®  (Seå ACCESÓ equatå descriptioî abovå +     foò informatioî oî detecting 'priviledged§ users). + +.pa Š +     3.6.9 Automatic Word Wrap + +     WRAР ió  seô tï thå columî positioî wherå  worä  wrað  wilì +     occur®  Iæ usinç MSGDESà anä havå problemó witè aî 'Invaliä +     format§ erroò froí MFMSG.COM¬  trù settinç WRAÐ tï somethinç +     smaller¬  likå 6² oò 63® (Worä wrað caî bå disableä bù thå +     useò  witè ^× durinç descriptioî entry®  Enteò 7²  herå  tï +     disablå WRAÐ completely). + +.pa Š +     3.7 Download Configurations + +     ACCMAР ió á biô mappeä flaç registeò ± bytå iî length®  Iô +     containó  ¸  flaç  bitó whicè  enable/disablå  thå  filenamå +     restrictionó  outlineä  below®   Thå  restrictionó   alwayó +     pertaiî tï thå filå beinç considereä foò transfer® Enablinç +     anù  oæ theså optionó causeó ZMÄ tï looë aô thå higè biô  oæ +     thå  bytå  positioî  indicateä belo÷  (F1=filenamå  bytå  1¬ +     T2=filå  typå bytå 2¬  etc)®  Theså restrictionó arå alwayó +     bypasseä wheî usinç ZCPÒ anä thå WHEEÌ ió set. + + +     3.7.1 Restricting .LBR and Single F1 Tagged Files + +     TAGFIL‚  switcè  ió enableä iæ yoõ wanô tï  restricô  calleró +     froí downloadinç certaiî files¬  sucè aó verù largå  overlaù +     libraries¬  gamå libraries¬  etc®  Iî mosô cases¬ remaininç +     timå  lefô  oî  systeí woulä bå sufficienô  foò  restrictinç +     downloads®  However¬ witè biô · oæ ACCMAÐ seô tï 1¬ ZMÄ wilì +     checë  thå  higè biô oæ filenamå bytå ± anä iæ thió ió  set¬ +     thå  filå  maù  noô  bå  downloaded®   Iæ  thå  filå  ió  á +     ARK/ARC/LBÒ  file¬  individuaì  memberó  maù  bå  downloadeä +     however®  Thió restrictioî ió bypasseä iæ thå WHEEÌ bytå ió +     set. + +      ACCMAP Switch: 10000000 +      Filename Byte: FILENAME.EXT +      + +     3.7.2 Disallowing .COM Downloads + +     NOCOMÓ  shoulä bå enableä iæ yoõ dï noô wanô calleró  tï  bå +     ablå  tï  downloaä *.COÍ files®  Mosô securå  systemó  wilì +     enablå  thió  restriction®  Thió featurå ió  bypasseä  wheî +     WHEEL byte is set. + +      ACCMAP Switch: 00001000 +      Filename Byte: FILENAME.EXT + + +     3.7.3 Disallowing .??# Downloads + +     NOLBÓ ió enableä foò thoså systemó whicè uså 'labels§ iî thå +     thirä  filå  extenô bytå oæ systeí fileó tï restricô  publiã +     accesó tï them® ZMÄ wilì checë T³ bytå foò á '#§ characters® +     Upoî  á  match¬  thå downloaä ió denied®  Thió  featurå  ió +     bypassed when the WHEEL byte is set. + +      ACCMAP Switch: 00010000 +      Filename Byte: FILENAME.EXT + +.pa Š +     3.7.4 Disallowing F2 Tagged $SYStem File Downloads + +     NOSYÓ  enableä telló ZMÄ tï ignorå alì fileó witè  thå  higè +     biô seô iî filenamå bytå T2®  Theså fileó arå considereä aó +     hiddeî $SYSteí fileó bù CP/Í anä caî bå treateä thå samå waù +     bù ZMD® Thió featurå ió bypasseä wheî thå WHEEÌ bytå ió set. + +      ACCMAP Switch: 00100000 +      Filename Byte: FILENAME.EXT + + +     3.7.5 Sending F3 Tagged Files Regardless of Access + +     DWNTAÇ  iæ enableä allowó anù filå witè thå higè biô seô  iî +     filenamå bytå ³ tï bå senô regardlesó oæ thå calleró access. +     Thió comeó iî verù handù foò closeä systemó requirinç  useró +     tï  downloaä  applications¬  systeí informatioî  files¬  BBÓ +     lists, etc. + +      ACCMAP Switch: 01000000 +      Filename Byte: FILENAME.EXT + + +     3.7.6 Special Sysop Downloads to Selected Caller + +     SPDRÖ  anä SPUSÒ contaiî thå drive/useò areá foò downloadinç +     privatå  'SP§ fileó froí Sysop®  Thió permitó you tï puô  á +     speciaì 'non-public§ filå iî thió area¬ theî leavå á privatå +     notå tï thå persoî iô ió intendeä foò mentioninç thå namå oæ +     thå  filå anä ho÷ tï downloaä it®  Althougè anybodù 'could§ +     downloaä thaô program¬  theù don'ô kno÷ whaô (iæ any©  fileó +     arå  there®  Á higè degreå oæ securitù exists¬  whilå  thå +     Sysoð stilì haó thå abilitù tï makå speciaì fileó available® +     Thuó anù persoî caî bå á temporarù 'privilegeä user'. + +     NOTEº Á breacè oæ securitù existó iæ SPUSÒ ió noô defineä aó +     á  higheò useò areá thaî thå maximuí allowablå  publiã  useò +     area.‚ + +.pa Š +     3.8 Logkeeping + +     Á clocë ió not necessary for this logkeeping features. + + +     3.8.1 Making ZMD.LOG File + +    LOGCAL‚ enableó thå loç keepinç routineó iî ZMD® Ne÷ uploadó +     wilì bå addeä tï thå currenô ZMD.LOÇ file®  Iæ nï loç  filå +     exists¬ onå wilì bå created® Alì filå transferó arå logged® +     Yoõ  caî  theî  uså  ZNEWP.COÍ tï sho÷  listingó  oæ  recenô +     uploadó oò ZNEWÓ tï adä loç entries. + + +     3.8.2 European Date Format (DD/MM/YY) + +     EDATE‚  causeó  ZMÄ anä utilitieó tï sho÷  datå  iî  dd/mm/yù +     formaô insteaä oæ mm/dd/yù format. + + +     3.8.3 Transfer Log Drive/User/Filename + +     LOGNAM/LOGDRV/LOGUSR‚  ió thå drive/useò anä filenamå oæ  thå +     ZMD.LOÇ  filå transfeò log®  Thió filenamå musô bå 1± byteó +     paddeä witè spaces®  Iæ usinç witè LOGCAÌ seô YES¬ yoõ musô +     indicatå  whaô drive/useò yoõ wanô thå 'ZMD.LOG§ filå tï  bå +     placed® + + +     3.8.4 LASTCALR Drive/User + +     LASTDRV/LASTUSR/LCNAME‚  ió thå drive/useò oæ youò BBÓ oò BYÅ +     program'ó LASTCALR.??¿ file® Thió filenamå musô bå 1± byteó +     paddeä witè spaces®  Iæ usinç witè LOGCAÌ seô YES¬ yoõ musô +     indicatå whaô drive/useò ZMÄ caî finä thå LASTCALR.??¿ file® +     LCNAMÅ shoulä bå seô tï thå columî positioî oæ thå  caller'ó +     namå iî thå LASTCALR.??¿ file® (° foò PBBS¬ 1± foò MBBS). + + +     3.8.5 Counting Files Transfers for BBS Software + +     LGLDS‚  seô YEÓ enableó sessioî uploaä anä downloaä counting® +     ZMÄ  wilì counô thå numbeò oæ up/downloadó foò  eacè  logon® +     Youò  BBÓ  prograí theî caî checë UPLDS‚  anä  DNLDS‚  counteò +     byteó wheî á useò logó ouô anä updatå eitheò thå user'ó filå +     oò á filå foò thió purpose®  Yoõ caî eitheò modifù youò BBÓ +     entrù prograí tï checë thå LASTCALÒ filå beforå updatinç anä +     theî  updatå  (risky)¬  oò makå á separatå prograí thaô  BYÅ +     calló wheî logginç ofæ á useò (preferred)®  (YEÓ foò PBBS)® +     Don'ô forgeô tï initializå UPLDÓ anä DNLDÓ counteò byteó  tï +     ° froí youò BBÓ prograí wheî somebodù logó in. + +     NOTEº  Cleaò  thå UPLÄ anä DNLÄ byteó ONLÙ wheî á useò  logó +     in¬ noô wheî hå re-enteró thå BBÓ prograí froí CP/M. Š + + + + + + + + + + + + + + + + + + + + + + +      APPENDICES + +.pa Š +     A.1 Modem Interface + + A.1.1 Creating ZMD Modem Input/Output Overlays + +     Alì  port/modeí overlayó arå alloweä 12¸ byteó betweeî  580È +     anä 5FFH®  Thió areá ió alwayó containeä iî thå  ZMDHDR.Z8° +     configuratioî   tablå  anä  includeä  durinç  thå   assemblù +     process®  Thå firsô 27 byteó oæ thió overlaù musô contaiî  ¸ +     JÐ instructionó iî thå followinç order: + + +      Routine Purpose Entry Exit +      -------------------------------------------------------- +      CONOUT Local console output (BIOS) A=char ----- +      INIT Initialization ----- ----- +      UNINIT Uninitialization ----- ----- +      SNDCHR Send character POP AF gets->A=char ----- + CARCHË Carrier check ----- Z=Carrier +      GETCHÒ  Receive a character ----- Char in A +      RCVRDÙ  Check receive ready ----- Z=char +      SNDRDÙ  Check send ready ----- Z=ready + + + A.1.2 Installing Your Modem I/O Overlays + +     ZMÄ musô havå accesó tï youò modeí foò obviouó reasons®  Iô +     needó tï senä data¬  receivå data¬  perforí erroò  checking¬ +     monitoò  carrieò  anä givå controì bacë tï youò BYÅ  prograí +     wheî  carrieò  ió lost®  Iô haó tï kno÷ wheî thå  modeí  ió +     readù  tï  senä  anotheò  characteò anä wheî  onå  haó  beeî +     received® Iæ youò systeí useó extendeä BDOÓ calló tï accesó +     youò BYÅ programó port/modeí routines¬  yoõ caî instalì  ZMÄ +     anä  utilitieó withouô regarä tï thió  section®  Otherwise¬ +     follo÷ these steps: + +      1©  Finä aî overlaù froí ZMDOVLn.LBÒ thaô besô fitó youò +      modem/porô requirements® Yoõ maù havå tï creatå onå +      foò youò systeí iæ onå doesn'ô exisô already® Some +      standarä  formató arå includeä (seå -OVERLAY.LSÔ  iî +      the ZMDOVLn.LBR). +    2©  Ediô iô witè youò favoritå wordprocessoò aó needed® +      Makå  surå yoõ locaì consolå outpuô  addresó  (BIOS© +      caî bå calculateä usinç standarä CP/Í methodó  (i.e® +      (JР COLDBOOT+9©  Iæ  youò BIOÓ JР TABLÅ  haó  beeî +      altered¬  yoõ  wilì havå tï providå thió addresó foò +      ZMÄ  aô labeì CONOUT®  Iî mosô cases¬  ZMÄ wilì  bå +      ablå tï calculatå thió addresó foò you® Iæ yoõ wilì +      neeä  tï  initializå anythinç aô prograí  starô  up¬ +      includå  youò custoí routinå aô labeì INIÔ anä  youò +      uninitializå  routinå aô UNINIT®  INIÔ ió calleä aô +      prograí startup¬  anä oæ courså UNINIÔ ió calleä aô +      prograí exit. +.pa Š      3© Assemblå witè M80¬ oò SLRMAà oò otheò Z8° compatiblå +      assembler to produce ZMxx-n.HEX +    4© Uså MLOAÄ (included© tï loaä ZMxx-n.HEØ oveò ZMD.COÍ +      likå this: + +      A0>MLOAD ZMD=ZMD.COM,ZMxx-n + + +     ZINSTÌ wilì no÷ recognizå youò modeí overlay®  Yoõ caî alsï +     uså  DDÔ tï patcè youò overlaù in®  Makå surå iô startó  aô +     580H and ends by 5FFH (128 bytes). + +     NOTEº  Iæ ZMÄ attemptó tï seô thå currenô useò areá tï  24± +     anä 7· ió returneä iî registeò A¬  BYE'ó extendeä BDOÓ calló +     will be used for modem I/O. +.pa Š +     B.1 RTC Clock/Date Reader Code + +     Á fe÷ oæ ZMD'ó nicå featureó arå dependenô upoî accesó tï  á +     Reaì Timå Clock®  MBYÅ anä BYEµ useró whï havå theiò  clocë +     anä  datå  readeò codå installeä neeä onlù seô CLOCË tï  YEÓ +     anä  leavå RTà seô NO®  Iæ oî thå otheò hanä youò BYÅ  doeó +     noô  reaä youò systeí clock¬  yoõ wilì havå tï  inserô  youò +     clocë  anä  datå readeò codå aô labeì RTCTIÍ iî  ZMDHDR.Z80® +     Witè  RTà seô  YES¬  alì ZMÄ routineó havå  accesó  tï  thå +     followinç binary valueó (pokeä bù youò clocë insert): + + +      Address Length Range +      +---------+--------+-------+ +      | MONTH | 1 byte | 1-12 | +      | DAY  | 1 byte | 1-31 | +      | YEAR  | 1 byte | 0-99 | +      | HOUR  | 1 byte | 0-23 | +      | MINUTE | 1 byte | 0-59 | +      +---------+----------------+ + + + Youò inserô musô starô aô 4FEÈ anä enä bù 57FÈ (13° bytes). +.pa Š +     C.1 File Descriptors/Categories + +     Thió  tablå  defineó  thå  texô tï  bå  includeä  iî  uploaä +     descriptioî  headeró  (DESCRI  anä ASKIND©  and/oò  defineó +     categorieó  foò uploadinç tï multiplå drive/useò  areaó  (Iæ +     ASKAREA)®  Changå aó desired¬ iæ thió lisô ió noô suitable® +     Dï  NOÔ  removå anù oæ thå texô aô KNDTBL®  Simplù ediô  thå +     categorù  texô  belo÷ uð to/includinç youò  MAXTYР setting® +     MAXTYP‚  belo÷  musô bå seô tï whateveò letteò  youò  maximuí +     choicå wilì be® + + +     MAXTYP: DB 'W' ; Highest category you will support. + +     KNDTBL: + +     DB ' A) - CP/M Utility ',CR,LF + D ' B© - CP/Í Applicatioî ',CR,LF +     D ' C© - CP/Í Gamå ',CR,LF +     D ' D© - Wordprocessinç ',CR,LF + DB ' E) - Text & Information ',CR,LF + DB ' F) - Printer Related ',CR,LF + DB ' G) - Communications - IMP ',CR,LF + DB ' H) - Communications - MEX ',CR,LF + DB ' I) - Communications - Other',CR,LF + DB ' J) - RCP/M Software ',CR,LF + DB ' K) - BBS List ',CR,LF + DB ' L) - ZCPR1/2/3 ',CR,LF +     DB ' M) - Pascal Utility/Source ',CR,LF + DB ' N) - dBase Utility/Source ',CR,LF + DB ' O) - Basic Utility/Source ',CR,LF + DB ' P) - ''Other'' Language ',CR,LF + DB ' Q) - EPSON Specific ',CR,LF + DB ' R) - ZMD Support ',CR,LF + DB ' S) - IBM Utility ',CR,LF + DB ' T) - IBM Application ',CR,LF + DB ' U) - IBM Game ',CR,LF + DB ' V) - IBM Communications ',CR,LF + DB ' W) - Mixed Batch/Misc ',CR,LF + DB ' X) - <<<< Not Defined! >>>>',CR,LF + DB ' Y) - <<<< Not Defined! >>>>',CR,LF + DB ' Z) - <<<< Not Defined! >>>>',CR,LF + DB 0 ; leave the table terminator alone. + + +     ------------------------------------------------------------ +     NOTEº  Makå surå yoõ leavå alì thå categorieó abovå EXACTLÙ +     3±  byteó lonç (2¹ byteó oæ texô pluó thå CR,LÆ equaló  31© +     oò yoõ wilì havå problemó witè thå doublå columî  formattinç +     routines. +     ------------------------------------------------------------ +.pa Š +     D.1 Upload Routing Table + +     Iæ  yoõ decideä tï enablå uploaä routinç tï  multiplå  drivå +     users¬ yoõ wilì havå tï seô thå followinç tablå foò youò owî +     requirements®  Ediô  alì areaó aô TYPTBÌ uð tï anä includinç +     youò  MAXTYР setinç  tï matcè thå messagå  texô  iî  KNDTBÌ +     above® Notå thaô PRIVATÅ uploadó maù bå senô tï á differenô +     drivå  aó  welì aó á differenô useò  area®  Eacè  entrù  ió +     expresseä aó 'drivå letter',useò area® Simplù seô MAXTYÐ tï +     thå  highesô letteò choicå supported®  (Dï NOÔ commenô  ouô +     anù oæ theså storagå bytes). + + _________ + NOTE: / A \ <--- Corresponds to category 'A' + 'A',1,'B',15, + \ / \ / + Normal upload --+ | + Private upload -------+ + + + TYPTBL: + _________ _________ _________ _________ + / A \ / B \ / C \ / D \ + DB 'A',1,'B',15, 'A',2,'B',15, 'B',2,'B',15, 'B',4,'B',15 + _________ _________ + / E \ / Z \ + DB 'B',3,'B',15, ... thru ... 'B',7,'C',12 + + + \ No newline at end of file diff --git a/Source/Apps/ZMD/zmd.z80 b/Source/Apps/ZMD/zmd.z80 new file mode 100644 index 00000000..c47274a7 --- /dev/null +++ b/Source/Apps/ZMD/zmd.z80 @@ -0,0 +1,4858 @@ +; + + TITLE ZMD.Z80 - 09/29/88 - Z80 RCP/M File Transfer Program +; Copyrighted (c) 1987, 1988 +; Robert W. Kramer III + + PAGE +;- -; +; Update History ; +; ; +; Date Release Comments ; +; -------- ------- ---------------------------------------------- ; +; ; +; 09/29/88 v1.50 - If an LBR/ARK/ARC member extraction is being ; +; made, a check at OPNOK5: determines if (FCB+9) ; +; is an 'L' for a .LBR member extraction. If so, ; +; ZMD informs the receiver that the file is ready ; +; for downloading. If (FCB+9) is other than an ; +; 'L' an ARC/ARK member extraction is assumed and ; +; the receiver is told to name the received file ; +; accordingly. Extractions on LBR/ARC/ARK files ; +; with the high bit set in (FCB+9) triggers this ; +; test unreliable. The simple fix has been made, ; +; which strips the parity bit of (FCB+9) before ; +; anylizing it. ; +; - Fixed a problem that caused some systems to ; +; ignore the first character typed in some ZMD ; +; utilities. The modification was made at the ; +; TYPE: routine in ZMDSUBS. Instead of using ; +; BDOS function 2 to display a character, we are ; +; now using BDOS call 6. ; +; - Fixed CONSTAT: routine in ZMDSUBS to properly ; +; react to cancel requests from Sysop. ; +; - Modified all low level I/O routines to preserve ; +; HL, DE, and BC registers. Whether you're using ; +; BYE's extended BDOS calls or have a custom I/O ; +; overlay installed in ZMD, those registers are ; +; will return intact. This allows those writing ; +; overlays to not have to worry about register ; +; integrity. ; +; - Single file Receive now defaults to 1k blocks. ; +; - Library extractions now default to 1k blocks. ; +; - Fixed bugs in the handshaking that have been ; +; around since 1k Batch was implemented on CPM ; +; systems. This required several modifications ; +; to the SNDFIL routines. All of them were ; +; modified specifically for the Batch routines, ; +; however, other Send routines were directly ; +; effected by them. ; +; ; +; 1. ZMD does not use the BDOS call 35 to get ; +; the file size since this information is ; +; supplied in the directory entry for each ; +; extent retreived during filename lookup. ; +; ; +; 2. We no longer open a file to send until ; +; the receiver has ACKnowledged header 0 ; +; *AND* sent his invitation for CRC ('C'). ; +; Previously, opening the file immediately ; +; after the header 0 ACK caused the 'C' to ; +; be missed during the time the sender is ; +; opening the file and filling his transmit ; +; buffer. ; +; ; +; 3. I personally feel there is no need to ; +; purge the line of incoming characters at ; +; anytime during a batch session. All of the; +; occurences of CALL CATCH have been removed; +; from the Send batch routines with the ; +; exception of the GTACK routine, in which ; +; case a call to CATCH is only made if the ; +; current byte received is other than an ; +; ACK, NAK, 7Bh, FBh, or a CANCEL. ; +; ; +; I do not have the resources to change all ; +; the other CP/M file transfer utilities ; +; floating around, so you may still notice ; +; some minor delays between files in BATCH ; +; protocol. Since most of the problem was ; +; in the Send routines, you'll not notice ; +; lengthy delays when using ZMD to send. ; +; Delays when using ZMD to receive will be ; +; dependant upon what software the sender ; +; is using. (IBM comm programs don't seem ; +; to have this problem, however all CP/M ; +; comm programs will have these irritating ; +; delays - except ZMD). ; +; ; +; - Added code to initialize KDRV with current ; +; drive at program startup. CPM3 systems were ; +; experiencing problems with BDOS 46. ; +; - CPM3 BDOS call 46 returns the current disk space; +; free in the first 3 bytes of the currently set ; +; DMA. This was being done during a check for ; +; the batch intention and destroying the current ; +; command line buffer (at 80h where DMA address is; +; usually set). CPM3 systems should now have no ; +; problems with ZMD. ; +; - Fixed bug to allow 255 files to be transferred ; +; when descriptions are disabled (either by the ; +; ZINSTL program or by using the 'RW' option). ; +; - Added CKWILD routine to prevent commands such ; +; as 'ZMD R *.*' enter '*.*' into the directory. ; +; Using any wildcards in the filename or extent ; +; of the receive filename will trigger YMODEM 1k ; +; Batch. ; +; - Log file routines were writing some filename ; +; attributes to the log file. Fixed at PUTLOG: ; +; - Modified ZMDSUBS.REL and send/send Batch code ; +; to take care of incorrect drive display problem ; +; for local terminal. Created new subroutine to ; +; poke the current binary 'BDOS' drive/user area ; +; into (DUU) and (DUD) in both SNDFIL: and SBTCH: ; +; routines. Both DUD and DUU have been moved to ; +; the ZMDSUBS file for global use. ; +; - Fixed EDATE routines for LOG and FOR files. ; +; Previously, the EDATE setting had no effect on ; +; the ZMD.Z80 program. ; +; - Fixed message upload routine at RCVFL to check ; +; for access restrictions. If ACCESS is set to ; +; NO, the message upload will be accepted, else ; +; bit 3 of AFBYTE will be anylized. ; +; ; +; 03/18/88 v1.49 - No change(s) made to this file ; +; 03/13/88 v1.48 - Had a small problem with TPA fix which has been ; +; corrected. CHKTPA was calculating the total ; +; number of bytes available for DBUF, but wasn't ; +; clearing register L (forcing an even amount of ; +; sectors before initializing OUTSIZ buffer limit ; +; comparison word). This may have introduced ; +; minimal garbage to your FOR file if your FOR ; +; file is large enough to fill available TPA with ; +; ZMD, ZFORS or to the log file if running ZMDEL. ; +; - Rewrote OUTCHR routine in ZMDSUBS. ; +; - Redefined buffer table at end of programs. STACK; +; and filename buffers now EQUated with offsets ; +; from the last switch/toggle in program instead ; +; of with DS directive. ; +; - Some systems which do NOT have an interrupt ; +; driven keyboard may have noticed problems when ; +; an invalid key was entered in the ZNEWP, ZFORP ; +; and ZMDEL programs. In ZNEWP and ZFORP, if a ; +; CR was entered to pause the output, output was ; +; limited to one line at a time per key pressed. ; +; If an invalid key was hit, output would have ; +; remained in a paused state until one of the ; +; abort keys were pressed. This was difficult to ; +; find since my keyboard is interrupt driven and ; +; I could not duplicate the problem on my own ; +; system. ; +; - Fixed a problem in the MODE parsing routines ; +; that caused ZMD to default to 128 byte blocks ; +; in single file SEND mode. Now defaults to 1k ; +; YMODEM. ; +; 02/25/88 v1.47 - Fixed a problem that caused only partial display; +; of the help guide if an invalid command such as ; +; ZMD RPC with no filename was entered. ; +; - Repaired routine that loads access flags byte ; +; into AFBYTE. If ACCESS was disabled and BYE ; +; was running, a check for a modem overlay was ; +; being made that caused a system hang up. v1.46 ; +; was the only version with this problem. ; +; - And then there were TPA problems. Past versions ; +; of ZMD required at least 48k TPA to run. If ; +; your system has less, and descriptions enabled, ; +; you most likely had a system hang up during the ; +; FOR file read/write operations. This version ; +; will run on any system with as little as 24k of ; +; available TPA. Maximum number of uploads is ; +; automatically calculated according to your TPA ; +; limitations. If upload descriptions have been ; +; disabled (either during installation or during ; +; program execution with the RW or RP options), ; +; as many as 255 files may be uploaded. ; +; - Fixed time out error in CRC receive routine. ; +; Register B contains the number of seconds to ; +; wait for a character on entry to RECV and some- ; +; how I inadvertanly removed the line that loads ; +; this value on entry. (Label RCVCRC2) ; +; - Fixed description routine so that the caller ; +; will be asked for the category of each uploaded ; +; file if ASKAREA is disabled. Problem caused ZMD ; +; to ask only 1 time for the file descriptor of ; +; uploaded files - no matter how many of them ; +; there were. ; +; 01/27/88 v1.46 - Fixed BYE time routines. Now displays correct ; +; time on system when exiting. ; +; - Fixed SUBS file so that discrepency check will ; +; not turn off CLOCK, and DSTAMP if MODE is set ; +; to 255. (So ZFORS and ZFORP can react to the ; +; clock related features without BYE running). ; +; - Added prompt to tell remote when ZMD is waiting ; +; for him to come back to terminal mode. Gets ; +; redisplayed every 3 seconds for a total of ; +; approximately 30 seconds before continuing on ; +; automatically. ; +; - Added code to SUBS file that determines if we ; +; are in private mode or not. If so, only private ; +; drive/user information is displayed when asking ; +; for file descriptors/categories choice. If in ; +; regular mode or in SPACE routines only the ; +; regular drive/user is shown. Fix is for upload ; +; routing routines. ; +; - Repaired message file exit routine. Command ; +; line wasn't being properly built. ; +; - Fixed so that batch mode is not valid with the ; +; RM option. (Slipped by during a rewrite of the ; +; command tail parsing routines). ; +; 01/17/88 v1.45 - First public release ; +; 01/14/88 v1.43 - Removed MBYE/BYE3 specific switches in ZMDHDR. ; +; Added new switch CLOCK. Removed Extended BDOS ; +; calls from time and date routines. Rewrote for ; +; 100% compatibility with BYE5/MBYE/BYE3 remote ; +; console programs. RTC switch can be set for ; +; user defined time and date routines at RTCTIM ; +; in ZMDHDR.Z80 ; +; - Fixed an error in send routines that allowed ; +; FCB+9-FCB+12 to remain initialized to nulls, if ; +; file requested had less than 3 characters in ; +; the filename extent. ; +; 12/29/87 v1.41 - Removed and rewrote description routines to be ; +; universal with ZMD, ZFORS and ZINSTL programs. ; +; Routine is now requested from ZMDSUBS.REL ; +; 12/23/87 v1.40 - Fixed numerous trivial bugs. ; +; - Rewrote the help and time/date routines. ; +; - Added code to determine if BIOS local console ; +; output address has been included in the modem ; +; overlay and if not calculate it according to ; +; standard CP/M specifications and store it for ; +; program use. ; +; 12/13/87 v1.39 - Rewrote common subroutines for inclusion in ; +; ZMDSUBS.REL subroutines file. ; +; 12/07/87 v1.38 - Modified to support drive/user area requests ; +; in SEND BATCH mode. Drive/user restrictions ; +; remain enforced. ; +; 10/02/87 v1.37 - Wrote code for automatic host disk block size ; +; detection. All file sizes (and total file ; +; sizes) are rounded to reflect this block size. ; +; 08/29/87 V1.36 - Rewrote all time routines. Moved RTC reader ; +; code insert address to ZMDHDR. Moved all date ; +; and time routines together to be updated all ; +; in same pass. Values stored at end of program ; +; to free up registers and retain values for any ; +; subsequent use. ; +; 08/14/87 v1.35 - Removed access restriction routines and rewrote ; +; completely. Access switches now bit mapped. ; +; 07/24/87 v1.34 - Updated to detect and process batch filename ; +; requests automatically. (AUTO-BATCH). ; +; - Removed entire SBTCH routines and threw away. ; +; Rewrote from scratch to enhance speed, ; +; efficiency, readability, and user friendliness. ; +; ZMD is capable of locating multiple filenames ; +; on multiple drive user areas with full drive ; +; and user area, filename, and time restrictions ; +; in force in 5 seconds (all other CP/M file ; +; transfer programs take 7 minutes or more) to ; +; find maximum 255 filenames. ; +; - Complete rewrites of: command line parsing, ; +; exit, abort, credit and descriptions routines. ; +; 06/18/87 v1.30 - Removed conditional assembly and modified to ; +; support .COM file installation/reconfiguration ; +; without reassembling. ; +; 06/17/87 v1.29 - Converted entire program to Microsoft MACRO-80 ; +; language. Programs no longer compatible with ; +; 8080 microcomputers. ; +;- -; + +;-------------------------------------------------------------------------; +; EXTERNAL Declarations: | +;------------------------------------------------------------------------- +; + + EXTRN BCDBIN,BLKSIZ,BUFSTR,BYECHK,CATCH,CHARLN,CKDIR,CLEARIT + EXTRN CMDBUF,CNREC,CONIN,CONONL,CONSTAT,CPDEHL,CPM3,CRCCHK + EXTRN CRCVAL,DATDEC,DATMSG,DBUF,DECOUT,DELAY,DIVREC,DSCFLG + EXTRN DSKSAV,DVHLDE,ERXIT,EXIT,FILCNT,FILTM1,FINCRC,FUNCHK + EXTRN GETDSC,GETKIND,GETOFF,GETSPD,GTCURDU,HEXO,ILPRT,ILPRTB + EXTRN ILPRTL,INCRNO,INITFCB,INITFLG,INITIT,INPUT,KDRV,KIND + EXTRN KSHOW,KTIM,LBRARC,LCASE,LOGBUF,LOW41K,MATCH,MCHFTYP + EXTRN MEMFCB,MODE,MOVFCB,MSGFLG,NAMBUF,NOARK,OLDDRV + EXTRN OLDUSR,PGSIZE,PRINTV,PRIVATE,RDARC,RDCOUNT,RECAR1 + EXTRN RECARE,RECDR1,RECDRX,RECTBL,RECV,RENFCB,RENTYP,RSDMA + EXTRN RSTLCK,SEND,SENDBEL,SETLCK,SHOCAT,SHONM,SHONM3,SHOSPD + EXTRN SNDABT,SPCDRV,STACK,STDMA,STORTM,TYPE,UCASE,USRSAV + EXTRN WAIT1,WHLCHK,XTIM,NEWNAM,SHONM4,NOROOM,BYEBDOS,BATCH + EXTRN FILIMT,PUPFLG,CHKTPA + +; +;-------------------------------------------------------------------------; +; PUBLIC Declarations: | +;-------------------------------------------------------------------------; +; + + PUBLIC KTABLE,XTABLE,KECTBL,DONE,EOTFLG,ABORT,ABORTX,HELP + PUBLIC KFLG,FCBBUF,HDRADR,RCNT,RECDNO,SAVEHL,RCDCNT,TIME + +; +;-------------------------------------------------------------------------; +; Program Starts Here | +;-------------------------------------------------------------------------; + + + .Z80 + ASEG + ORG 100H ; Program starts + JP BEGIN ; Jump around configuration table + INCLUDE ZMDHDR.Z80 ; Include the ZMD header overlay + .REQUEST ZMDSUBS ; Include the ZMD subroutines + +; +; +; Save current CP/M stack address +; +BEGIN: LD (STACK),SP ; Save current CP/M stack address + ;LD SP,STACK ; Initialize new one for ZMD + LD SP,0C000H ; [WBW] For HBIOS Fastpath + +; +; Save current drive and user area for later +; + LD A,255 + CALL RECAR1 ; Get current user + LD (OLDUSR),A ; Save current user + LD C,CURDRV ; Current drive + CALL BDOS + LD (OLDDRV),A ; Save current drive + ADD A,'A' ; Make it ASCII + LD (KDRV),A ; And store as default drive for DPB info + +; +; Display signon message and check environmental discrepencies +; + LD HL,ZMDNAM ; Point to this program's name + CALL PRINTV ; Display it and version number + +; +; If running under CPM3 tell rest of program +; + LD C,GETVER ; Get CPM version + CALL BDOS + CP 48 ; Version 3.0? + JR C,$+5 ; No, it's 2.n so skip next + LD (CPM3),A ; Else set CPM3 switch on + +; +; Locate modem I/O routines +; + CALL BYECHK ; BYE extended BDOS valid? + CP 5 + JR NZ,BEGIN0 ; No, check for I/O overlay + LD A,255 + LD (BYEBDOS),A ; Enable BYE extended BDOS for modem I/O + JR BEGIN1 + +BEGIN0: LD A,(MDINP+2) ; Check for MDINP address + OR A ; Anything there? + JP Z,NOIO ; No overlay either, bitch then exit + LD (INITFLG),A ; Tell exit routine to 'UNINIT' + CALL MINIT ; Initialize system routine (if included) + LD (MHZ),A ; [WBW] Save system speed reported by HBIOS + +; +; Get bit mapped access flags byte +; +BEGIN1: LD A,(ACCESS) ; Using access flags byte? + OR A + JR Z,BEGIN3 ; No + + CALL BYECHK ; Check version of BYE + CP 5 ; BYE5? + JR NZ,BEGIN2 ; No + + LD E,255 + LD C,85 ; Get access flags byte + CALL BDOS + LD (AFBYTE),A ; Store it + JR BEGIN3 + +BEGIN2: LD DE,ACBOFF ; Offset to access flags byte + CALL GETOFF ; Get address + LD A,(HL) ; HL points to access flags byte + LD (AFBYTE),A ; Store it + +; +; Set WRTLOC, display time on system +; +BEGIN3: CALL SETLCK ; Set WRTLOC if needed + CALL CATCH ; Gobble up garbage characters from line + CALL TIME ; Get clock values and display time on + +; +;-------------------------------------------------------------------------; +; P a r s e ' M o d e ' f r o m C o m m a n d T a i l | +;-------------------------------------------------------------------------; +; +; Second character in CP/M FCB contains program mode +; + LD HL,FCB+1 + LD A,(HL) ; Get the main option + LD (MODE),A ; Save it for later use + CP 'F' ; Free space? + JP Z,SPACE ; Yes + CP 'A' ; .ARC/.ARK member extraction? + JP Z,CKSND-3 ; Yes + CP 'L' ; .LBR member extraction? + JP Z,CKSND-3 ; Yes + CP 'S' ; Send a file? + JP Z,CKSND ; Yes + CP 'R' ; Receive a file? + JP NZ,HELP ; No, show help guide + +; +; Check additional 'R'eceive mode options +; + INC HL ; Point to next option + LD A,(HL) ; Put in A + CP 'P' ; Receive Private? + JR Z,CKRCV2-3 ; Yes + CP 'W' ; Receive Privileged? (No descriptions) + JR NZ,CKRCV1 ; No + LD A,(PUPOPT) ; Is >0 if allowing privileged uploads + LD (PUPFLG),A ; Sets our flag this way + OR A ; Allowed? + JP Z,HELP ; No, show help guide + JR CKRCV2 ; Else get next option + +CKRCV1: CP 'M' ; Receive message? + JR NZ,CKRCV3 ; No + LD A,(FCB1+1) ; See if a filename was requested + CP ' ' + JP Z,HELP ; No, batch mode not allowed + LD A,(MSGFIL) ; Is >0 if allowing message uploads + LD (MSGFLG),A ; Sets our flag this way + OR A ; Allowed? + JP Z,HELP ; No, show help guide + LD A,'P' ; Else... + LD (PRIVATE),A ; Set the private flag + +CKRCV2: INC HL ; Point to next option + LD A,(HL) ; Put in A + +CKRCV3: CP ' ' ; Anything there? + JP Z,BCHMSG ; No, see if requesting Batch + CP 'B' ; Batch mode? + JP Z,BCHMSG ; Yes + CP 'C' ; Force Checksum? + JP Z,CHKMSG ; Yes + CP 'X' ; Force 128 byte packets? + JP Z,XMDMSG ; Yes + CP 'K' ; Force 1k packets? + JP Z,YMDMSG ; Yes + JP HELP ; Invalid option, show help guide + +; +; Check additional 'S'end mode options +; + LD (LBRARC),A ; Set .LBR/.ARK/.ARC extraction flag + +CKSND: INC HL ; Next option on command line + LD A,(LBRARC) ; Get the member extraction flag + OR A ; Is is set? + JR Z,CKSND0 ; No, we can check for batch + LD A,(HL) ; Get the character + CP ' ' ; Any more options? + JP Z,YMDMSG ; No, and batch not used with extractions + +CKSND0: LD A,(HL) ; Get the character back + CP ' ' ; Any more options? + JR Z,BCHMSG ; No, check for batch intention + CP 'C' ; Force checksums? + JP Z,CHKMSG ; Show protocol + CP 'X' ; Force XMODEM protocol? + JP Z,XMDMSG ; Show protocol + CP 'K' ; Force 1k protocol? + JP Z,YMDMSG ; Show protocol + LD A,(LBRARC) ; Get LBR/ARC extraction flag + OR A ; Enabled? + JP NZ,NOMSG ; Yes, ignore Batch + LD A,(HL) ; Get option back + CP 'B' ; Forcing batch? + JR NZ,CKSND1 ; No + LD A,(PRIVATE) ; Get special download area flag + OR A ; Enabled? + JP NZ,NOMSG ; Yes, don't allow batch + JP BCMSG2 ; Go set batch flag and display mode + +CKSND1: CP 'P' ; Send private? + JP NZ,HELP ; No + LD (PRIVATE),A ; Enable private download + JR CKSND ; Loop for more options + +; +; Display the currently selected (or default) protocol. +; +BCHMSG: LD A,(MODE) ; Get main option again + CP 'R' ; Receiving? + JR NZ,BCMSG1 ; No + LD A,(FCB1+1) ; Was a file requested? + CP ' ' + JR Z,BCMSG2 ; No, in batch receive + + LD HL,FCB1+1 ; Point to secondary FCB + CALL CKWILD ; Check for wildcards + LD A,(BATCH) ; Batch enabled now? + OR A + JR NZ,BCMSG2 ; Yes, report protocol + JR YMDMSG ; Else, single file receive. Default to 1k + +; +; Scan the command line to see if there was any intention of batch and if +; so, set program environment to Ymodem 1k batch protocol. +; +BCMSG1: XOR A ; Clear accumulator + LD (MODE),A ; Gets us back from the SBTCH routines + CALL SBTCH ; Check for batch intention + LD A,'S' + LD (MODE),A ; Fix the transfer mode flag + LD A,(BATCH) ; Get the batch mode flag + OR A ; Was it enabled? + JR Z,YMDMSG ; No, sending single file. Default to 1k + +BCMSG2: CALL LOW41K ; 1k packets allowed? + JP C,TOOSLOW ; No, can't use batch + LD A,1 + LD (BATCH),A ; Enable batch + CALL ILPRTB + DB '1k Batch',0 + JR MSGEND + +YMDMSG: CALL LOW41K ; 1k packets allowed? + JR C,NOMSG ; No + LD (KFLG),A ; Enable 1k + CALL ILPRTB + DB '1k',0 + JR MSGEND + +XMDMSG: XOR A ; Clear accumulator + LD (KFLG),A ; Disable 1k blocks + CALL ILPRTB + DB '128 byte CRC',0 + JR MSGEND + +CHKMSG: XOR A ; Clear accumulator + LD (CRCFLG),A ; Disable CRC + LD (KFLG),A ; Disable 1k blocks (not allowed in Checksum) + CALL ILPRTB + DB '128 byte Checksum',0 + +MSGEND: CALL ILPRTB + DB ' enabled',0 + +NOMSG: CALL CHKTPA ; Calculate TPA limitations + CALL ILPRTB + DB CR,LF,0 + LD A,(MODE) ; Get transfer mode + CP 'R' ; Receiving? + JP Z,RCVFL ; Yes + LD A,'S' + LD (MODE),A ; Else make mode an 'S' (send mode) + +; +;-------------------------------------------------------------------------; +; ----> SNDFIL - S e n d f i l e ( s ) | +;-------------------------------------------------------------------------; +; +; The file specified in the ZMD command line is transferred over the phone +; to another computer with modem using the "S"end option. The data is sent +; 1 record at a time with headers, checksums, and retransmission on errors. +; +SNDFIL: LD A,(BATCH) ; Batch mode requested? + OR A + JP NZ,SBTCH ; Yes, go handle batch mode + +; +; Take care of single file transfer - not in batch +; + CALL LOGDU ; Log into drive and get DPB info + CALL GTCDUD ; Get current binary drive/user in DUU/DUD + CALL CNREC ; Calculate number of records (unless LBRARC) + CALL CATCH ; Clear the decks + CALL OPNFIL ; Open the file and check restrictions + +; +; Loop back here for the start of each BATCH file sent +; +SNDFL1: LD E,60 ; Number of seconds to wait for initial 'NAK' + +SNDFL2: CALL FUNCHK ; Check for function keys + CALL SNDABT ; Local abort? + LD B,1 + CALL RECV ; Wait 1 second for initial NAK + JR C,SNDFL3 ; No character + CP CRC ; CRC request? + JR Z,SNDFL4 ; Yes + CP KSND ; 1k request? + JR Z,SNDFL7 ; Yes + CP NAK ; NAK for checksum? + JR Z,SNDFL8 ; Yes + CP CANCEL ; Cancel? + JP Z,ABORT ; Yes + +SNDFL3: DEC E ; One less second + JP Z,ABORT ; Abort if 0 + JR SNDFL2 ; Else wait some more + +; +; Got a 'C', now wait up to 1 second for 'K' +; +SNDFL4: LD A,(BATCH) ; In batch mode? + OR A + JR NZ,SNDFL7 ; Yes, don't wait for 'K' + LD B,1 + CALL RECV ; Get character from remote + JR C,SNDFL5 ; No character received, so not using 1k + AND 7FH ; Strip high bit + CP '{' + JR Z,SNDFL4 ; Disregard noisy lines + CP KSND ; Requesting 1k? + JR Z,SNDFL7 ; Exit if yes, otherwise set CRC + +; +; Turn on the flag for CRC +; +SNDFL5: LD A,(KFLG) ; KFLG manually set from 'SK'? + OR A + JR NZ,SNDFL7 ; If yes, keep it set + +SNDFL6: XOR A + LD (KFLG),A ; Defaults to 128 character blocks + INC A + LD (CRCFLG),A ; Insures in CRC mode + CALL ILPRTL + DB CR + DB 'CRC',0 + JP SNDFL10 + +; +; Turn on the flag for 1k blocks and insure in CRC mode +; +SNDFL7: CALL LOW41K ; 1k packets allowed? + JP C,SNDFL6 ; No + LD (KFLG),A ; Set the flag for 1k blocks + LD (CRCFLG),A ; Insures in CRC mode + LD A,(BATCH) ; In Ymodem Batch? + OR A + CALL NZ,OPNFIL ; Yes, then open file/check restrictions + CALL ILPRTL + DB CR + DB 'Ymodem',0 + JR SNDFL10 + +; +; Turn on checksum flag, insure sending 128 character blocks +; +SNDFL8: LD A,(BATCH) ; In batch mode now? + OR A + JR NZ,SNDFL9 ; If yes, exit + XOR A + LD (CRCFLG),A ; Make sure in checksum mode + LD (KFLG),A ; Defaults to 128 character blocks + CALL ILPRTL + DB CR + DB 'Checksum',0 + JR SNDFL10 + +SNDFL9: CALL ILPRTL + DB CR + DB '-- Checksum not used in batch' + DB CR,LF,0 + JP SNDFL2 ; If yes, ignore checksum request + +SNDFL10:CALL ILPRTL + DB ' requested ' + DB CR,LF,0 + CALL RDBLOK ; Put up to 16k from file into buffer + CALL SETFLG ; Disable 1k if less than 8 records left + +; +; Loop back here to send the next 1k/128 byte block after a successful trans- +; mission. If using 1k blocks, check the ACK ratio. Check total error count +; vs. records sent, and switch from 1k to 128 byte transmissions if higher. +; +SNDLP: LD A,(KFLG) ; Using 1k blocks? + OR A + JP Z,RDRECD ; If not, skip checking 1k error ratio + LD A,(ERRCNT) ; See if we got any errors last record + CP 4 ; 4 or more? + JR NC,SNDLP1 ; Yes, switch to 128 size + LD A,(ACCERR) ; See if up to minimum errors yet + CP 3 ; Had as many as three errors yet? + JR C,RDRECD ; If not, don't get excited too quickly + + LD HL,(RECDNO) ; Get current record number increment + LD DE,65528 ; Have not successfully sent this 1k yet + ADD HL,DE ; Subtract the current increment, then + LD DE,(ACCERR) ; Number of non-'ACK' errors in HL + CALL DVHLDE ; Get ratio in BC of records/hit + CALL GETSPD ; Get current speed + CP 5 ; 1200 baud? + LD A,70 ; for 1200 bps + JR Z,$+4 ; If 1200, skip next line + LD A,42 ; for 2400 bps + CP C ; Compare with actual ratio + JR C,RDRECD ; Continue if less hits than allowed + +SNDLP1: XOR A ; Clear A + LD (KFLG),A ; Reset system to 128 byte blocks + CALL ILPRTL ; Inform locally + DB ' - YMODEM 1k blocks disabled' + DB CR,LF,0 + +; +; Read a record, refill buffer if empty, update record read +; +RDRECD: LD A,(RECNBF) ; Any records in the buffer? + OR A + JR Z,RDBLOCK ; No, go get some + LD A,(KFLG) ; Using 1k blocks? + OR A + JR Z,RDREC1 ; No, exit + LD A,(RECNBF) ; See how many records in buffer + CP 8 ; 8 or more records? + JR NC,RDREC2 ; Yes, stay in 1k blocks + XOR A + LD (KFLG),A ; Reset the 1k flag for 128 byte + +RDREC1: LD A,(RECNBF) ; Point to number of records in buffer + DEC A ; Decrement it for 128 character blocks + LD (RECNBF),A ; Store it + JP SNDLP2 ; Send it + +RDREC2: SUB 8 ; Subtract 8 records (1k worth) + LD (RECNBF),A ; Store it + JP SNDLP2 ; Send it + +; +; Buffer is empty - read in another block of 16k +; +RDBLOCK:LD A,(EOFLG) ; Get 'EOF' flag + CP 1 ; Is it set? + SCF ; To show 'EOF' + JP Z,SNDLP2 ; Got 'EOF' + CALL RDBLOK ; Read up to 16k into DBUF + JR RDRECD ; Pass record to caller + +; +; Read up to 16k from the disk file into the buffer, ready to send +; +RDBLOK: LD C,0 ; Set number of records in block to 0 + LD DE,DBUF ; Point to disk buffer as destination + +RDBLOK1:PUSH BC + PUSH DE + LD A,(LBRARC) ; Get ARK/ARC/LBR extraction flag + OR A ; Enabled? + JR Z,RDBLOK2 ; No, skip next + LD A,(FCB+9) ; Get filetype byte 1 + AND 7FH ; Strip high bit + CP 'A' ; Is it an ARK/ARC extraction? + CALL Z,RDARC ; Yes, (flags saved at RDARC) + JR Z,RDBLOK3 ; Same flags + +RDBLOK2:CALL STDMA ; Set DMA address + LD C,READ + LD DE,FCB + CALL BDOS + +RDBLOK3:POP DE + POP BC + OR A ; Read ok? + JR NZ,RDBLOK5 ; If not, error or end of file + LD HL,128 ; Add length of one record + ADD HL,DE ; To next buffer + EX DE,HL ; Buffer to 'DE' + INC C ; More records? + LD A,(BUFSIZ) + ADD A,A + ADD A,A + ADD A,A + CP C + JR NZ,RDBLOK1 ; Read more + +; +; Buffer is full or got EOF +; +RDBLOK4:LD (RECNBF),A ; Store record count + LD HL,DBUF ; Get the beginning buffer address + LD (RECPTR),HL ; Save for next record + JP RSDMA ; Reset DMA address to default + +RDBLOK5:DEC A ; 'EOF'? + JR NZ,READERR ; Got 'EOF' + +RDBLOK6:INC A + LD (EOFLG),A ; Set EOF flag + LD A,C + JR RDBLOK4 + +READERR:CALL ILPRTB + DB CR,LF + DB '-- Read Error: ',0 + CALL SHONM3 + JP EXIT + +; +; Now send the next record +; +SNDLP2: JP C,SNDEOF ; Send 'EOF' if done + CALL INCRNO ; Bump record number if sent ok + XOR A ; Initialize error count to zero + LD (ERRCNT),A + +SNDRPT: CALL CKABORT ; Check for remote abort + CALL SNDABT ; Check for local abort + CALL SNDHDR ; Send a header + CALL SNDREC ; Send data record + CALL SNDCHK ; Send CRC or checksum value + CALL GTACK ; Get the 'ACK' + CP ACK ; ACK? + JR NZ,SNDRPT ; No, repeat transmission + LD DE,128 ; For 128 character blocks + LD A,(KFLG) ; See if last block sent was 1k + OR A + JR Z,$+5 ; No, skip next line + LD DE,1024 ; Else set for 1024 character blocks + LD HL,(RECPTR) ; Get the buffer pointer + ADD HL,DE ; Increment for the record just sent + LD (RECPTR),HL ; New buffer address for next block + LD A,(LBRARC) ; Get LBR/ARC/ARK extraction flag + OR A ; Enabled? + JP Z,SNDLP ; No + LD A,(KFLG) ; 1k enabled? + LD DE,65535 ; 128 byte + OR A + JR Z,$+5 + LD DE,65528 ; 1k + LD HL,(RCNT) ; Alter the records-sent count + ADD HL,DE + LD (RCNT),HL ; One less transmission to go + OR A ; 'K' flag set? + CALL NZ,SETFLG ; Yes, see if enough records for 1k packet + LD HL,(RCNT) ; See if anything was actually sent + LD A,H + OR L ; L and H both zero now? + JP NZ,SNDLP ; No, continue + +; +; End of Transmission (Send mode) +; +SNDEOF: LD A,(LOGLDS) ; Counting transfers? + OR A + JR Z,SNDEOF1 ; No + LD A,(PRIVATE) ; Is this a private transfer? + OR A + JR NZ,SNDEOF1 ; Yes, don't increment download count + LD IY,(DNLDS) ; Get Downloads counter address + INC (IY) ; One more download since log in + +SNDEOF1:CALL LOGCALL ; Log transfer if supposed to + CALL EOFSND + CALL ADDTON ; Update BYE's time on byte if supposed to + CALL ALLDON + JP DONE + +; +; See if enough records left to use 1k protocol +; +SETFLG: LD HL,(RCNT) + LD A,H ; Anything in the 'H' register? + OR A + RET NZ ; Yes, enough records for another 1k packet + LD A,L ; Get number of records in 'L' register + CP 8 ; At least 8 yet? + RET NC ; Yes, keep going + XOR A ; Reset the 'K' flag + LD (KFLG),A + RET + +; +; HL points to filename FCB - now search for it wildcards. If any, enable +; BATCH flag and pad with '?' as needed +; +CKWILD: LD B,8 ; Check first 8 bytes + CALL CKWLD1 + LD B,3 ; And check filetype + +CKWLD1: LD A,(HL) ; Get the character + CP '*' ; '*'? + JR NZ,CKWLD2 ; No, check for little wildcards + LD (BATCH),A ; Enable AUTO-BATCH + LD A,'?' ; Fill rest with '?' character + JP INITIT ; Initialize + +CKWLD2: CP '?' ; '?'? + JR NZ,$+5 ; No, don't enable AUTO-BATCH + LD (BATCH),A ; Enable AUTO-BATCH + INC HL ; Point to next character + DJNZ CKWLD1 ; Loop until B=0 + RET + +; +; Get the current drive/user +; +GTCDUD: LD A,0FFH ; Stuffed into E at RECAR1 + CALL RECAR1 ; Get current user area + LD (DUU),A ; Store it + LD C,CURDRV ; Get current drive + CALL BDOS + LD (DUD),A ; Store it + RET + +; +;-------------------------------------------------------------------------; +; S e n d B a t c h | +;-------------------------------------------------------------------------; +; +; Copy original command line buffer to internal work buffer +; +SBTCH: LD A,(FSTFLG) ; If first time through + OR A + JP NZ,SBTCH1 ; If not first time, exit + + LD HL,TBUF ; Source + LD DE,CMDBUF ; Destination + LD BC,128 ; Count + LDIR ; Move + +; +; Locate end of command line and place a ' ' as a delimiter +; + LD HL,CMDBUF ; Point to number of bytes in line + LD B,0 ; Zero high order + LD C,(HL) ; Number of characters in command line + INC HL ; Point to start of line + ADD HL,BC ; Plus number of characters equals end of line + LD (HL),' ' ; Place the delimiter at end of line + INC BC ; Increment character count for delimiter + +; +; Count ambiguous/unambiguous filenames in command line +; + XOR A ; Clear accumulator + LD (FILCNT),A ; Reset the file count + LD (NAMECT),A ; Reset name count (used in parsing routines) + LD HL,CMDBUF+2 ; Point to command tail option + LD A,' ' ; Looking for space/non-space characters + CPIR ; On command option, look for next space + JP PO,SCANDN ; If at end of line, done + CPI ; Find first character of first name + JP PO,SCANDN ; If at end of line, done + JR Z,$-5 ; Eat extra spaces + DEC HL ; CPI is one ahead of us, so back up + LD (BGNMS),HL ; Store address of beginning name + INC HL ; And it was supposed to be, so restore it + +SCANLP: CPIR ; Move to end of current name (next space) + EX AF,AF' ; Save A (match char) & current flags (result) + LD A,(NAMECT) ; Get current name count + INC A ; Bump it one + LD (NAMECT),A ; Put it back + CP 255 ; 255 names? + JR Z,SCANDN ; Yes, that's all we allow + EX AF,AF' ; Restore A and old flags + JP PO,SCANDN ; If at end of line, done + CPI ; Find next non-space character + JP PO,SCANDN ; If at end of line, done + JR Z,$-5 ; Was a space, keep looking + JR SCANLP ; Found next non-space, find next name + +SCANDN: LD A,(NAMECT) ; Get the ambiguous filename count + OR A ; Were there any? + JP Z,HELP ; No, they must need help + CP 1 ; Just 1 name? + JR Z,$+5 ; If only 1, don't force AUTO-BATCH here + LD (BATCH),A ; Else set batch mode flag (for AUTO-BATCH) + LD HL,NAMBUF ; Get start of batch filename buffer + LD (NBSAVE),HL ; Save as address of the first name + +; +; Place a name in work buffer +; +TNLP: LD B,0 ; Initialize character count + LD HL,(BGNMS) ; Source is address of first name + LD DE,FCBBUF+2 ; Destination + +TNLP1: LD A,(HL) ; Get a byte in A + CP ' ' ; A space? + JR Z,TNLP2 ; Yes, done with name + LD (DE),A ; Move character to FCB buffer + INC HL ; Increment pointers + INC DE + INC B ; Bump count of characters in name + JR TNLP1 ; Loop until space + +TNLP2: INC HL ; Point to next character + LD A,(HL) ; Put it in A + CP ' ' ; Is it a ' '? + JR Z,TNLP2 ; Yes, eat extra spaces + LD (BGNMS),HL ; Store address of next name + LD HL,FCBBUF+1 ; # characters in filename + LD (HL),B ; Before name + +; +; Initialize FCB for search routines +; + LD A,0 ; String of all 0's for intitialization + LD HL,FCB ; Destination + LD B,16 ; 16 bytes + CALL INITIT ; Initialize FCB + + LD HL,FCBBUF+1 ; Point to # of bytes in command line + LD D,0 ; Zero high order + LD E,(HL) ; Load DE pair with # bytes + INC HL ; Increment to start of command line + ADD HL,DE ; Point to byte after last character + LD (HL),CR ; Store CR for delimiter + +; +; Check for valid drive/user combination and move filename to FCB +; + LD HL,FCBBUF+2 ; Start of filename + LD DE,DUSAVE ; Isolate possible 'duu:' + LD BC,4 ; Up to 4 bytes + LDIR ; For logging into specified d/u + + LD HL,FCBBUF+1 ; Point to amount of characters in filename + LD B,(HL) ; In B for d/u parsing routines + INC B ; Increment character count for CR terminator + INC HL ; And point to start filename again + LD (SAVEHL),HL ; Initialize 'current' address pointer + + LD A,(MODE) ; Get transfer mode + PUSH AF ; Save it while checking valid d/u + XOR A ; Zero accumulator for new mode + LD (MODE),A ; Save it (keeps us out of trouble in LGDU1:) + CALL LGDU1 ; Check valid d/u and copy filename to FCB + CALL GTCDUD ; Get current binary drive user in DUU/DUD + POP AF ; Get possible previously determined mode + LD (MODE),A ; Restore + LD HL,FCB+1 ; Filename FCB + CALL CKWILD ; Check it for wildcards, enable Batch if any + + LD A,(MODE) ; Get file transfer mode + OR A ; 0=checking batch intention + RET Z ; All done if so + +; +; Now search directory and store first matching filename +; + CALL RSDMA ; Reset to default memory address + LD A,'?' + LD (FCBEXT),A ; Fetch all extents of matching filenames + XOR A + LD (FCBRNO),A ; Clear FCB record number byte + LD DE,FCB ; Use default FCB for search + LD C,SRCHF ; Search for first occurence + CALL BDOS + CP 0FFH ; Anything found? + JP Z,NEXTNM ; No, go get next ambiguous filename + LD HL,(LIST) ; Initialize list pointer parameters + LD (LISTPOS),HL ; Save current position of list + +; +; Calculate offset to matched directory entry +; +FNDENT: AND 3 ; Zero based, two bit index + ADD A,A ; *2 + ADD A,A ; *4 + ADD A,A ; *8 + ADD A,A ; *16 + ADD A,A ; *32 to make position index + LD C,A ; Put in BC + XOR B ; Clear MSB + LD HL,TBUF ; Address of default command line buffer + ADD HL,BC ; And offset to matched directory entry + LD A,(DUD) ; Get drive number + LD (HL),A ; Put in front of name in name buffer + +; +; Check the match for download restrictions +; + PUSH HL ; Save address of matched entry + PUSH HL ; Save another copy + POP IX ; As address of filename to check + CALL RESTRCT ; Check for download restrictions + POP HL ; Get our matched entry address back + JP NZ,DONEXT ; NZ=entry not allowed + +; +; Trap zero length file before adding to list +; + PUSH HL ; Save matched entry address + POP IY ; Get a copy in IY + LD A,(IY+12) ; Get the extent byte + OR A ; Is this the first extent? (#0) + JR NZ,COPYNM ; No, can't be 0 length (at least 16k already) + LD A,(IY+15) ; Get it + OR A ; Any records? + JP Z,DONEXT ; No, zero length, but in batch so no messages + +; +; Copy the name to list +; +COPYNM: LD A,(FSTFLG) ; Displayed the following message yet? + OR A + JR NZ,NAM2LST ; Yes, they alreay know to wait + PUSH HL ; Save matched entry address + CALL ILPRTB + DB CR,LF + DB 'Locating selection(s)...',0 + LD A,1 + LD (FSTFLG),A ; Set so message don't show again + POP HL ; Restore matched entry address + +NAM2LST:LD DE,(LISTPOS) ; Pointer to current load point in list + LD B,12 ; Move drive number and name to list + +NM2LST1:LD A,(HL) ; HL contains address of entry + AND 7FH ; All done with high bits + LD (DE),A ; Move it to list + INC HL ; Increment pointer + INC DE + DJNZ NM2LST1 ; Loop until B equals 0 + LD A,(HL) ; Get the EX byte + LD (DE),A ; Put it in list + INC HL ; Increment to RC byte + INC HL + INC HL + INC DE + LD A,(HL) ; Get it + LD (DE),A ; Put it in list + INC DE ; Point to start of next name in list + LD A,(DUU) + LD (DE),A + INC DE + INC DE + LD (LISTPOS),DE ; Store address of next load point + +; +; Search for next occurance of specified filename +; +DONEXT: LD C,SRCHN ; Search next function code + LD DE,FCB ; Filename specification field + CALL BDOS + CP 0FFH ; See if all through directory yet + JP NZ,FNDENT ; If not, calculate code offset and add 2 list + +; +; Trap conditions of 0 files found +; + LD HL,(LISTPOS) ; Get the end of list address + LD DE,(LIST) ; Get beginning of list address + CALL CPDEHL ; Are they the same? + JP Z,NEXTNM ; Yes, none of the files found were allowed + +; +; Prepare associated sort parameters +; + LD HL,(LIST) ; Adjust I and J pointers for initial sort + LD (LISTI),HL ; Beginning of list + LD DE,ITEMSZ ; Get offset to next name + ADD HL,DE ; Add the offset + LD (LISTJ),HL ; Into J variable + +; +; Don't need a sort if only 1 file extent found +; + LD HL,(LIST) ; Was there more than one entry found? + LD BC,ITEMSZ + ADD HL,BC + EX DE,HL + LD HL,(LISTPOS) ; Next load name of list is start of buffer + LD (LISTEND),HL ; Set list end marker + CALL CPDEHL ; Compare DE address with HL address + JP Z,MINNN ; If same, no sort needed + +; +; Sort the list by disk, filename, and EX byte. +; +SORT: LD HL,(LISTI) ; Compare entries I and J + LD DE,(LISTJ) + LD B,13 ; Number of bytes to compare + CALL MATCH ; + JR NC,SORT1 ; Swap entries if J is larger than I + LD HL,(LISTI) ; Get our original pointers back + LD DE,(LISTJ) + LD B,ITEMSZ ; Counter for number of bytes to swap + +SWAP: LD C,(HL) ; Get character from string 1 + LD A,(DE) ; And one from other string + LD (HL),A ; Second into first + LD A,C ; First into second + LD (DE),A + INC HL ; Bump swap pointers + INC DE + DJNZ SWAP ; Loop until B=0 + +SORT1: LD HL,(LISTJ) ; Increment J pointer + LD DE,ITEMSZ ; By the amount of items per entry + ADD HL,DE + LD (LISTJ),HL + LD DE,(LISTEND) ; Get the address of the end of list + CALL CPDEHL ; DE and HL the same? + JR NZ,SORT ; No, so more J loop + + LD HL,(LISTI) ; Get the I pointer + LD DE,ITEMSZ ; Get offset to next name + ADD HL,DE ; Add + LD (LISTI),HL + ADD HL,DE ; Add offset to next name + LD (LISTJ),HL ; Start J loop over again + LD DE,(LISTEND) ; Get the address of the end of list + CALL CPDEHL ; DE and HL the same? + JR NZ,SORT ; No, must be more I loop to go + +; +; List minimization loop +; + LD HL,(LIST) ; Point to the beginning of our list + LD (LISTI),HL ; Initialize current name pointer + LD DE,ITEMSZ ; Get offset to next name + ADD HL,DE ; Add it to current name address + LD (LISTJ),HL ; Store as next name + +MINCL: LD DE,(LISTEND) ; End of list address + LD HL,(LISTJ) ; Next name address + CALL CPDEHL ; Are they the same? + JR Z,MINNN ; Yes, go set kbytes on last name (End of list) + + LD DE,(LISTJ) ; Next name address + LD HL,(LISTI) ; Current name address + LD B,12 ; # of bytes to check + CALL MATCH ; Are they the same? + JR NZ,MINNN ; No, go set kbytes on last extent (Next name) + +; +; Increment next name pointer and get parameter bytes +; + LD HL,(LISTJ) ; Fetch EX and RC from next name + LD DE,ITEMSZ ; Offset to next name + ADD HL,DE ; Add it + LD (LISTJ),HL ; Save bumped J value + + DEC HL ; Point to parameter bytes of previous name + DEC HL + DEC HL + LD B,(HL) ; Save the RC byte + DEC HL + LD C,(HL) ; Save the EX number + + LD HL,(LISTI) ; Point at current name + ADD HL,DE ; Point at current name info bytes + DEC HL + DEC HL + DEC HL + LD D,(HL) ; Fetch that RC byte + DEC HL + LD E,(HL) ; Fetch current EX byte + + LD A,E ; Check if new EXtent is bigger than last + CP C + JR NC,MINCL ; Skip using size of a less or equal EX + LD (HL),C ; Put new sizes into the location + INC HL + LD (HL),B ; New RC byte too + JR MINCL ; Continue handling as current file + +; +; File size computation loop +; +MINNN: LD HL,(LISTI) ; Point to name to convert records + LD DE,ITEMSZ-4 ; Index to largest extent number + ADD HL,DE ; Add the offset + LD B,(HL) ; Get the extent number for a loop counter + INC HL ; Bump to the last extent RC byte + PUSH HL ; Save pointer to list parameters + LD HL,0 ; Zero extent total record count + LD DE,128 ; Set size of one extent + +; +; Calculate total number of 128 byte records +; +MINEL: LD A,B ; Get the number of extents left + OR A ; Any more? + JR Z,MINELD ; No, done with 128 multiply + ADD HL,DE ; Else add another 128 to HL + DEC B ; 1 less extent left + JR MINEL ; Loop until no more + +MINELD: EX DE,HL ; Total extent size to DE + POP HL ; Get back RC byte pointer + LD B,0 + LD C,(HL) ; Get final extent size to BC + EX DE,HL ; Add remainder to total records in DE + ADD HL,BC + LD B,H ; Move total record count to BC + LD C,L + LD HL,(TOTREC) ; Get current total records + ADD HL,BC ; Add records of this file + LD (TOTREC),HL ; And save it for later display + EX DE,HL ; Get table entry pointer back in HL + CALL ROUNDK ; Get disk space needed for file DE + LD (HL),D ; Put kilobyte count in table + DEC HL + LD (HL),E + LD A,(FILCNT) ; Bump the file count + CP 255 ; 255 file names yet? + JR Z,MINN0 ; Yes, that's all we allow + INC A ; Else bump it one + LD (FILCNT),A ; Store it + LD HL,(FILEK) ; Get current total file kilobytes + ADD HL,DE ; Add in the current file's kilobyte size + LD (FILEK),HL ; And store it + LD HL,(LISTI) ; Source + LD DE,(NBSAVE) ; Destination + LD BC,16 ; 16 byte count + LDIR ; Move filename to names buffer + LD (NBSAVE),DE ; And store address to put next filename + +MINN0: LD DE,(LISTJ) ; Done with all names + LD HL,(LISTEND) ; Check if at end of list + CALL CPDEHL + JR Z,NEXTNM ; Get next ambiguous filename, if finished + LD HL,(LISTI) ; Point to LISTI value + LD DE,ITEMSZ ; Point to next position + ADD HL,DE + LD (LISTI),HL ; Set new working LISTI + LD DE,(LISTI) + LD HL,(LISTJ) ; Next name position to copy from + CALL CPDEHL ; See if pointers only one apart + JR Z,MINN1 ; If so, don't cover up one name + LD BC,ITEMSZ + LDIR ; Move that name up there + JR MINN2 + +MINN1: LD DE,ITEMSZ ; No open slot, so just move LISTJ up one slot + ADD HL,DE + +MINN2: LD (LISTJ),HL + JP MINCL ; Go to MIN NAME start of loop + +NEXTNM: LD A,(OLDDRV) + CALL RECDRX ; Restore default drive + LD A,(OLDUSR) + CALL RECAR1 ; Restore default user + LD A,(NAMECT) ; Get number of names found + DEC A ; Decrement it + LD (NAMECT),A ; Put it back + JP NZ,TNLP ; Loop until zero + LD (FSTFLG),A ; Done with first time flag, reinitialize it + LD HL,NAMBUF ; Save start of buffer + LD (NBSAVE),HL + + LD A,(FILCNT) ; Get total files + LD (SHOCNT),A + OR A ; Were there any? + JR NZ,NXTNM1 ; Yes + CALL ILPRT + DB CR,LF,0 + JP NOFILE ; No + +NXTNM1: CALL ILPRTB + DB CR + DB 'Number of files found > ',0 + LD A,(SHOCNT) + LD L,A + LD H,0 + CALL DECOUT ; Show number of files found + LD HL,(TOTREC) + LD (RCNT),HL + LD A,1 + LD (SBSHOW),A ; Get's us back early + CALL OPNOK2 ; Go show total file stats + XOR A + LD (SBSHOW),A + +SBTCH1: LD A,(FILCNT) ; Get the count of files to send + OR A ; Is there any? + JP Z,SNDFN ; No + LD A,(FSTFLG) ; Past first batch file yet? + LD (CONONL),A ; Toggle to local display only + OR A + CALL NZ,CLEARIT ; Else show local + CALL ILPRT + DB CR,LF,LF + DB 'Total transfer time > ',0 + CALL GETSPD ; Get speed indicator + CP 1 ; Are we at 300 bps? + LD HL,XTABLE ; This gives us 128-byte transfer time + JR Z,$+5 ; Yes, skip next line, show 128-byte time + LD HL,KTABLE ; This gives us 1k transfer time + LD D,0 + LD E,A ; Set up for table access + ADD HL,DE ; Index to proper factor + ADD HL,DE + LD E,(HL) + INC HL + LD D,(HL) + LD HL,(TOTREC) ; Get number of records + CALL FILTM1 + CALL XFRTIM ; Check for time restrictions + CALL ILPRT + DB CR,LF,0 + LD A,(FSTFLG) + OR A + CALL Z,DLRDY + +; +; Send the batch filename to remote +; +SNDFN: CALL CKABORT ; Check for remote abort + LD HL,FCB + CALL INITFCB ; Initialize FCB + XOR A + LD (ERRCNT),A ; Reset the error count + INC A + LD (CONONL),A ; Set to local display only + LD A,(FILCNT) ; Get file count + OR A + JP Z,CCHECK ; No more files, exit + LD A,1 + LD (CRCFLG),A ; Make sure in CRC mode + + LD A,0FFH + CALL RECAR1 ; Get the current user area + LD B,A ; Save current user area + PUSH BC ; On stack + LD HL,(NBSAVE) ; Get start of filename + LD BC,14 ; Offset to user area + ADD HL,BC ; Point to binary user area + LD A,(HL) ; Get it + POP BC ; Get current user area back + CP B ; Same? + CALL NZ,RECAR1 ; No, but it is now + CALL SPCDRV ; Get disk parameter block info + + LD HL,(NBSAVE) ; Get address of next batch filename + INC (HL) ; Escape default situation in FCB drive byte + LD DE,FCB ; Where to put it + LD BC,12 ; 12 bytes for drive and filename + LDIR ; Move + LD BC,4 ; Next filename is 4 bytes away + ADD HL,BC ; Add offset + LD (NBSAVE),HL ; Store address for next filename + LD HL,(RECPTR) ; Where to load the 0 block + EX DE,HL ; Put into DE + LD HL,FCB+1 ; Get the start of the filename in HL + LD B,8 + +SZMD1: LD A,(HL) + AND 7FH ; Strip any high bit set + OR A + JR Z,SZMD6 ; Null pathname + CP ' ' + JR Z,SZMD3 + +SZMD2: CALL LCASE ; Put file name in lower case for UNIX + LD (DE),A + INC HL + INC DE + DJNZ SZMD1 + JR SZMD4 + +SZMD3: INC HL ; Skip over spaces if short name + DJNZ SZMD3 + +SZMD4: LD A,(HL) + CP ' ' + JR Z,SZMD6 ; Missing file type field + LD A,'.' ; Send name-type seperator + LD (DE),A + INC DE + LD B,3 + +SZMD5: LD A,(HL) + AND 7FH ; Strip any high bit set + CP ' ' + JR Z,SZMD6 + CALL LCASE ; Put in lower case for UNIX + LD (DE),A + INC HL + INC DE + DJNZ SZMD5 + +SZMD6: EX DE,HL ; Get the address back to HL + LD (HL),0 + INC HL + LD (HDRADR),HL + CALL CNREC ; Get number of records in this file + CALL CHARLN ; Include the ASCII character length + +SZMD7: LD (HL),0 ; Fill rest with zeroes + INC L ; Pad to end of block with binary 0 + JR NZ,SZMD7 + LD HL,(RCNT) + LD (BUFSTR),HL ; Store the file length at end of block + XOR A ; Make sure the header starts with Zero + LD (RCDCNT),A + +; +; Wait for 'C' from remote to indicate he is ready +; +CCHECK: LD E,60 ; Wait up to 60 seconds to abort + +CCHECK1:CALL CKABORT ; Manually requesting an abort? + LD B,3 + CALL RECV ; Wait up to 5 seconds for a character + JR C,CCHECK2 ; No character, decrement counter + CP CANCEL ; If they sent a CTL-X, abort now + CALL Z,CKCAN + CP CRC ; If they sent a CRC, go to work + JR Z,SZMD8 + JR CCHECK ; None of these, wait some more + +CCHECK2:DEC E ; One less to go + JR NZ,CCHECK1 + JP ACKMSG ; Abort if timed out and no character + +SZMD8: LD A,(FILCNT) ; Any files to send? + OR A + JR NZ,SZMD9 ; Yes, continue + XOR A ; Reset the pointers + LD (ACKCHK),A ; Reset flag for normal GTACK use + LD (RCDCNT),A ; Reset the record counter + LD (KFLG),A ; Show in 128 size now + LD HL,(RECPTR) + LD (HL),A ; Reset record pointer + LD A,SOH ; Send a start of header + CALL SEND + CALL SNDHNM ; This header is a zero count + CALL SNDREC ; Send an empty record + CALL SNDCRC ; Send the CRC for the empty record + LD A,(GOTONE) ; Did we actually send at least one? + OR A + JP Z,ABORT ; If not, don't act like we did + CALL EOFSND ; No more files so send EOT to finish + CALL XFRDON + JP EXIT + +; +; Now send the 128 byte filename record +; +SZMD9: DEC A ; Decrement file count for this one + LD (FILCNT),A ; Store it + +SZMD10: XOR A + LD (KFLG),A + LD A,SOH ; Send SOH + LD (ACKCHK),A + CALL SEND ; Send SOH character to the modem + CALL SNDHNM ; Send header (record number, inverse) + CALL SNDREC ; Send a 128 byte record + CALL SNDCRC ; Send a two byte CRC + CALL GTACK + CP ACK + JR NZ,SZMD10 ; Not an ACK, send it again + XOR A + LD (ACKCHK),A ; Reset flag for normal GTACK use + CALL LOW41K ; Check speed being used + JR C,$+7 ; Don't allow 1k blocks if less than MINKSPD + LD A,1 + LD (KFLG),A ; Change to 1k for normal file xfer + XOR A ; Clear A + LD (ERRCNT),A ; Start fresh for the main file + JP SNDFL1 + +; +; Send EOT. Get Acknowledgement from remote. Try up to 4 times then abort. +; +EOFSND: LD A,EOT ; Send an 'EOT' + CALL SEND + LD A,(CHKEOT) ; Did not get an ACK, try again + INC A + LD (CHKEOT),A ; Limit number of retries to 4 + CP 4 ; (to prevent possible 'lock-up') + RET NC ; Quit if already sent 4 or more + CALL GTACK ; Get the ACK + CP ACK + JR NZ,EOFSND ; Resend if no ACK + RET + +ALLDON: LD A,(BATCH) ; In batch mode? + OR A + RET NZ ; If yes, ignore message + CALL ILPRT ; (Want to keep this a separate message) + DB CR,LF,0 + +XFRDON: CALL ILPRTL + DB CR,LF + DB '-- Transfer completed' + DB CR,LF,0 + RET + +; +;-------------------------------------------------------------------------; +; ----> RCVFL - R e c e i v e f i l e ( s ) | +;-------------------------------------------------------------------------; +; +; The filename specified in ZMD command line is transferred over the phone +; from the user's computer to the RCPM system via modem using the 'R' +; (receive) option. The data is sent one record at a time, with headers +; and checksums and retransmissions on errors. 'RM' option is disallowed +; at time of command tail parsing at beginning of program (MSGFLG cannot +; be set unless MSGFIL is enabled). +; +RCVFL: LD A,(MSGFLG) ; Get message file upload flag + OR A ; Enabled? + JR Z,RCVF2 ; No, skip the rest + CALL WHLCHK ; Yes, WHEEL byte set? + JR NZ,RCVF1 ; Yes, turn it off and skip access check + + LD A,(ACCESS) ; Checking access restrictions? + OR A + JR Z,RCVF3 ; No + LD A,(AFBYTE) ; Get access flags byte + AND 8 ; Test for write access (bit 3) + JP Z,NOACC ; Not allowed to write messages + +RCVF1: XOR A ; Clear A + LD HL,(WHEEL) ; Point to WHEEL byte + LD (HL),A ; And stuff a 0 to turn WHEEL off + JR RCVF3 ; WHEEL 'was' on, so skip access check + +; +; Check additional receive flags +; +RCVF2: LD A,(ACCESS) ; Checking access restrictions? + OR A + JR Z,RCVF3 ; No + CALL WHLCHK ; SYSOP online? + JR NZ,RCVF3 ; Yep, skip all this checking + LD A,(PUPFLG) ; Privileged transfer option request? + OR A + LD A,(AFBYTE) ; Get access flags byte + JR Z,$+7 ; No + AND 80H ; Test for privileged user access (bit 7) + JP Z,NOACC ; Not allowed to use "RW" option + AND 40H ; Test for upload access (bit 6) + JP Z,NOACC ; Not allowed to upload files + +; +; User has the access he asked for +; +RCVF3: LD A,(BATCH) ; Requesting batch mode? + OR A + JP NZ,RBTCH ; Yes, go do batch stuff first + CALL RCVFL1 ; Find drive/user/filetype permitted + LD IX,FCB + CALL RESTRCT ; Check restrictions on uploads + CALL CONTIN ; Display drive/user area + CALL MAKEFIL ; Open the file, ready to receive + +; +; Receive records until EOT +; +RCVLP: XOR A + LD (ERRCNT),A ; Initialize error count to zero + CALL RCVRECD ; Receive a record + JR NC,RCVLP1 ; If not EOT, store this record and get next + LD HL,(RECDNO) ; Get number of records + LD A,H + OR L ; 0 length file? + JP Z,ABORT ; Yes, abort and erase file + LD A,(EOTFLG) ; This the first EOT character? + OR A + JP NZ,RCVEOT ; No, exit + LD A,NAK + LD (EOTFLG),A ; Set the flag + CALL SEND ; Send a NAK + JR RCVLP ; Go wait another EOT + +; +; Increment record number +; +RCVLP1: CALL INCRNO ; Bump record number, if received ok + LD HL,(RECPTR) ; Get buffer address + LD DE,128 ; 128 chars/record + LD A,(KFLG) ; Using 1k blocks? + OR A + JR Z,$+5 ; If not, skip next line + LD DE,1024 ; 1k/record + ADD HL,DE ; To next buffer + LD (RECPTR),HL ; Save buffer address + LD A,(KFLG) ; Using 1k blocks? + OR A + LD A,(RECNBF) ; Get number of records in buffer + JR Z,$+6 ; If not, skip next 2 lines + ADD A,8 ; Increment it 8 records for 1k + JR $+3 ; Skip next line + INC A ; Else only 1 record + LD (RECNBF),A ; Store new record count + +; +; If 16k in buffer, write to disk +; + LD C,A ; Put the record count in C + LD A,(BUFSIZ) ; Buffer size in A + ADD A,A + ADD A,A + ADD A,A + CP C ; Is the buffer full, yet? + CALL Z,WRBLOCK ; No, return + CALL SNDACK ; Ack the record + JP RCVLP ; Loop until 'EOF' + +; +; End of transmission received +; +RCVEOT: CALL SNDACK ; ACK the record + CALL WRBLOCK + JP RCVEOT0 + +WRBLOCK:LD A,(RECNBF) ; Number of records in the buffer + OR A ; 0 means end of file + RET Z ; None to write + LD C,A ; Save count + LD DE,DBUF ; Point to disk buff + +WRBLOK1:PUSH HL + PUSH DE + PUSH BC + CALL STDMA ; Set DMA + LD DE,FCB ; Then write the block + LD C,WRITE + CALL BDOS + POP BC + POP DE + POP HL + OR A ; Write error? + JR Z,WRBLOK2 ; No + CALL RSDMA ; Reset DMA to normal + LD A,CANCEL ; Cancel + CALL SEND ; Sender + CALL SEND + CALL SEND + CALL CLOSFIL ; Kill received file + CALL ILPRTB ; Exit with msg: + DB CR,LF + DB '-- Write Error: ',0 + CALL SHONM3 + JP EXIT + +WRBLOK2:LD HL,128 ; Length of 1 record + ADD HL,DE ; 'HL'= next buff + EX DE,HL ; To 'DE' for setdma + DEC C ; More records? + JR NZ,WRBLOK1 ; Yes, loop + XOR A ; Get a zero + LD (RECNBF),A ; Reset number of records + LD HL,DBUF ; Reset buffer + LD (RECPTR),HL ; Save buffer address + JP RSDMA + +; +; Write record to log file if LOGCAL is YES +; +RCVEOT0:CALL CLOSFIL ; Close the file + LD HL,(RECDNO) ; Get # of records + LD (RCNT),HL ; Stuff in RCNT + CALL XTIM ; Calculate approximate transfer time + CALL STORTM ; Store time + CALL LOGCALL ; Log transfer if supposed to + +RCVEOT1:LD A,(LOGLDS) ; Counting uploads? + OR A + JR Z,RCVEOT2 ; No + LD A,(PRIVATE) ; Private upload? + OR A + JR NZ,RCVEOT2 ; Yes, no credit for private uploads + LD IY,(UPLDS) ; Get Upload Counter + INC (IY) ; One more upload since log in + +RCVEOT2:CALL ALLDON ; If not in BATCH, print transfer complete + JP CRED ; Credit upload time and ask for descriptions + +; +;-------------------------------------------------------------------------; +; R e c e i v e B a t c h | +;-------------------------------------------------------------------------; +; +RBTCH: XOR A ; Using batch so reset some flags + LD (FRSTIM),A ; Needs to be reset for each new file + LD A,(FSTFLG) ; First batch file? + OR A + JR Z,RBTCH0 ; Yes, give them time to setup + LD A,CRC + CALL SEND ; In case he's quick like us + JP RBTCH1 + +; +; Initial setup only +; +RBTCH0: CALL RCVFL1 ; Find drive/user/filetype permitted + CALL CONTIN ; Display drive/user area + LD HL,NAMBUF + LD (NBSAVE),HL + LD A,1 + LD (FSTFLG),A ; No need to run those routines again + +; +; Get the batch file name and display +; +RBTCH1: LD HL,FCB + CALL INITFCB ; Initialize FCB + XOR A + LD (RCVTRY),A + INC A ; Set to local display only + LD (CONONL),A + +RBTCH2: CALL CKABORT ; Check for user abort + LD B,5 + CALL RECV ; Wait up to 5 seconds for SOH from remote + JR C,RBTCH3 ; No character, decrement counter + CP CANCEL ; Was it a CTL-X for cancel? + CALL Z,CKCAN ; Check for abort + CP SOH + JR Z,RBTCH5 ; Got SOH + JR RBTCH2 ; None of these, wait some more + +RBTCH3: LD A,CRC ; Send a 'C' + CALL SEND + +RBTCH4: LD A,(RCVTRY) + INC A + LD (RCVTRY),A + CP 20 + JR C,RBTCH2 + JP ABORT ; Quit and try to force him to quit also + +RBTCH5: LD B,5 + CALL RECV ; Wait up to 5 seconds for sector number + JP C,TOTERR + LD D,A ; Save sector number in D + OR A ; Must be a 0 if sending batch + JP NZ,WRGHDR + LD B,5 + CALL RECV ; Wait up to 5 seconds for reciprocal + JP C,TOTERR + CPL ; Invert it and compare to sector # + CP D + JP NZ,CRCERR ; Bad match + LD HL,0 + LD (CRCVAL),HL ; Clear CRC counter + LD E,128 ; Expecting a 128 character block + LD HL,(RECPTR) ; Point to the buffer address + +RBTCH6: LD B,5 + CALL RECV ; Up to 5 seconds for 128 byte header block + JP C,TOTERR ; Exit if no character + LD (HL),A ; Store the character + INC HL ; Point to next buffer location + DEC E ; One less to go + JR NZ,RBTCH6 + LD E,2 ; Number of CRC bytes to get + +RBTCH7: LD B,5 + CALL RECV ; Up to 5 seconds for CRC bytes + JP C,TOTERR + DEC E ; Done? + JR NZ,RBTCH7 ; No + CALL CRCCHK ; Compare CRC received against ours + OR A ; Ok? + JP NZ,CRCERR ; No + CALL SNDACK ; Yes, acknowledge to remote + +; +; Decode pathname into CPM format +; + LD DE,FCB+1 ; Where to put it + LD HL,(RECPTR) ; Where to get it + LD B,8 ; Filename length + +RBTCH8: LD A,(HL) ; Get the character from the buffer + OR A ; Was it a zero? + JR Z,RBTCH12 ; If yes, all done + CP '.' ; Was it a delimiter? + JR Z,RBTCH9 + CALL UCASE ; Insure name is in upper case + CP '_' ; Is it an underline? + JR NZ,$+4 ; No + LD A,'-' ; Else make it a dash + LD (DE),A ; Store filename character in FCB + INC DE ; Increment pointers + INC HL + DJNZ RBTCH8 ; If not 8, keep going + LD A,(HL) ; Get the character back + OR A ; We had 8, was there an extent? + JR Z,RBTCH11 ; If zero, was all done + JR RBTCH10 ; Else must be a '.' + +RBTCH9: LD A,' ' ; Spaces to make up 8 spaces for name + LD (DE),A ; Store space character in FCB + INC DE ; Increment pointers + DJNZ RBTCH9 ; Keep going until in extent area + +RBTCH10:INC HL ; Skip the '.' position + LD B,3 ; Extent length + +RBTCH11:LD A,(HL) ; Get the character from the buffer + OR A ; Was it a zero? + JR Z,RBTCH12 ; If yes, all done + CALL UCASE ; Insure extent is in upper case + LD (DE),A ; Store extent character + INC DE ; Increment pointers + INC HL + DJNZ RBTCH11 ; Keep going until finished + +RBTCH12:LD A,(FCB+1) ; See if there was any filename at all + CP ' ' + JP Z,RBCHDON ; No, all done, no more files + CALL CLEARIT ; Clear screen locally if suppose to + +RBTCH13:LD HL,(BUFSTR) ; Get the file length, if provided + LD A,H + OR L + JR NZ,$+7 ; If not both zero, length is provided + CALL SHONM ; Else show the filename + JR RBTCH14 ; And wait to receive + LD (RCNT),HL ; Store the file length + CALL OPNOK1 ; Show filename and file sizes + CALL ILPRTL + DB CR,LF + DB 'Ymodem transfer time > ',0 + CALL GETSPD ; Get speed indicator + CP 5 ; Are we less than 1200 bps? + JR C,$+7 ; Yes, skip 1k time + CALL KTIM ; Get 1k transfer time + JR $+5 ; Skip 128 byte transfer time + CALL XTIM ; Get 128 byte transfer time + CALL XFRTIM ; Display transfer time + +RBTCH14:CALL ILPRTL + DB CR,LF,LF,0 ; Finish the filename line + XOR A ; Reset the carry flag + LD (RCVTRY),A ; Reset the error counter + LD IX,FCB + CALL RESTRCT ; Check restrictions on uploads + CALL CHEKFIL ; Already have a file with that name? + CALL MAKEFIL ; If not, make it + CALL BCHINR + CALL WAITMSG ; Display '[ waiting ]' message locally + LD A,CRC + CALL SEND + JP RCVLP ; Start receiving the file + +RBCHDON:XOR A ; Zero the batch mode flag + LD (BATCH),A + LD A,(GOTONE) ; Were there any files received? + OR A + JP Z,ABORT ; No, abort + CALL XFRDON ; Show transmission is finished + JP CRED ; Ask for descriptions + +CRCERR: CALL ILPRTL + DB '-- CRC error' + DB CR,LF,0 + JP INCERR + +WRGHDR: CALL ILPRTL + DB '-- Wrong header type' + DB CR,LF,0 + JR INCERR + +TOTERR: CALL ILPRTL + DB '-- Timeout receiving filename' + DB CR,LF,0 + +INCERR: CALL WAIT1 ; Make sure sender has stopped + LD A,NAK ; Tell sender it was not successful + CALL SEND + LD A,(RCVTRY) ; Increment the error counter + INC A + LD (RCVTRY),A + CP 33 + JP C,RBTCH4 ; Send a NAK and tell him to try again + JP ABORT ; Else abort + +; +;-------------------------------------------------------------------------; +; C r e d i t R o u t i n e s | +;-------------------------------------------------------------------------; +; +; The following credits the caller for the amount of time spent uploading +; any non-private files with descriptions. +; +CRED: LD A,(BATCH) + OR A + JR NZ,CRED0A + LD E,10 ; Set up for a 30 second wait + +CRED0: LD B,3 ; 3 seconds to receive a character + CALL RECV + JR NC,CRED0A ; Got one, continue + CALL ILPRTB ; Make sure this goes to modem + DB CR + DB '-- Hit a key' + DB CR,0 ; Let them know we're waiting + DEC E ; 2 less seconds + JR NZ,CRED0 ; Wait until 0 + +CRED0A: LD A,(CREDIT) ; Credit caller with upload time? + OR A + JP Z,CRED2 ; No + CALL WHLCHK ; WHEEL byte set? + JP NZ,CRED2 ; Yes, skip credit + LD A,(PUPFLG) ; Privileged transfer request? + OR A + JP NZ,CRED2 ; Yes, skip credit + LD A,(PRIVATE) ; Was this a private file? + OR A + JP NZ,CRED2 ; Yes, skip credit + LD A,(BATCH) ; In batch mode now? + OR A + JP NZ,CRED1 ; If yes, skip following messages + + CALL ILPRTB ; Show to remote also + DB CR,LF + DB 'Thanks for the ',0 + CALL SHOCAT ; Show upload area descriptor, if supposed to + CALL ILPRTB + DB 'upload(s)!',CR,LF,0 + CALL ILPRTB + DB 'Upload time has been credited to time left.',0 + +CRED1: LD A,(MAXTOS) ; Get maximum time allowed + OR A ; Unlimited? + JR Z,CRED2 ; Yes, skip credit + LD HL,(RECDNO) ; Else get the number of records + LD (RCNT),HL + CALL XTIM ; Get transfer time in C + LD A,(MAXTOS) ; Get maximum time allowed back + INC A ; Increment to next full minute + ADD A,C ; Add upload time + LD (MAXTOS),A ; Save for internal use + +; +; If not still in BATCH mode, ask for file description +; +CRED2: LD A,(BATCH) ; Still in batch? + OR A + JP NZ,DONE ; Yes, see if anymore files left + LD A,(HIDEIT) ; Did we make this upload a $SYS file? + OR A + JR Z,CRED3 ; No, skip all this + CALL WHLCHK ; Wheel byte set? + JR NZ,CRED3 ; Yes, file not set to $SYS + LD A,(PRIVATE) ; Was this a private upload? + OR A + JR NZ,CRED3 ; Yes, file not set to $SYS + CALL ILPRTB + DB CR,LF + DB 'Uploads remain hidden until cleared by Sysop.',0 + +CRED3: CALL ILPRTB + DB CR,LF,LF,0 + CALL RSTLCK ; Clear WRTLOC before descriptions + CALL ADDTON ; Update BYE's time on byte if supposed to + +; +;-------------------------------------------------------------------------; +; D e s c r i p t i o n R o u t i n e s | +;-------------------------------------------------------------------------; + +ASK: LD A,(PRIVATE) ; Private upload? + OR A + JP NZ,EXIT ; Yes, no descriptions + LD A,(PUPFLG) ; Privileged transfer request? + OR A + JP NZ,EXIT ; Yes, no descriptions + LD A,(DESCRIB) ; Requiring descriptions? + OR A + JR NZ,ASK1 ; Yes + + LD A,(MSGDESC) ; To BBS message base? + OR A + JP Z,EXIT ; No + LD (DSCFLG),A ; Set flag to show message base descriptions + LD A,(PRUSR) ; Get the private user + LD (USER),A ; FOR destination + LD A,(PRDRV) ; Get the private drive + LD (DRIVE),A ; FOR destination + +ASK1: CALL GETTIME + LD HL,DATMSG+6 + + LD A,(EDATE) ; European date format? + OR A + JR Z,ASK1A ; No + LD A,(DAY) + CALL DATDEC ; Print DD + INC HL + LD A,(MONTH) ; Print MM + JR ASK1B ; And finish with YY + +ASK1A: LD A,(MONTH) + CALL DATDEC ; Print MM + INC HL + LD A,(DAY) + +ASK1B: CALL DATDEC ; Print DD + INC HL + LD A,(YEAR) + CALL DATDEC ; Print YY + + LD A,(FILCNT) ; Any batch filenames? + OR A + JR Z,ASK3 ; No + LD HL,NAMBUF ; Point to name buffer + LD (NBSAVE),HL + +ASK2: LD IY,FILCNT ; One less file to describe + DEC (IY) + LD HL,(NBSAVE) ; Get address of next batch filename + LD DE,FCB ; Where to put it + LD BC,12 + LDIR + LD (NBSAVE),HL ; Store address for next filename + +ASK3: LD A,(DESCRIB) ; FOR file descriptions? + OR A + JR Z,ASK6 ; No + + LD A,(ASKAREA) ; Using upload routing? + OR A + JR Z,ASK4 ; No, KIND contents doesn't matter + + LD A,(KIND) ; Do we have a the upload area yet? + OR A + JR NZ,ASK6 ; Yes, don't ask them twice + + CALL ILPRTB + DB CR,LF,LF + DB 'Upload category: ' + DB CR,LF,0 + JR ASK5 + +ASK4: LD A,(ASKIND) ; Need file descriptors for FOR entries? + OR A + JR Z,ASK6 ; No + + CALL ILPRTB + DB CR,LF,LF,0 + CALL SHONM3 ; Show the file name + + CALL ILPRTB + DB ' - this file is for:' + DB CR,LF,0 + +ASK5: CALL GETKIND ; Get file category for description header + CALL TYPE ; Output to both consoles + +ASK6: CALL ILPRTB + DB CR + DB 'Describe ',0 + CALL SHONM3 ; Show the filename + CALL ILPRTB + DB ' - 7 lines or less - ^W disables WRAP - CR when done',0 + + LD HL,FCB+1 ; FCB contains current filename + LD DE,NEWNAM ; Needed in here for description routines + LD B,8 ; Filename is up to 8 bytes long + CALL ASK7 ; Go store it until a space + + LD A,'.' + LD (DE),A ; Add seperator + + INC DE + LD HL,FCB+9 ; Point to file extent at FCB + LD B,3 ; File extent is up to 3 bytes long + CALL ASK7 ; Go store until space or B=3 + + LD A,LF ; Stuff Terminator + LD (DE),A + + CALL GETDSC ; Show typing guide and get upload description + JP Z,ASK2 ; If we got a description, get next + JP ASK3 ; Else get this one over again + +; +; Small subroutine to store the filename located at FCB+1 into buffer area +; located at DE +; +ASK7: LD A,(HL) ; Get character + AND 7FH ; Done with high bits + CP ' ' ; A space? + RET Z ; Yes, all done + LD (DE),A ; Else store it in destination + INC HL ; Increment source pointer + INC DE ; Increment destination + DJNZ ASK7 ; Keep looping until B=0 or (HL)=' ' + RET + +; +;----------------------- +; Set upload drive/user +; +RCVFL1: CALL LOGDU ; Select drive/user for upload + LD A,(PUPFLG) ; Place "RW" file as needed + OR A ; Can only be set if user is privileged + JR NZ,RCVFL2 ; Privileged, else check if sysop... + CALL WHLCHK ; Let WHEEL user put file wherever he wants + JR Z,RCVFL6 ; If WHEEL byte not set, stay normal + +RCVFL2: LD A,(RCVDRV) + OR A + JR Z,RCVFL3 + SUB 'A' ; Convert ASCII drive to binary + JR RCVFL4 + +RCVFL3: LD A,(OLDDRV) + +RCVFL4: INC A + LD (FCB),A + ADD A,'A'-1 ; Convert binary to ASCII + LD (DRV),A ; Drive + LD A,(RCVDRV) ; See if a drive was requested + OR A + LD A,(OLDUSR) ; Current user + JR Z,RCVFL5 ; If not, use current user + LD A,(RCVUSR) ; Else get requested user + +RCVFL5: LD (USR),A ; User + RET + +RCVFL6: LD A,(SETAREA) + OR A + JR NZ,RCVFL7 + LD A,(ASKAREA) + OR A + JR Z,RCVFL8 + +RCVFL7: LD A,(DRV) + SUB 40H + LD (FCB),A + +RCVFL8: LD A,(PRIVATE) ; Receiving to a private area? + OR A + RET Z ; If not, exit + LD A,(PRDRV) ; Private area takes precedence + SUB 40H ; Convert to binary + LD (FCB),A ; Store drive to be used + RET + +; +; Display where file(s) will go, open file and display name +; +CONTIN: LD A,(ASKAREA) ; Upload routing enabled? + OR A + JR NZ,CONT0 ; No + LD A,(ASKIND) + OR A + JR Z,CONT1 + +CONT0: CALL WHLCHK ; Is WHEEL byte set? + JR NZ,CONT1 ; No, skip this + CALL GETKIND ; Get upload area + LD A,CR ; So the line feed (LF) doesn't get printed + LD (CONT1+4),A + +CONT1: CALL ILPRTB + DB CR,LF + DB 'Receiving on: Drive ',0 + LD A,(PRIVATE) ; Private upload? + OR A + LD A,(PRUSR) ; Get private user area + LD B,A ; Put in B for now + LD A,(PRDRV) ; Get private drive + JR NZ,CONT2+3 ; Yes, priority 1 + LD A,(USR) ; Get the regular user area + LD B,A ; And put it in B + LD A,(PUPFLG) ; Privileged upload? + OR A + JR NZ,CONT2 ; Yes, priority 2 + CALL WHLCHK ; WHEEL set? + JR NZ,CONT2 ; Yes, priority 3 + LD A,(SETAREA) ; Uploading to designated drive/user? + OR A + JR NZ,CONT2 ; Yes, priority 4 + LD A,(ASKAREA) ; Upload routing enabled? + OR A + JR Z,CONT3 ; No + +CONT2: LD A,(DRV) ; Get regular upload drive + PUSH AF ; Save ASCII upload drive + SUB 40H ; Convert drive to binary + LD (FCB),A ; Store it in File Control Block + POP AF ; Get ASCII drive back + JR CONT4 ; All done, now display it + +CONT3: LD A,(OLDUSR) ; Get current user area for default + LD B,A ; Save in B + DB 0,0 ; Contains 'LD B,n' (DUU) from GETDU + LD A,(OLDDRV) ; Get current drive for default + ADD A,'A' ; Convert to ASCII + DB 0,0 ; Contains 'LD A,n' (DUD) from GETDU + +CONT4: LD (KDRV),A ; Save it for KSHOW + CALL TYPE ; Print the drive to store on + CALL ILPRTB + DB ', User ',0 + LD A,B ; B contains the user area + LD (USR),A ; Save for MSGDESC upload info + LD H,0 + LD L,A ; Binary user area in L + CALL DECOUT ; Decimal output + CALL ILPRTB + DB '. (',0 + CALL KSHOW ; Show available space remaining + CALL ILPRTB + DB ')',0 + CALL CHEKFIL ; See if file exists + + LD A,(DESCRIB) ; Descriptions enabled? + OR A + JR NZ,CONT5 ; Yes + LD A,(MSGDESC) ; Message base descriptions? + OR A + JR Z,CONT6 ; No + +CONT5: LD A,(PRIVATE) ; Private upload? + OR A + JR NZ,CONT6 ; Yes, no descriptions + LD A,(PUPFLG) ; Privileged upload? + OR A + JR NZ,CONT6 ; Yes, no descriptions + CALL ILPRTB + DB CR,LF + DB 'Description(s) needed - ',0 + JR CONT7 + +CONT6: CALL ILPRTB + DB CR,LF,0 + +CONT7: CALL ILPRTB + DB 'Abort: ^X pause ^X' + DB CR,LF,LF,0 + CALL WAITMSG + RET + +; +; Increment the file count +; +BCHINR: LD HL,(NBSAVE) ; Where to put the name + LD DE,FCB ; Where to get the name + EX DE,HL + LD BC,12 ; Move current filename to buffer for ASK: + LDIR + EX DE,HL + LD (NBSAVE),HL ; Store address for next filename + LD A,(FILCNT) ; Increment the file count + INC A + LD (FILCNT),A + RET + +; +;-------------------------------------------------------------------------; +; T r a n s f e r c o m p l e t e | +;-------------------------------------------------------------------------; +; +; Done transferring current file. Check to see if in BATCH mode and if so, +; display filename transferred and reset flags for next possible file. +; Otherwise eat garbage from line, reset WRTLOC, do timekeeping and exit +; to CP/M (Forward text file to BBS message base if supposed to). +; +DONE: LD A,(BATCH) ; Still in batch mode? + OR A + JP Z,EXIT ; No. All done + LD A,(OLDDRV) ; Restore the original drive + CALL RECDRX + LD A,(OLDUSR) ; Restore the original number + CALL RECAR1 + CALL RSDMA ; Reset to default DMA address + LD A,1 ; Display filename locally only + LD (GOTONE),A ; Indicates there was a file handled + CALL ILPRTL ; Display the file name + DB CR,LF,0 + CALL SHONM3 ; Show the filename at FCB+1 + CALL ILPRT + DB ' transferred',CR,LF,0 + +; +; Now reset some flags for another possible batch file +; + XOR A + LD (EOFLG),A ; Clear end of file flag + LD (EOTFLG),A ; And end of transmission flag + LD (CHKEOT),A ; Clear the "resend EOT" flag + LD HL,0 + LD (ACCERR),HL ; Reset the accumulate error count + LD (RECNBF),HL ; Zero number of records in the buffer + LD (RECDNO),HL ; Zero the current record number + LD (RCDCNT),HL ; Zero the transmit record counter + LD HL,DBUF ; Reset buffer pointers + LD (RECPTR),HL + LD A,(MODE) ; Get transfer mode + CP 'S' ; Sending files? + JP Z,SNDFIL ; Yes + + LD A,(FILIMT) ; Maximum upload (TPA limitation) + LD B,A ; Into B for comparison + LD A,(FILCNT) ; Get current count received + CP B ; Received BATCH transfer limit yet? + JP C,RCVFL + LD A,CANCEL + CALL SEND + CALL SEND + CALL SEND + CALL WAIT1 + + CALL ILPRTB + DB CR,LF + DB '-- ',0 + LD A,(FILIMT) + LD H,0 + LD L,A + CALL DECOUT + CALL ILPRTB + DB ' file limit in BATCH receive',CR,LF,0 + + XOR A + LD (BATCH),A ; Reset the batch mode flag to zero + JP CRED3 ; Go back and ask for descriptions + +; +;-------------------------------------------------------------------------; +; C o m m o n S u b r o u t i n e s | +;-------------------------------------------------------------------------; +; +; Universal access check routine checks restrictions of current file being +; considered for transfer. +; +; On entry: IX = start address of byte before filename +; On exit: Z = File ok to send/receive +; NZ = Transfer denied +; +; Each bit of this word contains an image of the high bit within the filename +; pointed to by IX+1 on entry. +; +HBITMAP:DW 0000000000000000B + +; +; First, make a bit map containing an image of the high bits in the filename +; pointed to by IX+1 on entry. +; +RESTRCT:LD B,11 ; Number of bytes to map + LD HL,0 ; Initialize destination for bit map + PUSH IX ; Save current filename address + INC IX ; Skip past drive indicator + +ACCMASK:LD A,(IX) ; Get next character of filename + AND 80H ; Isolate attribute bit + RLCA ; Move MS bit into LS bit + OR L ; OR in any previously set bits + LD L,A ; Save result + ADD HL,HL ; Shift HL left one bit for next time + INC IX ; IY+1 equals next character in filename-type + DJNZ ACCMASK ; Loop through all 11 bytes + POP IX ; Get our original filename pointer back + +; +; Most significant bit will already be in bit 11 of HL, so only 4 shifts are +; necessary +; + ADD HL,HL ; 000?????$??????00 + ADD HL,HL ; 00??????$?????000 + ADD HL,HL ; 0???????$????0000 + ADD HL,HL ; ????????$???00000 + LD (HBITMAP),HL ; Store filename high bit image + +; +; See which (if any) restrictions we need to enforce +; + CALL WHLCHK ; WHEEL byte set? + JP NZ,SENDOK ; Yes, transfer is approved + LD A,(ACCMAP) ; Get user defined restriction flags + LD B,A + LD A,(MODE) ; Get the file transfer mode + CP 'S' ; Sending? + JR Z,RSTRCT2 ; Yes, check send restrictions + +; +; Check RECEIVE restrictions +; + LD IX,FCB + BIT NOCOMR,B ; Rename '.COM' uploads to '.OBJ'? + JR Z,RSTRCT1 ; No, check for ZCPR restrictions + LD DE,COMCHG ; Compare to 'COM' + CALL MCHFTYP ; Are they the same? + CALL Z,RENTYP ; Yes, rename it to 'OBJ' + +RSTRCT1:BIT ZCPR,B ; Using with ZCPR? + RET Z ; No, all done + LD DE,SYSCHK ; Compare to 'SYS' + CALL MCHFTYP ; Are they the same? + JR Z,FTYPERR ; Yes, tell them to use a different filetype + LD DE,NDRCHK ; Compare to 'NDR' + CALL MCHFTYP ; ... + JR Z,FTYPERR ; ... + LD DE,RCPCHK ; Compare to 'RCP' + CALL MCHFTYP ; ... + RET NZ ; If no match, filetype is ok to receive + +FTYPERR:CALL ERXIT + DB CR,LF + DB '-- Use a different file extent','$' + +; +; Check SEND restrictions +; +RSTRCT2:LD A,(BATCH) ; In BATCH? + OR A + JR NZ,RSTRT2A ; Yes, require send access for any batch file + BIT DWNTAG,B ; Allow F3 tagged file regardless of access? + JR Z,RSTRT2A ; No, skip this + BIT 5,H ; Byte 3 of filename set? + JP NZ,SENDOK ; Yes, send it immediately + +RSTRT2A:LD A,(ACCESS) + OR A + JR Z,RSTRCT3 + LD A,(AFBYTE) ; Get BYE or BBS bit mapped access flag + AND 20H ; Download access allowed? + JP Z,NOACC ; No, inform user of restricted function + +RSTRCT3:LD A,(LBRARC) ; Get member extraction flag + OR A ; Enabled? + JR NZ,RSTRCT4 ; Yes, skip these restrictions + BIT TAGFIL,B ; Restricting tagged files? + JR Z,RSTRCT4 ; No + BIT 7,H ; First byte of filename set? + JR NZ,NOSEND ; Yes, can't send it + +RSTRCT4:BIT NOSYS,B ; Restricting $SYS files? + JR Z,RSTRCT5 ; No + BIT 6,L ; First byte of filetype set? + JR NZ,NOSEND ; Yes, can't send + +RSTRCT5:LD A,(LBRARC) ; Get member extraction flag + OR A ; Enabled? + RET NZ ; Yes, and file was not tagged (returning NZ) + BIT NOLBS,B ; Restricting files with labels (#)? + JR Z,RSTRCT6 ; No + LD A,(IX+11) ; Get possible label + AND 7FH ; Strip the high bit + CP '#' ; Labeled? + JR Z,NOSEND ; Yes, can't send + +RSTRCT6:BIT NOCOMS,B ; Allow sending 'COM' files? + JP Z,SENDOK ; Yes + LD DE,COMCHG ; Point to string to compare with + CALL MCHFTYP ; Is it a .COM file? + JP NZ,SENDOK ; No + +; +; Common exit point +; +COMTRY: LD A,(BATCH) ; In batch mode? + OR A + JP NZ,NOSND2 ; Yes, just set flag to not include (NZ) + POP HL ; Remove call from OPNOK from stack + CALL ERXIT + DB CR,LF + DB '-- Can''t send .COM files','$' + +NOSEND: LD A,(BATCH) ; Are we in batch mode? + OR A + JP NZ,NOSND2 ; Yes, no error messages, just checking + LD DE,LBRNAM + CALL NOSND0 + JR Z,NOSND1 + LD DE,ARKNAM + CALL NOSND0 + JR Z,NOSND1 + LD DE,ARCNAM + CALL NOSND0 + JR Z,NOSND1 + CALL ERXIT + DB CR,LF + DB '-- File is not for distribution','$' + +NOSND0: LD B,3 + LD HL,FCB+9 + CALL MATCH + RET + +NOSND1: CALL ERXIT + DB CR,LF + DB '-- Individual members only','$' + +NOSND2: LD A,1 ; Return NZ if file not allowed + OR A + RET + +SENDOK: XOR A ; Return Z if file is ok + RET + +; +; See if next character is ' ' or non ' '. File name error if no ASCII +; character. +; +CHKFSP: LD A,(BATCH) ; Requesting batch mode now? + OR A + JR Z,CHKFSP2 ; Exit if not + LD A,(MODE) ; Sending batch? + CP 'S' + JR Z,CHKFSP2 ; If yes, exit + DEC B + JR Z,CHKFSP1 + INC B + JR CHKFSP2 + +CHKFSP1:POP HL ; Do not return to LOGDU + RET ; Return instead to SNDFIL + +CHKFSP2:DEC B + JP Z,NFN1 ; Error if end of chars. + LD A,(HL) + CP ' '+1 + RET NC ; Ok if valid character so return + INC HL + JR CHKFSP + +; +; Check next character to see if a space or non-space, go to menu if a command +; error. +; +CHKSP: LD A,(BATCH) ; Requesting batch mode? + OR A + JR Z,CHKSP2 ; Exit if not + LD A,(MODE) ; Sending in batch mode now? + CP 'S' + JR Z,CHKSP2 ; If yes, exit + DEC B + JR Z,CHKSP1 + INC B + JR CHKSP2 + +CHKSP1: POP HL ; Don't return to LOGDU + RET ; Return to SNDFIL + +CHKSP2: DEC B + JP Z,HELP + INC HL + LD A,(HL) ; Get the character there + CP ' ' ; Space character? + RET ; Z = space, NZ = non-space + +; +; Determine the amount of disk storage needed for the current file. On +; entry: BC = total record count of file +; +ROUNDK: LD DE,(BLKSIZ) ; Fetch block size in kilobytes + PUSH DE ; Save block size + PUSH BC ; Save file record count + LD B,3 ; Make a mask for size limit + +MSKCMP: OR A ; Clear carry + RL E ; Make mask for size limit + RL D ; Shift until + DJNZ MSKCMP ; Shift until DE is A + DEC DE ; Mask of records per block + POP BC ; Get a copy of file record count + PUSH BC + + LD A,C ; Mask file size with block size mask + AND E + LD C,A + LD A,B + AND D + OR C ; Zero result indicates no block + POP BC + PUSH AF ; Remainder in file size + LD A,D ; Compliment mask and zero file size + CPL ; Remainder in BC + AND B + LD B,A + LD A,E + CPL + AND C + LD C,A + LD E,3 ; Shift count to divide masked file + +MINKL: OR A ; Clear carry + RR B ; Rotate high byte through carry + RR C + DEC E ; Decrement shift count + JR NZ,MINKL + + POP AF ; Check if even block size + POP DE ; Get back block size + PUSH HL ; Save kilobyte insert address + LD HL,0 ; Initial zero of remainderI + JR Z,MINKS ; Zero if even + EX DE,HL ; Block size to HL if remainder + +MINKS: ADD HL,BC ; Add in total kilobyte count + EX DE,HL ; Total size to DE + POP HL ; Get back load address + RET + +; +; Log into drive and user +; +; (If specified). If none mentioned, falls through to 'TRAP' routine for +; normal use. +; +LOGDU: LD HL,TBUF ; Point to default buffer command line + LD B,(HL) ; Store number of characters in command + INC B ; Add in current location + CALL CHKSP ; Skip spaces to find 1st command + JR Z,$-3 ; Loop until non-space character + CALL CHKSP ; Skip 1st command (non-spaces) + JR NZ,$-3 ; Loop until a space + INC HL + CALL CHKFSP ; Skip spaces to find 2nd command + LD (SAVEHL),HL ; Save start address of the 2nd command + +; +; Now pointing to the first byte in the argument. (If it was of a format +; similar to: 'B6:HELLO.DOC' then we point at the drive character 'B'. Then +; transfer up to 4 bytes from the command line buffer (pointed at by HL) to +; the drive/user storage buffer pointed at by DE +; +LGDU1: PUSH HL ; Save command line position + PUSH BC ; And character count + LD DE,DUSAVE ; Destination buffer + LD C,4 ; Drive/user is 4 characters maximum 'B15:' + +LGDU2: LD A,(HL) ; Get character + CP ' '+1 ; Space or return? + JP C,TRAP ; Yes, all done + LD (DE),A ; Else store it in DUSAVE + INC HL ; Increment to next argument + INC DE ; Increment DUSAVE + CP ':' ; Was it a colon? + JR Z,LGDU3 ; Yes, was drive/user requested + DEC B ; One less position to check + DEC C ; One less to go + JR NZ,LGDU2 ; Loop until a colon or C=0 + JP TRAP ; Move name to FCB + +; +; Get Disk and User from DUSAVE and log in if valid. +; +LGDU3: EXX ; Save HL (buffer) pointer and BC (char count) + POP BC ; We don't need these back, but fix the stack + POP HL + EXX ; And get HL and BC back to continue + LD A,(BATCH) ; Requesting batch mode? + OR A + JR Z,LGDU4 ; No + LD A,(MODE) ; Get program transfer mode + CP 'R' ; Receiving batch? + JR Z,LGDU5 ; Yes, skip next two lines + +LGDU4: CALL CHKFSP ; See if a file name is included + LD (SAVEHL),HL ; Save location of the filename + +LGDU5: LD A,(PRIVATE) ; Uploading to a private area? + OR A + JP NZ,TRAP2 ; If yes, going to a specified area + + LD A,(OLDDRV) ; Get current drive + LD (DUD),A + ADD A,'A' + LD (RCVDRV),A + + LD HL,DUSAVE ; Point to drive/user + LD A,(HL) ; Get 1st character + CP '0' ; It is a ' ', CR or LF? + JR C,LGDU6 ; Yes, skip next 2 lines + CP '9'+1 ; Is it an ASCII number 0-9? + JR C,LGDU10 + +LGDU6: LD (RCVDRV),A ; Allows SYSOP to upload to any drive + CP 'A'-1 + JR C,LGDU9 ; Satisfied with current drive + SUB 'A' + LD (DUD),A + + LD A,(PUPFLG) ; Privileged user upload request? + OR A + LD A,(DUD) + JR NZ,LGDU8 ; Yes + + CALL WHLCHK + LD A,(DUD) + JR NZ,LGDU8 + + LD A,(USEMAX) ; Using ZCPR low memory bytes? + OR A + JR NZ,LGDU7 ; Yes + LD A,(MAXDRV) + LD C,A + LD A,(DUD) + CP C + JP NC,ILLDU ; Drive selection not available + JR LGDU8 + +LGDU7: LD A,(DUD) ; Get the drive back + LD IY,(DRIVMAX) ; Point to max drive byte + INC (IY) + CP (IY) ; And check it + PUSH AF ; Save flags from the CP + DEC (IY) ; Restore max drive to normal + POP AF ; Restore flags from the CP + JP NC,ILLDU + +LGDU8: INC HL ; Get 2nd character + +LGDU9: LD A,(HL) + CP ':' + JP Z,LGDU17 ; Colon for drive only, no user number + CALL CKNUM ; Check if numeric + +LGDU10: SUB '0' ; Convert ASCII to binary + LD (DUU),A ; Save it + INC HL ; Get 3rd character if any + LD A,(HL) + CP ':' + JR Z,LGDU11 + LD A,(DUU) + CP 1 ; Is first number a '1'? + JP NZ,ILLDU + LD A,(HL) + CALL CKNUM + SUB 38 + LD (DUU),A + INC HL ; Get 4th (and last character) if any + LD A,(HL) + CP ':' + JP NZ,ILLDU + +LGDU11: LD A,(MODE) + CP 'R' ; Receiving a file? + LD A,(DUU) + JR Z,LGDU12 + LD A,(SPLDRV) + SUB 'A' + LD C,A + LD A,(DUD) + CP C + JR NZ,LGDU12 + LD A,(SPLUSR) + LD C,A + LD A,(DUU) + CP C + JR Z,LGDU15 + +LGDU12: CALL WHLCHK ; SYSOP using the system? + JR Z,LGDU13 + LD A,(DUU) ; Restore desired user area + LD (RCVUSR),A ; Allows SYSOP to upload anywhere + JR NZ,LGDU15 ; If yes, let him have all user areas + +LGDU13: LD A,(USEMAX) ; Using ZCPR low memory bytes? + OR A + JR NZ,LGDU14 ; Yes + LD A,(MAXUSR) ; Check for maximum user download area + ADD A,1 + LD C,A + LD A,(DUU) + CP C + JP NC,ILLDU ; Error if more (and not special area) + JR LGDU15 + +LGDU14: LD A,(DUU) + LD IY,(USRMAX) ; Point at maximum user byte + CP (IY) ; And check it + JP NC,ILLDU + +LGDU15: LD E,A + LD A,(SETAREA) ; Using designated drv/usr for reg. uploads? + OR A + JR NZ,LGDU16 ; Yes + LD A,(ASKAREA) ; Using upload routing? + OR A + JR NZ,LGDU16 ; Yes + LD A,E + LD (CONT3+5),A ; Store requested user area + LD A,6 ; 'LD B,n' instruction + LD (CONT3+4),A + +LGDU16: LD C,SETUSR ; Set to requested user area + CALL BDOS + +LGDU17: LD A,(DUD) ; Get drive + LD E,A + LD A,(SETAREA) ; Using designated drv/usr for reg. uploads? + OR A + JR NZ,LGDU18 ; Yes + LD A,(ASKAREA) ; Using upload routing? + OR A + JR NZ,LGDU18 ; Yes + LD A,E + ADD A,'A' + LD (CONT3+12),A ; Store requested drive + LD A,3EH ; 'LD A,n' instruction + LD (CONT3+11),A + +LGDU18: LD C,SELDSK ; Set to requested drive + CALL BDOS + JR TRAP2 ; Now find file selected + +; +; If we get here, no d/u was specified. Restore original command line pointer +; and character count and move name to FCB. +; +TRAP: POP BC ; Get original character count back + POP HL ; And original command line buffer position + +; +; Check for no file name or ambiguous name +; +TRAP1: LD A,(PRIVATE) ; Get the private transfer flag + OR A ; Is it enabled? + JR Z,TRAP2 ; No, current du stays normal + LD A,(SPLUSR) ; Get the special download user area + CALL RECAR1 ; Set user area to special download user + LD A,(SPLDRV) ; Get the special download drive + CALL RECDR1 ; Set drive to special download drive + +TRAP2: CALL SPCDRV ; Keep DPB info straight + LD HL,FCB + CALL INITFCB ; Make sure FCB initialized + CALL MOVFCB ; Move the filename into the file block + LD HL,FCB+1 ; Point to file name + LD A,(HL) ; Get first character + CP ' ' ; Any there? + JR NZ,TRAP3 ; Yes, check wildcards + LD HL,FCB+9 ; Else point to file extent + LD A,(HL) ; Get character + CP ' ' ; Space also? + JP Z,NFN ; Yes, we have no filename, exit with error + LD HL,FCB+1 ; Else point to start again + +TRAP3: LD A,(PRIVATE) ; Get the private transfer flag + OR A ; Is it enabled? + RET Z ; No, then don't trap wildcards + LD B,11 ; Else check all 11 characters of filename + +TRAP4: LD A,(HL) ; Get char from FCB + CP '?' ; Ambiguous? + JR Z,NOWILD ; Yes, exit with error message + CP '*' ; Even more ambiguous? + JR Z,NOWILD ; Yes, exit with error message + INC HL ; Point to next character + DJNZ TRAP4 ; Not done, check some more + RET + +CKNUM: CP '0' + JR C,ILLDU ; Error if less than ascii '0' + CP '9'+1 + RET C ; Error if more than ascii '9' + +ILLDU: CALL ERXIT + DB CR,LF + DB '-- Unauthorized drive/user','$' + +NFN: CALL ILPRT + DB CR,LF,0 + +NFN1: CALL ERXIT ; Print message, exit + DB '-- No filename(s) requested','$' + +NOWILD: CALL ERXIT ; Print message, exit + DB CR,LF + DB '-- Wildcards not valid for PRIVATE downloads','$' + +; +; Previous record repeated, due to the last ACK being garbaged. ACK it so the +; sender will catch up +; +RCVACK: CALL SNDACK ; Send the ACK + XOR A + LD (ERRCNT),A ; Reset the error count + +; +; Receive a record - returns with carry bit set if EOT received +; +RCVRECD:CALL FUNCHK ; Check function keys + CALL SNDABT ; See if wanting to abort + LD A,(FRSTIM) ; Have we started, yet? + OR A + LD B,10 ; Check every ten seconds if already started + JR Z,$+4 ; If yes, skip next line + LD B,5 ; Check every 5 seconds until started + CALL RECV ; Get character + JP C,RCVSTOT ; Timeout error if no character received + CP SOH ; SOH? + JP Z,RCVSOH ; Yes, get record + CP STX ; STX for 1k blocks? + JR NZ,$+11 ; No + LD (KFLG),A ; Set the 1k flag + LD (CRCFLG),A ; Insure in CRC mode for 1k blocks + JP RCVS1 + + CP CANCEL ; Was it a CTL-X to abort? + CALL Z,CKCAN ; If yes, check for aborting + OR A ; Get another character, if a null + JR Z,RCVRECD + CP 7BH ; V.22 synch character, ignore + JR Z,RCVRECD + CP 0FBH ; V.22 synch character with high bit set + JR Z,RCVRECD + CP EOT ; See if end of transmission + SCF ; Set carry + RET Z ; Return with carry set + CP CRC ; Ignore our own character coming back + JR Z,RCVRECD + CP KSND ; Ignore our own character coming back + JR Z,RCVRECD + CP NAK ; Ignore our own character coming back + JR Z,RCVRECD + CALL ILPRTL ; Show locally only + DB CR,'-- ',0 + LD A,B + CALL HEXO + CALL ILPRTL + DB 'H received not SOH',CR,LF,0 + JR RCVSR + +; +; Checksum error +; +CKSMERR:CALL ILPRTL + DB ' - Checksum error',CR,LF,0 + JR RCVSR ; Go check the error limit and send NAK + +; +; Bad record number in header error +; +HDRERR: CALL ILPRTL + DB ' - Error in header',CR,LF,0 + JR RCVSR ; Go check error limit and send NAK + +; +; Timed out on receive error +; +RCVSTOT:LD A,(FRSTIM) ; First time flag set yet? + OR A + JR Z,RCVSR ; If not, don't show an error + CALL TOTMSG + +; +; Didn't get SOH or EOT or did not get valid header so purge the line, then +; send NAK. +; +RCVSR: CALL WAIT1 ; Get anything coming in and discard + CALL SNDABT ; See if wanting to abort + LD A,(FRSTIM) ; Get first time switch + OR A ; Has first 'SOH' been received? + LD A,NAK + JR NZ,RCVSR1 ; Yes, then send 'NAK' + LD A,(CRCFLG) ; Get the 'CRC' flag + OR A ; 'CRC' in effect? + LD A,NAK ; Put 'NAK' in 'A' register + JR Z,RCVSR1 ; No, send the 'NAK' for checksum + LD A,CRC ; Tell sender we have 'CRC' + CALL SEND + LD A,(KFLG) ; Requesting 1k transmissions? + OR A + JR Z,RCVSR1 ; If not, exit + LD A,KSND ; Tell sender we also have 1k capability + +RCVSR1: CALL SEND ; The 'NAK' or 'CRC' request + LD A,(ERRCNT) ; Get the error count + INC A ; Increment error count + LD (ERRCNT),A ; Store new value + LD B,A ; Keep the error count for now + LD A,(FRSTIM) ; Have we gotten under way yet? + OR A + LD A,B ; get the value back + JR Z,RCVSR2 ; If not, exit + CP 10 ; 10 errors the limit, once under way + JP NC,ABORT ; Abort if over the limit + CALL RDCOUNT ; Display record count before repeating + JP RCVRECD ; Less than 10, keep going + +RCVSR2: CP 7 ; 7 times for 1k/CRC yet? (40 seconds) + JP C,RCVRECD ; Keep trying if less + XOR A ; Else flip to checksum mode + LD (CRCFLG),A + LD A,B ; Get the count back + CP 3 ; Another 3 times for checksum? + JP C,RCVRECD ; If less, try again, quit at 60 seconds + JP ABORT + +; +; Aborts with 1 CTL-X if first time flag is not set, two otherwise +; +CKCAN: LD A,(FRSTIM) ; First time flag set yet? + OR A + JR Z,CKCAN1 ; If not, abort + LD B,2 + CALL RECV ; Maximum of 2 seconds for extra ^X + RET C ; No additional character, ignore single ^X + CP CANCEL ; Got a character, is it a ^X? + RET NZ ; No, ignore 1st ^X and return + +CKCAN1: POP HL ; Reset stack for CALL CKCAN + JP ABORT ; Got 2nd ^X, abort and close file + +; +; Got SOH - get block number (complemented) +; +RCVSOH: XOR A + LD (KFLG),A ; If SOH, clear the 1k flag + +RCVS1: LD A,1 ; Get something to store + LD (FRSTIM),A ; Indicate first 'SOH' or 'STX' recvd. + LD B,5 + CALL RECV ; Wait up to 5 seconds for block number + JP C,RCVSTOT ; Got timeout + LD D,A ; Save block number + LD B,5 + CALL RECV ; 5 seconds for complimented record number + JP C,RCVSTOT ; Timeout + CPL ; Get the complement + CP D ; Same as original block number? + JP NZ,HDRERR ; No, go report bad record number in header + LD A,D ; Get record number + LD (RCVCNT),A ; Save it + LD C,0 ; Initialize checksum + LD HL,0 ; Initialize CRC + LD (CRCVAL),HL ; Clear CRC counter + LD DE,128 ; For 128 character blocks + LD A,(KFLG) ; Using 1k blocks? + OR A + JR Z,$+5 ; If not, skip next line + LD DE,1024 ; If using 1k blocks + LD HL,(RECPTR) ; Get buffer address + +RCVCHR: LD B,5 + CALL RECV ; 5 seconds for character + JP C,RCVSTOT ; Timeout + LD (HL),A ; Store the character + INC HL ; Point to next character + DEC DE ; One less to go + LD A,E ; See if 'D' and 'E' are both empty + OR D + JR NZ,RCVCHR ; No, get next character + LD A,(CRCFLG) ; Using 'CRC'? + OR A + JP NZ,RCVCRC ; If yes go get 'CRC' + +; +; Verify checksum +; + LD D,C ; Save checksum + LD B,5 + CALL RECV ; Up to 5 seconds for checksum + JP C,RCVSTOT ; Timeout + CP D ; Checksum ok? + JP NZ,CKSMERR ; No, report error + +; +; Got a record, it's a duplicate if equal to the previous number, it's OK if +; previous + 1 record +; +CHKSNUM:LD A,(RCVCNT) ; Get received record number + LD B,A ; Save it + LD A,(RCDCNT) ; Get previous record number + CP B ; Previous record repeated? + JP Z,RCVACK ; If yes 'ACK' to catch up + INC A ; Increment by 1 for 120 character block + CP B ; Match this one we just got? + JP NZ,ABORT ; No match, stop the sender, exit + RET ; Else return with carry not set, was ok + +; +; Receive the Cyclic Redundancy Check characters (2 bytes) and see if the CRC +; received matches the one calculated. If they match, get next record, else +; send a NAK requesting the record be sent again. +; +RCVCRC: LD E,2 ; Number of bytes to receive + +RCVCRC2:LD B,5 + CALL RECV ; Up to 5 seconds for CRC byte + JP C,RCVSTOT ; Timeout + DEC E ; Decrement the number of bytes + JR NZ,RCVCRC2 ; Get both bytes + CALL CRCCHK ; Check received CRC against calc'd CRC + OR A ; Is CRC okay? + JR Z,CHKSNUM ; Yes, go check record numbers + CALL ILPRTL ; Show locally only + DB ' - CRC error',CR,LF,0 + JP RCVSR ; Go check error limit and send NAK + +; +;------------------ +; Send subroutines +;------------------ +; +; Send an ACK for the record +; +SNDACK: LD A,ACK ; Get 'ACK' + JP SEND ; And send it + +; +; Send SOH, block number and complemented block number (3 bytes total) +; +SNDHDR: LD A,(KFLG) ; Sending 1k blocks? + OR A + LD A,STX ; If yes, send a STX rather than SOH + JR NZ,$+4 + LD A,SOH ; Send start of header + CALL SEND + +SNDHNM: LD A,(RCDCNT) ; Send the current record number + CALL SEND + LD A,(RCDCNT) ; Get the record number again + CPL ; Complemented + JP SEND ; From SENDHDR + +; +; Send data record +; +SNDREC: LD C,0 ; Initialize checksum + LD HL,0 ; Initialize CRC + LD (CRCVAL),HL + LD A,(KFLG) ; Sending 1k blocks? + OR A + LD DE,1024 + JR NZ,$+5 ; If yes, skip the next line + LD DE,128 + LD HL,(RECPTR) ; Get buffer address + +SENDC: LD A,(HL) ; Get a character + CALL SEND ; Send it + INC HL ; Point to next character + DEC DE + LD A,E + OR D + JR NZ,SENDC ; If DE not zero, keep going + RET ; From SENDREC + +; +; Send the CRC or checksum value +; +SNDCHK: LD A,(CRCFLG) ; See if sending 'CRC' or 'checksum' + OR A + JR NZ,SNDCRC ; If not zero, send the 'CRC' value + +; +; Send Checksum +; +SNDCKS: LD A,C ; Send the checksum + JP SEND ; From SNDCKS + +; +; Send CRC (2 characters). Call FINCRC to calculate the CRC which will be +; in 'DE' upon return. +; +SNDCRC: CALL FINCRC ; Calculate the 'CRC' for this record + LD A,D ; Put first 'CRC' byte in accumulator + CALL SEND ; Send it + LD A,E ; Put second 'CRC' byte in accumulator + CALL SEND ; Send it + XOR A ; Set zero return code + RET + +; +; Get acknowlegement +; +; After a record is sent, a character is returned telling if it was received +; properly or not. An ACK allows the next record to be sent. A NAK causes +; the current record to be resent. If no character (or any character other +; than ACK or NAK) is received after a short wait (10-12 seconds), a timeout +; error message is shown and the record will be resent. +; +GTACK: LD B,12 + CALL RECV ; Wait up to 12 seconds for ACK or NAK + JR NC,GTACK1 ; Got one + CALL TOTMSG + JP ACKERR ; Set the carry bit and return + +GTACK1: CP ACK ; See if an ACK already + RET Z ; If yes, return + CP NAK ; See if a NAK + JR Z,GTACK2 ; If yes, print error, then resend + CP 07BH ; V.22 synch character? + JR Z,GTACK ; If yes, ignore it + CP 0FBH ; V.22 synch character? + JR Z,GTACK ; If yes, ignore it + CP CANCEL ; CTL-X to cancel attempt? + CALL Z,CKCAN + +GTACK2: LD B,A ; Save the character + LD A,(CHKEOT) ; Sending EOT? + OR A + JP NZ,ACKERR ; If yes, don't show error (for ZMD) + CALL ILPRTL + DB ' - ',0 + LD A,B + CP NAK + JR Z,GTACK3 + CALL HEXO + CALL ILPRTL + DB 'H',0 + JR GTACK4 + +GTACK3: CALL ILPRTL + DB 'NAK',0 + +GTACK4: CALL ILPRTL + DB ' received not ACK',CR,LF,0 + CALL CATCH ; None of them, establish clear line again + +; +; Timeout or error on ACK - bump error count then resend the record if +; error limit is not exceeded +; +ACKERR: LD A,(ACCERR) ; Count accumulated errors on ACK + INC A ; Add in this error + LD (ACCERR),A + LD A,(ERRCNT) ; Get count + INC A ; Bump it + LD (ERRCNT),A ; Save back + CP 10 ; At limit? + JR NC,ACKMSG ; If yes, send error message and abort + LD A,(ACKCHK) ; Checking after a batch header? + OR A + CALL Z,RDCOUNT ; Yes, show the record count for repeat + + LD A,B ; Get character back + CP NAK ; NAK? + JP NZ,GTACK ; No, ignore and wait for ACK or NAK + RET ; And go back + +; +; Reached error limit +; +ACKMSG: CALL WAIT1 ; Wait for any input to stop + LD A,CANCEL ; Tell remote we are quitting + CALL SEND + CALL SEND + CALL SEND + LD B,2 + CALL RECV ; Up to 2 seconds for remote to quit too + LD A,BS + CALL SEND ; Clear any CTL-X from buffer + CALL SEND + CALL SEND + CALL ERXIT + DB CR + DB '-- File transfer aborted','$' + +; +; Routines to trap abort conditions +; +; Check to see if a cancel requested. Fall through to ABORT if so. +; +CKABORT:CALL CONSTAT + OR A + RET Z + CALL CONIN + CP CANCEL + RET NZ + +; +; Aborts send or receive routines and returns to command line +; +ABORT: CALL WAIT1 ; 1- second delay to clear input + CALL CATCH + LD A,(EOTFLG) ; Timed out after only 1 EOT? + OR A + JP NZ,RCVEOT+3 ; Accept as valid EOT then + LD A,CANCEL ; Show you are cancelling + CALL SEND ; They may quit also with enough CTL-X + CALL SEND + CALL SEND + CALL WAIT1 ; 1-second delay to clear input + CALL CATCH + LD A,BS + CALL SEND + CALL SEND + CALL SEND + +ABORTX: CALL CATCH ; Eat garbage characters + CALL ABRTMSG ; Show we have aborted + LD A,(MODE) ; Get file transfer mode + CP 'R' ; Sending a file? + JP NZ,EXIT ; Yes, quit to CP/M + +; +; Take care of received file (if any). +; +CLOSFIL:LD C,CLOSE ; Get function + LD DE,FCB ; Point to file + CALL BDOS ; Close it + INC A ; Close ok? + JR NZ,CLOSFL1 ; Yes + CALL ILPRT ; No, abort + DB CR,LF + DB '-- Received file not closed',0 + JP NTDEL1 + +CLOSFL1:LD A,(EOTFLG) ; Get end of transmission flag + OR A ; Received entire file? + RET NZ ; Yes, return to RCVEOT routines + CALL ILPRTB + DB CR,LF + DB '-- Upload has been cancelled',0 + +; +; Delete the received file +; + LD C,DELETE ; Get function + LD DE,FCB ; Point to file + CALL BDOS ; Delete it + INC A ; Delete ok? + JR Z,NOTDEL ; No + CALL ERXIT ; Print second half of message + DB CR,LF + DB '-- Partial file is deleted','$' + +; +; Unsuccessful delete +; +NOTDEL: CALL ILPRT + DB CR,LF + DB '-- Received file not deleted' + +NTDEL1: CALL ERXIT + DB ' or no file received','$' + +; +; See if a file exists. If it exists, ask for a different name. +; +CHEKFIL:LD A,(SETAREA) ; Uploading to designated drive/user? + OR A + JR NZ,CHEKF1 ; Yes + LD A,(ASKAREA) ; Upload routing enabled? + OR A + JR NZ,CHEKF1 ; Yes + LD A,(PRIVATE) ; Receiving in private area? + OR A + JR Z,$+5 ; No + +CHEKF1: CALL RECARE ; Set the designated area up + LD C,SRCHF ; See if it exists + LD DE,FCB ; Point to control block + CALL BDOS + INC A ; Found? + RET Z ; No, return + LD A,CANCEL ; Tell the remote we are aborting + CALL SEND ; Send several cancel requests + CALL SEND + CALL SEND + +CHEKF2: LD B,1 + CALL RECV ; Up to 1 seconds for character + JR NC,CHEKF2 ; Wait until no more characters + LD A,(BATCH) ; Using batch mode now? + LD (CONONL),A ; If not, send message to modem also + OR A + JR Z,CHEKF3 ; If not, exit + LD A,CANCEL + CALL SEND + CALL SEND + CALL SEND + LD A,BS + CALL SEND + +CHEKF3: CALL ERXIT ; Exit, print error message + DB CR,LF + DB '-- File already exists','$' + +; +; Make the file to be received +; +MAKEFIL:XOR A ; Set extent and record number to 0 + LD (FCBEXT),A + LD (FCBRNO),A + LD A,(HIDEIT) + OR A + JR Z,MAKEF1 ; HIDEIT not enabled, skip all this + CALL WHLCHK + JR NZ,MAKEF1 ; Don't make it $SYS if SYSOP online + LD A,(PRIVATE) + OR A + JR NZ,MAKEF1 ; Don't make it $SYS if private upload + + LD DE,FCB+10 ; Point at second char of file extent + LD A,(DE) + OR 80H ; And turn on the high bit (Make file $SYS) + LD (DE),A ; Put it back + +MAKEF1: LD C,MAKE ; Get BDOS FNC + LD DE,FCB ; Point to FCB + CALL BDOS ; To the make + PUSH AF ; Save MAKE error code + + LD C,SETFILE ; Set up for BDOS FUNCTION 30 + LD DE,FCB + CALL BDOS ; Set file attributes + POP AF ; Error code from BDOS make function + INC A ; 0FFH=bad? + RET NZ ; Open ok + + LD HL,FCB+1 + JP NOROOM ; Tell them directory might be full + +; +; Open file to be sent +; +OPNFIL: XOR A ; Zero accumulator + LD (FCBEXT),A ; Set extent to 0 + LD (FCBRNO),A ; Set record number to 0 + LD DE,FCB ; Point to file + LD C,OPEN ; Open it + CALL BDOS + INC A ; Open ok? + JR NZ,OPNOK ; Yes, check restrictions + + LD A,(LBRARC) ; Get extraction flag + OR A ; Enabled? + JP Z,NOFILE ; No, abort + LD HL,ARCNAM ; Force .ARC filetype + CALL CHNGEXT ; Try to open it + JR NZ,OPNOK ; File found + LD HL,ARKNAM ; Force .ARK filetype + CALL CHNGEXT ; Try to open it + JR NZ,OPNOK ; File found + LD HL,LBRNAM ; Force .LBR filetype + CALL CHNGEXT ; Try to open it + JR NZ,OPNOK ; File found + JP NOARK ; Not found and no more filetypes to try + +CHNGEXT:LD DE,FCB+9 + LD BC,3 + LDIR + LD C,OPEN + LD DE,FCB + CALL BDOS + INC A + RET ; Z flag set=file not found + +; +; Requested file was found, now check some restrictions +; +OPNOK: LD IX,FCB ; Point to filename + CALL RESTRCT ; Check it for restrictions + LD A,(LBRARC) ; Get the member extraction flag + OR A ; Enabled? + JR Z,OPNOK1 ; No, skip this + CALL RSDMA ; Reset to default DMA address + LD C,READ ; Read first file record + LD DE,FCB + CALL BDOS + OR A ; Read ok? + JP NZ,READERR ; If not, error + CALL CKDIR ; Take care of LBR stuff + +OPNOK1: LD HL,(RCNT) ; Get record count + LD A,H + OR L + JP Z,ZEROLN ; Can't send 0-length files + LD A,(BATCH) + OR A + JR Z,OPNOK1A ; Don't clear screen unless in BATCH mode + LD A,(FSTFLG) ; Get first file sent flag + OR A ; Sent it already? + LD A,1 ; Show we have for next time + LD (FSTFLG),A + CALL Z,CLEARIT ; No, need to clear screen here first time + +OPNOK1A:CALL SHONM ; Show the name of this file + CALL LOW41K ; Less than MINKSPD? + JR C,OPNOK3 ; Yes, don't show 1k packets + +OPNOK2: CALL ILPRT + DB CR,LF + DB 'Ymodem packets total > ',0 + LD HL,(RCNT) ; Get record count + CALL DIVREC ; Divide number of records by 8 + CALL DECOUT ; Show # of 1k packets + +OPNOK3: CALL ILPRT + DB CR,LF + DB 'Xmodem packets total > ',0 + LD HL,(RCNT) ; Get original count + CALL DECOUT ; Show # of 128 byte packets + LD A,(MODE) ; Get transfer mode + CP 'R' ; Receiving? + RET Z ; Yes, all done + + CALL ILPRT + DB CR,LF + DB 'Disk space you need > ',0 + + LD A,(SBSHOW) ; Displaying intial BATCH screen to remote? + OR A + PUSH AF ; Save answer + LD HL,(FILEK) ; Get precalculated total 'k' for all files + JR NZ,OPNOK4 ; Go show it + LD BC,(RCNT) ; Else get single file record count back + CALL ROUNDK ; Round disk space needed + EX DE,HL +; +OPNOK4: CALL DECOUT ; Decimal output + CALL ILPRT + DB 'k (',0 + LD HL,(BLKSIZ) ; Get host disk block size + CALL DECOUT ; Decimal output + CALL ILPRT + DB 'k blocks)',0 + POP AF ; Displaying initial BATCH screen to remote? + RET NZ ; Yes, then we're done in here + +; +; Show transfer time, first for 1k blocks, then for 128-byte blocks. If we are +; at 300 bps, report both transfer times the same. (skip the 1k times for +; speeds slower than MINKSPD bps.) +; +KSPD: CALL LOW41K ; Less than MINKSPD? + JR C,XSPD ; Yes, skip 1k display + CALL ILPRT + DB CR,LF + DB 'Ymodem time / 1k > ',0 + CALL GETSPD ; Get current modem speed + CP 1 ; At 300 bps? + JR Z,KSPD1 ; 1k transfer time in BC (minutes) if >300 + CALL KTIM + JR KSPD2 + +KSPD1: LD HL,XECTBL + LD (RECTBL+1),HL + CALL XTIM + +KSPD2: CALL STORTM ; Store it + CALL XFRTIM ; Display it + +XSPD: CALL ILPRT + DB CR,LF + DB 'Xmodem time / 128 byte > ',0 + LD HL,XECTBL ; 128 size values (300 bps) + LD (RECTBL+1),HL + CALL XTIM ; Xmodem transfer time + LD A,(KFLG) ; If 'SK' set, 1k time already stored + OR A + CALL Z,STORTM + CALL XFRTIM + LD HL,KECTBL ; Restore to original 1k values + LD (RECTBL+1),HL + CALL ILPRT + DB CR,LF,0 + + LD A,(BATCH) ; In batch mode? + OR A + JP Z,OPNOK5 ; No, couldn't have been here before + LD A,(FSTFLG) ; Yes, been here before? + OR A + JP Z,OPNOK5 ; No, following gets shown next time + +; +; In batch, show files remaining after this one is sent +; + CALL ILPRTL + DB CR,LF + DB 'Files remaining > ',0 + LD A,(SHOCNT) ; Get cumulative files + DEC A + LD (SHOCNT),A ; Less one + LD L,A + LD H,0 + CALL DECOUT + + CALL ILPRTL + DB CR,LF + DB 'Ymodem packets remaining > ',0 + LD HL,(RCNT) ; Get this file's record count again + EX DE,HL ; Put in DE + LD HL,(TOTREC) ; Total records remaining + LD A,L + SUB E + LD L,A + LD A,H + SBC A,D + LD H,A + JR NC,$+5 + LD HL,0 ; In case of a slightly negative number + PUSH HL ; Save it for Xmodem packets show + CALL DIVREC ; Divide number of records by 8 + CALL DECOUT + + CALL ILPRTL + DB CR,LF + DB 'Xmodem packets remaining > ',0 + POP HL ; Get total records remaining after this file + LD (TOTREC),HL + CALL DECOUT ; Show remote remaining records + CALL ILPRTL + DB CR,LF,LF,0 + CALL WAITMSG ; Display '[ waiting ]' message locally + RET + +; +; If sending an ARC or ARK file, tell user to rename to .ARK or .ARC file type. +; +OPNOK5: LD A,(LBRARC) ; Get extraction flag + OR A ; Enabled? + JP Z,DLRDY ; No, skip this + LD A,(FCB+9) ; Point to member filetype + AND 7FH ; Strip parity + CP 'L' ; LBR member extraction? + JP Z,DLRDY ; Yes, skip this + CALL ILPRTB + DB CR,LF + DB 'You MUST name file > ',0 + LD D,8 ; Filename count - ignore filetype + LD HL,MEMFCB ; Get requested member name + +OPNOK6: LD A,(HL) + CP ' ' ; Short filename? + JR Z,OPNOK7 ; If so, fill in type + CALL TYPE + + DEC D ; One less... + INC HL ; Next character + JR NZ,OPNOK6 ; Loop until done + +OPNOK7: LD A,(FCB+11) ; Get last character of parent filetype + LD ($+9),A ; Stuff it below to display + CALL ILPRTB + DB '.AR?' ; Either a 'C' or a 'K' gets poked at '?' + DB CR,LF,0 + CALL DLRDY ; Tell them their download(s) are ready + RET + +; +; These routines display the transfer time in minutes & seconds and check for +; time restrictions, if a clock is enabled. +; +XFRTIM: PUSH HL ; Save seconds in 'L' + CALL WHLCHK ; Sysop online? + JR NZ,SKPTIM ; Yes, then skip the limit + + LD A,(MAXTOS) + OR A + JR Z,SKPTIM + LD D,C ; Save minutes for now + INC D ; Increment to next full minute + LD A,(TIMEON) ; Using TIMEON? + OR A + LD A,D ; Get length of this program + JR Z,XFRTM1 ; No, don't increment time + LD HL,TON ; Point to time on system + ADD A,(HL) ; Else add time on system to transfer time + +XFRTM1: LD (XFRMIN),A ; Store it + OR A + LD A,B ; Get hours in A + JR NZ,$+3 ; Don't increment if not zero + INC A ; Increment to next full minute + LD (XFRMIN+1),A + +SKPTIM: LD H,B ; Get most significant in H (hours) + LD L,C ; Get least significant byte of minutes in L + CALL DECOUT ; Print decimal number of minutes + CALL ILPRT + DB ':',0 + POP HL ; Get seconds back + LD A,L ; Get the number of seconds + CP 10 ; 10 seconds or more? + JR NC,$+7 ; If yes, disregard next two lines + CALL ILPRT + DB '0',0 + CALL DECOUT ; Print decimal number of seconds + CALL ILPRT + DB ' at ',0 + CALL GETSPD ; Get modem speed value in A + CALL SHOSPD ; Display in BPS + +; +; Determine if the caller has enough time left online to make the +; requested download(s). +; +XFRTM3: LD A,(MODE) ; Get transfer mode + CP 'R' ; Receiving? + RET Z ; Yes, all done + + LD A,(MAXTOS) ; Get maximum time allowed + OR A ; Unlimited? + RET Z ; Yes, skip time restriction + + LD A,(XFRMIN+1) ; Get most significant byte of minutes + OR A ; 0? + JR NZ,OVERTM ; If not, over 255 minutes + LD A,(XFRMIN) ; Get least significant byte of minute count + LD B,A ; Put in B + LD A,(MAXTOS) ; Get maximum time allowed + INC A + SBC A,B + RET NC + +; +; There is not enough time to download the requested file(s). Inform user and +; abort to CP/M. +; +OVERTM: CALL ILPRTB + DB CR,LF,LF,0 + CALL ABRTMSG ; Display both local and remote we aborted + CALL ILPRTB + DB CR,LF,LF + DB 'Required send time exceeds the ',0 + LD A,(TLOS) ; Get time left on system + LD H,0 ; Zero H + LD L,A ; Time left on system in L + CALL DECOUT ; Decimal output routine + CALL ERXIT ; Display following message and abort to CP/M + DB ' minutes allowed','$' + +; +;-------------------------------------------------------------------------; +; L o g F i l e T r a n s f e r | +;-------------------------------------------------------------------------; +; +; Main log file routine, adds record to log file +; +LOGCALL:LD A,(LOGCAL) ; Logging file transfers? + OR A + RET Z ; No + CALL GTCURDU ; Get current drive/user in USRSAV and DSKSAV + + LD HL,FCBCLR ; FCB to initialize + LD DE,LSTCLR ; Filename to insert + CALL RENFCB ; Initialize FCB + + LD A,(LASTDRV) + SUB 'A' + LD (DEFDSK),A + LD A,(LASTUSR) + LD (DEFUSR),A + LD DE,FCBCLR + CALL OPENF ; Open LASTCALR file + JR NZ,LGCAL1 + CALL ILPRT + DB CR,LF + DB '-- File not Found: LASTCALR.???' + DB CR,LF,0 + RET ; Now go send EOT + +LGCAL1: LD C,SETRRD ; Get random record # + LD DE,FCBCLR ; (for first record in file) + CALL BDOS + + LD DE,DBUF ; Set DMA to DBUF + CALL STDMA + + LD C,RRDM ; Read first (and only) record + LD DE,FCBCLR + CALL BDOS + + LD HL,DBUF ; Set pointer to beginning of record + LD A,(CLOCK) ; Is there a clock installed? + OR A + JR Z,LGCAL2 ; No, skip this then + LD DE,0 ; Zero DE + LD A,(LCNAME) ; Offset to start of caller's name + LD E,A ; To E + ADD HL,DE ; HL now points to start of name + +LGCAL2: LD (CLRPTR),HL + LD DE,LOGBUF ; Set DMA address to LOGBUF + CALL STDMA + + LD HL,FCBLOG ; FCB to initialize + LD DE,LOGNAM ; Filename to insert + CALL RENFCB ; Initialize FCB + + LD A,(LOGDRV) + SUB 'A' + LD (DEFDSK),A + LD A,(LOGUSR) + LD (DEFUSR),A + LD DE,FCBLOG + CALL OPENF ; Open log file + JR NZ,LGCAL5 ; If file exists, skip create + LD DE,FCBLOG + LD C,MAKE ; Create a new file if needed + CALL BDOS + INC A + JR NZ,LGCAL3 ; No error, continue + CALL ILPRT ; File create error + DB CR,LF + DB '-- Directory Full: ',0 + LD HL,LOGNAM + CALL SHONM4 + RET ; Go back and send EOT + +LGCAL3: LD DE,LOGBUF ; Set DMA back to LOGBUF + CALL STDMA + + LD C,SETRRD ; Set random record # + LD DE,FCBLOG ; (for first record in file) + CALL BDOS + +LGCAL4: LD A,EOF + LD (LOGBUF),A + JR LGCAL6 + +LGCAL5: LD DE,LOGBUF ; Set DMA to LOGBUF + CALL STDMA + + LD C,FILSIZ ; Get file length + LD DE,FCBLOG + CALL BDOS + LD HL,(FCBLOG+33) ; Back up to last record + LD A,L + OR H + JR Z,LGCAL4 ; Unless zero length file + DEC HL + LD (FCBLOG+33),HL + LD DE,FCBLOG + LD C,RRDM ; And read it + CALL BDOS + +LGCAL6: CALL RSTLP ; Initialize LOGPTR and LOGCNT + +LGCAL7: LD A,(LOGCNT) + INC A + LD (LOGCNT),A + CP 129 + JR NZ,LGCAL8 + LD HL,(FCBLOG+33) + INC HL + LD (FCBLOG+33),HL + LD HL,LOGBUF+1 + LD (LOGPTR),HL + LD A,1 + LD (LOGCNT),A + LD A,EOF + JR LGCAL8A + +LGCAL8: LD HL,(LOGPTR) + LD A,(HL) + INC HL + LD (LOGPTR),HL + +LGCAL8A:CP EOF + JR NZ,LGCAL7 ; Until EOF + LD A,(LOGCNT) ; Then backup one character + DEC A + LD (LOGCNT),A + LD HL,(LOGPTR) + DEC HL + LD (LOGPTR),HL + +; +; Print file transfer mode to LOG file (R, S, P, A, L) +; + LD A,(PUPFLG) + OR A ; Privileged upload option request? + JR Z,LGCAL8B ; No, skip next 2 lines + LD A,'P' ; Else, + JR LGCAL9 ; Show as private upload for log file + +LGCAL8B:LD A,(PRIVATE) + OR A + JR NZ,LGCAL9 + LD A,(MODE) ; Get transfer mode back and put in file + +LGCAL9: CALL PUTLOG + +; +; Print baud rate to LOG file +; + CALL GETSPD ; Get speed factor + ADD A,30H + CALL PUTLOG + CALL PUTSP ; Blank + +; +; Print program size (in minutes and seconds) to LOG file +; + LD A,(PGSIZE) ; Now the program size in minutes.. + CALL PNDEC ; Of transfer time (mins) + LD A,':' + CALL PUTLOG ; ':' + LD A,(PGSIZE+2) + CALL PNDEC ; And seconds + CALL PUTSP ; Blank + +; +; Log the drive and user area as a prompt +; + LD A,(FCB) + OR A + JR NZ,WDRV + LD A,(DSKSAV) + INC A + +WDRV: ADD A,'A'-1 + CALL PUTLOG + LD A,(USRSAV) + CALL PNDEC + LD A,'>' ; Make it look like a prompt + CALL PUTLOG + LD A,(LBRARC) + OR A ; Member extraction? + JR Z,WDRV1 ; No, won't be member name + LD HL,MEMFCB ; Name of file in library + LD B,11 + CALL PUTSTR + CALL PUTSP ; ' ' + +; +; Put filename in LOG file +; +WDRV1: LD HL,FCB+1 ; Now the name of the file + LD B,11 + CALL PUTSTR + LD A,(LBRARC) + OR A ; Member extraction? + JR Z,WDRV2 ; No, won't be member name + LD C,1 + JR SPLOOP + +WDRV2: LD C,13 + +SPLOOP: PUSH BC + CALL PUTSP ; Put ' ' + POP BC + DEC C + JR NZ,SPLOOP + +; +; Print number of 'k' to LOG file +; + LD HL,(RECDNO) ; Get record count + CALL DIVREC ; Divide record count by 8 + +EXKB2: CALL PNDEC3 ; Print to log file (right just xxxk) + LD HL,LOGK ; 'k ' + LD B,2 + CALL PUTSTR + XOR A + LD (COMMA),A ; Reset field counter + +; +; Print date and time of transfer to LOG file +; + LD A,(CLOCK) ; Clock available in BYE? + OR A + JR NZ,EXKB3 ; Yes, continue + LD A,(RTC) ; Else how about an RTC overlay? + OR A + JR Z,CLOOP ; Nope, foget date and time + +EXKB3: CALL GETTIME ; Get CURRENT time for log + + LD A,(EDATE) ; European date format? + OR A + JR Z,EXKB4 ; No + + LD A,(DAY) + CALL PNDEC ; Print DD + LD A,'/' ; '/' + CALL PUTLOG + LD A,(MONTH) + CALL PNDEC ; Print MM + JR EXKB5 + +EXKB4: LD A,(MONTH) + CALL PNDEC ; Print MM + LD A,'/' ; '/' + CALL PUTLOG + LD A,(DAY) + CALL PNDEC ; Print DD + +EXKB5: LD A,'/' ; '/' + CALL PUTLOG + LD A,(YEAR) + CALL PNDEC ; Print YY + CALL PUTSP ; ' ' + LD A,(HOUR) ; Get current hour + CALL PNDEC ; Print hr to file + LD A,':' ; With ':' + CALL PUTLOG ; Between HH:MM + LD A,(MINUTE) ; Get min + CALL PNDEC ; And print min + CALL PUTSP ; Print a space + +; +; Print name of caller to LOG file +; +CLOOP: LD HL,(CLRPTR) + LD A,(HL) + INC HL + LD (CLRPTR),HL + CP EOF ; End of file? + JR Z,QUIT ; Yes + CP CR ; Do not print 2nd line of 'LASTCALR' + JR NZ,CLOP1 + +CEND: CALL PUTLOG + LD A,LF + CALL PUTLOG ; And add a LF + JR QUIT + +CLOP1: CP ' ' ; Space? + JR NZ,CLOP1A ; No, check for comma + LD A,',' ; Convert space to comma for field checking + +CLOP1A: CP ',' ; Comma? + JR NZ,CLOP2 + LD A,(COMMA) + CP 1 ; Is this the second comma or space? + JR NZ,CLOP1B ; No, bump the counter + LD A,CR + JR CEND ; Yes, stop taking data from lastcalr + +CLOP1B: INC A ; Bump it one + LD (COMMA),A + LD A,' ' ; Instead send a ' ' + +CLOP2: CALL PUTLOG + JR CLOOP + +QUIT: LD A,EOF ; Put in EOF + CALL PUTLOG + LD A,(LOGCNT) ; Check count of chars in buffer + CP 1 + JR NZ,QUIT ; Fill last buffer & write it + LD DE,FCBCLR ; Close lastcaller file + LD C,CLOSE + CALL BDOS + INC A + JR Z,QUIT1 + LD HL,(FCBLOG+33) ; Move pointer back to show + DEC HL ; Actual file size + LD (FCBLOG+33),HL + LD DE,FCBLOG ; Close log file + LD C,CLOSE + CALL BDOS + INC A + RET NZ ; If OK, return now... + +QUIT1: CALL ILPRT ; If error, oops + DB CR,LF + DB '-- Close Error: ',0 + LD HL,LOGNAM + CALL SHONM4 + RET ; Go back and send EOT + +; +;------------------------- +; LOGCAL Support Routines +; +; Open file with FCB pointed to by DE (disk/user passed in DEFDSK and DEFUSR) +; +OPENF: PUSH DE ; Save FCB address + LD A,(DEFDSK) ; Get disk for file + CALL RECDRX ; Log into it + LD A,(DEFUSR) ; Get default user + CALL RECAR1 ; Log into it + POP DE ; Get FCB address + LD A,(CPM3) ; Using with CPM3? + OR A + JR Z,OPENF1 ; No + PUSH DE ; Save FCB address + CALL RSDMA ; Set DMA to 80H + POP DE ; Get back pointer to FCB + PUSH DE ; Save FCB pointer again + LD C,SRCHF ; Search for first match + CALL BDOS + INC A ; Did file match? + POP DE + RET Z ; No, return + PUSH DE + DEC A ; A=directory code (0-3) + ADD A,A ; *2 + ADD A,A ; *4 + ADD A,A ; *8 + ADD A,A ; *16 + ADD A,A ; *32 + LD E,A + LD D,0 + LD HL,TBUF ; Add (32*dir code) to default DMA + ADD HL,DE ; to find first match filename + POP DE ; DE=FCB + PUSH DE ; Save DE again + INC HL ; Move HL past user # byte in buffer + INC DE ; Move DE past drive # byte in FCB + LD BC,11 + LDIR ; Move name found to FCB + POP DE ; And continue with open + +OPENF1: LD C,OPEN ; Open file + CALL BDOS + CP 0FFH ; Not present? + RET ; Return to caller + +; +; Write character to log file +; +PUTLOG: LD HL,(LOGPTR) ; Get pointer + AND 7FH ; Strip any attributes + LD (HL),A ; Put data + INC HL ; Increment pointer + LD (LOGPTR),HL ; Update pointer + LD B,A ; Save character in B + LD A,(LOGCNT) ; Get count + INC A ; Increment it + LD (LOGCNT),A ; Update count + CP 129 ; Check it + RET NZ ; If not EOB, return + PUSH BC ; Save character + LD DE,FCBLOG ; Else, write this sector + LD C,WRDM + CALL BDOS + OR A + JR Z,ADVRCP ; If ok, cont. + CALL ILPRT + DB CR,LF + DB '-- Disk Full: ',0 + LD HL,LOGNAM + CALL SHONM4 + RET + +ADVRCP: LD HL,(FCBLOG+33) ; Advance record number + INC HL + LD (FCBLOG+33),HL + CALL RSTLP ; Reset buffer pointers + POP AF ; Get saved character + JP PUTLOG ; Put it in buffer and return + +RSTLP: LD HL,LOGBUF ; Reset pointers + LD (LOGPTR),HL ; And return + LD A,0 + LD (LOGCNT),A + RET + +; +; Print number in decimal format (into log file) IN: HL=binary number +; OUT: nnn=right justified with spaces +; +PNDEC3: LD A,H ; Check high byte + OR A + JR NZ,DECOT ; If on, is at least 3 digits + LD A,L ; Else, check low byte + CP 100 + JR NC,TEN + CALL PUTSP + +TEN: CP 10 + JR NC,DECOT + CALL PUTSP + JR DECOT + +; +; Print number in decimal format (into log file) +; +PNDEC: CP 10 ; Two column decimal format routine + JR C,ONE ; One or two digits to area number? + JR TWO + +ONE: PUSH AF + LD A,'0' + CALL PUTLOG + POP AF + +TWO: LD H,0 + LD L,A + +DECOT: PUSH BC + PUSH DE + PUSH HL + LD BC,-10 + LD DE,-1 + +DECOT2: ADD HL,BC + INC DE + JR C,DECOT2 + LD BC,10 + ADD HL,BC + EX DE,HL + LD A,H + OR L + CALL NZ,DECOT + LD A,E + +DECOT3: ADD A,'0' + CALL PUTLOG + +DECOT4: POP HL + POP DE + POP BC + RET + +; +; Put string to log file +; +PUTSTR: LD A,(HL) + PUSH HL + PUSH BC + CALL PUTLOG + POP BC + POP HL + INC HL + DJNZ PUTSTR + RET + +; +; Puts a single space in log file, saves PSW/HL +; +PUTSP: PUSH AF + PUSH HL + LD A,' ' + CALL PUTLOG + POP HL + POP AF + RET + +; +;-------------------------------------------------------------------------; +; T I M E & D A T E R o u t i n e s | +;-------------------------------------------------------------------------; +; +; Get RTCBUF address if running BYE +; +TIME: LD A,(CLOCK) ; Clock in BYE? + OR A + JR Z,TIME1 ; No + LD DE,25 ; Offset to RTCBUF address + CALL GETOFF ; Point to JP COLDBOOT + offset in DE + LD E,(HL) ; HL points to RTCBUF address + INC HL ; To most significant byte of address + LD D,(HL) + EX DE,HL ; Back to HL + LD (RTCBUF),HL ; Save for later use + CALL GETTIME ; Store RTCBUF contents internally + + LD HL,(RTCBUF) ; Get RTC buffer address + LD DE,7 ; Offset to time on system (TOS) word + ADD HL,DE ; Address in HL + LD A,(HL) ; Get minutes on system + LD (TON),A ; Store time on system for SHOWTOS + +; +; Get MAXTOS if restricting downloads to time left +; + LD A,(TIMEON) ; Policing time on system? + OR A + JP Z,SHOWTOS ; No + LD DE,24 ; Offset to maximum time allowed + CALL GETOFF ; Point to JP COLDBOOT + offset in D + + LD A,(MODE) ; Exiting? (Gets set NZ in exit routine) + OR A + JR Z,TIME0 ; No, skip next + LD A,(MAXTOS) ; Reset maximum time allowed + LD (HL),A + JR TIME0A + +TIME0: LD A,(HL) ; Get maximum time allowed + LD (MAXTOS),A ; Store it + LD (HL),0 ; Disable BYE from checking time for now + +TIME0A: LD A,(TON) + LD B,A ; Save time on system for comparison + LD A,(MAXTOS) ; Get maximum time allowed + SUB B ; Get time left on system + LD (TLOS),A ; Store time left on system + JP SHOWTOS ; Go show TON + +; +; Get TON if RTC +; +TIME1: LD A,(RTC) ; Clock reader code installed in ZMD? + OR A + JP Z,SHOWTOS ; No + CALL GETTIME + + LD HL,(LHOUR) ; Get address to logon hour + LD A,(HOUR) + CP (HL) ; Same as current hour? + INC HL ; Point to logon minute + LD D,(HL) ; Get it in D + JR NZ,TIME2 ; No, not the same + LD A,(MINUTE) ; Else get current minute + SUB D ; Subtract logon minute + LD (TON),A ; Store it as time on system + JR TIME3 ; Get maximum allowed + +TIME2: LD A,60 ; Fake an hour + SUB D ; Subtract logon minute + LD HL,MINUTE ; Point to current minute + ADD A,(HL) ; Add them + LD (TON),A ; Store as current time on system + +; +; Get MAXTOS if TIMEON +; +TIME3: LD A,(TIMEON) ; Restricting downloads to time left? + OR A + JR Z,SHOWTOS ; No + CALL WHLCHK ; WHEEL byte set? + JR NZ,SHOWTOS ; Yes, just display time on system + LD A,(MODE) ; Else been here before? + OR A + JR NZ,TIME4 ; Yes (MODE is 0 first time through) + LD A,(MAXMIN) + LD (MAXTOS),A ; Else set maximum time allowed + LD (TLOS),A ; And current time left on system + +TIME4: LD A,(MAXTOS) ; Get current maximum time allowed + OR A ; Unlimited? + JR Z,SHOWTOS ; Yes, just display time on system + LD A,(MAXMIN) ; Else get original maximum minutes allowed + LD B,A ; Into B + LD A,(TON) ; Get current time on system + SUB B ; Time up? + JR C,SHOWTOS ; No, just display time on system + + CALL ILPRTB + DB CR,LF,LF + DB '-- Your time is up, please share the system with others' + DB CR,LF,0 + POP HL + LD A,0CDH + LD (0),A + JP 0 + +; +; Display the time on system +; +SHOWTOS:LD A,(DSPTOS) ; Display time on system message? + OR A + RET Z ; No, all done + LD A,(MODE) ; Else exiting? + OR A + JR Z,SHOTOS1 ; Yes, no line feed + CALL ILPRTB + DB CR,LF,0 + +SHOTOS1:CALL ILPRTB + DB 'Online ',0 + LD A,(TON) ; Get time on system + LD H,0 ; Zero H + LD L,A ; TON in L + CALL DECOUT ; Decimal output + CALL ILPRTB + DB ' minute',0 + LD A,(TON) ; Get time on system + CP 1 ; 1? + JR Z,SHOTOS2 ; Yes, leave display as 'minute' + CALL ILPRTB + DB 's',0 ; Else make it plural + +SHOTOS2:LD A,(MODE) + OR A + RET NZ + CALL ILPRT + DB CR,LF,0 + RET + +; +; Transfer BYE's RTCBUF contents to internal storage +; +GETTIME:LD A,(RTC) ; User installed clock routines? + OR A + JP NZ,RTCTIM ; Yes, go do it + LD HL,(RTCBUF) + + LD A,(HL) ; 00: + CALL BCDBIN ; Convert to binary + LD (HOUR),A ; Save + + CALL GETTIM3 ; :00 + LD (MINUTE),A ; Save + + INC HL ; Skip seconds + INC HL ; Skip '19'nn + CALL GETTIM3 ; YY + LD (YEAR),A ; Save + + CALL GETTIM3 ; MM + LD (MONTH),A ; Save + + CALL GETTIM3 ; DD + LD (DAY),A ; Save + RET ; And return + +GETTIM3:INC HL ; Increment to next RTC byte value + LD A,(HL) ; Get it + JP BCDBIN ; Return with binary value in A + +; +; Add the time of the last upload/download to BYE's time on system byte +; +ADDTON: LD A,(TIMEON) ; Using TIMEON? + OR A + RET Z + + CALL BYECHK ; If so, see if BYE is running + OR A ; 0 if no clock, or 0 if no BYE. + LD HL,TON ; Prepare for internal RTC + JR Z,ADDTN1 + + LD HL,(RTCBUF) ; Get RTC buffer address + LD DE,7 ; Get offset to TOS word + ADD HL,DE ; Add offset, HL contains TON address + +ADDTN1: PUSH HL ; Save it + LD HL,(RECDNO) + LD (RCNT),HL + CALL XTIM ; Calculate transfer time + POP HL ; Restore TON address + LD A,(HL) ; Get time on in A + LD B,A ; Save it + LD A,(MODE) ; Get current transfer mode + CP 'S' ; Is this a download? + JR Z,ADDTN2 ; Yes, subtract download time + LD A,(CREDIT) ; Else crediting upload time? + OR A + RET Z ; No, skip this + LD A,B ; Else get time on system back + SUB C ; Subtract upload time + LD (HL),A ; Store it + RET + +ADDTN2: LD A,B + INC A ; Bump it one + ADD A,C ; Add transfer time + LD (HL),A ; Put it back for BYE + RET + +; +;-------------------------------------------------------------------------; +; A v a i l a b l e U p l o a d S p a c e | +;-------------------------------------------------------------------------; +; +; This routine is called with the 'F' option from both CP/M (with 'ZMD F') +; or from The HELP Guide routines. First determine where uploads are +; suppose to go. +; +SPACE: CALL RSTLCK ; Go reset WRTLOC if needed + CALL WHLCHK ; WHEEL byte set? + JR NZ,SPACE1 ; Yes, give space for current drive/user + LD A,(ASKAREA) + OR A + JR NZ,SPACE2 + LD A,(SETAREA) + OR A + JR NZ,SPACE2 ; Yes + +SPACE1: LD A,(OLDDRV) ; Get currently logged drive + ADD A,'A' ; Make it ASCII + LD (DRV),A + LD (KDRV),A ; Store it for KSHOW + LD A,(OLDUSR) ; Get currently logged user + LD (USR),A ; Store it for KSHOW + +SPACE2: CALL WHLCHK + CALL Z,GETKIND ; Get upload area if ASKAREA + CALL ILPRTB + DB CR + DB ' Regular ',0 + CALL SPACE8 + CALL ILPRTB + DB CR,LF + DB ' Private ',0 + LD A,1 + LD (PRVSPC),A + CALL SPACE8 + JP EXIT ; Exit to CP/M + +; +; Displays the file descriptor/category when showing available upload space. +; +SPACE8: CALL WHLCHK + CALL Z,SHOCAT ; Show upload area descriptor, if supposed to + CALL ILPRTB + DB 'uploads received on ',0 + LD A,(PRVSPC) ; Want private area space? + OR A + JR NZ,SPACE9 ; Yes, do private stuff + LD A,(DRV) ; Get drive to receive regular upload + LD (KDRV),A ; Store it for KSHOW + CALL TYPE ; Output to modem + LD A,(USR) ; Get user area to receive regular upload + JR SPACE10 ; Go show free space + +SPACE9: LD A,(PRDRV) ; Get drive to receive private upload + LD (KDRV),A ; Store it for KSHOW + CALL TYPE ; Output to modem + LD A,(PRUSR) ; Get user area to receive private upload + +SPACE10:LD H,0 + LD L,A ; User area in L + CALL DECOUT ; Decimal output + CALL ILPRTB + DB ':',0 + LD A,(PRVSPC) ; Getting private info? + OR A + JR Z,SPACE11 ; No + LD A,(DRV) ; Else get regular drive + LD HL,PRDRV ; Point to private drive + CP (HL) ; Private same as regular drive? + RET Z ; Yes, don't report 'k' this time + +SPACE11:CALL ILPRTB + DB ' (',0 + LD A,(KDRV) ; Get upload drive + CALL KSHOW ; Show available space for drive + CALL ILPRTB + DB ')',0 + RET + +; +;-------------------------------------------------------------------------; +; R u n t i m e H e l p G u i d e | +;-------------------------------------------------------------------------; +; +; Either 'ZMD' was entered by itself from CP/M, or an invalid option +; given. +; +HELP: CALL ILPRTB + DB CR,LF,' mode drive/user' + DB CR,LF,' / /' + DB CR,LF,'Usage: ZMD SK {du:} ' + DB CR,LF,' / /' + DB CR,LF,' protocol filename' + DB CR,LF + DB CR,LF,'Mode: Protocol:' + DB CR,LF,' S - Send file from BBS ' + DB 'X - Xmodem 128 byte blocks (CRC)' + DB CR,LF,' SP - Send from private area ' + DB 'C - Xmodem 128 byte blocks (Checksum)' + DB CR,LF,' A - Send ARK/ARC/LBR member ' + DB 'K - Ymodem 1024 byte blocks (CRC only)' + DB CR,LF,' R - Receive file from YOU' + DB CR,LF,' RP - Receive in private area',0 + + + CALL ILPRTB + DB CR,LF,0 + LD A,(MSGFIL) + OR A + JR Z,HELP1 + CALL ILPRTB + DB ' RM - Receive preformatted message base upload',0 + +HELP1: CALL ILPRTB + DB CR,LF,0 + CALL WHLCHK + JR Z,HELP2 + CALL ILPRTB + DB ' RW - Receive without description(s)',0 + +HELP2: CALL ILPRTB + DB CR,LF,' F - Displays available upload space' + DB CR,LF + DB CR,LF + DB CR,LF + DB '--SPACE BAR displays specific examples--',0 + + CALL INPUT + CP ' ' + JP NZ,EXIT + + LD HL,ZMDNAM + CALL PRINTV + CALL ILPRTB + DB 'Usage examples:' + DB CR,LF + DB CR,LF,' ZMD S filename.ext ' + DB 'Send single file (Automatic detect)' + DB CR,LF,' ZMD S B4:filename.ext ' + DB 'Send single file (Automatic detect)' + DB CR,LF,' ZMD SK filename.ext ' + DB 'Send single file (Ymodem 1k)' + DB CR,LF,' ZMD S filename.* ' + DB 'Send from current d/u (Ymodem 1k Batch)' + DB CR,LF,' ZMD S D1:*.* B9:*.doc ' + DB 'Send from multiple d/u (Ymodem 1k Batch)' + DB CR,LF,' ZMD A librnam lbrmber.ext ' + DB 'Send ARK/ARC/LBR member (Automatic detect)' + DB CR,LF,' ZMD AK librnam lbrmber.ext ' + DB 'Send ARK/ARC/LBR member (Ymodem 1k)' + DB CR,LF + DB CR,LF,' ZMD R filename.ext ' + DB 'Receive single file (Automatic detect)' + DB CR,LF,' ZMD R ' + DB 'Receive multiple files (Ymodem 1k Batch)' + DB CR,LF,' ZMD RPC filename.ext ' + DB 'Receive to private area (Checksum)' + DB CR,LF,LF + DB 'Protocol may be omitted for automatic protocol detection.' + DB CR,LF + DB 'Ymodem 1k Batch is enabled upon detection of wildcards or' + DB ' multiple' + DB CR,LF + DB ' filenames on command line (can also be forced with' + DB ' ''SB'' mode).',0 + JP EXIT + + +ABRTMSG:CALL ILPRTB + DB CR + DB '-- ZMD Aborted',0 + RET + +NOACC: CALL SENDBEL ; Send a bell out modem only + CALL ERXIT + DB CR,LF + DB '-- Restricted Function - Access Denied','$' + +ZEROLN: CALL ERXIT + DB CR,LF + DB '-- File empty - ZMD aborted','$' + +NOFILE: CALL ERXIT + DB CR + DB '-- No matching filename(s) found','$' + +NOIO: XOR A + LD (RTC),A + LD (TIMEON),A + LD (DSPTOS),A + LD (CLOCK),A + CALL ERXIT + DB BELL + DB '-- Modem I/O unavailable - Aborting','$' + +TOOSLOW:CALL ERXIT + DB CR,LF,LF + DB '-- YMODEM 1k/BATCH not valid - Modem speed too slow','$' + + +TOTMSG: CALL ILPRTL + DB ' - Timeout, no character received',CR,LF,0 + RET + +DLRDY: CALL ILPRT + DB CR,LF + DB 'Your file(s) now ready to download',0 + CALL CONT6 + RET + +WAITMSG:CALL ILPRTL + DB ' -- Waiting --' + DB CR,0 + RET + +; +;------------------------------- +; File type restriction storage +;------------------------------- +; +; Don't allow ___ (If ZCPR is YES) +; \ +SYSCHK: DB 'SYS' +NDRCHK: DB 'NDR' +RCPCHK: DB 'RCP' + +; +; If receiving __ change it to __ (If NOCOMR is YES) +; \ \ +COMCHG: DB 'COM', 'OBJ' +PRLCHG: DB 'PRL', 'OBP' + +; +; If the library extraction flag (LBRARC) is set and an unsuccessful open with +; the default filetype occurs, the following file types are copied to FCB+9 +; and the open attempt is repeated. +; +ARCNAM: DB 'ARC' ; Copied to FCB+9 +LBRNAM: DB 'LBR' ; Copied to FCB+9 +ARKNAM: DB 'ARK' ; Copied to FCB+9 + +; +;--------------------- +; LOGCALL allocations +;--------------------- +; +DEFDSK: DB 0 ; Disk for open stored here +DEFUSR: DB 0 ; User for open stored here +CLRPTR: DW LOGBUF +LOGPTR: DW DBUF +LOGCNT: DB 0 +LOGK: DB 'k ' +DUSAVE: DB 0,0,0,0 ; Buffer for drive/user + +; +;------------------ +; Time allocations +;------------------ +; +MAXTOS: DB 0 ; Maximum time left on system +RTCBUF: DW 0 ; RTCBUF address +TLOS: DB 0 ; Current time left on system +TON: DB 0 ; Current time on system + +; +XTABLE: DW 5, 13, 19, 25, 30, 48, 85, 141, 210, 280, 0 +KTABLE: DW 5, 14, 21, 27, 32, 53, 101, 190, 330, 525, 0 +XECTBL: DB 192, 74, 51, 38, 32, 20, 11, 8, 5, 3, 0 +KECTBL: DB 192, 69, 46, 36, 30, 18, 10, 5, 3, 2, 0 + +; +;-------------------- +; Batch mode storage +;-------------------- +; +BGNMS: DW 0 ; Start address of filenames in TBUFF +LIST: DW DBUF ; Filename storage in send batch mode +LISTPOS:DW 0 ; Next position to store matching filename +LISTEND:DW 0 ; Address of last matching filename +LISTI: DW 0 ; Pointer 1 for two-dimensional bubble sort +LISTJ: DW 0 ; Pointer 2 for two-dimensional bubble sort +FILEK: DW 0 ; Total kilobytes of files found (send batch) +FCBBUF: DS 21 ; Batch filename from command line +FSTFLG: DB 0 ; Set to 1 when command line scan done +NAMECT: DB 0 ; # of names on command line +NBSAVE: DW 0 ; Start address in NAMBUF for next file +SBSHOW: DB 0 ; Set shows partial stat display in batch +SHOCNT: DB 0 ; Counter to show files left +TOTREC: DW 0 ; Total records to be sent + +; +;------------------------ +; Temporary storage area +;------------------------ +; +ACKCHK: DB 0 ; Lets batch header user GTACK routine +AFBYTE: DB 0 ; Access flags byte storage +CHKEOT: DB 0 ; Prevents locking up after an EOT +COMMA: DB 0 ; Field counter for logcal +CRCFLG: DB 1 ; For sending checksum rather than CRC +EOFLG: DB 0 ; EOF (End of file) flag +EOTFLG: DB 0 ; EOT (End of transmission) status flag +ERRCNT: DB 0 ; Error count +FRSTIM: DB 0 ; Turned on after first 'SOH' received +GOTONE: DB 0 ; Prevents asking for a description +KFLG: DB 1 ; For sending 1k blocks (Defaults to 1k) +PRVSPC: DB 0 ; Shows in private display in SPACE: if set +RCVCNT: DB 0 ; Record number received +RCVTRY: DB 0 ; Keeps track of number of attempts +RCVDRV: DB 0 ; Requested drive number +RCVUSR: DB 0 ; Requested user number + +ACCERR: DW 0 ; No 'ACK' error count for 1k ratio +HDRADR: DW 0 ; Current location in batch header block +RCNT: DW 0 ; Record count +RECDNO: DW 0 ; Current record number +RCDCNT: DW 0 ; Used in sending the record header +RECPTR: DW DBUF +RECNBF: DW 0 ; Number of records in the buffer +SAVEHL: DW 0 ; Saves TBUF command line address +XFRMIN: DW 0 ; Transfer time in mins for TIMEON + +; + END ; 'Almost'... + \ No newline at end of file diff --git a/Source/Apps/ZMD/zmdel.z80 b/Source/Apps/ZMD/zmdel.z80 new file mode 100644 index 00000000..81113f46 --- /dev/null +++ b/Source/Apps/ZMD/zmdel.z80 @@ -0,0 +1,264 @@ +; + + TITLE ZMDEL.Z80 - 09/29/88 - ZMD Sysop Transfer Log Purge Utility +; Copyrighted (c) 1987, 1988 +; Robert W. Kramer III + + PAGE +;- -; +; Update History ; +; ; +; Date Release Comments ; +; -------- ------- ---------------------------------------------- ; +; ; +; 09/29/88 v1.50 - No change(s) made to this file ; +; 03/18/88 v1.49 - No change(s) made to this file ; +; 03/13/88 v1.48 - Had a small problem with TPA fix which has been ; +; corrected. CHKTPA was calculating the total ; +; number of bytes available for DBUF, but wasn't ; +; clearing register L (forcing an even amount of ; +; sectors before initializing OUTSIZ buffer limit ; +; comparison word). This may have introduced ; +; minimal garbage to your FOR file if your FOR ; +; file is large enough to fill available TPA with ; +; ZMD, ZFORS or to the log file if running ZMDEL. ; +; - Rewrote OUTCHR routine in ZMDSUBS. ; +; - Redefined buffer table at end of programs. STACK; +; and filename buffers now EQUated with offsets ; +; from the last switch/toggle in program instead ; +; of with DS directive. ; +; - Some systems which do NOT have an interrupt ; +; driven keyboard may have noticed problems when ; +; an invalid key was entered in the ZNEWP, ZFORP ; +; and ZMDEL programs. In ZNEWP and ZFORP, if a ; +; CR was entered to pause the output, output was ; +; limited to one line at a time per key pressed. ; +; If an invalid key was hit, output would have ; +; remained in a paused state until one of the ; +; abort keys were pressed. This was difficult to ; +; find since my keyboard is interrupt driven and ; +; I could not duplicate the problem on my own ; +; system. ; +; 02/25/88 v1.47 - Fixed line count display routine. Number of ; +; lines read was being improperly decremented ; +; before displaying. Same fix included removing ; +; code that added an extra CR,LF to the beginning ; +; of the file. Count is now right. ; +; 01/27/88 v1.46 - Some changes were made to the ZMDSUBS file that ; +; are not directly related to this file ; +; 01/17/88 v1.45 - First public release ; +; 11/20/87 v1.00 - Initial version ; +;- -; + +;-------------------------------------------------------------------------; +; EXTERNAL Declarations: | +;-------------------------------------------------------------------------; + + + EXTRN CKABRT,CLEARIT,CLRLIN,DBUF,DECOUT,ERXIT,EXIT,ILPRTB + EXTRN INPUT,NOFILE,NOLOG,NOROOM,OLDDRV,OLDUSR,OUTCHR,PRINTV + EXTRN RECAR1,RECDR1,RENFCB,RERROR,RSDMA,SHONM4,STACK,STDMA + EXTRN TDONE,TYPE,UCASE + +; +;-------------------------------------------------------------------------; +; Program Starts Here | +;-------------------------------------------------------------------------; + + + .Z80 + ASEG + ORG 100H ; Program starts + JP BEGIN ; Jump around configuration table + INCLUDE ZMDHDR.Z80 ; Include the ZMD header overlay + .REQUEST ZMDSUBS ; Include the ZMD subroutines + +; +; +; Save CP/M stack, initialize new one for this program +; +BEGIN: LD (STACK),SP ; Save return address to CCP + LD SP,STACK + +; +; Save current drive/user +; + LD A,255 ; Get user function + CALL RECAR1 + LD (OLDUSR),A ; Save user area for later + LD C,CURDRV ; Get current drive function + CALL BDOS + LD (OLDDRV),A ; Save drive for later + +; +; Tell em who we are and ask if they want to continue +; + LD HL,PRGUTL + CALL PRINTV + + LD A,(LOGCAL) ; Log file enabled? + OR A + JP Z,NOLOG ; No, then don't run program + + CALL ILPRTB + DB 'Purge all except "R" entries from log? ',0 + LD A,0 + LD (DESWAIT),A ; Disable sleepy caller timout + CALL INPUT + CALL UCASE + CP 'Y' ; Continue? + JP NZ,EXIT ; No, exit to CP/M + CALL CLRLIN + +; +; Now log into drive/user area of ZMD.LOG +; + LD A,(LOGUSR) ; Get user area to find ZMD.LOG file + CALL RECAR1 + LD A,(LOGDRV) ; Get drive to find ZMD.LOG file + CALL RECDR1 + +; +; Open the 'ZMD .LOG' file +; + LD DE,LOGNAM ; Point to LOG filename + LD HL,FILE ; Destination is internal FCB1 + CALL RENFCB ; Initialize FCB + + LD DE,FILE ; Point to ZMD.LOG FCB + LD C,OPEN ; Open file + CALL BDOS + INC A ; Does file exist? + LD HL,LOGNAM ; Point to log filename + JP Z,NOFILE ; No, inform user and abort to CP/M + +; +; Open the ' .$$$' file +; + LD DE,TEMPFIL ; Point to temporary filename + LD HL,DEST ; Destination is internal FCB2 + CALL RENFCB ; Initialize FCB + + LD HL,FILE ; Point to default FCB + LD DE,DEST ; + LD BC,9 ; Move drive and filename bytes + LDIR + + LD C,DELETE ; Delete possible '$$$' temporary file + LD DE,DEST + CALL BDOS + + LD C,MAKE ; And make new one for this session + LD DE,DEST + CALL BDOS + INC A ; Successful create? + JP Z,NOROOM ; No, inform user and exit to CP/M + + CALL ILPRTB ; Warn them of the wait + DB CR + DB 'Cleaning ',0 + LD HL,LOGNAM + CALL SHONM4 + +RDRECD: CALL RSDMA ; Reset DMA + LD DE,FILE ; Read a record from ZMD.LOG + LD C,READ + CALL BDOS + OR A ; Read ok? + JP NZ,RERROR ; No, inform user and exit + LD HL,TBUF ; Point to first character in read buffer + +GETBYT: LD A,(HL) ; Get a byte from read buffer + AND 7FH ; Strip parity bit + CP 7FH ; Del (Rubout) + JP Z,NEXT ; Yes, ignore it + CP EOF ; End of file marker + JP Z,TDONE ; Transfer done. Close and exit + LD B,A ; Save character + CP LF ; Was it a line feed? + JP Z,NEWLIN ; Yes toggle line counters, start new line + +; +; LOGMODE is set to 0 everytime a line feed is encountered. If LOGMODE is +; is 0 at this point, the current byte is anylized as this log entry's +; mode of transfer. Only entries made in the 'R' receive mode are written +; to the new ZMD.$$$ file. Encountering an 'R' when LOGMODE is 0 causes +; KEEPER to be set non zero +; + LD A,(LOGMODE) ; Start of new line? + OR A + JP NZ,NXTBYT ; No, then we don't care what this byte is + INC A + LD (LOGMODE),A ; Else show we are not on LOGMODE byte anymore + LD A,B ; Get the character back + CP 'R' ; Is this an upload entry? + LD (KEEPER),A ; Indicate saving byte just in case + JP Z,NXTBYT ; Yes, leave KEEPER non-zero so it's written + XOR A + LD (KEEPER),A ; Else 0 keep flag (0=don't keep this entry) + +NXTBYT: LD A,(KEEPER) ; Keeping this log entry? + OR A + JP Z,NEXT ; No, get next byte + +; +; Place current byte in buffer and write to disk if buffer full +; +WRTBYT: LD A,B + CALL OUTCHR + +NEXT: INC L ; Done with sector? + JP Z,RDRECD ; Yes, get another sector + JP GETBYT ; Else get another byte + +NEWLIN: XOR A ; Zero accumulator + LD (LOGMODE),A ; Show current byte is log mode byte + LD IY,(LNSREAD) ; Get lines read counter + INC IY ; Add one more + LD (LNSREAD),IY + LD A,1 ; Disable page pauses + CALL CKABRT ; User abort? + LD A,(KEEPER) ; Are we keeping this entry? + OR A + JP Z,NEXT ; No, read another byte + LD IY,(LNSWROT) ; Get lines written count + INC IY ; Add one more + LD (LNSWROT),IY + JP WRTBYT + +; +DONE:: CALL CLRLIN + CALL ILPRTB + DB CR,'Finished.' + DB CR,LF + DB ' ',0 + + LD HL,(LNSREAD) + CALL DECOUT + CALL ILPRTB + DB TAB + DB 'original lines',CR,LF + DB ' ',0 + + LD HL,(LNSWROT) + CALL DECOUT + CALL ILPRTB + DB TAB + DB 'retained lines ',0 + JP EXIT + +; +; These next are dummy routines to satisfy external ZMDSUBS requests. +; They do nothing, but leave alone. +; +TIME:: RET + + +KEEPER: DB 0 +LOGMODE:DB 0 +LNSREAD:DW 0 +LNSWROT:DW 0 + + + END + \ No newline at end of file diff --git a/Source/Apps/ZMD/zmdhb.z80 b/Source/Apps/ZMD/zmdhb.z80 new file mode 100644 index 00000000..9d4cddd5 --- /dev/null +++ b/Source/Apps/ZMD/zmdhb.z80 @@ -0,0 +1,916 @@ +;======================================================================= +; +; XMHB.Z80 - XMODEM12 PATCH FILE FOR ROMWBW HBIOS +; +; Wayne Warthen - wwarthen@gmail.com +; +; 2020-05-23 WBW Rewrite for HBIOS FastPath(tm) +; +;======================================================================= +; + ASEG +; +BASE EQU 100H ; Start of CP/M normal program area +FCB EQU 005CH ; System FCB +; +BDOS EQU 0005H ; BDOS function dispatch vector +; +;======================================================================= +; +; Jump table: The jump table must be in exactly the same sequence as the +; one in ZMD. +; + ORG 0580H ; ZMD I/O overlay address +; + JP CONOUT ; must be 00000h if not used, see below + JP MINIT ; initialization routine (if needed) + JP UNINIT ; undo whatever 'MINIT' did (or return) +JPTBL: + JP SENDR ; send character (via pop psw) + JP CAROK ; test for carrier + ;JP MDIN ; receive data byte (not present in ZMD) + JP GETCHR ; get character from modem + JP RCVRDY ; check receive ready + JP SNDRDY ; check send ready + JP SPEED ; get speed value for file transfer time + JP EXTRA1 ; extra for custom routine + JP EXTRA2 ; extra for custom routine + JP EXTRA3 ; extra for custom routine +; + ORG 0600H +; +; ZMD expects to find a byte with the baud rate code somewhere. For +; lack of a better location, we put it at 0600H. The highest baud +; rate code understood by ZMD is 9 which means 19200 baud. We just +; use that since we are almost certainly running faster than this. +; +BAUDCD DB 9 ; Baud rate storage +; +;----------------------------------------------------------------------- +; +; Output character to console +; +; This is intended to write file transfer progress to a RCPM +; BBS console. It is stubbed out because it will write to the +; active file transfer port when not using an RCPM. +; +CONOUT: + RET +; +;----------------------------------------------------------------------- +; +; Initialize modem +; +; This procedure has been usurped to dynamically detect the type +; of system we are running on and install the *real* jump table +; entries as appropriate. +; +MINIT: +; +; Scan the command line for a number. If found, this is used +; as the HBIOS unit number. +; + LD HL,FCB+1 ; Start after drive byte + LD B,8 ; Check 8 characters +MINIT1: + LD A,(HL) ; Get character + CP '0' ; Start of numerics + JR C,MINIT2 ; If below '0', continue scan + CP '9' ; Last numeric + JR NC,MINIT2 ; If above '9', continue scan + SUB '0' ; Got it, convert to binary + LD (UNIT),A ; Save it + LD A,' ' ; Space character to accum + LD (HL),A ; Remove numberic from FCB + JR MINIT3 ; Proceed with initialization + +MINIT2: + INC HL + DJNZ MINIT1 + +MINIT3: + ; Announce + LD DE,TAG ; Tagline + LD C,9 ; BDOS string display function + CALL BDOS ; Do it +; + ; Identify BIOS (RomWBW HBIOS or UNA UBIOS) + CALL IDBIO ; 1=HBIOS, 2=UBIOS + LD (BIOID),A ; Save it + DEC A ; Test for HBIOS + JR Z,MINIT_HB ; Do HBIOS setup + DEC A ; Test for UBIOS + JR Z,MINIT_UB ; Do UBIOS setup +; + ; Neither UNA nor RomWBW + LD DE,ERR_BIO ; BIOS error message + JP FAIL ; Print msg and bail out +; +MINIT_HB: + ; Display RomWBW notification string + LD DE,HB_TAG ; BIOS notification string + LD C,9 ; BDOS string display function + CALL BDOS ; Do it +; + ; Get CPU speed from RomWBW HBIOS and save it + LD B,0F8H ; HBIOS SYSGET function 0xF8 + LD C,0F0H ; CPUINFO subfunction 0xF0 + RST 08 ; Do it, L := CPU speed in MHz + LD A,L ; Move it to A + LD (CPUSPD),A ; Save it +; + ; Get HBIOS bank id + LD BC,0F8F2H ; HBIOS SYSGET, Bank Info + RST 08 ; do it + JP NZ,APIERR ; handle API error + LD A,D ; BIOS bank id to A + LD (BIOSBID),A ; save it +; + LD A,(UNIT) ; get current unit specified + CP 0FFH ; check for undefined + JR NZ,MINIT_HB1 ; if not undefined, go ahead +; + ; Lookup current console to use as default for transfer + LD B,0FAH ; HBIOS PEEK + LD A,(BIOSBID) ; get BIOS bank id + LD D,A ; ... and put in D + LD HL,100H + 12H ; HCB console unit address + RST 08 ; E := value + LD A,E ; put in A + LD (UNIT),A ; replace UNIT with console UNIT +; +MINIT_HB1: + ; Get HBIOS device type + LD B,06H ; HBIOS DEVICE function 0x06 + LD A,(UNIT) ; Get xfer unit + LD C,A ; Put in C + RST 08 ; Do it, D=device type + LD A,D ; Put result in A + CP 00H ; UART? + JP Z,MINIT_HB2 ; If so, do UART H/W init + CP 80H ; USB-FIFO? + JP Z,UF_INIT ; If so, do USB-FIFO H/W init + JP HB_INIT ; Otherwise, use BIOS I/O +; +MINIT_HB2: + ; Handle UART driver special. If receive interrupts active, + ; we must use BIOS I/O. Otherwise, direct UART I/O is best + LD B,06H ; Serial device function + LD A,(UNIT) ; Get xfer unit + LD C,A ; Put in C + RST 08 ; Do it, H = UART TYPE + BIT 7,H ; Check for interrupt driven receive + JP Z,UA_INIT ; If not, do direct UART I/O + JP HB_INIT ; else use BIOS I/O +; +MINIT_UB: + ; Display UNA notification string + LD DE,UB_TAG ; BIOS notification string + LD C,9 ; BDOS string display function + CALL BDOS ; Do it +; + ; Get CPU speed from UNA and save it + LD C,0F8H ; UNA BIOS Get PHI function + RST 08 ; Returns speed in Hz in DE:HL + LD B,4 ; Divide MHz in DE:HL by 100000H +MINIT_UB1: + SRL D ; ... to get approx CPU speed in + RR E ; ...MHz. Throw away HL, and + DJNZ MINIT_UB1 ; ...right shift DE by 4. + INC E ; Fix up for value truncation + LD A,E ; Put in A + LD (CPUSPD),A ; Save it +; + JP UB_INIT ; UNA BIOS init +; +MINIT_RET: + PUSH HL ; Save HL (JP table adr) + + ; Display handler label + LD C,9 ; BDOS string display function + CALL BDOS ; Do it +; + ; Display port (unit number) + LD DE,COM_LBL ; Prefix + LD C,9 ; BDOS string display function + CALL BDOS ; Do it + LD A,(UNIT) ; Get unit number + ADD A,'0' ; Make displayable + LD E,A ; Put in E for display + LD C,2 ; BDOS console write char + CALL BDOS ; Do it +; + ; Newline + LD C,9 ; BDOS string display function + LD DE,CRLF ; Newline + CALL BDOS ; Do it +; + ; Copy real vectors into active jump table + POP HL ; Recover HL + LD DE,JPTBL ; Real jump table is destination + LD BC,7 * 3 ; Copy 7 3-byte entries + LDIR ; Do the copy +; + ; Return with CPU speed in A + LD A,(CPUSPD) ; A := CPU speed in MHz + LD HL,(RCVSCL) ; HL := receive scalar + RET ; and return +; +;----------------------------------------------------------------------- +; +; Uninitialize modem +; +UNINIT: + LD A,(BIOID) + CP 1 ; Is HBIOS? + JR Z,HUNINIT ; Handle HBIOS + CP 2 ; Is UBIOS? + JR Z,UUNINIT ; Handle UBIOS + RET ; Just return +; +HUNINIT: + ; HBIOS: Reset character device 0 + LD B,04H ; HBIOS CIOINIT function 0x04 + LD A,(UNIT) ; HBIOS serial unit number + LD C,A ; Put in C for func call + LD DE,-1 ; Reset w/ current settings + RST 08 ; Do it + RET ; not initialized, so no 'UN-INITIALIZE' +; +UUNINIT: + ; UBIOS: Reset character device 0 + LD C,10H ; UNA INIT function 0x10 + LD A,(UNIT) ; UBIOS serial unit number + LD B,A ; Put in B for func call + LD DE,-1 ; Reset w/ current settings + RST 08 ; Do it + RET ; not initialized, so no 'UN-INITIALIZE' +; +; Identify active BIOS. RomWBW HBIOS=1, UNA UBIOS=2, else 0 +; +IDBIO: +; + ; Check for UNA (UBIOS) + LD A,(0FFFDH) ; fixed location of UNA API vector + CP 0C3H ; jp instruction? + JR NZ,IDBIO1 ; if not, not UNA + LD HL,(0FFFEH) ; get jp address + LD A,(HL) ; get byte at target address + CP 0FDH ; first byte of UNA push ix instruction + JR NZ,IDBIO1 ; if not, not UNA + INC HL ; point to next byte + LD A,(HL) ; get next byte + CP 0E5H ; second byte of UNA push ix instruction + JR NZ,IDBIO1 ; if not, not UNA, check others + LD A,2 ; UNA BIOS id = 2 + RET ; and done +; +IDBIO1: + ; Check for RomWBW (HBIOS) + LD HL,(0FFFEH) ; HL := HBIOS ident location + LD A,'W' ; First byte of ident + CP (HL) ; Compare + JR NZ,IDBIO2 ; Not HBIOS + INC HL ; Next byte of ident + LD A,~'W' ; Second byte of ident + CP (HL) ; Compare + JR NZ,IDBIO2 ; Not HBIOS + LD A,1 ; HBIOS BIOS id = 1 + RET ; and done +; +IDBIO2: + ; No idea what this is + XOR A ; Setup return value of 0 + RET ; and done +; +HWERR: + ; Failed to identify target comm hardware + LD DE,ERR_HW ; Hardware error message + JP FAIL ; Print message and bail out +; +APIERR: + ; API returned unepected failure + LD DE,ERR_API ; API error message + JP FAIL ; Pprint message and bail out +; +FAIL: + ; DE has error string address + LD C,9 ; BDOS string display function + CALL BDOS ; Do it + JP 0 ; Bail out! +; +;----------------------------------------------------------------------- +; +; The following are all dummy routines that are unused because MINIT +; dynamically installs the real jump table. +; +SENDR: +CAROK: +MDIN: +GETCHR: +RCVRDY: +SNDRDY: +SPEED: +EXTRA1: +EXTRA2: +EXTRA3: + RET +; +BIOID DB 0 ; BIOS ID, 1=HBIOS, 2=UBIOS +CPUSPD DB 10 ; CPU speed in MHz +RCVSCL DW 6600 ; RECV loop timeout scalar +UNIT DB 0FFH ; BIOS serial device unit number +BIOSBID DB 00H ; BIOS bank id +; +TAG DB "RomWBW, 30-May-2020$" +; +HB_LBL DB ", HBIOS FastPath$" +UB_LBL DB ", UNA UBIOS$" +UA_LBL DB ", UART$" +UF_LBL DB ", USB-FIFO$" +COM_LBL DB " on COM$" +; +UB_TAG DB " [UNA]$" +HB_TAG DB " [WBW]$" +; +CRLF DB 13, 10, "$" +; +ERR_BIO DB 13, 10, 13, 10, "++ Unknown BIOS ++", 13, 10, "$" +ERR_HW DB 13, 10, 13, 10, "++ Unknown Hardware ++", 13, 10, "$" +ERR_API DB 13, 10, 13, 10, "++ BIOS API Error ++", 13, 10, "$" +; +;======================================================================= +;======================================================================= +; +; RomWBW HBIOS Interface +; +;======================================================================= +;======================================================================= +; +; Following jump table is dynamically patched over initial jump +; table at program startup. See MINIT above. Note that only a +; subset of the jump table is overlaid (SENDR to SPEED). +; +HB_JPTBL: + JP HB_SENDR ; send character (via pop psw) + JP HB_CAROK ; test for carrier + ;JP HB_MDIN ; receive data byte (not present in ZMD) + JP HB_GETCHR ; get character from modem + JP HB_RCVRDY ; check receive ready + JP HB_SNDRDY ; check send ready + JP HB_SPEED ; get speed value for file transfer time +; +;----------------------------------------------------------------------- +; +; HBIOS initialization +; +HB_INIT: + LD HL,2150 ; Smaller receive loop timeout scalar + LD (RCVSCL),HL ; ... to compensate for BIOS overhead +; + ; Patch SENDR w/ FastPath addresses + LD BC,0F801H ; Get CIO func/data adr + LD D,01H ; Func=CIO OUT + LD A,(UNIT) ; get desired char unit + LD E,A ; and put in E + RST 08 + JP NZ,APIERR ; handle API error + LD (HB_UDAT),DE ; Plug in data adr + LD (HB_SCFN),HL ; Plug in func adr +; + ; Patch GETCHR/MDIN w/ FastPath addresses + LD BC,0F801H ; Get CIO func/data adr + LD D,00H ; Func=CIO IN + LD A,(UNIT) ; get desired char unit + LD E,A ; and put in E + RST 08 + JP NZ,APIERR ; handle API error + LD (HB_GCFN),HL ; Plug in func adr +; + ; Patch RCVRDY w/ FastPath addresses + LD BC,0F801H ; Get CIO func/data adr + LD D,02H ; Func=CIO IST + LD A,(UNIT) ; get desired char unit + LD E,A ; and put in E + RST 08 + JP NZ,APIERR ; handle API error + LD (HB_RRFN),HL ; Plug in func adr +; + ; Patch SNDRDY w/ FastPath addresses + LD BC,0F801H ; Get CIO func/data adr + LD D,03H ; Func=CIO OST + LD A,(UNIT) ; get desired char unit + LD E,A ; and put in E + RST 08 + JP NZ,APIERR ; handle API error + LD (HB_SRFN),HL ; Plug in func adr +; + ; Claim 1 MHz CPU to offset overhead of HBIOS + LD A,1 + LD (CPUSPD),A ; Save it +; + LD HL,HB_JPTBL + LD DE,HB_LBL + JP MINIT_RET +; +;----------------------------------------------------------------------- +; +; Send character on top of stack +; +HB_SENDR: + POP AF ; get character to send from stack + PUSH BC + PUSH DE + PUSH HL + LD E,A ; character to E + LD IY,(HB_UDAT) + LD A,(BIOSBID) ; call into HBIOS bank + LD IX,0000H +HB_SCFN EQU $-2 + CALL 0FFF9H ; HBIOS bank call + POP HL + POP DE + POP BC + RET +; +;----------------------------------------------------------------------- +; +; Test and report carrier status, Z set if carrier present +; +HB_CAROK: + XOR A ; not used, always indicate present + RET +; +;----------------------------------------------------------------------- +; +; Get a character +; +; GETCHR must not block +; +HB_GETCHR: + CALL HB_RCVRDY + RET NZ + ; Fall thru if char ready +; +; MDIN can assume a character is ready +; +HB_MDIN: + PUSH BC + PUSH DE + PUSH HL + LD IY,(HB_UDAT) + LD A,(BIOSBID) ; call into HBIOS bank + LD IX,0000H +HB_GCFN EQU $-2 + CALL 0FFF9H ; HBIOS bank call + LD A,E ; byte received to A + POP HL + POP DE + POP BC + RET +; +;----------------------------------------------------------------------- +; +; Test for character ready to receive, Z = ready +; Error code returned in A register +; *** Error code does not seem to be used *** +; +HB_RCVRDY: + PUSH BC + PUSH DE + PUSH HL + LD IY,(HB_UDAT) + LD A,(BIOSBID) ; call into HBIOS bank + LD IX,0000H +HB_RRFN EQU $-2 + CALL 0FFF9H ; HBIOS bank call + SUB 1 ; CF set IFF zero + RL A ; CF to bit 0 of A + AND 01H ; set Z flag as needed + LD A,0 ; report no line errors + POP HL + POP DE + POP BC + RET +; +;----------------------------------------------------------------------- +; +; Test for ready to send a character, Z = ready +; +HB_SNDRDY: + PUSH BC + PUSH DE + PUSH HL + LD IY,(HB_UDAT) + LD A,(BIOSBID) ; call into HBIOS bank + LD IX,0000H +HB_SRFN EQU $-2 + CALL 0FFF9H ; HBIOS bank call + SUB 1 ; CF set IFF zero + RL A ; CF to bit 0 of A + AND 01H ; set Z flag as needed + POP HL + POP DE + POP BC + RET +; +;----------------------------------------------------------------------- +; +; Report baud rate (index into SPTBL returned in register A) +; +HB_SPEED: + LD A,8 ; arbitrarily return 9600 baud + RET +; +; +; +HB_UDAT DW 0000H ; Unit data address +; +; +;======================================================================= +;======================================================================= +; +; UNA UBIOS Interface +; +;======================================================================= +;======================================================================= +; +; Following jump table is dynamically patched over initial jump +; table at program startup. See MINIT above. Note that only a +; subset of the jump table is overlaid (SENDR to SPEED). +; +UB_JPTBL: + JP UB_SENDR ; send character (via pop psw) + JP UB_CAROK ; test for carrier + ;JP UB_MDIN ; receive data byte (not present in ZMD) + JP UB_GETCHR ; get character from modem + JP UB_RCVRDY ; check receive ready + JP UB_SNDRDY ; check send ready + JP UB_SPEED ; get speed value for file transfer time +; +;----------------------------------------------------------------------- +; +; UBIOS initialization +; +UB_INIT: +; +; TODO: +; - TEST!!! +; - ADJUST RCVSCL? +; + LD HL,3000 ; Smaller receive loop timeout scalar + LD (RCVSCL),HL ; ... to compensate for BIOS overhead +; + ; Claim 1 MHz CPU to offset overhead of HBIOS + LD A,1 + LD (CPUSPD),A ; Save it +; + LD HL,UB_JPTBL + LD DE,UB_LBL + JP MINIT_RET +; +;----------------------------------------------------------------------- +; +; Send character on top of stack +; +UB_SENDR: + POP AF ; get character to send from stack + PUSH BC + PUSH DE + PUSH HL + LD BC,0012H ; unit 0, func 12h (write char) + LD E,A ; character to E + RST 08 + POP HL + POP DE + POP BC + RET +; +;----------------------------------------------------------------------- +; +; Test and report carrier status, Z set if carrier present +; +UB_CAROK: + XOR A ; not used, always indicate present + RET +; +;----------------------------------------------------------------------- +; +; Get a character +; +; GETCHR must not block +; +UB_GETCHR: + CALL UB_RCVRDY + RET NZ + ; Fall thru if char ready +; +; MDIN can assume a character is ready +; +UB_MDIN: + PUSH BC + PUSH DE + PUSH HL + LD BC,0011H ; unit 0, func 12h (write char) + RST 08 + LD A,E ; byte received to A + POP HL + POP DE + POP BC + RET +; +;----------------------------------------------------------------------- +; +; Test for character ready to receive, Z = ready +; Error code returned in A register +; *** Error code does not seem to be used *** +; +UB_RCVRDY: + PUSH BC + PUSH DE + PUSH HL + LD BC,0013H ; unit 0, func 13h (input stat) + RST 08 + XOR A ; zero accum ; 4 + CP E ; CF means not zero ; 4 + CCF ; CF means zero ; 4 + RLA ; ZF means not zero ; 4 + LD A,0 ; report no line errors + POP HL + POP DE + POP BC + RET +; +;----------------------------------------------------------------------- +; +; Test for ready to send a character, Z = ready +; +UB_SNDRDY: + PUSH BC + PUSH DE + PUSH HL + LD BC,0014H ; unit 0, func 14h (output stat) + RST 08 + XOR A ; zero accum ; 4 + CP E ; CF means not zero ; 4 + CCF ; CF means zero ; 4 + RLA ; ZF means not zero ; 4 + POP HL + POP DE + POP BC + RET +; +;----------------------------------------------------------------------- +; +; Report baud rate (index into SPTBL returned in register A) +; +UB_SPEED: + LD A,8 ; arbitrarily return 9600 baud + RET +; +;======================================================================= +;======================================================================= +; +; 8250-like UART +; +;======================================================================= +;======================================================================= +; +; UART constants +; +UA_SNDB EQU 20H ; bit to test for send ready +UA_SNDR EQU 20H ; value when ready to send +UA_RCVB EQU 01H ; bit to test for receive ready +UA_RCVR EQU 01H ; value when ready to receive +UA_PARE EQU 04H ; bit for parity error +UA_OVRE EQU 02H ; bit for overrun error +UA_FRME EQU 08H ; bit for framing error +UA_ERRS EQU UA_FRME | UA_OVRE | UA_PARE +; +; Following jump table is dynamically patched into real jump +; table at program startup. See MINIT above. Note that only a +; subset of the jump table is overlaid (SENDR to SPEED). +; +UA_JPTBL: + JP UA_SENDR ; send character (via pop psw) + JP UA_CAROK ; test for carrier + ;JP UA_MDIN ; receive data byte (not present in ZMD) + JP UA_GETCHR ; get character from modem + JP UA_RCVRDY ; check receive ready + JP UA_SNDRDY ; check send ready + JP UA_SPEED ; get speed value for file transfer time +; +;----------------------------------------------------------------------- +; +; UART initialization +; +UA_INIT: + LD DE,13000 ; receive loop timeout scalar + LD (RCVSCL),DE ; ... for UART RCVRDY timing +; + LD A,L ; get base I/O port address + LD (UA_SCP),A ; set port value in SENDR + LD (UA_GCP),A ; set port value in GETCHR + ADD A,5 ; UART control port is 5 higher + LD (UA_RRP),A ; set port value in RCVRDY + LD (UA_SRP),A ; set port value in SNDRDY +; + LD HL,UA_JPTBL + LD DE,UA_LBL + JP MINIT_RET +; +;----------------------------------------------------------------------- +; +; Send character on top of stack +; +UA_SENDR: + POP AF ; get character to send from stack + OUT (0FFH),A ; send to port +UA_SCP EQU $-1 ; port value + RET +; +;----------------------------------------------------------------------- +; +; Test and report carrier status, Z set if carrier present +; +UA_CAROK: + XOR A ; not used, always indicate present + RET +; +;----------------------------------------------------------------------- +; +; Get a character +; +; GETCHR must not block +; +UA_GETCHR: + CALL UA_RCVRDY + RET NZ + ; Fall thru if char ready +; +; MDIN can assume a character is ready +; +UA_MDIN: + IN A,(0FFH) ; read character from port +UA_GCP EQU $-1 ; port value + RET +; +;----------------------------------------------------------------------- +; +; Test for character ready to receive, Z = ready +; Error code returned in A register +; *** Error code does not seem to be used *** +; +UA_RCVRDY: + IN A,(0FFH) ; get modem status +UA_RRP EQU $-1 ; port value + AND UA_RCVB ; isolate ready bit + CP UA_RCVR ; test it (set flags) + LD A,0 ; report no line errors +; + RET +; +;----------------------------------------------------------------------- +; +; Test for ready to send a character, Z = ready +; +UA_SNDRDY: + IN A,(0FFH) ; get status +UA_SRP EQU $-1 ; port value + AND UA_SNDB ; isolate transmit ready bit + CP UA_SNDR ; test for ready value + RET +; +;----------------------------------------------------------------------- +; +; Report baud rate (index into SPTBL returned in register A) +; +UA_SPEED: + LD A,8 ; arbitrarily return 9600 baud + RET +; +; +; +UA_BASE DB 00H ; UART base port I/O address +UA_CTLP DB 00H ; UART control port I/O address +; +; +;======================================================================= +;======================================================================= +; +; WILL SOWERBUTTS ECB USB-FIFO +; +;======================================================================= +;======================================================================= +; +UF_BASE EQU 0CH +UF_DATA EQU (UF_BASE+0) +UF_STATUS EQU (UF_BASE+1) +UF_SEND_IMM EQU (UF_BASE+2) +; +; Following jump table is dynamically patched over initial jump +; table at program startup. See MINIT above. Note that only a +; subset of the jump table is overlaid (SENDR to SPEED). +; +UF_JPTBL: + JP UF_SENDR ; send character (via pop psw) + JP UF_CAROK ; test for carrier + ;JP UF_MDIN ; receive data byte (not present in ZMD) + JP UF_GETCHR ; get character from modem + JP UF_RCVRDY ; check receive ready + JP UF_SNDRDY ; check send ready + JP UF_SPEED ; get speed value for file transfer time +; +;----------------------------------------------------------------------- +; +; USB-FIFO initialization +; +UF_INIT: + LD DE,12000 ; receive loop timeout scalar + LD (RCVSCL),DE ; ... for UART RCVRDY timing +; + LD A,L ; get base I/O port address (data port) + LD (UF_SCDP),A ; set data port in SENDR + LD (UF_GCDP),A ; set data port in GETCHR/MDIN + INC A ; bump to status port + LD (UF_RRSP),A ; set status port in RCVRDY + LD (UF_SRSP),A ; set status port in SNDRDY + INC A ; bump to send immediate port + LD (UF_SCIP),A ; set send immed port in SENDR +; + LD HL,UF_JPTBL + LD DE,UF_LBL + JP MINIT_RET +; +;----------------------------------------------------------------------- +; +; Send character on top of stack +; +UF_SENDR: + + POP AF ; get character to send from stack + OUT (0FFH),A ; write to fifo +UF_SCDP EQU $-1 ; data port + OUT (0FFH),A ; send immediate +UF_SCIP EQU $-1 ; send immediate port + RET +; +;----------------------------------------------------------------------- +; +; Test and report carrier status, Z set if carrier present +; +UF_CAROK: + XOR A ; not used, always indicate present + RET +; +;----------------------------------------------------------------------- +; +; Get a character (assume character ready has already been tested) +; +; GETCHR must not block +; +UF_GETCHR: + CALL UF_RCVRDY ; check for char ready + RET NZ ; return if not + ; Fall thru if char ready +; +; MDIN can assume a character is ready +; +UF_MDIN: + IN A,(0FFH) ; get char +UF_GCDP EQU $-1 ; data port + RET +; +;----------------------------------------------------------------------- +; +; Test for character ready to receive, Z = ready +; Error code returned in A register +; *** Error code does not seem to be used *** +; +UF_RCVRDY: + IN A,(0FFH) ; bit 7 = 0 if char avail, = 1 if no char. +UF_RRSP EQU $-1 ; status port + RLCA ; bit 0 = 0 if char avail, = 1 if no char. + AND 00000001B ; A = 0, ZF = 1 if no char, A = 1, ZF = 0 if char avail. + LD A,0 ; no errors + RET +; +;----------------------------------------------------------------------- +; +; Test for ready to send a character, Z = ready +; +UF_SNDRDY: + IN A,(0FFH) ; bit 0 = 0 if space avail, = 1 if full +UF_SRSP EQU $-1 ; status port + AND 00000001B ; A = 0, ZF = 1 if space avail, A = 1, ZF = 0 if full. + RET +; +;----------------------------------------------------------------------- +; +; Report baud rate (index into SPTBL returned in register A) +; +UF_SPEED: + LD A,8 ; arbitrarily return 9600 baud + RET +; + END diff --git a/Source/Apps/ZMD/zmdhdr.z80 b/Source/Apps/ZMD/zmdhdr.z80 new file mode 100644 index 00000000..f5c96da5 --- /dev/null +++ b/Source/Apps/ZMD/zmdhdr.z80 @@ -0,0 +1,637 @@ +; + + TITLE ZMDHDR.Z80 - 09/29/88 - ZMD Configuration Header +; Copyrighted (c) 1987, 1988 +; Robert W. Kramer III + + PAGE +;- -; +; Update History ; +; ; +; Date Release Comments ; +; -------- ------- ---------------------------------------------- ; +; ; +; 09/29/88 v1.50 - Changed file descriptor table. (Sorry, but as ; +; many times as I am required to reassemble the ; +; ZMD system, it saves alot of time for me). ; +; 03/18/88 v1.49 - No change(s) were made to this file ; +; 03/13/88 v1.48 - Added STDBUF switch to enable/disable automatic ; +; calculation of memory available for DBUF. If ; +; enabled, CHKTPA will set OUTSIZ with an even ; +; paged maximum memory comparison word according ; +; to the address contained at location 6 and 7. ; +; The value set as end of program during assembly ; +; is subtracted from it. If BYE is NOT running, ; +; an additional 806H is subtracted. The LSB of ; +; the result is discarded and the new even paged ; +; value is stored for later comparison as maximum ; +; Read/Write memory available for disk buffer ; +; operations. ; +; ; +; * * SPECIAL NOTE * * MOST ALL systems will benefit by enabling this ; +; feature. Some special CP/M systems which place ; +; buffers below location (6 and 7), may need to ; +; disable this feature in which case DBUF size ; +; will be set to 16k. This fix consumed 1 more ; +; byte in the switch/value table below. Previous ; +; configuration headers are incompatible with this; +; release. Additional program code is 9 bytes. ; +; (See explaination at STDBUF:) ; +; ; +; 02/25/88 v1.47 - No change(s) made to configuration file ; +; 01/27/88 v1.46 - No change(s) made to configuration file ; +; 01/17/88 v1.45 - First public release ; +; 11/19/87 v1.00 - Initial version ; +;- -; + +;-------------------------------------------------------------------------; +; Introduction | +;-------------------------------------------------------------------------; +; +; This document is a detailed listing of all the program option toggles +; and their functions within the ZMD environment which when used in +; conjunction with the source listings, install program and reference +; manual, provide all the necessary documentation to support program +; maintenance. + +; +;-------------------------------------------------------------------------; +; EQUates Header | +;-------------------------------------------------------------------------; + + + INCLUDE EQUATES.INS ; Include system constant definitions + +; +;-------------------------------------------------------------------------; +; PUBLIC Declarations: | +;-------------------------------------------------------------------------; + + + PUBLIC ACCMAP,ASKAREA,ASKIND,CLRSCRN,CLRSTR,DESWAIT,DRV + PUBLIC LOCOFF,MHZ,MINKSPD,MSPEED,PAGLEN,PRDRV,PRUSR,USR,WHEEL + PUBLIC WRAP,WRTLOC,CONOUT,MDINST,MDINP,MDOUTST,MDCARCK,MDOUTP + PUBLIC KNDTBL,TYPTBL,MAXTYP,DESCRIB,FORNAM,MSGDESC,DSTAMP + PUBLIC INCLDU,UNINIT,DRIVE,USER,LOGNAM,SETAREA,CLOCK,RTC + PUBLIC TIMEON,CREDIT,EDATE,DSPTOS,STDBUF + +; +;-------------------------------------------------------------------------; +; EXTERNAL Declarations: | +;-------------------------------------------------------------------------; + + + EXTRN MONTH,DAY,YEAR,HOUR,MINUTE,DEST,FILE,ZMDNAM,INSNAM + EXTRN MAPNAM,PRGUTL,PUBFOR,PUBNEW,SYSFOR,PUBFOR,INSNAM + EXTRN SYSNEW,FCBCLR,FCBLOG,TEMPFIL,BCDBIN,TIMBUF,DUD,DUU + +; +;-------------------------------------------------------------------------; +; Program configuration starts here | +;-------------------------------------------------------------------------; +; +; Options that are most often changed are marked with ';*' at the start of +; the comment line for that option. Simple systems not using time clocks, +; user logs, etc. will keep most of those 'NO'. RCPM systems running the +; usual bulletin board systems, etc., will change most of those to 'YES'. +; +MHZ: DB 10 ; Microprocessor speed - use integer 1,4,5, etc. +;MSPEED: DW 003CH ; Location of modem speed indicator byte +MSPEED: DW 0600H ; Location of modem speed indicator byte + ; [WBW] placed in I/O overlay + +WRTLOC: DB NO ; Set/reset WRTLOC so BYE won't hang up. Check +LOCOFF: DB 12 ; your BBS documentation - many modern systems + ; don't need WRTLOC. If unsure, set WRTLOC to NO. + ; Code to set and reset WRTLOC assumes the WRTLOC + ; byte to be located "LOCOFF" bytes from the JP + ; COLDBOOT instruction at the beginning of the BYE + ; BIOS jump table. (YES for MBBS and PBBS). + +STDBUF: DB NO ; If the size of your TPA cannot be calculated by + ; using one of the two following methods, disable + ; this by setting to NO. ZMD will Automatically + ; calculate the maximum disk buffer size allowed. If + ; enabled, CHKTPA will determine whether or not + ; BYE is running, if so uses (0006)-1. Else + ; subtracts 806H from (0006). If disabled, DBUF + ; setting will be used as default (Normally set to + ; 16k). Either way, if descriptions are allowed, + ; the total number of uploads allowed is set based + ; on the value of OUTSIZ divided by maximum bytes + ; per description entry. + +DESWAIT:DB 2 ; This is the number of minutes of inactivity during + ; an upload description or Help Guide prompt before + ; logging aborting the input routine. If the + ; caller was entering a description, the current + ; description buffer is written to disk before + ; resetting your BYE program's disk write lock flag + ; (WRTLOC), if enabled. + +MINKSPD:DB 1 ; Minimum speed acceptable for 1k packet file + ; transfers. If you are on a network such as PC + ; Pursuit, and are able to RECEIVE incoming calls, + ; set this byte to 1. The delays these networks + ; use to send data back and forth make 1k packets + ; advantageous to even 300 bps users. If you are + ; not on a network such as PC Pursuit, it's simply + ; a matter of preference, but why not let the 300 + ; bps callers experience the 1k packet transfers? + ; (1 = 300, 5 = 1200, 6 = 2400, ..., 9 = 19,200) + +BUFSIZ: DB 16 ; Normal disk systems can transfer 16k from + ; computer to disk in 2-3-4 seconds and less. Some + ; very slow 5-1/4" floppy systems (such as North + ; Star) may take up to 20-30 seconds to transfer + ; 16k. This would cause several timeouts at 10 + ; seconds each. If you experience any timeouts, + ; try changing BUFSIZ to something smaller, perhaps + ; 8k or even 4k. + +CLRSCRN:DB NO ; Yes, you want ZMD to clear your screen locally +CLRSTR: DB 1AH,00H ; during display of batch file transfers and all + DB 00H,00H ; the help menus. If you set CLRSCRN to YES, enter + DB 00H,00H ; your clear screen sequence in the 6 bytes aside. + DB '$' ; (If your terminal uses ^Z, leave as is, 1AH = ^Z) + +PAGLEN: DB 24 ; This is the number of lines to display in between + ; [more] pauses. (Set to 0 to disable pauses). + +; +;-------------------------------------------------------------------------; +; Timekeeping Considerations | +;-------------------------------------------------------------------------; +; +; If you have a clock installed (either in your BYE program or internal), +; set the following switches to your liking. If running ZMD without a +; clock, set these all NO. +; +CLOCK: DB NO ; Clock/date reader code installed in BYE program +RTC: DB NO ; Clock/date reader code installed at RTCTIM: + +TIMEON: DB NO ; Restrict downloads to maximum time allowed +MAXMIN: DB 60 ; Total minutes allowed for downloads. This should + ; be set if TIMEON is YES and CLOCK is NO. +DSPTOS: DB NO ; Yes to display 'Online nn minutes' messages +LHOUR: DW 0000H ; Logon hour address (If RTC). LHOUR+2 = logon + ; minute address. + +; +;-------------------------------------------------------------------------; +; Bit Map Layout | +;-------------------------------------------------------------------------; +; +; The following byte contains information corresponding to the filename +; bytes of the file being considered for transfer. Enabling any of the +; options causes ZMD to look at the high bit of the byte position +; indicated below (F1=filename byte 1, T2=file type byte 2, etc). These +; restrictions are always bypassed when using ZCPR and the WHEEL is set. +; +; Bit: 76543210 ; Correspond to definitions below +; |||||||| +ACCMAP: DB 11111101B ; Set any bits of this byte according +; __________\______/ ; to your own preference. +; / +; +; 7 | F1 | File not for distribution. If file is a ARK/ARC/LBR +; | | file, individual members may be downloaded (no Batch) +; 6 | F3 | File can be downloaded regardless of user's access +; 5 | T2 | $SYS files not sent or reported +; 4 | T3 | .??# files with labels not sent +; 3 | T1/2/3 | .COM files not sent or reported +; 2 | T1/2/3 | Rename .COM to .OBJ and .PRL to .OBP on receive +; 1 | -- | RESERVED FOR FUTURE USE +; 0 | T1/2/3 | .SYS, .NDR, .RCP, file extents not accepted. (ZCPR) + +; +;-------------------------------------------------------------------------; +; ZCMD/ZCPR | +;-------------------------------------------------------------------------; +; +; If using ZCPR low memory bytes to keep track of maximum drive and user, +; set USEMAX to yes. ZMD will use the values at locations DRIVMAX and +; USRMAX for maximum drive/user. If USEMAX is NO, hardcode MAXDRV and +; MAXUSR to your own requirements. +; +WHEEL: DW 3EH ; Location of ZCPR wheel byte +USEMAX: DB NO ;*Use values at DRIVMAX and USRMAX for maximum + ; (Else use MAXDRV and MAXUSR values) +DRIVMAX:DW 3DH ; ZCPR maximum drive memory byte +USRMAX: DW 3FH ; ZCPR maximum user memory byte +MAXDRV: DB 16 ; Maximum download drive allowed +MAXUSR: DB 16 ; Maximum download user allowed + +; +;-------------------------------------------------------------------------; +; Access Restrictions | +;-------------------------------------------------------------------------; +; +; If ACCESS is YES, ZMD will inspect AFBYTE (located ACBOFF bytes from JP +; COLDBOOT) for the following flag data: +; +; +; Bit: 7 6 5 4 3 2 1 0 +; | | | | | | | | +; Privileged user ---* | | | | | | | +; Upload -----* | | | | | | +; Download -------* | | | | | * Of these bits, only 3, 5, 6 +; CP/M ---------+ | | | | and 7 are used by ZMD. Bit +; Write -----------* | | | numbers are powers of 2, with +; Read -------------+ | | bit 0 being least significant +; BBS ---------------+ | bit of byte. +; System -----------------+ +; +; +ACCESS: DB NO ;*Yes, your system sets BYE's bit-mapped flag + ; register to restrict user's ability to upload, + ; download, use the 'RM' option to upload message + ; files to your BBS's message base, or to use the + ; 'RW' option for 'privileged user' upload without + ; being required to give upload descriptions. + +ACBOFF: DB 21 ; If you set ACCESS to YES, you 'might' need to + ; set this to reflect the number of bytes from JP + ; COLDBOOT to ACCESS byte. In most cases, leave + ; alone. + +; +;-------------------------------------------------------------------------; +; Upload Configurations | +;-------------------------------------------------------------------------; +; +MSGFIL: DB NO ; Some BBS's allow callers to upload preformatted + ; text files which are appended to the message + ; base. (MBBS and PBBS are examples of this). If + ; you're running MBBS or PBBS and wish to support + ; this, simply set MSGFIL to YES. Message file + ; uploads go to PRDRV and PRUSR. + +HIDEIT: DB NO ; Yes, make all normal uploads $SYS files. This + ; way, new uploads will not appear in a DIRectory + ; listing and cannot be viewed or even downloaded + ; until they are cleared by SYSOP. (New uploads + ; will show up when the WHEEL byte is ON and a $S + ; option is used to show SYSTEM files. Use the $O + ; option to list ONLY $SYS files. Reference will + ; be made to these files in the in the NEW and FOR + ; listings if those features are enabled). Private + ; uploads, and uploads made with the WHEEL byte + ; set are NOT made $SYS. You can use POWER or + ; NSWEEP to set to $DIR. + +; +;-------------------------------------------------------------------------; +; Upload Routing Options | +;-------------------------------------------------------------------------; +; +; The following equates determine what drive/user area uploads will be sent +; to. If you prefer to enable upload routing (ASKAREA set YES), you will +; have to set MAXTYP to the letter of the highest category you wish to +; support, and configure TYPTBL: and KNDTBL: tables below for your own +; system. Do NOT set ASKAREA and SETAREA both to YES. +; +ASKAREA:DB NO ;*Yes, you want upload routing to multiple drive + ; and user areas. The caller will be asked what + ; the file (or files) he is uploading are for and + ; his uploads will then be forwarded to the + ; appropriate area. You will need to set up the + ; categories at KNDTBL: for your own system and + ; set the drive/user area each category belongs on + ; at label TYPTBL:. There can be up to 26 different + ; drive/user and category combinations. This applies + ; for both private and normal uploads. Upload + ; routing is disabled when the WHEEL byte is set, + ; in which case, normal uploads will go to the + ; current drive/user area and private uploads will + ; go to the drive/user equated at PRDRV and PRUSR. + +SETAREA:DB NO ;*Yes, you wish to have all regular uploads sent +DRV: DB 'B' ; to the drive/user equated at DRV and USR to left. +USR: DB 0 ; If WHEEL byte is set, regular uploads will go to + ; the current or specified drive/user. Unless you + ; ASKAREA is YES, all private files uploaded with + ; the 'RP' option will be sent to PRDRV and PRUSR + ; regardless of WHEEL status. + +PRDRV: DB 'H' ;*This is the drive/user area where ALL files sent +PRUSR: DB 15 ;*to the sysop with the 'RP' option will go (unless + ; ASKAREA below is YES). This permits experimental + ; files, replacement and/or proprietary programs to + ; be sent to an area only accessible by the sysop. + ; This is also the drive and user area where message + ; files are uploaded, if MSGFIL is set YES. (If + ; ASKAREA is YES, this is the drive/user where + ; uploads will go when 'RP' is specified, and WHEEL + ; is set). (If MSGDESC is YES, this is the drive + ; and user area the FOR text file will be placed + ; before appending it to the BBS system's message + ; base). + +CREDIT: DB NO ;*Yes, callers are given credit for the amount of + ; time they spend uploading non-private files. A + ; caller who spends 30 minutes sending an upload + ; gets 30 minutes added to his TLOS. (You must + ; set either CLOCK or TIMEON to YES to use this + ; feature). + +; +;-------------------------------------------------------------------------; +; Upload Description Options | +;-------------------------------------------------------------------------; +; +; This section has to do with upload descriptions. If you do not intend +; on implementing upload descriptions, set DESCRIB and MSGDESC to NO. The +; rest of these values are then ignored. If using descriptions, set ONLY +; one of these to YES, not both. +; +MSGDESC:DB NO ; Yes, your BBS system supports message uploads, + ; and you prefer upload descriptions to be placed + ; in your BBS message system (set DESCRIB NO). + ; MBBS users need to install MFMSG.COM with the + ; MBBSINIT program. Then set your BYE program to + ; know about message file uploads by setting the + ; MSGFIL option in BYE/MBYE to YES. If set YES, + ; ZMD will produce a FOR text file when writing + ; upload descriptions. This FOR file will go to + ; the drive and user area equated at PRDRV and + ; PRUSR just before being appended to your BBS + ; system's message base. + +DESCRIB:DB NO ;*Yes, requiring users to provide descriptions for + ; any files they upload. These descriptions will + ; be added to the current FOR file where they can + ; be viewed by callers with the ZFORP utility. + ; Sysop can add new descriptions with the ZFORS + ; utility (See ZMD.WS for more information on ZMD + ; support files). Uploads sent to the SYSOP private + ; upload area will not be require descriptions, nor + ; will files uploaded with the 'RW' option - user + ; must be a privileged user (bit 7 in ACCESS byte + ; set) or have WHEEL access and PUPOPT must be set + ; YES to use the 'RW' option. + +FORNAM: DB 'FOR ' ; Description text file (Must be 11 bytes) +DRIVE: DB 'A' ;*If using with DESCRIB set YES, you must indicate +USER: DB 14 ;*what drive/user you want the 'FOR' file to be + ; placed. + +; +; If DESCRIB above is set to YES, you'll have to tell ZMD what information +; you want included in the first line of each description. Code is included +; in ZMD to place all (any) information in the upload description header in +; in the same column position no matter what the filename or file category +; length is. The following illustrates a full implementation of DESCRIB. +; +; Example upload description header: +; +; ----- +; ZMD150.LBR - Communications (C3:) Rcvd: 09/21/88 +; / / / +; _______/ ______/ _______/ +; ASKIND INCLDU DSTAMP +; +; +ASKIND: DB NO ;*Yes, ask for the category of uploads and write it + ; into the upload description header. If you set + ; this to YES, make sure you set MAXTYP below to + ; the highest letter choice you wish to support and + ; edit the text at KNDTBL: up to and including your + ; MAXTYP setting. (Used only with DESCRIB). + +INCLDU: DB YES ;*Yes, include the drive/user area of the uploaded + ; file into the upload description header. + ; (Used only with DESCRIB). + +DSTAMP: DB YES ;*Yes, include the date the upload was received into + ; the upload description header. (NO if no clock) + ; (Used only with DESCRIB). + +PUPOPT: DB YES ;*Yes, description request of file upload will be + ; skipped when "RW" is used in the ZMD command line + ; (i.e. ZMD RW FILE.EXT). This command may only be + ; used by those considered "priviledged" users on + ; your system or WHEEL users. Uploads of this type + ; will be tagged in the ZMD.LOG file as private, so + ; as not to display with the NEW command. (See + ; ACCESS equate description above for information + ; on 'priviledged' users). + +WRAP: DB 64 ; Column position where word wrap will occur. If + ; you are using MSGDESC and have problems with an + ; 'Invalid format' error from MFMSG.COM, try setting + ; WRAP to something smaller, like 62 or 63. (Word + ; wrap can be disabled by the user with ^W during + ; description entry. Enter 72 here to disable + ; completely). + +; +;-------------------------------------------------------------------------; +; Special Sysop Downloads | +;-------------------------------------------------------------------------; +; +SPLDRV: DB 'H' ;*Drive/user area for downloading private files +SPLUSR: DB 14 ;*from sysop. This permits him to put a special + ; file in this area, then leave a private note + ; to that person mentioning the name of the file + ; and how to download it (ZMD SP filename.ext). + ; Although anybody 'could' download that program, + ; they don't know what (if any) files are there. + ; A high degree of security exists, while the + ; SYSOP still has the ability to make special + ; files available. Thus any person can be a + ; temporary 'privileged user'. + +; +;-------------------------------------------------------------------------; +; File Transfer Log | +;-------------------------------------------------------------------------; +; +LOGCAL: DB NO ;*ZMD.LOG is produced if LOGCAL is set YES. All + ; file transfers are logged. You can then use + ; ZNEWP.COM to show listings of recent uploads. +EDATE: DB NO ; Yes, show date in ZMD.LOG in dd/mm/yy format + ; instead of mm/dd/yy format. + +LOGNAM: DB 'ZMD LOG' ; File transfer log (Must be 11 bytes) +LOGDRV: DB 'A' ;*Drive to find ZMD.LOG on. +LOGUSR: DB 14 ;*User area to find ZMD.LOG on. + +LSTCLR: DB 'LASTCALR???' ; Last caller file (Must be 11 bytes) +LASTDRV:DB 'A' ;*Drive to find LASTCALR??? file on. +LASTUSR:DB 14 ;*User area to find LASTCALR??? file on. +LCNAME: DB 0 ;*Position of last caller's name in the LASTCALR??? + ; file. (MBBS is 11, PBBS is 0). + +LOGLDS: DB NO ;*Count number of up/down loads since login. Your +UPLDS: DW 0054H ; BBS program can check UPLDS and DNLDS when a user +DNLDS: DW 0055H ; logs out and update either the user's file or a + ; file for this purpose. You can either modify + ; your BBS entry program to check the LASTCALR file + ; before updating and then update (risky), or make + ; a separate program that BYE calls when logging off + ; a user (preferred). (YES for PBBS). Clear UPLDS + ; and DNLDS to 0 from your BBS program when somebody + ; logs in. NOTE: Clear ONLY when a user logs in, + ; not when he re-enters the BBS program from CP/M. + +; +;-------------------------------------------------------------------------; +; File Descriptors | +;-------------------------------------------------------------------------; +; +; This table defines the text to be included in upload description headers +; (DESCRIB and ASKIND) and/or defines categories for uploading to multiple +; drive/user areas (If ASKAREA and NOT SETAREA). Change as desired, if +; this list is not suitable. Do NOT remove any of the text at KNDTBL:. +; Simply edit the text below up to/and including your MAXTYP setting. +; MAXTYP below must be set to whatever letter your maximum choice will be. +; Make sure you leave all the following categories EXACTLY 31 bytes long +; (29 bytes of text plus the CR,LF equals 31) or you will be CERTAIN to +; have problems with the double column formatting later on in the program. +; +MAXTYP: DB 'W' ; Letter of highest category you will support. + +KNDTBL: DB ' A) - BBS Lists, PC Pursuit ',CR,LF + DB ' B) - CP/M Modem Program ',CR,LF + DB ' C) - CP/M Utility ',CR,LF + DB ' D) - CP/M Lbr, Ark, Catalog',CR,LF + DB ' E) - CP/M Plus Specific ',CR,LF + DB ' F) - CP/M Games & Humor ',CR,LF + DB ' G) - CP/M Wordprocessing ',CR,LF + DB ' H) - CP/M Printer Utility ',CR,LF + DB ' I) - CP/M OS Enhancement ',CR,LF + DB ' J) - CP/M BBS Software ',CR,LF + DB ' K) - CP/M Assemb/Disassemb ',CR,LF + DB ' L) - CP/M Language (Other) ',CR,LF + DB ' M) - Turbo Pascal ',CR,LF + DB ' N) - dBase & Database ',CR,LF + DB ' O) - "C" ',CR,LF + DB ' P) - Text & Information ',CR,LF + DB ' Q) - DOS Modem Program ',CR,LF + DB ' R) - DOS BBS Software ',CR,LF + DB ' S) - DOS Language ',CR,LF + DB ' T) - DOS Assemb/Disassemb ',CR,LF + DB ' U) - DOS Lbr, Arc, Catalog ',CR,LF + DB ' V) - DOS Wordprocessing ',CR,LF + DB ' W) - DOS Printer Utility ',CR,LF + DB ' X) - DOS Games & Humor ',CR,LF + DB ' Y) - DOS Application ',CR,LF + DB ' Z) - DOS Utility ',CR,LF + DB 0 ; leave the table terminator alone. + +; +;-------------------------------------------------------------------------; +; Upload Routing Table | +;-------------------------------------------------------------------------; +; +; If ASKAREA is set YES, then set these areas up to match the message text +; in KNDTBL: above. Note that PRIVATE uploads may be sent to a different +; drive as well as a different user area. Each entry is expressed as +; 'drive letter',user area. Simply set MAXTYP above to the highest +; letter choice supported. (Do NOT comment out any of the following +; storage bytes). +; +; _________ +; NOTE: / A \ <--- 'A' Corresponds to category 'A' above +; 'A',1,'B',15, +; \ / \ / +; Normal upload --+ | +; Private upload -------+ +; + +TYPTBL: +; _________ _________ _________ _________ +; / A \ / B \ / C \ / D \ + DB 'B',1,'F',15, 'B',0,'F',15, 'B',2,'F',15, 'B',4,'F',15 +; _________ _________ _________ _________ +; / E \ / F \ / G \ / H \ + DB 'B',5,'F',15, 'B',6,'F',15, 'C',0,'F',15, 'C',1,'F',15 +; _________ _________ _________ _________ +; / I \ / J \ / K \ / L \ + DB 'C',2,'F',15, 'C',3,'F',15, 'A',1,'F',15, 'A',5,'F',15 +; _________ _________ _________ _________ +; / M \ / N \ / O \ / P \ + DB 'A',2,'F',15, 'A',3,'F',15, 'A',4,'F',15, 'A',6,'F',15 +; _________ _________ _________ _________ +; / Q \ / R \ / S \ / T \ + DB 'E',0,'F',15, 'E',1,'F',15, 'E',2,'F',15, 'E',3,'F',15 +; _________ _________ _________ _________ +; / U \ / V \ / W \ / X \ + DB 'F',0,'F',15, 'F',1,'F',15, 'F',2,'F',15, 'F',3,'F',15 +; _________ _________ +; / Y \ / Z \ + DB 'G',0,'F',15, 'H',0,'F',15 + +; +;=========================================================================; +;>>>>>>>>>>>>>> DO NOT CHANGE ANYTHING BEYOND THIS POINT <<<<<<<<<<<<<<<| +;=========================================================================; +;-------------------------------------------------------------------------; +; Version Identification | +;-------------------------------------------------------------------------; +; +; If/when INSTALL is first ran, it checks these next 3 bytes to make sure +; it is installing the proper version of ZMD.COM. If these bytes do not +; match, the INSTALL procedure will abort. (Don't change this one) +; +INSVERS:DB '150' ; Don't change this one + +; +;-------------------------------------------------------------------------; +; User Definable Storage Bytes | +;-------------------------------------------------------------------------; +; +; If you make changes to the configuration table, make them here. You +; are allowed 2 bytes for switches, or storage for an address, etc. Any +; changes before this point and ZINSTL will not run. +; +SPARE1: DB 0 ; User definable storage +SPARE2: DB 0 + +; +;-------------------------------------------------------------------------; +; Clock/Date Reader Code | +;-------------------------------------------------------------------------; +; +; Install your clock/date reader code here. RTCTIM gets called to retrieve +; the current date and time. All values must be stored in binary form. +; A 6 byte clock buffer called TIMBUF can be used as a work area. Call +; BCDBIN to convert your BCD (Binary Coded Decimal) value in A to binary +; value in A. Delete all ';<=' lines; after installing your custom +; routine. +; + ORG 4FEH ; Allow 130 bytes for RTC insert +; +RTCTIM::LD A,0 ;<= Delete lines if reader code installed + LD (MONTH),A ;<= Current month (1-12) + LD (DAY),A ;<= Current date (1-31) + LD (YEAR),A ;<= Current year (0-99) + LD (MINUTE),A ;<= Current minute (0-59) + LD (HOUR),A ;<= Current hour (0-23) + RET + +; +;-------------------------------------------------------------------------; +; Input/Output Patch Area | +;-------------------------------------------------------------------------; + + ORG 580H ; Modem routine starts here + +CONOUT: JP 0000H ; BIOS local console output routine address +MINIT: JP 0000H ; Startup initialization routine +UNINIT: JP 0000H ; Exit uninitialize routine +MDOUTP: JP 0000H ; Send character out modem +MDCARCK:JP 0000H ; Test for carrier +MDINP: JP 0000H ; Get character from modem +MDINST: JP 0000H ; Check receive ready +MDOUTST:JP 0000H ; Check send ready + + ;ORG 600H ; Allow 128 bytes for I/O overlay + ORG 1000H ; Allow for large I/O overlay + + +; +; Overlay ends here +; + \ No newline at end of file diff --git a/Source/Apps/ZMD/znewp.z80 b/Source/Apps/ZMD/znewp.z80 new file mode 100644 index 00000000..56f8750f --- /dev/null +++ b/Source/Apps/ZMD/znewp.z80 @@ -0,0 +1,517 @@ +; + + TITLE ZNEWP.Z80 - 09/29/88 - ZMD Public Transfer Log Utility +; Copyrighted (c) 1987, 1988 +; Robert W. Kramer III + +;- -; +; Update History ; +; ; +; Date Release Comments ; +; -------- ------- ---------------------------------------------- ; +; ; +; 09/29/88 v1.50 - No change(s) made to this file ; +; 03/18/88 v1.49 - No change(s) made to this file ; +; 03/13/88 v1.48 - Redefined buffer table at end of programs. STACK; +; and filename buffers now EQUated with offsets ; +; from the last switch/toggle in program instead ; +; of with DS directive. ; +; - Some systems which do NOT have an interrupt ; +; driven keyboard may have noticed problems when ; +; an invalid key was entered in the ZNEWP, ZFORP ; +; and ZMDEL programs. In ZNEWP and ZFORP, if a ; +; CR was entered to pause the output, output was ; +; limited to one line at a time per key pressed. ; +; If an invalid key was hit, output would have ; +; remained in a paused state until one of the ; +; abort keys were pressed. This was difficult to ; +; find since my keyboard is interrupt driven and ; +; I could not duplicate the problem on my own ; +; system. ; +; 02/25/88 v1.47 - Fixed to determine if CLOCK is enabled before ; +; inserting spaces after 8 'date' positions. ; +; (Keeps caller name from being split with an ; +; extra space at column 52). ; +; 01/27/88 v1.46 - Now uses BDOS call 35 to calculate virtual size ; +; of log file (in records) which is returned in ; +; bytes 33 and 34 of log FCB. It then uses BDOS ; +; call 33 to compute the extent of the specified ; +; record number (bytes 33 and 34 of log FCB), ; +; decrements the record number for next random ; +; read and displays current record. This method ; +; of reading the log file allows for files up to ; +; 8,388,480 bytes in size to be displayed at an ; +; instant. ; +; 01/17/88 v1.45 - First public release ; +; 11/01/87 v1.00 - Initial version ; +;- -; + +;-------------------------------------------------------------------------; +; EXTERNAL Declarations: | +;-------------------------------------------------------------------------; + + + EXTRN CKABRT,CLEARIT,DBUF,ERXIT,EXIT,ILPRTB,LINCNT,MODE + EXTRN NOFILE,NOLOG,OLDDRV,OLDUSR,PRINTV,PRIVATE,RECAR1 + EXTRN RECDR1,RENFCB,RSDMA,SHONM4,STACK,TYPE,WHLCHK + +; +;-------------------------------------------------------------------------; +; Program Starts Here | +;-------------------------------------------------------------------------; + + + .Z80 + ASEG + ORG 100H ; Program starts + JP BEGIN ; Jump around configuration table + INCLUDE ZMDHDR.Z80 ; Include the ZMD header overlay + .REQUEST ZMDSUBS ; Include the ZMD subroutines + +; +; +; Save CP/M stack, initialize new one for this program +; +BEGIN: LD (STACK),SP ; Save return address to CCP + LD SP,STACK ; Initialize new one for this program + +; +; Get current drive/user +; + LD A,255 ; Get current user + CALL RECAR1 + LD (OLDUSR),A ; Store it + LD C,CURDRV ; Get current drive + CALL BDOS + LD (OLDDRV),A ; Store it + +; +; Tell em who we are +; + LD A,255 ; Need this so discrepency check will + LD (MODE),A ; Leave clock settings alone in case local + LD HL,PUBNEW ; Point to this filename + CALL PRINTV ; Display it + + LD A,(LOGCAL) ; See if log file enabled + OR A + JP Z,NOLOG ; Don't run program if not + + CALL ILPRTB + DB '(S to Pause - C K or X Abort)' + DB CR,LF,LF + DB 0 + + LD A,9 ; Leave program name on first screen + LD (LINCNT),A + +; +; If WHEEL byte set, check to see if 'A' specified in command tail. If +; it is, set switch to display entire transfer log +; + CALL WHLCHK ; WHEEL byte set? + JP Z,BEGIN2 ; No don't look for options + LD A,(FCB+1) ; Get possible option + CP 'A' ; Want to show all of file? + JP NZ,BEGIN2 ; No + LD A,1 + LD (SHOWALL),A ; Set to show all entries + LD A,8 + LD (LINCNT),A + +; +; See if user wants file displayed 'nonstop' ($N) +; +BEGIN2: LD HL,FCB+1 ; Get first character on command line + LD A,(HL) ; Into A + CP '$' ; Must specify '$' first + JP NZ,OPNLOG ; Nope, continue normal + INC HL ; Point to next byte + LD A,(HL) ; Into A for comparison + CP 'N' ; 'N' for nonstop display? + JP NZ,OPNLOG ; No + LD A,0 + LD (PAGLEN),A ; Else disable page pauses + +; +; Set drive/user to the log file area and open ZMD.LOG +; +OPNLOG: LD A,(LOGUSR) ; Set user area to ZMD.LOG area + CALL RECAR1 + LD A,(LOGDRV) ; Set drive to ZMD.LOG area + CALL RECDR1 + + LD HL,FILE ; Destination is internal FCB + LD DE,LOGNAM ; For log filename + CALL RENFCB ; Initialize and rename + + LD DE,FILE + LD C,OPEN ; Open log file + CALL BDOS + INC A ; Check for no open + LD HL,FILE+1 + JP Z,NOFILE ; No file, exit + +; +; See if special sysop access was allowed/requested. Display enabled +; message if so. +; + LD A,(SHOWALL) ; Showing entire transfer log? + OR A + JP Z,SHOHDR ; No, display header as usual + CALL ILPRTB + DB CR + DB '-- Sysop access enabled --',0 + JP CALCSIZ + +; +; Display all applicable field titles +; +SHOHDR: CALL ILPRTB + DB CR + DB 'D/u Filename Size Speed ',0 + + LD A,(CLOCK) + OR A + JP Z,SHOHDR1 + CALL ILPRTB + DB ' Date Time ',0 + +SHOHDR1:CALL ILPRTB + DB ' Uploaded by' + DB CR,LF,0 + +; +; Get number of records in log file +; +CALCSIZ:LD DE,FILE ; Point to log FCB + LD C,FILSIZ ; Compute file size function + CALL BDOS + LD DE,DBUF+81 ; Point to beggining of write buffer + LD A,CR + LD (DE),A ; Force first CR + DEC E + +; +; Decrement number of records left. If any left, read on into write +; buffer, otherwise close file and exit +; +NXTRCD: PUSH DE ; Save write buffer address + LD HL,FILE+33 ; Get current record counter + LD E,(HL) ; LSB record count + INC HL + LD D,(HL) ; MSB record count + DEC DE ; Decrement it + LD (HL),D ; Put it back + DEC HL + LD (HL),E + LD A,E + CP 0FFH ; Any more records? + JP NZ,RDRCD ; Yes, go read it + LD A,D ; Maybe not, check MSB + CP 0FFH ; Any more? + JP Z,TDONE ; No, all done + +; +; Read a record from source file +; +RDRCD: CALL RSDMA ; Reset DMA to 80H + LD DE,FILE + LD C,RRDM ; Random read + CALL BDOS + POP DE ; Get write buffer address back + OR A ; Read ok? + JP NZ,RDERR ; Yes + LD HL,TBUF+127 ; End address of read buffer + LD B,128 ; Buffer is filled backwards + +; +; Write record from disk to memory (in reverse order) +; +WRTBYT: LD A,(HL) ; Get byte from read buffer + AND 7FH ; Strip parity bit + CP LF ; End of line? + JP Z,DSPLIN ; Yes, show it if supposed to + CP 7FH ; Del (rubout)? + JP Z,NXTBYT ; Yes, ignore it + CP EOF ; End of file marker? + JP Z,NXTBYT ; Yes, ignore it + LD (DE),A + DEC E ; Decrement write buffer pointer + +NXTBYT: DEC L ; Decrement read buffer pointer + DJNZ WRTBYT ; And character count, get next if any left + JP NXTRCD ; Else read another record + +; +; Found end (CR) of current entry. Display it. +; +DSPLIN: DEC B ; Decrement character counter + PUSH AF ; Save flags + DEC L ; Decrement write buffer pointer + PUSH HL ; Save write address + PUSH BC ; Save character count + EX DE,HL ; HL now contains current buffer read address + LD (HL),A ; Store the LF + + LD A,(SHOWALL) ; Show entire file? + OR A + JP NZ,NEXT ; Yes + + INC L ; Else next character is transfer mode + LD A,(HL) ; Get it + DEC L ; Restore read pointer + CP 'R' ; Uploaded entry? + JP NZ,SENDLF1 ; No, ignore it and reset pointers + +; +; Get next character from read buffer. If end of line, go display CR,LF. +; +NEXT: INC L ; Increment next read byte + LD A,(HL) ; Get character + LD B,A ; Into B + CP CR ; End of line? + JP Z,SENDLF ; Yes, send a CR,LF and reset pointers + + LD A,(COLUMN) ; Get column count + CP 79 ; End of line? + JP Z,DSPLP2 ; Yes, start new line + OR A ; At beginning of line? + JP NZ,DSPLP3 ; No, continue + INC A + LD (COLUMN),A ; We aren't anymore + + LD A,B ; Get the character back + LD (STORE),A ; Store it for later comparison + + CP 'P' ; This entry private upload? + JP NZ,DSPLP1 ; No, check for regular upload + LD A,(SHOWALL) ; Yes, were we supposed to show entire file? + OR A + JP Z,DSPLP2 ; No, so ignore it + LD (PRIVATE),A ; Set private flag + JP DSPLP4 ; Go show it + +DSPLP1: CP 'R' ; Regular upload? + JP Z,DSPLP4 ; Yes, keep the flag set + + LD A,(SHOWALL) + OR A + JP NZ,DSPLP4 + + XOR A + LD (STORE),A + LD (COLUMN),A ; Start in column 0 + JP NEXT + +DSPLP2: XOR A + LD (STORE),A ; Otherwise reset flag to zero + +DSPLP3: LD A,(STORE) ; Storing into memory? + OR A + JP Z,NEXT ; If not, exit + +DSPLP4: LD A,(COLUMN) ; Increment the column counter + INC A + LD (COLUMN),A + + CP 3 ; User's modem speed is in column 2 + JP NZ,DSPLP5 ; If not column 2, continue + LD A,B ; Otherwise get the character + LD (STORE),A ; Store it for conversion to baud rate + JP NEXT ; Do not print the "MSPEED" number + +DSPLP5: CP 11 + JP C,NEXT ; Skip everything through column 10 + +; +; Display drive and user of file +; + CP 14 + JP C,SEND ; Print everything through column 13 + JP NZ,DSPFN + +; +; If a private file, make a special note of it +; + LD A,(PRIVATE) ; Private entry? + OR A + JP Z,DSPDU ; No + + XOR A ; Reset flag for next time + LD (PRIVATE),A + LD A,'*' ; Displays entry is private + CALL TYPE + LD B,' ' ; Keep our distance from next field + JP SEND + +DSPDU: LD A,':' ; Stick in a colon after column 12 + CALL TYPE + LD B,' ' ; Send a space + JP SEND + +; +; Display filename and extent +; +DSPFN: CP 22 ; Print through column 20 + JP C,SEND + JP NZ,DSPFT + LD A,B + CALL TYPE ; Send character in colum 21 + LD B,'.' ; Add a period after the file name + JP SEND + +DSPFT: CP 27 + JP C,SEND ; Print file type and some spaces + CALL Z,PRTSPC + CP 39 + JP C,NEXT ; Ignore the "big gap" + CP 43 + JP C,SEND ; Print the file size + JP Z,DSPBD + JP DSPDAT + +; +; Display the baud rate (300-19200 bps) +; +DSPBD: PUSH HL + LD A,(STORE) + CP '1' + JP Z,B300 + CP '5' + JP Z,B1200 + CP '6' + JP Z,B2400 + CP '7' + JP Z,B4800 + CP '8' + JP Z,B9600 + CP '9' + JP Z,B19200 + CALL ILPRTB + DB ' ',0 + POP HL + JP NEXT ; Go get next byte from read buffer + +B300: CALL ILPRTB + DB ' 3',0 + JP BFINISH + +B1200: CALL ILPRTB + DB ' 12',0 + JP BFINISH + +B2400: CALL ILPRTB + DB ' 24',0 + JP BFINISH + +B4800: CALL ILPRTB + DB ' 48',0 + JP BFINISH + +B9600: CALL ILPRTB + DB ' 96',0 + JP BFINISH + +B19200: CALL ILPRTB + DB ' 192',0 + +BFINISH:CALL ILPRTB + DB '00 bps ',0 + POP HL + JP NEXT + +; +; Display time and date +; +DSPDAT: LD A,(CLOCK) ; Clock enabled? + OR A + LD A,(COLUMN) + JP Z,SEND ; No, leave caller's name alone + CP 52 + JP C,SEND ; Print the date + JP NZ,DSPTIM + CALL PRTSPC ; Keep our distance from next field + JP SEND + +DSPTIM: CP 58 + JP C,SEND ; Print the time + JP NZ,SEND + CALL PRTSPC ; Keep our distance from next field + +; +; Display character in B +; +SEND: LD A,B ; Get the character back + CALL TYPE ; Display it + JP NEXT + +; +; Reached end of entry. Send CR,LF and reset pointers +; +SENDLF: LD A,CR ; Output CR + CALL TYPE + LD A,LF ; And LF for next line + CALL TYPE + XOR A ; Enable page pauses for output + JP $+5 + +SENDLF1:LD A,1 + CALL CKABRT ; Check for aborts/pauses + XOR A ; Start new line + LD (COLUMN),A ; And indicate column 0 + LD DE,DBUF+80 ; Beginning of write buffer again + POP BC ; Number of characters left in buffer + POP HL ; Current read buffer address + POP AF ; Were there any characters left? + JP Z,NXTRCD ; No, get next record + JP WRTBYT ; Else get next character + +; +; S u b r o u t i n e s +;----------------------- +; +; Routine to display a space - saves character in A on entry +; +PRTSPC: PUSH AF + LD A,' ' + CALL TYPE + POP AF + RET + +; +; Transfer is done - close destination file +; +TDONE: LD C,CLOSE + LD DE,FILE + CALL BDOS + CALL ERXIT + DB CR,LF + DB '-- End of listing','$' + +; +RDERR: CALL ILPRTB + DB CR,LF + DB '-- Read Error: ',0 + LD HL,FILE+1 + CALL SHONM4 + JP EXIT + +; +; +; These next are just to satisfy ZMDSUBS external requests. Leave alone. +; +DONE:: JP EXIT +TIME:: RET +; +; +; Initialized storage area +;-------------------------- +; +COLUMN: DB 0 ; Column of ZMD.LOG line +STORE: DB 0 +SHOWALL:DB 0 ; 1=all transfers, 0=uploads only + + + END + \ No newline at end of file diff --git a/Source/Apps/ZMD/znews.z80 b/Source/Apps/ZMD/znews.z80 new file mode 100644 index 00000000..12fdb725 --- /dev/null +++ b/Source/Apps/ZMD/znews.z80 @@ -0,0 +1,298 @@ +; + + TITLE ZNEWS.Z80 - 09/29/88 - ZMD Sysop Transfer Log Utility +; Copyrighted (c) 1987, 1988 +; Robert W. Kramer III + + PAGE +;- -; +; Update History ; +; ; +; Date Release Comments ; +; -------- ------- ---------------------------------------------- ; +; ; +; 09/29/88 v1.50 - Fixed problem that caused a 'ZMD .L$$' file ; +; to not be deleted from directory after aborted ; +; sessions. ; +; - Also, was moving 9 filename bytes intead of 8, ; +; this is what caused the mysterious filename of ; +; '.L$$' as mentioned above. The filename left ; +; in the directory should have been '.$$$'. ; +; - Some minor cosmetic changes. ; +; 03/18/88 v1.49 - No change(s) made to this file ; +; 03/13/88 v1.48 - Redefined buffer table at end of programs. STACK; +; and filename buffers now EQUated with offsets ; +; from the last switch/toggle in program instead ; +; of with DS directive. ; +; 02/25/88 v1.47 - No change(s) made to this file +; 01/27/88 v1.46 - Some changes were made to ZMDSUBS file that are ; +; not directly related to this file ; +; 01/17/88 v1.45 - First public release ; +; 11/19/87 v1.00 - Initial version ; +;- -; + +; +;-------------------------------------------------------------------------; +; EXTERNAL Declarations: | +;-------------------------------------------------------------------------; + + + EXTRN CASEFLG,CKABRT,CLEARIT,CMDBUF,DESC,DSTOR,DSTOR1,ERXIT + EXTRN EXIT,ILPRTB,INPUT,LNLNGTH,NOFILE,NOLOG,NOROOM,OLDDRV + EXTRN OLDUSR,OLINE,PRINTV,RECAR1,RECDR1,RENFCB,RERROR,RSDMA + EXTRN SHONM4,STACK,TDONE,UCASE + +; +;-------------------------------------------------------------------------; +; Program Starts Here | +;-------------------------------------------------------------------------; + + + .Z80 + ASEG + ORG 100H ; Program starts + JP BEGIN ; Jump around configuration table + INCLUDE ZMDHDR.Z80 ; Include the ZMD header overlay + .REQUEST ZMDSUBS ; Include the ZMD subroutines + +; +; +; Save CP/M stack, initialize new one for this program +; +BEGIN: LD (STACK),SP ; Save current CCP stack address + LD SP,STACK ; Initialize new one for this program + +; +; Get current drive/user area and store for later +; + LD A,255 ; Get current user area + CALL RECAR1 + LD (OLDUSR),A ; Save it + LD C,CURDRV ; Get current drive + CALL BDOS + LD (OLDDRV),A ; Save it + +; +; Display program name, version, and copyright notice +; +BEGIN1: LD HL,SYSNEW + CALL PRINTV + + LD A,(LOGCAL) ; Log file enabled? + OR A + JP Z,NOLOG ; No, then don't run program + + LD A,(GOTLAST) ; Already located last entry? + OR A + JP NZ,GTNEW ; Yes, then just show it + LD (DESWAIT),A ; Disable sleepy caller time out + + CALL ILPRTB + DB 'Working.',0 + +; +; Log into log file drive/user +; + LD A,(LOGUSR) ; User area to find ZMD.LOG + CALL RECAR1 + LD A,(LOGDRV) ; Drive to find ZMD.LOG + CALL RECDR1 + +; +; Open 'ZMD .LOG' file +; + LD DE,LOGNAM ; Current log filename + LD HL,FILE ; Internal FCB + CALL RENFCB ; Initialize + + LD DE,FILE + LD C,OPEN ; Open log file + CALL BDOS + INC A ; ZMD.LOG file exist? + LD HL,LOGNAM + JP Z,NOFILE ; No, inform user and exit to CP/M + +; +; Open 'ZMD .$$$' file +; + LD DE,TEMPFIL ; Current '$$$' filename + LD HL,DEST ; Internal FCB + CALL RENFCB ; Initialize + + LD HL,FILE+1 ; Point to log filename + LD DE,DEST+1 ; And temporary filename + LD BC,8 ; Set to move filename bytes only + LDIR + + LD C,OPEN ; Open new log file + LD DE,DEST + CALL BDOS + INC A ; Did file already exist? + + LD C,DELETE ; Prepare for delete + LD DE,DEST + CALL NZ,BDOS ; Yes, delete existing file + + LD C,MAKE ; Make new temporary file + LD DE,DEST + CALL BDOS + INC A + LD HL,DEST+1 + JP Z,NOROOM ; Exit if no more disk space + +; +; Read record from ZMD.LOG file +; + LD DE,CMDBUF ; Point to last log entry buffer + +RDRECD: PUSH DE ; Save current buffer position + CALL RSDMA ; Reset DMA + LD DE,FILE + LD C,READ + CALL BDOS + POP DE ; Last entry buffer address + OR A ; Read ok? + JP NZ,RERROR ; No + +; +; Now look for the end of the file overwriting OLINE with each entry found +; (from LF to LF). Upon ^Z (EOF) display last entry and get prompt for new +; one +; + LD HL,TBUF + +WRDLP: LD A,(HL) ; Get a character + AND 7FH + CP 7FH ; Delete character? + JP Z,NEXT ; Yes, don't store this character + + CP EOF ; End of file? + JP Z,GTNEW ; Yes, display last entry and get new one + + LD (DE),A ; Else store character in last entry buffer + INC DE ; Next positition in last entry buffer + CP LF ; Was it a line feed? + JP NZ,NEXT ; No, get next character + +; +; Check periodically (every LF) for user abort +; + LD A,1 ; Disable page pausing + CALL CKABRT ; Check for user requests + LD A,'$' ; Terminator for BDOS print function + LD (DE),A ; At end of last entry string + + PUSH HL + LD HL,CMDBUF + CALL DSTOR1 + POP HL + LD DE,CMDBUF + +NEXT: INC L + JP Z,RDRECD + JP WRDLP + +; +; Get new entry to ZMD.LOG. First display the last entry added to the file +; for use as a typing guide. +; +GTNEW: CALL ILPRTB + DB CR + DB 'Current format of ',0 + + LD HL,LOGNAM ; Point to log filename + CALL SHONM4 + + CALL SHWLAST ; Show last entry in log file + LD A,1 + LD (GOTLAST),A ; Show we've found/displayed last entry + +; +; Get the new entry. Process input - CR terminates entry. +; + LD A,79 + LD (LNLNGTH+1),A ; Set for up to 79 character string + LD (WRAP),A ; Disable word wrap + LD (CASEFLG),A ; Convert all input to uppercase + CALL DESC ; Go get string + LD A,0 + LD (CASEFLG),A ; Disable uppercase lock + JP Z,NOCHANG ; Z=CR entered on blank line + LD (HL),'$' ; Place a '$' for BDOS print function + +; +; Done with entry, ask for verification before writing to disk +; + CALL ILPRTB + DB CR,LF + DB ' Repeating to verify:',0 + + CALL SHWLAST ; Show last entry + LD DE,OLINE ; Point to new entry buffer + LD C,PRINT ; BDOS print function + CALL BDOS + + CALL ILPRTB + DB CR,LF + DB 'Correct? (Y/N): ',0 + +GETOK1: CALL INPUT ; Get repsonse + CALL UCASE ; Convert to uppercase + CP 'N' ; No? + JP NZ,GETOK2 ; Yes, all done + + CALL ILPRTB + DB 'No.' + DB CR,LF,0 + JP BEGIN1 + +GETOK2: CP 'Y' ; Yes? + JP NZ,GETOK1 ; Loop until we get a yes or no + + CALL ILPRTB + DB CR + DB 'Writing log entry to ',0 + LD HL,LOGNAM + CALL SHONM4 + CALL ILPRTB + DB '...',0 + CALL DSTOR ; Go store it in disk buffer + JP TDONE ; Transfer to disk +; +; +;------------------- +; UTILITIES SECTION +;------------------- +; +NOCHANG:CALL ILPRTB ; Else nothing typed, abort + DB CR,LF + DB '-- Log entry aborted... ',0 + + LD C,DELETE + LD DE,DEST + CALL BDOS ; Clean up (Erase 'ZMD .$$$' file) + + JP EXIT + +; +; Show last entry in ZMD.LOG file +; +SHWLAST:CALL ILPRTB + DB CR,LF,LF,0 + LD DE,CMDBUF ; Point to last entry buffer + LD C,PRINT ; BDOS print function + JP BDOS + +; +; These next are just dummy routines to satisfy external ZMDSUBS requests. +; They do nothing but leave alone. +; +DONE:: JP EXIT +TIME:: RET + + +GOTLAST:DB 0 + + + END + \ No newline at end of file diff --git a/Source/Images/Build.cmd b/Source/Images/Build.cmd index 5288225f..f2e81edb 100644 --- a/Source/Images/Build.cmd +++ b/Source/Images/Build.cmd @@ -1,13 +1,16 @@ @echo off setlocal +::call BuildDisk.cmd bp wbw_hd512 || exit /b +::goto :eof + echo. echo Building Floppy Disk Images... echo. call BuildDisk.cmd cpm22 wbw_fd144 ..\cpm22\cpm_wbw.sys || exit /b call BuildDisk.cmd zsdos wbw_fd144 ..\zsdos\zsys_wbw.sys || exit /b ::call BuildDisk.cmd nzcom wbw_fd144 ..\zsdos\zsys_wbw.sys || exit /b -call BuildDisk.cmd cpm3 wbw_fd144 ..\cpm3\cpmldr.sys || exit /b +::call BuildDisk.cmd cpm3 wbw_fd144 ..\cpm3\cpmldr.sys || exit /b ::call BuildDisk.cmd zpm3 wbw_fd144 ..\cpm3\cpmldr.sys || exit /b call BuildDisk.cmd ws4 wbw_fd144 || exit /b diff --git a/Source/Images/Makefile b/Source/Images/Makefile index 0bb2a201..7f5a082e 100644 --- a/Source/Images/Makefile +++ b/Source/Images/Makefile @@ -3,8 +3,7 @@ # SYSTEMS = ../CPM22/cpm_wbw.sys ../ZSDOS/zsys_wbw.sys ../CPM3/cpmldr.sys -FDIMGS = fd144_cpm22.img fd144_zsdos.img \ - fd144_cpm3.img fd144_ws4.img +FDIMGS = fd144_cpm22.img fd144_zsdos.img fd144_ws4.img HD512IMGS = hd512_cpm22.img hd512_zsdos.img hd512_nzcom.img \ hd512_cpm3.img hd512_zpm3.img hd512_ws4.img # HDIMGS += hd512_bp.img diff --git a/Source/Images/d_bp.txt b/Source/Images/d_bp.txt index 82cf1a97..e6ce4a2b 100644 --- a/Source/Images/d_bp.txt +++ b/Source/Images/d_bp.txt @@ -31,6 +31,8 @@ ../../Binary/Apps/zmterm.ovr 15: ../../Binary/Apps/zminit.ovr 15: ../../Binary/Apps/zmconfig.ovr 15: +../../Binary/Apps/zmd.com 15: + # #../../Binary/Apps/i2clcd.com 2: #../../Binary/Apps/i2cscan.com 2: diff --git a/Source/Images/d_cpm22.txt b/Source/Images/d_cpm22.txt index 6c9810d9..8e4245a9 100644 --- a/Source/Images/d_cpm22.txt +++ b/Source/Images/d_cpm22.txt @@ -27,6 +27,7 @@ d_cpm22/ReadMe.txt 0: ../../Binary/Apps/zmterm.ovr 0: ../../Binary/Apps/zminit.ovr 0: ../../Binary/Apps/zmconfig.ovr 0: +../../Binary/Apps/zmd.com 0: # #../../Binary/Apps/i2clcd.com 2: #../../Binary/Apps/i2cscan.com 2: diff --git a/Source/Images/d_cpm3.txt b/Source/Images/d_cpm3.txt index cf1e0335..036adcf8 100644 --- a/Source/Images/d_cpm3.txt +++ b/Source/Images/d_cpm3.txt @@ -43,6 +43,7 @@ ../../Binary/Apps/zmterm.ovr 0: ../../Binary/Apps/zminit.ovr 0: ../../Binary/Apps/zmconfig.ovr 0: +../../Binary/Apps/zmd.com 0: # #../../Binary/Apps/i2clcd.com 2: #../../Binary/Apps/i2cscan.com 2: diff --git a/Source/Images/d_nzcom.txt b/Source/Images/d_nzcom.txt index 3e1a2c3c..e9cc1e3f 100644 --- a/Source/Images/d_nzcom.txt +++ b/Source/Images/d_nzcom.txt @@ -44,6 +44,7 @@ d_zsdos/u0/*.* 0: ../../Binary/Apps/zmterm.ovr 0: ../../Binary/Apps/zminit.ovr 0: ../../Binary/Apps/zmconfig.ovr 0: +../../Binary/Apps/zmd.com 0: # #../../Binary/Apps/i2clcd.com 2: #../../Binary/Apps/i2cscan.com 2: diff --git a/Source/Images/d_zpm3.txt b/Source/Images/d_zpm3.txt index 7ef5d483..8bf0ce43 100644 --- a/Source/Images/d_zpm3.txt +++ b/Source/Images/d_zpm3.txt @@ -42,6 +42,7 @@ ../../Binary/Apps/zmterm.ovr 15: ../../Binary/Apps/zminit.ovr 15: ../../Binary/Apps/zmconfig.ovr 15: +../../Binary/Apps/zmd.com 15: # #../../Binary/Apps/i2clcd.com 2: #../../Binary/Apps/i2cscan.com 2: diff --git a/Source/Images/d_zsdos.txt b/Source/Images/d_zsdos.txt index 247ed7d7..a691c5df 100644 --- a/Source/Images/d_zsdos.txt +++ b/Source/Images/d_zsdos.txt @@ -40,6 +40,7 @@ d_cpm22/u0/XSUB.COM 0: ../../Binary/Apps/zmterm.ovr 0: ../../Binary/Apps/zminit.ovr 0: ../../Binary/Apps/zmconfig.ovr 0: +../../Binary/Apps/zmd.com 0: # #../../Binary/Apps/i2clcd.com 2: #../../Binary/Apps/i2cscan.com 2: diff --git a/Source/ver.inc b/Source/ver.inc index 7c0b44a9..e3ae1f93 100644 --- a/Source/ver.inc +++ b/Source/ver.inc @@ -2,4 +2,4 @@ #DEFINE RMN 1 #DEFINE RUP 1 #DEFINE RTP 0 -#DEFINE BIOSVER "3.1.1-pre.125" +#DEFINE BIOSVER "3.1.1-pre.126" diff --git a/Source/ver.lib b/Source/ver.lib index 2ab0d992..28df2c0e 100644 --- a/Source/ver.lib +++ b/Source/ver.lib @@ -3,5 +3,5 @@ rmn equ 1 rup equ 1 rtp equ 0 biosver macro - db "3.1.1-pre.125" + db "3.1.1-pre.126" endm