mirror of
https://github.com/callapple/LLUCE.git
synced 2025-01-16 03:30:16 +00:00
1862 lines
70 KiB
ArmAsm
1862 lines
70 KiB
ArmAsm
LST OFF
|
|
LSTDO OFF
|
|
*
|
|
* July 15, 1991
|
|
*
|
|
* This file is hereby dedicated to the public domain.
|
|
* -- Andrew Nicholas
|
|
*
|
|
XC
|
|
TR
|
|
TR ADR
|
|
Y = 1
|
|
y = 1
|
|
N = 0
|
|
n = 0
|
|
LISTOBJ KBD 'List This Source? (Y/N)'
|
|
LISTSYM KBD 'List Symbol Table? (Y/N)'
|
|
SAVEOBJ KBD 'Save Object Code? (Y/N)'
|
|
|
|
DO LISTOBJ
|
|
LST
|
|
FIN
|
|
LST OFF
|
|
|
|
BUILDIIC KBD 'Build IIc version? (Y/N)'
|
|
NOTBUILDIIC = 1-BUILDIIC
|
|
BUILDFLUSH KBD 'Build using MDMFLUSH calls? (GBBS v2.14 & later only) (Y/N)'
|
|
NOTBUILDFLUSH = 1-BUILDFLUSH
|
|
BUILDDEBUG KBD 'Build with debugging display? (Y/N)'
|
|
NOTBUILDDEBUG = 1-BUILDDEBUG
|
|
DO BUILDDEBUG
|
|
BUILDPRINT KBD 'Build debug dumped to printer? (Y/N)'
|
|
ELSE
|
|
BUILDPRINT = 0
|
|
FIN
|
|
NOTBUILDPRINT = 1-BUILDPRINT
|
|
|
|
PUT EQUATES
|
|
PUT ZEQUATES
|
|
LST RTN
|
|
|
|
*-------------------------------------------------
|
|
* RZ -- receive via ZMODEM
|
|
*
|
|
* syntax is: call ed+3,lg$,f$
|
|
* where f$ is 15 spaces and return the filename
|
|
* and lg$ is the pathname to put it on
|
|
*
|
|
* second entry point syntax is: call ed+6,lg$,f$,0
|
|
*
|
|
* the second entry point passes a variable where
|
|
*
|
|
* 0 = overwrite the file unconditionally
|
|
* 1 = append to the existing file
|
|
* 2 = rename the incoming file
|
|
* 3 = skip this file
|
|
* 4 = abort the xfer
|
|
|
|
ORG $9E00
|
|
|
|
*-------------------------------------------------
|
|
* receive via ZMODEM
|
|
|
|
JMP FIRST
|
|
JMP RZ ;+3
|
|
JMP RZCONTINUE ;+6
|
|
|
|
INFOPARMS
|
|
DB 10 ;+9
|
|
DA PREFIX
|
|
DB 0 ;access
|
|
DB 0 ;filetype
|
|
DW 0 ;total_blocks
|
|
DB 0 ;storage_type
|
|
DW 0 ;blocks_used
|
|
DW 0 ;mod_date
|
|
DW 0 ;mod_time
|
|
DW 0 ;create_date
|
|
DW 0 ;create_time
|
|
|
|
EOFPARMS DB 2 ;+27
|
|
DB 0
|
|
|
|
BYTECOUNT DS 3
|
|
XBLOCKS DS 3
|
|
PBLOCKS DS 3
|
|
|
|
*-------------------------------------------------
|
|
* LOGVOLUME -- gobble the comma and log LG$
|
|
|
|
LOGVOLUME
|
|
JSR GOBCOM ;gobble the comma
|
|
JSR INPSTR ;get the first string
|
|
CPY #5 ;how many characters?
|
|
BCC OVER ;less than 5! continue
|
|
|
|
DIE SEC
|
|
RTS
|
|
|
|
*-------------------------------------------------
|
|
|
|
STRIPHI INY
|
|
LDA ($D),Y
|
|
AND #$7F
|
|
STA DRIVESPEC,Y
|
|
RTS
|
|
|
|
DRIVESPEC DB 0
|
|
LOG_LO DB 0
|
|
LOG_HI DB 0
|
|
ADDNUM DB 0
|
|
|
|
*-------------------------------------------------
|
|
* After INPSTR call, $D points to the string that was just read..
|
|
|
|
OVER DEY
|
|
LDA ($D),Y
|
|
CMP #':' ;is the last character ':'?
|
|
BNE DIE ;nope trash it
|
|
|
|
TYA
|
|
TAX ;save y in x
|
|
LDY #0
|
|
STY LOG_LO ;init DRIVESPEC's to 0
|
|
STY LOG_HI ;and 0
|
|
|
|
LDA ($D),Y ;get the first character
|
|
AND #$7F ;strip high bit
|
|
|
|
CMP #'a' ;is it 'a'?
|
|
BCC UPPER ;nope, try others..
|
|
CMP #'m' ;is it 'm'?
|
|
BCS UPPER ;yes, trash it
|
|
SBC #$1F ;nope, make it uppercase
|
|
|
|
UPPER CMP #'A' ;is it less than 'a'?
|
|
BCC DIE ;yeah, trash it
|
|
CMP #'M' ;is it greater than 'l'
|
|
BCS DIE ;yeah, trash it
|
|
|
|
STA DRIVESPEC ;actual letter specifier
|
|
DEX ;get last character's position
|
|
BEQ NOT3 ;is it the last one already? yep
|
|
|
|
JSR STRIPHI ;not last,strip high from letter
|
|
DEX ;is it the last one now?
|
|
BEQ NOT3 ;yep, just continue
|
|
JSR STRIPHI ;otherwise, strip bit again
|
|
|
|
NOT3 LDX LOG_HI ;get high part of log #
|
|
LDA LOG_LO ;get low part of log #
|
|
BNE NOT0 ;low part is not 0, try others
|
|
CMP LOG_HI ;is the high part also 0?
|
|
BEQ BOTH0 ;yes, go do normal log
|
|
|
|
NOT0 CPX #0 ;is the high part a 0?
|
|
BNE :NOT0
|
|
TAX
|
|
|
|
LDA #0
|
|
:NOT0 AND #$F
|
|
STA ADDNUM
|
|
|
|
TXA
|
|
AND #$F
|
|
LDY #10
|
|
:LOOP CLC
|
|
ADC ADDNUM
|
|
DEY
|
|
BNE :LOOP
|
|
|
|
TAX ;x=number to log
|
|
BOTH0 LDA DRIVESPEC ;a=letter to log
|
|
JSR LOG ;set prefix for that pathname
|
|
CLC
|
|
RTS
|
|
|
|
*-------------------------------------------------
|
|
* RZ -- receive a file with zmodem
|
|
|
|
RZ STZ SYNTAX
|
|
STZ FAILFLAG
|
|
|
|
JSR LOGVOLUME
|
|
BCC :LOGOK
|
|
INC SYNTAX
|
|
|
|
:LOGOK JSR GOBCOM ;grab the comma
|
|
JSR INPSTR ;get filename area
|
|
|
|
LDA SYNTAX
|
|
BNE :DIE
|
|
CPY #15 ;is it >= than 15?
|
|
BEQ REALLYRZ ;yes, go there
|
|
|
|
:DIE LDA #ERROR
|
|
STA FAILFLAG
|
|
RTS
|
|
|
|
*-------------------------------------------------
|
|
* REALLYRZ -- really receive a file 'cause we're setup to do it right
|
|
|
|
REALLYRZ JSR CLEARFILENAME
|
|
JSR CLEARTOSPACES
|
|
JSR STARTUP
|
|
|
|
*
|
|
* we got the memory, make the crc lookup table and see if the other side wants
|
|
* to send us something with zmodem
|
|
*
|
|
JSR TRYZ ;get something?
|
|
|
|
CMP #ERROR
|
|
BEQ :DONE ;nope, skip over the receive part
|
|
CMP #ABORT
|
|
BEQ :DONE
|
|
CMP #TIMEOUT
|
|
BEQ :DONE
|
|
CMP #ZCOMPL
|
|
BEQ :COMPLETE
|
|
CMP #ZFILE
|
|
BNE :DONE
|
|
|
|
JSR RZFILES
|
|
|
|
CMP #ZEOF
|
|
BEQ :COMPLETE
|
|
CMP #ZCOMPL
|
|
BNE :DONE
|
|
:COMPLETE LDA #NO_ERROR
|
|
:DONE STA FAILFLAG
|
|
|
|
CMP #ABORT
|
|
BNE :NOABORT
|
|
|
|
JSR CANCEL
|
|
:NOABORT
|
|
|
|
*-------------------------------------------------
|
|
* COMMONSHUTDOWN -- both RZ and RZCONTINUE arrive here
|
|
|
|
COMMONSHUTDOWN
|
|
DO NOTBUILDDEBUG
|
|
JSR CLEARLASTLINE
|
|
FIN
|
|
|
|
JSR MLI ;how much did we receive, and what?
|
|
DB $D1
|
|
DA EOFPARMS
|
|
JSR MLI
|
|
DB $CC
|
|
DA CLOSEPARMS
|
|
|
|
LDA BYTECOUNT
|
|
STA XBLOCKS
|
|
STA PBLOCKS
|
|
LDA BYTECOUNT+1
|
|
STA XBLOCKS+1
|
|
STA PBLOCKS+1
|
|
LDA BYTECOUNT+2
|
|
STA XBLOCKS+2
|
|
STA PBLOCKS+2
|
|
|
|
LDX #6 ;divide bytes sent by 128 to find out
|
|
:XLOOP LSR XBLOCKS+2 ;how many blocks were sent
|
|
ROR XBLOCKS+1
|
|
ROR XBLOCKS
|
|
DEX
|
|
BPL :XLOOP
|
|
|
|
LDX #8 ;divide bytes sent by 512 to find out
|
|
:PLOOP LSR PBLOCKS+2 ;how many blocks were sent
|
|
ROR PBLOCKS+1
|
|
ROR PBLOCKS
|
|
DEX
|
|
BPL :PLOOP
|
|
|
|
LDA #<PATHNAME
|
|
STA INFOPARMS+1
|
|
LDA #>PATHNAME
|
|
STA INFOPARMS+2
|
|
|
|
JSR MLI ;return the file's info
|
|
DB $C4
|
|
DA INFOPARMS
|
|
JSR SHUTDOWN
|
|
JMP MOVEFILENAME
|
|
|
|
*-------------------------------------------------
|
|
* RZCONTINUE -- figure out to do with the filename
|
|
|
|
RZCONTINUE
|
|
STZ SYNTAX
|
|
STZ FAILFLAG
|
|
|
|
JSR LOGVOLUME
|
|
BCC :LOGOK
|
|
INC SYNTAX
|
|
:LOGOK
|
|
|
|
JSR GOBCOM ;grab the comma
|
|
JSR INPSTR ;get filename area
|
|
CPY #15 ;is it >= than 15?
|
|
BEQ :FILENAMEOK ;yes, go there
|
|
INC SYNTAX
|
|
:FILENAMEOK
|
|
|
|
JSR GOBCOM
|
|
JSR INPNUM ;get 0,1,2,3,4
|
|
|
|
LDA SYNTAX
|
|
BNE :DIE
|
|
CPX #5
|
|
BLT :ACTIONOK
|
|
|
|
:DIE LDA #ERROR
|
|
STA FAILFLAG
|
|
RTS
|
|
:ACTIONOK
|
|
|
|
STX NAMEHOW
|
|
STZ RENAMETRIES
|
|
|
|
JSR CLEARFILENAME
|
|
JSR STARTUP
|
|
|
|
LDA NAMEHOW
|
|
ASL A
|
|
TAX
|
|
JMP (:ADDR,X)
|
|
|
|
:ADDR DA :OVERWRITE
|
|
DA :APPEND
|
|
DA :RENAME
|
|
DA :SKIP
|
|
DA :ABORT
|
|
|
|
*
|
|
* trash the existing file and then create the file again
|
|
*
|
|
:OVERWRITE
|
|
LDA #<PATHNAME
|
|
STA INFOPARMS+1
|
|
LDA #>PATHNAME
|
|
STA INFOPARMS+2
|
|
|
|
JSR MLI ;unlock it
|
|
DB $C4
|
|
DA INFOPARMS
|
|
BCS :GORZDONE
|
|
|
|
LDA #$C3
|
|
STA INFOPARMS+3
|
|
|
|
JSR MLI
|
|
DB $C3
|
|
DA INFOPARMS
|
|
BCS :GORZDONE
|
|
|
|
JSR MLI
|
|
DB $C1
|
|
DA DESTROYPARMS
|
|
BCS :GORZDONE ;something screwed up again
|
|
|
|
JSR CREATEFILE
|
|
CMP #NO_ERROR
|
|
BEQ :GORZFILEAT0
|
|
:GORZDONE JMP :RZDONE
|
|
:GORZFILEAT0 JMP :RZFILEAT0
|
|
|
|
*
|
|
* append to the end of the existing file by finding its EOF and sending the
|
|
* ZRPOS packet from there
|
|
*
|
|
:APPEND
|
|
JSR MLI
|
|
DB $C8
|
|
DA OPENPARMS
|
|
BCS :GORZDONE
|
|
|
|
LDA OPENPARMS+5
|
|
STA WRITEPARMS+1
|
|
STA CLOSEPARMS+1
|
|
STA EOFPARMS+1
|
|
STA MARKPARMS+1
|
|
|
|
JSR MLI
|
|
DB $D1
|
|
DA EOFPARMS
|
|
BCS :GORZDONE
|
|
|
|
LDA EOFPARMS+2
|
|
STA MARKPARMS+2
|
|
STA RXCOUNT
|
|
LDA EOFPARMS+3
|
|
STA MARKPARMS+3
|
|
STA RXCOUNT+1
|
|
LDA EOFPARMS+4
|
|
STA MARKPARMS+4
|
|
STA RXCOUNT+2
|
|
STZ RXCOUNT+3
|
|
|
|
JSR MLI
|
|
DB $CE
|
|
DA MARKPARMS
|
|
BCS :GORZDONE
|
|
JMP :RZFILEATEOF
|
|
|
|
*
|
|
* rename the incoming file so that we can create it without incident
|
|
*
|
|
:RENAME INC RENAMETRIES
|
|
LDA RENAMETRIES
|
|
CMP #26
|
|
BNE :RENAMEOK
|
|
LDA #$47
|
|
BRA :RZDONE
|
|
|
|
:RENAMEOK LDY PATHNAME
|
|
CPY #15
|
|
BEQ :GOT15
|
|
|
|
INY
|
|
LDA #'.'
|
|
STA PATHNAME,Y
|
|
STY PATHNAME
|
|
|
|
JSR CREATEFILE
|
|
CMP #NO_ERROR
|
|
BEQ :RZFILEAT0
|
|
CMP #$47
|
|
BEQ :RENAME
|
|
BRA :RZDONE
|
|
|
|
:GOT15 LDA PATHNAME+2
|
|
CMP #'Z'
|
|
BEQ :MAKEA
|
|
INC PATHNAME+2
|
|
|
|
JSR CREATEFILE
|
|
CMP #NO_ERROR
|
|
BEQ :RZFILEAT0
|
|
CMP #$47 ;if it's duplicate file, try again
|
|
BEQ :RENAME
|
|
BRA :RZDONE
|
|
|
|
:MAKEA LDA #'A'
|
|
STA PATHNAME+2
|
|
|
|
JSR CREATEFILE
|
|
CMP #NO_ERROR
|
|
BEQ :RZFILEAT0
|
|
CMP #$47
|
|
BEQ :RENAME
|
|
BRA :RZDONE
|
|
|
|
*
|
|
* skip the file, someone doesn't want us to receive it
|
|
*
|
|
:SKIP JSR ZEROPOS
|
|
LDA #ZSKIP
|
|
STA FRAMETYPE
|
|
|
|
JSR ZSENDHHEADER ;send the ZSKIP packet
|
|
LDA #NO_ERROR ;tell it to more-or-less abort without an error
|
|
BRA :RZDONE
|
|
|
|
*
|
|
* just abort the transfer, the user is all messed up
|
|
*
|
|
:ABORT LDA #ERROR
|
|
BRA :RZDONE
|
|
|
|
*
|
|
* receive something after we've either created, renamed, or deleted the file
|
|
*
|
|
:RZFILEAT0
|
|
JSR GOODFILE ;this entry point zeroes ZRPOS's position
|
|
BRA :RZDONE
|
|
|
|
:RZFILEATEOF
|
|
JSR GOODHEADER
|
|
|
|
:RZDONE CMP #ZEOF
|
|
BEQ :COMPLETE
|
|
CMP #ZCOMPL
|
|
BNE :DONE
|
|
:COMPLETE LDA #NO_ERROR
|
|
:DONE STA FAILFLAG
|
|
|
|
CMP #ABORT
|
|
BNE :NOABORT
|
|
|
|
JSR CANCEL
|
|
:NOABORT
|
|
|
|
JMP COMMONSHUTDOWN
|
|
|
|
RENAMETRIES DB 0
|
|
|
|
*-------------------------------------------------
|
|
* TRYZ -- try to receive via zmodem - handle ZSINIT header
|
|
|
|
TRYZ
|
|
STZ ERRORS
|
|
|
|
:RETRYZ LDA #<MAXBUFFERSIZE
|
|
STA ZP0 ;we have a 16k buffer
|
|
LDA #>MAXBUFFERSIZE
|
|
STA ZP1
|
|
|
|
STZ ZF1 ;we can't do squat
|
|
|
|
DO BUILDFLUSH
|
|
LDA #CANFC32+CANFDX ;we can do CRC32 and do full duplex
|
|
ELSE
|
|
LDA #CANFC32 ;otherwise, it's an older driver and we can only
|
|
FIN ;do half duplex, sort of (simulated full duplex)
|
|
STA ZF0 ;ivan better not send ZCRCQ packets
|
|
|
|
LDA #ZRINIT
|
|
STA FRAMETYPE
|
|
|
|
JSR ZSENDHHEADER ;send the ZRINIT frame to the other end
|
|
|
|
:SWITCH STZ ZPTR ;init where the filename gets sent
|
|
LDA #>ZBUFFER
|
|
STA ZPTR+1
|
|
|
|
JSR ZGETHEADER ;grab the return header
|
|
|
|
CMP #20
|
|
BLT :HEADER
|
|
|
|
CMP #ABORT
|
|
BEQ :ABORT
|
|
CMP #TIMEOUT
|
|
BNE :ABORT
|
|
|
|
INC ERRORS
|
|
LDA ERRORS
|
|
CMP #5
|
|
BLT :RETRYZ
|
|
|
|
LDA #TIMEOUT
|
|
RTS
|
|
|
|
:RETURN LDA #ERROR
|
|
:ABORT RTS
|
|
|
|
:HEADER ASL A
|
|
TAX
|
|
JMP (:ADDR,X)
|
|
|
|
:ADDR DA TRYZ ZRQINIT
|
|
DA :RETRYZ ZRINIT
|
|
DA :DOZSINIT 2
|
|
DA :RETURN ZACK
|
|
DA :DOZFILE 4
|
|
DA :RETURN ZSKIP
|
|
DA :SWITCH ZNAK
|
|
DA :RETURN ZABORT
|
|
DA :DOZFIN ZFIN
|
|
DA :RETURN ZRPOS
|
|
DA :RETURN ZDATA
|
|
DA :RETURN ZEOF
|
|
DA :RETURN ZFERR
|
|
DA :RETURN ZCRC
|
|
DA :RETURN ZCHALLENGE
|
|
DA :SWITCH ZCOMPL
|
|
DA :RETURN ZCAN
|
|
DA :DOZFREECNT 17
|
|
DA :DOZCOMMAND 18
|
|
DA :RETURN ZSTDERR
|
|
|
|
*
|
|
* handle ZFILE
|
|
*
|
|
:DOZFILE LDA ZF0
|
|
STA ZCONVERT
|
|
LDA ZF1
|
|
STA ZMANAGE
|
|
LDA ZF2
|
|
STA ZTRANSPORT
|
|
|
|
LDA #<ZBUFFER
|
|
STA ZPTR
|
|
LDA #>ZBUFFER
|
|
STA ZPTR+1
|
|
|
|
JSR ZRDATA
|
|
|
|
CMP #ZCRCW
|
|
BNE :ERRORZFILE
|
|
|
|
LDA #0 ;store an extra zero at the end so programs like
|
|
STA (ZPTR) ;proterm which don't have the double zero after the
|
|
;filename and no length will still work
|
|
|
|
LDA #ZFILE ;we got a ZFILE packet
|
|
RTS ;it was good
|
|
|
|
:ERRORZFILE
|
|
LDA #ZNAK
|
|
STA FRAMETYPE
|
|
JSR ZSENDHHEADER
|
|
JMP :SWITCH
|
|
|
|
*
|
|
* ZSINIT -- got ZSINIT
|
|
*
|
|
:DOZSINIT
|
|
JSR ZRDATA ;get the attention string
|
|
|
|
CMP #ZCRCW
|
|
BNE :ERRORZSINIT
|
|
|
|
LDA RXBYTES
|
|
STA ATTNLENGTH
|
|
|
|
LDY #0 ;move the attention string
|
|
:ZSLOOP LDA (ZPTR),Y
|
|
STA ATTENTION,Y
|
|
INY
|
|
CPY #32
|
|
BGE :DONEATTN
|
|
CPY ATTNLENGTH
|
|
BLT :ZSLOOP
|
|
:DONEATTN
|
|
|
|
JSR ZEROPOS
|
|
LDA #1
|
|
STA ZP0
|
|
|
|
LDA #ZACK
|
|
STA FRAMETYPE
|
|
|
|
JSR ZSENDHHEADER
|
|
JMP :SWITCH
|
|
|
|
:ERRORZSINIT
|
|
LDA #ZNAK
|
|
STA FRAMETYPE
|
|
JSR ZSENDHHEADER
|
|
JMP :SWITCH
|
|
|
|
*
|
|
* doZFREECNT -- got ZFREECNT
|
|
*
|
|
:DOZFREECNT
|
|
JSR MLI
|
|
DB $C7
|
|
DA PREFIXPARMS
|
|
|
|
LDX #2
|
|
:PLOOP LDA PREFIX,X
|
|
CMP #'/'
|
|
BEQ :GOTSLASH
|
|
INX
|
|
CPX PREFIX
|
|
BLT :PLOOP
|
|
|
|
:GOTSLASH
|
|
STX PREFIX
|
|
|
|
LDA #<PREFIX
|
|
STA INFOPARMS+1
|
|
LDA #>PREFIX
|
|
STA INFOPARMS+2
|
|
|
|
JSR MLI
|
|
DB $C4
|
|
DA INFOPARMS
|
|
|
|
LDA INFOPARMS+5 ;free blocks is (total_blocks-used_blocks)
|
|
SEC
|
|
SBC INFOPARMS+8
|
|
STA ZP0
|
|
LDA INFOPARMS+6
|
|
SBC INFOPARMS+9
|
|
STA ZP1
|
|
STZ ZP2
|
|
STZ ZP3
|
|
|
|
LDX #0 ;show them how many bytes are free by multiplying
|
|
:ZLOOP ASL ZP0 ;the number of free blocks by 512 bytes (per block)
|
|
ROL ZP1
|
|
ROL ZP2
|
|
ROL ZP3
|
|
INX
|
|
CPX #9
|
|
BLT :ZLOOP
|
|
|
|
LDA #ZACK
|
|
STA FRAMETYPE
|
|
|
|
JSR ZSENDHHEADER
|
|
JMP :SWITCH
|
|
|
|
*
|
|
* doZCOMMAND -- go ZCOMMAND
|
|
*
|
|
:DOZCOMMAND
|
|
JSR ZRDATA
|
|
|
|
CMP #ZCRCW
|
|
BNE :ERRORZCOMMAND
|
|
|
|
LDA ZF0
|
|
AND #ZCACK1
|
|
|
|
STZ ERRORS
|
|
|
|
:ZCLOOP JSR ZEROPOS
|
|
|
|
LDA #ZCOMPL
|
|
STA FRAMETYPE
|
|
JSR ZSENDHHEADER
|
|
|
|
INC ERRORS
|
|
LDA ERRORS
|
|
CMP #20
|
|
BGE :ZCERRS
|
|
|
|
JSR ZGETHEADER
|
|
|
|
CMP #20
|
|
BGE :ZCERRS
|
|
CMP #ZFIN
|
|
BNE :ZCLOOP
|
|
|
|
JSR ACKBIBI
|
|
|
|
:ZCERRS LDA #ZCOMPL
|
|
RTS
|
|
|
|
:ERRORZCOMMAND
|
|
LDA #ZNAK
|
|
STA FRAMETYPE
|
|
JSR ZSENDHHEADER
|
|
JMP :SWITCH
|
|
|
|
*
|
|
* doZFIN -- got ZFIN
|
|
*
|
|
:DOZFIN JSR ACKBIBI ;hey bud, we're done!
|
|
|
|
LDA #ZCOMPL
|
|
RTS
|
|
|
|
*-------------------------------------------------
|
|
* PROCHEADER -- process the header we got
|
|
* longest allowable filename is 15 chars.
|
|
* we parse a valid prodos filename from the
|
|
* name we are given, provided we are given a name
|
|
|
|
PROCHEADER
|
|
STZ ZPTR
|
|
LDA #>ZBUFFER
|
|
STA ZPTR+1
|
|
|
|
LDA (ZPTR)
|
|
BNE :GOODNAME
|
|
|
|
LDA #ERROR
|
|
SEC
|
|
RTS
|
|
|
|
*
|
|
* if we get this far, we have at least a single char filename, so it's ok and
|
|
* no one's been fooling with us.
|
|
*
|
|
:GOODNAME
|
|
LDY #0
|
|
:FLOOP LDA (ZPTR),Y ;get the length of the filename
|
|
BEQ :GOTEND
|
|
INY
|
|
CPY #15
|
|
BLT :FLOOP
|
|
LDY #15
|
|
|
|
:GOTEND TYA
|
|
STA PATHNAME ;save the length byte
|
|
|
|
LDY #0
|
|
:PLOOP LDA (ZPTR),Y
|
|
|
|
CMP #$80
|
|
BGE :REPLACE
|
|
|
|
CMP #'{'
|
|
BGE :REPLACE
|
|
CMP #'a'
|
|
BGE :UPPER ;change lowercase into uppercase
|
|
CMP #'['
|
|
BGE :REPLACE
|
|
CMP #'A'
|
|
BGE :VALID
|
|
CMP #':'
|
|
BGE :REPLACE
|
|
CMP #'0'
|
|
BLT :REPLACE
|
|
BRA :VALID
|
|
|
|
:UPPER SEC ;take lowercase and make it uppercase
|
|
SBC #$20
|
|
BRA :VALID
|
|
|
|
:REPLACE LDA #'.' ;replace bad char with period
|
|
:VALID STA PATHNAME+1,Y
|
|
|
|
INY
|
|
CPY PATHNAME
|
|
BLT :PLOOP
|
|
|
|
LDA PATHNAME+1
|
|
CMP #'A'
|
|
BGE :FIRSTNOTDOT
|
|
LDA #'A' ;always change the first char to an alpha char
|
|
STA PATHNAME+1
|
|
|
|
:FIRSTNOTDOT
|
|
*
|
|
* start setting up the statLine by putting spaces over top of the # of bytes
|
|
* being received (our moving counter), and then putting the length of the file
|
|
* over top of the 'xxxxx's
|
|
*
|
|
|
|
DO NOTBUILDDEBUG
|
|
LDX #0 ;put spaces on top of the old byte counts
|
|
LDA #' '
|
|
:RSLOOP STA RZSTATLINE+16,X
|
|
STA RZSTATLINE+28,X
|
|
INX
|
|
CPX #8
|
|
BLT :RSLOOP
|
|
|
|
LDY #0 ;then find the end of the filename
|
|
:NEXTC LDA (ZPTR),Y
|
|
BEQ :FOUNDFEND
|
|
INY
|
|
BNE :NEXTC
|
|
|
|
:FOUNDFEND LDX #0
|
|
:LENLOOP INY ;next character after the filename should be
|
|
LDA (ZPTR),Y ;the length of the file, unless someone just didn't
|
|
BEQ :DONEWLENGTH ;include the filename, like greg in proterm
|
|
AND #$7F
|
|
CMP #' '
|
|
BEQ :DONEWLENGTH
|
|
STA RZSTATLINE+28,X
|
|
INX
|
|
BRA :LENLOOP
|
|
|
|
:DONEWLENGTH
|
|
FIN
|
|
|
|
LDA #<PATHNAME
|
|
STA CREATEPARMS+1
|
|
STA DESTROYPARMS+1
|
|
STA OPENPARMS+1
|
|
LDA #>PATHNAME
|
|
STA CREATEPARMS+2
|
|
STA DESTROYPARMS+2
|
|
STA OPENPARMS+2
|
|
|
|
JSR CREATEFILE
|
|
RTS
|
|
|
|
*-------------------------------------------------
|
|
* CREATEFILE -- create the file or return an error code in (A)
|
|
|
|
CREATEFILE
|
|
JSR MLI ;create the file
|
|
DB $C0
|
|
DA CREATEPARMS
|
|
BCS :BAD
|
|
JSR MLI ;open it
|
|
DB $C8
|
|
DA OPENPARMS
|
|
BCS :BAD
|
|
|
|
LDA OPENPARMS+5
|
|
STA WRITEPARMS+1
|
|
STA CLOSEPARMS+1
|
|
STA EOFPARMS+1
|
|
STA MARKPARMS+1
|
|
|
|
LDA #NO_ERROR
|
|
:BAD RTS
|
|
|
|
*-------------------------------------------------
|
|
* RZFILES -- receive a bunch of files (wow, something high-level for a change)
|
|
|
|
RZFILES JSR RZFILE
|
|
|
|
CMP #ERROR
|
|
BEQ :DONE
|
|
CMP #ABORT
|
|
BEQ :DONE
|
|
CMP #TIMEOUT
|
|
BEQ :DONE
|
|
|
|
CMP #ZSKIP
|
|
BEQ RZFILES
|
|
|
|
CMP #ZEOF
|
|
BEQ :DONE
|
|
|
|
CMP #ZFILE ;(we'd really be screwed.. hmmm...)
|
|
BEQ :TRYAGAIN
|
|
|
|
CMP #$47 ;duplicate filename error
|
|
BEQ :DONE
|
|
|
|
LDA #NO_ERROR
|
|
:DONE RTS
|
|
|
|
:TRYAGAIN JSR TRYZ ;try to get another filename or quit
|
|
|
|
CMP #ERROR
|
|
BEQ :DONE ;nope, skip over the receive part
|
|
CMP #ABORT
|
|
BEQ :DONE
|
|
CMP #TIMEOUT
|
|
BEQ :DONE
|
|
CMP #ZCOMPL
|
|
BEQ :DONE
|
|
CMP #ZFILE
|
|
BEQ RZFILES
|
|
|
|
LDA #NO_ERROR
|
|
RTS
|
|
|
|
*-------------------------------------------------
|
|
* RZFILE -- try to receive a single file via zmodem. this assumes we've
|
|
* already got a filename and the ZSINIT and ZRINIT packets have
|
|
* been exchanged.
|
|
|
|
RZFILE JSR PROCHEADER ;process what we got as the header
|
|
CMP #NO_ERROR
|
|
BEQ GOODFILE
|
|
|
|
RTS
|
|
|
|
GOODFILE LDX #3
|
|
:RXBYTES STZ RXBYTES,X ;we haven't received squat yet
|
|
DEX
|
|
BPL :RXBYTES
|
|
|
|
LDX #3
|
|
:RXCOUNT STZ RXCOUNT,X
|
|
DEX
|
|
BPL :RXCOUNT
|
|
|
|
LDX #2
|
|
:BYTECOUNT STZ BYTECOUNT,X
|
|
DEX
|
|
BPL :BYTECOUNT
|
|
|
|
*
|
|
* this is the entry point for zContinue when it decides that it's going to
|
|
* append to the file
|
|
*
|
|
GOODHEADER
|
|
DO NOTBUILDDEBUG
|
|
JSR PRINTRZSTAT
|
|
FIN
|
|
|
|
STZ ERRORS
|
|
|
|
STZ ZPTR ;init where the data, etc, goes to
|
|
LDA #>ZBUFFER
|
|
STA ZPTR+1
|
|
|
|
:CONTINUE LDA RXCOUNT
|
|
STA ZP0
|
|
STA BYTES
|
|
LDA RXCOUNT+1
|
|
STA ZP1
|
|
STA BYTES+1
|
|
LDA RXCOUNT+2
|
|
STA ZP2
|
|
STA BYTES+2
|
|
LDA RXCOUNT+3
|
|
STA ZP3
|
|
|
|
JSR PRINTBYTES
|
|
|
|
LDA #ZRPOS
|
|
STA FRAMETYPE
|
|
|
|
JSR ZSENDHHEADER ;send our received position
|
|
|
|
*
|
|
* loop -- come back here every time we need to get a new zmodem packet header
|
|
*
|
|
:LOOP JSR ZGETHEADER
|
|
|
|
CMP #20
|
|
BLT :HEADER
|
|
|
|
CMP #ABORT
|
|
BEQ :GOTABORT
|
|
CMP #TIMEOUT
|
|
BNE :IGNORE ;if anything else happened, try real hard to get
|
|
;back in sync with the other side
|
|
|
|
INC ERRORS
|
|
LDA ERRORS
|
|
CMP #5
|
|
BLT :IGNORE
|
|
|
|
:RETURN JSR WRITEZBUFFER
|
|
LDA #ERROR
|
|
RTS
|
|
|
|
:HEADER ASL A
|
|
TAX
|
|
JMP (:ADDR,X)
|
|
|
|
:ADDR DA :IGNORE ;ZRQINIT - 0
|
|
DA :IGNORE ;ZRINIT - 1
|
|
DA :IGNORE ;ZSINIT - 2
|
|
DA :IGNORE ;ZACK - 3
|
|
DA :GOTZFILE ;ZFILE - 4
|
|
DA :GOTZSKIP ;ZSKIP - 5
|
|
DA :IGNORE ;ZNAK - 6
|
|
DA :GOTABORT ;ZABORT - 7
|
|
DA :RETURN ;ZFIN - 8
|
|
DA :IGNORE ;ZRPOS - 9
|
|
DA :GOTZDATA ;ZDATA - 10
|
|
DA :GOTZEOF ;ZEOF - 11
|
|
DA :IGNORE ;ZFERR - 12
|
|
DA :IGNORE ;ZCRC - 13
|
|
DA :IGNORE ;ZCHALLENGE - 14
|
|
DA :IGNORE ;ZCOMPL - 15
|
|
DA :GOTABORT ;ZCAN - 16
|
|
DA :IGNORE ;ZFREECNT - 17
|
|
DA :IGNORE ;ZCOMMAND - 18
|
|
DA :IGNORE ;ZSTDERR - 19
|
|
|
|
*
|
|
* ignore -- the other side is doing some wacko stuff.. try to get in sync
|
|
* again
|
|
*
|
|
:IGNORE JSR WRITEZBUFFER
|
|
|
|
JSR SENDATTN
|
|
JMP :CONTINUE
|
|
|
|
*
|
|
* gotABORT -- someone aborted us
|
|
*
|
|
:GOTABORT
|
|
JSR WRITEZBUFFER
|
|
|
|
LDA #ABORT
|
|
RTS
|
|
|
|
*
|
|
* ZSKIP -- close our file we were about to receive and return zskip
|
|
*
|
|
:GOTZSKIP
|
|
JSR WRITEZBUFFER ;write out what we got so far
|
|
|
|
LDA #ZSKIP
|
|
RTS
|
|
|
|
*
|
|
* ZEOF -- test for correct EOF, if not, force timeout -- if EOF, then just
|
|
* return normally
|
|
*
|
|
:GOTZEOF JSR WRITEZBUFFER ;write (ZPTR-ZBUFFER) bytes
|
|
|
|
JSR GETRXPOSITION ;munge a longword from the header
|
|
|
|
LDX #3
|
|
:RCMPLOOP1 LDA RXPOSITION,X
|
|
CMP RXCOUNT,X
|
|
BNE :GOLOOP
|
|
DEX
|
|
BPL :RCMPLOOP1
|
|
JMP :ZEOFCLOSE ;ignore eof if it's at the wrong place
|
|
:GOLOOP JMP :LOOP ;force a timeout because the eof might
|
|
;eof might have gone out before our ZRPOS
|
|
:ZEOFCLOSE
|
|
LDA #ZEOF
|
|
RTS
|
|
|
|
*
|
|
* ZFILE -- receive a packet after the zfile header, then keep going
|
|
* this naughty bit of code protects us against the foolishness
|
|
* of people who sent multiple ZFILE packets before they start
|
|
* sending the file data
|
|
*
|
|
:GOTZFILE
|
|
JSR ZRDATA
|
|
JMP GOODFILE
|
|
|
|
*
|
|
* ZDATA -- oh joy, get possibly streamed packets from the sender
|
|
*
|
|
:GOTZDATA
|
|
JSR GETRXPOSITION ;munge a longword from the header
|
|
|
|
LDX #3
|
|
:RCMPLOOP2 LDA RXPOSITION,X
|
|
CMP RXCOUNT,X
|
|
BNE :SENDATTENTION
|
|
DEX
|
|
BPL :RCMPLOOP2
|
|
JMP :GETDATA
|
|
|
|
:SENDATTENTION
|
|
JSR SENDATTN
|
|
JMP :CONTINUE ;resend the ZRPOS
|
|
|
|
*
|
|
* GETDATA -- get data subpackets (ZCRCQ, ZCRCE, ZCRCW, and ZCRCG)
|
|
*
|
|
:GETDATA JSR ZRDATA
|
|
|
|
CMP #ERROR
|
|
BNE :DATANOTERROR
|
|
|
|
:ZDATAERROR
|
|
JSR WRITEZBUFFER
|
|
JSR SENDATTN
|
|
JMP :CONTINUE ;resend the ZRPOS
|
|
|
|
:DATANOTERROR
|
|
CMP #OVERFLOW ;if we overflowed, write what we HAD, then
|
|
BEQ :ZDATAERROR ;reset the buffer and tell it how much
|
|
;we have NOW
|
|
|
|
CMP #TIMEOUT
|
|
BEQ :ZDATAERROR
|
|
|
|
CMP #ABORT
|
|
BNE :DATANOTABORT
|
|
|
|
JSR WRITEZBUFFER
|
|
LDA #ABORT
|
|
RTS
|
|
|
|
:DATANOTABORT
|
|
CMP #ZCRCW
|
|
BNE :DATANOTZCRCW
|
|
|
|
*
|
|
* ZCRCW -- wait for a response from us. The sender is waiting for us to
|
|
* send a ZACK packet in response to their overture
|
|
* so, while we sit there, we might as well write out our buffer
|
|
*
|
|
JSR ADDRXBYTES2RXCOUNT
|
|
JSR PRINTBYTES
|
|
|
|
JSR WRITEZBUFFER ;this also resets ZPTR
|
|
|
|
LDX #3
|
|
:RXLOOP1 LDA RXCOUNT,X
|
|
STA ZP0,X
|
|
DEX
|
|
BPL :RXLOOP1
|
|
|
|
LDA #ZACK
|
|
STA FRAMETYPE
|
|
|
|
JSR ZSENDHHEADER ;receiver always sends a HEX header
|
|
JMP :LOOP ;next header
|
|
|
|
:DATANOTZCRCW
|
|
CMP #ZCRCQ
|
|
BNE :DATANOTZCRCQ
|
|
|
|
*
|
|
* ZCRCQ -- query exactly where we are in the file, send ZACK and keep
|
|
* receiving cause we CANFDX, just not CANOVIO
|
|
* if we are about to overflow our buffer, write the buffer out
|
|
*
|
|
JSR ADDRXBYTES2RXCOUNT
|
|
JSR PRINTBYTES
|
|
|
|
LDA ZPTR+1 ;so, did they (almost) overflow our buffer?
|
|
CMP #>ZBUFFER+MAXBUFFERSIZE
|
|
BLT :ZCRCQNOWRITE ;not yet
|
|
|
|
JSR WRITE2000 ;fall through and send our ZACK frame
|
|
|
|
:ZCRCQNOWRITE
|
|
LDX #3
|
|
:RXLOOP2 LDA RXCOUNT,X
|
|
STA ZP0,X
|
|
DEX
|
|
BPL :RXLOOP2
|
|
|
|
LDA #ZACK
|
|
STA FRAMETYPE
|
|
|
|
JSR ZSENDHHEADER ;receiver always sends a HEX header
|
|
JMP :GETDATA ;get more data
|
|
|
|
:DATANOTZCRCQ
|
|
CMP #ZCRCG
|
|
BNE :DATANOTZCRCG
|
|
|
|
*
|
|
* ZCRCG -- go. sender doesn't want a response unless something screwed up
|
|
* the CRC for this packet, just keep receiving
|
|
* if the buffer is about to overflow, write it out
|
|
*
|
|
JSR ADDRXBYTES2RXCOUNT
|
|
JSR PRINTBYTES
|
|
|
|
LDA ZPTR+1 ;so, did they overflow our buffer?
|
|
CMP #>ZBUFFER+MAXBUFFERSIZE
|
|
BLT :ZCRCGNOWRITE ;not yet
|
|
|
|
JSR WRITE2000
|
|
:ZCRCGNOWRITE
|
|
JMP :GETDATA
|
|
|
|
:DATANOTZCRCG
|
|
CMP #ZCRCE
|
|
BEQ :GOTZCRCE
|
|
JMP :GETDATA ;get some more data no matter what
|
|
|
|
*
|
|
* ZCRCE -- they encountered EOF while sending the packet. sender doesn't
|
|
* want a response unless there's an error
|
|
* is the buffer is full, write it out
|
|
*
|
|
:GOTZCRCE
|
|
JSR ADDRXBYTES2RXCOUNT
|
|
JSR PRINTBYTES
|
|
|
|
LDA ZPTR+1 ;so, did they overflow our buffer?
|
|
CMP #>ZBUFFER+MAXBUFFERSIZE
|
|
BLT :ZCRCENOWRITE ;not yet
|
|
|
|
JSR WRITE2000
|
|
:ZCRCENOWRITE
|
|
JMP :LOOP ;better get ZEOF next time!
|
|
|
|
*-------------------------------------------------
|
|
* ADDRXBYTES2RXCOUNT
|
|
|
|
ADDRXBYTES2RXCOUNT
|
|
LDA RXBYTES
|
|
CLC
|
|
ADC RXCOUNT
|
|
STA RXCOUNT
|
|
LDA RXBYTES+1
|
|
ADC RXCOUNT+1
|
|
STA RXCOUNT+1
|
|
LDA RXBYTES+2
|
|
ADC RXCOUNT+2
|
|
STA RXCOUNT+2
|
|
|
|
LDA RXBYTES
|
|
CLC
|
|
ADC BYTES
|
|
STA BYTES
|
|
LDA RXBYTES+1
|
|
ADC BYTES+1
|
|
STA BYTES+1
|
|
LDA RXBYTES+2
|
|
ADC BYTES+2
|
|
STA BYTES+2
|
|
|
|
LDA RXBYTES
|
|
CLC
|
|
ADC BYTECOUNT
|
|
STA BYTECOUNT
|
|
LDA RXBYTES+1
|
|
ADC BYTECOUNT+1
|
|
STA BYTECOUNT+1
|
|
LDA RXBYTES+2
|
|
ADC BYTECOUNT+2
|
|
STA BYTECOUNT+2
|
|
RTS
|
|
|
|
*-------------------------------------------------
|
|
* WRITEZBUFFER -- write (ZPTR-ZBuffer) bytes
|
|
|
|
WRITEZBUFFER
|
|
LDA ZPTR
|
|
BNE :WRITE
|
|
LDA ZPTR+1
|
|
CMP #>ZBUFFER
|
|
BEQ :NOWRITE
|
|
|
|
:WRITE STZ WRITEPARMS+2 ;where
|
|
LDA #>ZBUFFER
|
|
STA WRITEPARMS+3
|
|
|
|
LDA ZPTR ;how much
|
|
SEC
|
|
SBC #<ZBUFFER
|
|
STA WRITEPARMS+4
|
|
LDA ZPTR+1
|
|
SBC #>ZBUFFER
|
|
STA WRITEPARMS+5
|
|
|
|
JSR MLI
|
|
DB $CB
|
|
DA WRITEPARMS
|
|
|
|
STZ ZPTR ;reset the buffer!!
|
|
LDA #>ZBUFFER
|
|
STA ZPTR+1
|
|
:NOWRITE RTS
|
|
|
|
*-------------------------------------------------
|
|
* WRITE2000 -- write MAXBUFFERSIZE bytes to the file
|
|
|
|
WRITE2000
|
|
STZ WRITEPARMS+2 ;where
|
|
LDA #>ZBUFFER
|
|
STA WRITEPARMS+3
|
|
|
|
LDA #<MAXBUFFERSIZE ;how much
|
|
STA WRITEPARMS+4
|
|
LDA #>MAXBUFFERSIZE
|
|
STA WRITEPARMS+5
|
|
|
|
JSR MLI
|
|
DB $CB
|
|
DA WRITEPARMS
|
|
|
|
STZ ZPTR ;reset the buffer!!
|
|
LDA #>ZBUFFER
|
|
STA ZPTR+1
|
|
RTS
|
|
|
|
*-------------------------------------------------
|
|
* SENDATTN -- send the attention string to the other end
|
|
|
|
SENDATTN LDA ATTNLENGTH ;if we don't have an attention string,
|
|
BEQ :DONE ;we shouldn't send anything
|
|
|
|
LDY #0
|
|
:LOOP LDA ATTENTION,Y
|
|
JSR MDMOUT
|
|
INY
|
|
CPY #32 ;never send more than we got
|
|
BEQ :DONE
|
|
CPY ATTNLENGTH
|
|
BLT :LOOP
|
|
|
|
:DONE
|
|
DO BUILDFLUSH
|
|
JSR MDMFLUSH
|
|
FIN
|
|
|
|
RTS
|
|
|
|
*-------------------------------------------------
|
|
* ACKBIBI() -- send a ZFIN packet and say goodbye...
|
|
|
|
ACKBIBI JSR ZEROPOS
|
|
|
|
LDA #ZFIN
|
|
STA FRAMETYPE
|
|
|
|
JSR ZSENDHHEADER
|
|
|
|
DO BUILDFLUSH
|
|
JSR MDMFLUSH
|
|
FIN
|
|
|
|
:OLOOP JSR GETC ;get the OO or wait 10 seconds trying
|
|
BCC :DONE
|
|
CMP #'O'
|
|
BEQ :NEXTO
|
|
CMP #CAN ;also accept CAN characters
|
|
BEQ :DONE
|
|
BRA :OLOOP
|
|
|
|
:NEXTO JSR GETC
|
|
CMP #'O'
|
|
BEQ :DONE
|
|
CMP #CAN
|
|
BNE :NEXTO
|
|
|
|
:DONE RTS
|
|
|
|
*-------------------------------------------------
|
|
* GETRXPOSITION -- munge a longword from ZP0..ZP3
|
|
|
|
GETRXPOSITION
|
|
LDA ZP0
|
|
STA RXPOSITION
|
|
LDA ZP1
|
|
STA RXPOSITION+1
|
|
LDA ZP2
|
|
STA RXPOSITION+2
|
|
LDA ZP3
|
|
STA RXPOSITION+3
|
|
RTS
|
|
|
|
*-------------------------------------------------
|
|
* ZRDATA -- get a data subpacket and return a result code
|
|
*
|
|
* outputs = (A) = result code
|
|
|
|
ZRDATA LDA FRAMEKIND
|
|
CMP #ZBIN32
|
|
BNE :NORMAL
|
|
JMP ZRDATA32
|
|
|
|
:NORMAL STZ CRC
|
|
STZ CRC+1
|
|
|
|
STZ RXBYTES
|
|
STZ RXBYTES+1
|
|
|
|
LDA ZPTR
|
|
STA ZSTART
|
|
CLC
|
|
ADC #<1025
|
|
STA ZEND
|
|
LDA ZPTR+1
|
|
STA ZSTART+1
|
|
ADC #>1025
|
|
STA ZEND+1
|
|
|
|
:LOOP JSR ZGETCHAR
|
|
|
|
LDX ESCAPED
|
|
BEQ :NOTESCAPED
|
|
CPX #ABORT
|
|
BEQ :BOGUS
|
|
CPX #TIMEOUT
|
|
BNE :NOTBOGUS
|
|
:BOGUS TXA
|
|
JMP :BAD
|
|
|
|
:NOTBOGUS CMP #ZCRCW
|
|
BEQ :GOOUT ;damn 128 byte branches
|
|
CMP #ZCRCQ
|
|
BEQ :GOOUT ;**** 128 byte branches
|
|
CMP #ZCRCG
|
|
BEQ :GOOUT ;**** 128 byte branches
|
|
CMP #ZCRCE
|
|
BNE :NOTESCAPED
|
|
:GOOUT JMP :OUT
|
|
|
|
:NOTESCAPED INC RXBYTES
|
|
BNE :NC
|
|
INC RXBYTES+1
|
|
:NC JSR CRCBYTE
|
|
STA (ZPTR)
|
|
|
|
LDA ZCONVERT
|
|
AND #ZCBIN
|
|
BNE :NOCONVERT
|
|
|
|
LDA ZCONVERT
|
|
AND #ZCNL
|
|
BEQ :NOCONVERT
|
|
|
|
LDA (ZPTR)
|
|
CMP #cr
|
|
BNE :NOTCR
|
|
|
|
LDA #$FF
|
|
STA GOTCR ;this falls through to go to NOCONVERT
|
|
INC ZPTR
|
|
BNE :AFTERMSDOS
|
|
INC ZPTR+1
|
|
BRA :AFTERMSDOS
|
|
|
|
:NOTCR CMP #lf
|
|
BNE :NOCONVERT
|
|
|
|
LDA GOTCR
|
|
BMI :MSDOS
|
|
|
|
:UNIX LDA #cr
|
|
STA (ZPTR)
|
|
|
|
:NOCONVERT INC ZPTR
|
|
BNE :MSDOS
|
|
INC ZPTR+1
|
|
:MSDOS STZ GOTCR ;always reset this so we don't have any stragling LFs
|
|
|
|
:AFTERMSDOS
|
|
LDA ZPTR+1 ;see if we have received a packet larger than
|
|
CMP ZEND+1 ;1k -- this is a good thing to do because Chuck
|
|
BLT :NOTOVER1K ;Forsberg's routines also can't receive larger than
|
|
LDA ZPTR ;1k packets, and we are protecting against lost
|
|
CMP ZEND ;characters at 9600 baud concatenating 2 packets
|
|
BEQ :OVER1K ;together
|
|
|
|
:NOTOVER1K
|
|
LDA ZPTR+1
|
|
CMP #>ZBUFFER+MAXBUFFERSIZE+1
|
|
BLT :LOOP
|
|
LDA ZPTR ;see if they went 1 byte over since we
|
|
CMP #<ZBUFFER+MAXBUFFERSIZE+1 ;can match $4000 bytes exactly and not overflow
|
|
BEQ :OVER1K
|
|
JMP :LOOP ;but we need to check for overflow when we get back
|
|
|
|
:OVER1K
|
|
DO BUILDDEBUG
|
|
LDA ZPTR
|
|
SEC
|
|
SBC ZSTART
|
|
TAY
|
|
LDA ZPTR+1
|
|
SBC ZSTART+1
|
|
TAX
|
|
LDA #1 ;zr
|
|
JSR PRINTSUB ;print the subpacket
|
|
FIN
|
|
|
|
LDA ZSTART+1 ;we overflowed. This is very bad. restore ZPTR
|
|
STA ZPTR+1 ;to the last good spot (where we started this
|
|
LDA ZSTART ;subpacket within the buffer)
|
|
STA ZPTR
|
|
|
|
LDA #OVERFLOW
|
|
RTS
|
|
|
|
:OUT STA FRAMEEND
|
|
|
|
JSR CRCBYTE ;add the frameend into the CRC
|
|
|
|
JSR ZGETCHAR
|
|
STA FRAMECRC+1
|
|
JSR ZGETCHAR
|
|
STA FRAMECRC
|
|
|
|
CMP CRC
|
|
BNE :BADPACKET
|
|
LDA FRAMECRC+1
|
|
CMP CRC+1
|
|
BEQ :GOODPACKET
|
|
|
|
:BADPACKET
|
|
DO BUILDDEBUG
|
|
LDA ZPTR
|
|
SEC
|
|
SBC ZSTART
|
|
TAY
|
|
LDA ZPTR+1
|
|
SBC ZSTART+1
|
|
TAX
|
|
LDA #1
|
|
JSR PRINTSUB ;print the subpacket
|
|
FIN
|
|
|
|
LDA #ERROR ;tell zfile to try again
|
|
:BAD LDX ZSTART+1
|
|
STX ZPTR+1
|
|
LDX ZSTART
|
|
STX ZPTR
|
|
RTS
|
|
|
|
:GOODPACKET ; hey! ;it's good!
|
|
DO BUILDDEBUG
|
|
LDY RXBYTES
|
|
LDX RXBYTES+1
|
|
LDA #1
|
|
JSR PRINTSUB ;print the subpacket
|
|
FIN
|
|
|
|
LDA FRAMEEND ;tell them the kind of frame we got
|
|
RTS
|
|
|
|
*-------------------------------------------------
|
|
* ZRDATA32 -- get a data subpacket and return a result code
|
|
*
|
|
* outputs = (A) = result code
|
|
|
|
ZRDATA32 LDA #$FF ;init the CRC32
|
|
STA CRC32
|
|
STA CRC32+1
|
|
STA CRC32+2
|
|
STA CRC32+3
|
|
|
|
STZ RXBYTES
|
|
STZ RXBYTES+1
|
|
|
|
LDA ZPTR
|
|
STA ZSTART
|
|
CLC
|
|
ADC #<1025
|
|
STA ZEND
|
|
LDA ZPTR+1
|
|
STA ZSTART+1
|
|
ADC #>1025
|
|
STA ZEND+1
|
|
|
|
:LOOP JSR ZGETCHAR
|
|
|
|
LDX ESCAPED
|
|
BEQ :NOTESCAPED
|
|
CPX #ABORT
|
|
BEQ :BOGUS
|
|
CPX #TIMEOUT
|
|
BNE :NOTBOGUS
|
|
:BOGUS TXA
|
|
JMP :BAD
|
|
|
|
:NOTBOGUS CMP #ZCRCW
|
|
BEQ :GOOUT
|
|
CMP #ZCRCQ
|
|
BEQ :GOOUT
|
|
CMP #ZCRCG
|
|
BEQ :GOOUT
|
|
CMP #ZCRCE
|
|
BNE :NOTESCAPED
|
|
:GOOUT JMP :OUT
|
|
|
|
:NOTESCAPED INC RXBYTES
|
|
BNE :NC
|
|
INC RXBYTES+1
|
|
:NC JSR UPDATECRC32
|
|
STA (ZPTR)
|
|
|
|
LDA ZCONVERT
|
|
AND #ZCBIN
|
|
BNE :NOCONVERT
|
|
|
|
LDA ZCONVERT
|
|
AND #ZCNL
|
|
BEQ :NOCONVERT
|
|
|
|
LDA (ZPTR)
|
|
CMP #cr
|
|
BNE :NOTCR
|
|
|
|
LDA #$FF
|
|
STA GOTCR ;this falls through to go to NOCONVERT
|
|
INC ZPTR
|
|
BNE :AFTERMSDOS
|
|
INC ZPTR+1
|
|
BRA :AFTERMSDOS
|
|
|
|
:NOTCR CMP #lf
|
|
BNE :NOCONVERT
|
|
|
|
LDA GOTCR
|
|
BMI :MSDOS
|
|
|
|
:UNIX LDA #cr
|
|
STA (ZPTR)
|
|
|
|
:NOCONVERT INC ZPTR
|
|
BNE :MSDOS
|
|
INC ZPTR+1
|
|
:MSDOS STZ GOTCR ;always reset this so we don't have any stragling LFs
|
|
|
|
:AFTERMSDOS
|
|
LDA ZPTR+1 ;see if we have received a packet larger than
|
|
CMP ZEND+1 ;1k -- this is a good thing to do because Chuck
|
|
BLT :NOTOVER1K ;Forsberg's routines also can't receive larger than
|
|
LDA ZPTR ;1k packets, and we are protecting against lost
|
|
CMP ZEND ;characters at 9600 baud concatenating 2 packets
|
|
BEQ :OVER1K ;together
|
|
|
|
:NOTOVER1K
|
|
LDA ZPTR+1
|
|
CMP #>ZBUFFER+MAXBUFFERSIZE+1
|
|
BLT :LOOP
|
|
LDA ZPTR ;see if they went 1 byte over since we can
|
|
CMP #<ZBUFFER+MAXBUFFERSIZE+1 ;can match $2000 bytes exactly and not overflow
|
|
BEQ :OVER1K
|
|
JMP :LOOP ;but we need to check for overflow when we get back
|
|
|
|
:OVER1K
|
|
DO BUILDDEBUG
|
|
LDA ZPTR
|
|
SEC
|
|
SBC ZSTART
|
|
TAY
|
|
LDA ZPTR+1
|
|
SBC ZSTART+1
|
|
TAX
|
|
LDA #3 ;zr32
|
|
JSR PRINTSUB ;print the subpacket
|
|
FIN
|
|
|
|
LDA ZSTART+1 ;we overflowed. This is very bad. restore ZPTR
|
|
STA ZPTR+1 ;to the last good spot (where we started this
|
|
LDA ZSTART ;subpacket within the buffer)
|
|
STA ZPTR
|
|
|
|
LDA #OVERFLOW
|
|
RTS
|
|
|
|
:OUT STA FRAMEEND
|
|
|
|
JSR UPDATECRC32 ;add the frameend into the CRC
|
|
|
|
JSR ZGETCHAR
|
|
STA FRAMECRC32
|
|
JSR ZGETCHAR
|
|
STA FRAMECRC32+1
|
|
JSR ZGETCHAR
|
|
STA FRAMECRC32+2
|
|
JSR ZGETCHAR
|
|
STA FRAMECRC32+3
|
|
|
|
JSR invertCRC32
|
|
|
|
LDX #3
|
|
:CRC32LOOP LDA FRAMECRC32,X
|
|
CMP CRC32,X
|
|
BNE :BADPACKET
|
|
DEX
|
|
BPL :CRC32LOOP
|
|
BRA :GOODPACKET
|
|
|
|
:BADPACKET
|
|
DO BUILDDEBUG
|
|
LDA ZPTR
|
|
SEC
|
|
SBC ZSTART
|
|
TAY
|
|
LDA ZPTR+1
|
|
SBC ZSTART+1
|
|
TAX
|
|
LDA #3 ;zr32
|
|
JSR PRINTSUB ;print the subpacket
|
|
FIN
|
|
|
|
LDA #ERROR ;tell zfile to try again
|
|
:BAD LDX ZSTART+1
|
|
STX ZPTR+1
|
|
LDX ZSTART
|
|
STX ZPTR
|
|
RTS
|
|
|
|
:GOODPACKET ; hey! ;it's good!
|
|
DO BUILDDEBUG
|
|
LDY RXBYTES
|
|
LDX RXBYTES+1
|
|
LDA #3 ;zr32
|
|
JSR PRINTSUB ;print the subpacket
|
|
FIN
|
|
|
|
LDA FRAMEEND ;tell them the kind of frame we got
|
|
RTS
|
|
|
|
*-------------------------------------------------
|
|
* MOVEFILENAME
|
|
|
|
MOVEFILENAME
|
|
LDY #0 ;move the filename to a spot where it can be used
|
|
:NLOOP LDA PATHNAME+1,Y ;by acos
|
|
STA ($D),Y
|
|
INY
|
|
CPY PATHNAME
|
|
BLT :NLOOP
|
|
RTS
|
|
|
|
*-------------------------------------------------
|
|
* CLEARFILENAME -- put spaces into acos's filename
|
|
|
|
CLEARFILENAME
|
|
LDY #14 ;clear out the last filename string
|
|
LDA #' '
|
|
:CLOOP STA ($D),Y
|
|
DEY
|
|
BPL :CLOOP
|
|
RTS
|
|
|
|
*-------------------------------------------------
|
|
* CLEARTOSPACES -- clear the filename to spaces
|
|
|
|
CLEARTOSPACES
|
|
LDX #15 ;and clear out the pathname since it's going
|
|
STX PATHNAME ;to be copied back to acos's name
|
|
LDA #' '
|
|
:PLOOP STA PATHNAME+1,X
|
|
DEX
|
|
BPL :PLOOP
|
|
RTS
|
|
|
|
*-------------------------------------------------
|
|
* PRINTRZSTAT -- print the receiver's status line
|
|
|
|
DO NOTBUILDDEBUG
|
|
|
|
PRINTRZSTAT
|
|
JSR CLEARLASTLINE
|
|
|
|
LDX #<RZSTATLINE
|
|
LDA #>RZSTATLINE
|
|
JSR PRINTCSTRING
|
|
|
|
LDX #<PATHNAME
|
|
LDA #>PATHNAME
|
|
JMP PRINTPSTRING
|
|
|
|
*-------------------------------------------------
|
|
* CLEARLASTLINE -- get rid of anything on the last line
|
|
|
|
CLEARLASTLINE
|
|
LDY #0
|
|
STY HTAB
|
|
:LOOP LDA #" "
|
|
JSR LOCPRINT
|
|
INY
|
|
CPY #79
|
|
BLT :LOOP
|
|
STZ HTAB
|
|
RTS
|
|
|
|
RZSTATLINE ASC 'Receiving byte # of file '00
|
|
FIN
|
|
|
|
*-------------------------------------------------
|
|
* put the common zmodem routines at the end of RZ
|
|
|
|
NAMEHOW DB 0 ;rename this thing how?
|
|
SYNTAX DB 0 ;Did something they didn't provide kill us?
|
|
WAITFOR DW 120*9 ;9 second timeout, don't wait long
|
|
|
|
CREATEPARMS
|
|
DB 7
|
|
DW 0 ;pathname
|
|
DB $C3
|
|
DB 4 ;TXT
|
|
DW 0 ;auxtype = 0
|
|
DB 1 ;storage type
|
|
DW 0 ;create date
|
|
DW 0 ;create time
|
|
|
|
PREFIXPARMS
|
|
DB 1
|
|
DA PREFIX
|
|
|
|
WRITEPARMS
|
|
DB 4
|
|
DB 0
|
|
DA ZBUFFER
|
|
DW $1000
|
|
DW 0
|
|
|
|
DESTROYPARMS
|
|
DB 1
|
|
DW 0
|
|
|
|
DO BUILDDEBUG
|
|
PUT NO.LONG2DEC
|
|
FIN
|
|
|
|
DO NOTBUILDDEBUG
|
|
PUT LONG2DEC
|
|
FIN
|
|
|
|
PUT ZMODEM ;always
|
|
PUT ZMODEM2 ;always
|
|
|
|
SAV RZ
|
|
|