°°°±° ; °°°²° ; Source Filename: XMODEM/SRC °°°³° ; Object Filename: XMODEM/CMD °°°´° ; °°°µ° ; Program Author: Steven Bradley °°°¶° ; Creation Date: 01-27-84 °°°·° ; Version: 2.02 °°°¸° ; °°°¹° ; Last changed on: 06-05-84 °°±°° ; °°±±° ; This program is supplied for your personal and °°±²° ; non-commercial use only. No commercial use is °°±³° ; permitted. Any distribution for profit is °°±´° ; prohibited. Distribution to any system that °°±µ° ; charges for computer access is prohibited °°±¶° ; unless written permission has been obtained °°±·° ; from the program author. °°±¸° ; °°±¹° ; Please send problem reports and suggestions °°²°° ; °°²±° ; To: Steven Bradley °°²²° ; 121 Cambridge Drive °°²³° ; Longwood, Florida 32779 °°²´° ; °°²µ° ; Or call (305) 788-1968 °°²¶° ; °°²·° XKEY EQU 0 ; Bit for the 'X' key °°²¸° SOH EQU 1 ; Start of header °°²¹° BRKKEY EQU 2 ; Break key bit °°³°° EOL EQU 3 ; End of line °°³±° EOT EQU 4 ; End of transmission °°³²° DWNARR EQU 4 ; Down arrow pressed °°³³° ACK EQU 6 ; Acknowledge °°³´° BELL EQU 7 ; Ding-dong! °°³µ° BCKSPC EQU 8 ; Backspace °°³¶° LF EQU 10 ; Linefeed °°³·° CR EQU 13 ; Carriage return °°³¸° ILLFNM EQU 19 ; Illegal filename error °°³¹° INPBYT EQU 19 ; Input byte routine °°´°° NAK EQU 21 ; Negative acknowledge °°´±° CANCEL EQU 24 ; Cancel (ctrl-x) °°´²° OUTBYT EQU 27 ; Output byte routine °°´³° EOF EQU 28 ; End of file error °°´´° LCTOUC EQU 32 ; Lower to uppercase °°´µ° SPACE EQU 32 ; Space °°´¶° COMMA EQU 44 ; Comma °°´·° CHROUT EQU 51 ; Character to crt °°´¸° FEXIST EQU 53 ; File exists error °°´¹° OUTMEM EQU 59 ; Out of memory °°µ°° INPUT EQU 40H ; Line input routine °°µ±° MODEL3 EQU 49H ; Test for model III °°µ²° LCCHAR EQU 60H ; Test for lowercase char °°µ³° CONFIG EQU 6DH ; 8-1-N configuration °°µ´° HIGH EQU 80H ; Bit 7 value °°µµ° RETURN EQU 0C9H ; Return instr. °°µ¶° MR EQU 0E8H ; Master reset (rs232) °°µ·° MODEM EQU 0E8H ; Modem status port °°µ¸° CARDET EQU 5 ; Carrier detect °°µ¹° BAUD EQU 0E9H ; Set baud location °°¶°° RSCTRL EQU 0EAH ; RS232 control port °°¶±° STATUS EQU 0EAH ; RS232 status port °°¶²° DRECVD EQU 7 ; Data received °°¶³° XEMPTY EQU 6 ; Transmit buffer empty °°¶´° OVRERR EQU 5 ; Over-run error °°¶µ° FRMERR EQU 4 ; Framing error °°¶¶° RSDATA EQU 0EBH ; RS232 data port °°¶·° PORT EQU 0FEH ; Custom options port °°¶¸° M1OR3 EQU 125H ; Model I/III addr check °°¶¹° VIDEO3 EQU 473H ; Model III video driver °°·°° P10TBL EQU 13D8H ; Powers of ten table °°·±° XYZVEC EQU 3808H ; XYZ keyboard vector °°·²° CTLVEC EQU 3840H ; Control keys °°·³° SHIFT EQU 3880H ; Shift key °°·´° VIDDCB EQU 401EH ; Video DCB °°·µ° DOS EQU 402DH ; DOS exit °°·¶° NMSERR EQU 4030H ; No message error exit °°··° HIMEM1 EQU 4049H ; Model I himem °°·¸° ERROR EQU 4409H ; Error exit °°·¹° HIMEM3 EQU 4411H ; Model III himem °°¸°° GFSPEC EQU 441CH ; Get filespec °°¸±° OPENN EQU 4420H ; Open new file °°¸²° OPENE EQU 4424H ; Open old file °°¸³° CLOSE EQU 4428H ; Close file °°¸´° KILL EQU 442CH ; Kill file °°¸µ° MSGOUT EQU 4467H ; Display message °°¸¶° ORIGIN EQU 5300H ; Origin of program °°¸·° STACK EQU ORIGIN ; Stack location °°¸¸° ; °°¸¹° BR50 EQU 0 ; Baud rate values °°¹°° BR75 EQU 11H °°¹±° BR110 EQU 22H °°¹²° BR135 EQU 33H °°¹³° BR150 EQU 44H °°¹´° BR300 EQU 55H °°¹µ° BR600 EQU 66H °°¹¶° BR1200 EQU 77H °°¹·° BR1800 EQU 88H °°¹¸° BR2000 EQU 99H °°¹¹° BR2400 EQU 0AAH °±°°° BR3600 EQU 0BBH °±°±° BR4800 EQU 0CCH °±°²° BR7200 EQU 0DDH °±°³° BR9600 EQU 0EEH °±°´° BR1920 EQU 0FFH °±°µ° ; °±°¶° ORG ORIGIN °±°·° ; °±°¸° START PUSH HL ; Save command pointer °±°¹° LD HL,(HIMEM1) ; Model I addresses °±±°° LD DE,VIDEO1 °±±±° LD BC,3000H °±±²° LD A,(M1OR3) ; Check model °±±³° CP MODEL3 ; Is it a model III? °±±´° JR NZ,CM1OR3 ; No, a model I °±±µ° LD HL,(HIMEM3) ; Model III addresses °±±¶° LD DE,VIDEO3 °±±·° LD BC,4000H °±±¸° CM1OR3 LD (NEWDVR),DE ; Store video driver °±±¹° LD (RSIDLY),BC ; and input delay °±²°° LD DE,ENDPGM ; Get end of pgm addr °±²±° OR A ; Clear carry °±²²° SBC HL,DE ; Enough memory? °±²³° POP HL ; Restore command pointer °±²´° LD A,OUTMEM ; Out of memory err code °±²µ° JP C,ERROR ; and take error exit °±²¶° XOR A ; Turn off any custom °±²·° OUT (PORT),A ; port 254 options °±²¸° LD (STKSAV),SP ; Save stack pointer °±²¹° LD SP,STACK ; and set new stack °±³°° PUSH HL °±³±° CALL ILPRNT °±³²° DEFB LF °±³³° DEFM 'XMODEM File Transfer Utility - Version 2.02 / June 5, 1984' °±³´° DEFB LF °±³µ° DEFM 'Written by Steven Bradley. *** Not for sale. ***' °±³¶° DEFB CR °±³·° POP HL °±³¸° GETOPT LD A,(HL) ; Get option °±³¹° CP CR ; CR? °±´°° JP NZ,CHKOPT ; No, so check the option °±´±° BADOPT CALL ILPRNT ; Missing or bad option °±´²° DEFB LF °±´³° DEFB BELL °±´´° DEFM 'Parameters available are:' °±´µ° DEFB LF °±´¶° DEFB LF °±´·° DEFM 'Receive a new file: R {filename}' °±´¸° DEFB LF °±´¹° DEFM 'Send an existing file: S {filename}' °±µ°° DEFB LF °±µ±° DEFM 'Initialize the RS232 interface: I {=baud rate}' °±µ²° DEFB CR °±µ³° IN A,(MODEM) ; Check for carrier °±µ´° BIT CARDET,A ; Any present? °±µµ° JP Z,EXIT ; Yes, so skip this cmd °±µ¶° CALL ILPRNT °±µ·° DEFM 'Direct transfer, no modems: X' °±µ¸° DEFB CR °±µ¹° EXIT LD SP,(STKSAV) ; Restore system stack °±¶°° JP DOS ; and exit to DOS °±¶±° ; °±¶²° CHKOPT CP LCCHAR ; Is it lowercase? °±¶³° JR C,NOTLCO ; No, do not convert °±¶´° SUB LCTOUC ; Make it uppercase °±¶µ° NOTLCO LD (OPTSAV),A ; Save option °±¶¶° CP 'R' ; Receive? °±¶·° JR Z,RECSND °±¶¸° CP 'S' ; Send? °±¶¹° JR Z,RECSND °±·°° CP 'I' ; Initialize RS232 board? °±·±° JP Z,RSINIT °±·²° PUSH AF °±·³° IN A,(MODEM) ; Check for carrier °±·´° BIT CARDET,A ; any present? °±·µ° JP Z,BADOPT ; Yes, so bad option °±·¶° POP AF °±··° CP 'X' ; Direct transfer? °±·¸° JP Z,NMDMCK °±·¹° JP BADOPT ; Bad option °±¸°° ; °±¸±° FNDCHR INC HL ; Point to next character °±¸²° LD A,(HL) ; Get the char. °±¸³° CP SPACE ; Is it a space? °±¸´° JR Z,FNDCHR ; Yes, so look some more °±¸µ° CP COMMA ; Is it a comma? °±¸¶° JR Z,FNDCHR ; Yes, so look some more °±¸·° CP CR ; Set Z flag if CR °±¸¸° RET ; and return °±¸¹° ; °±¹°° FNDOPT CALL FNDCHR ; Get next character °±¹±° JP Z,EXIT ; If CR, end options chk °±¹²° JP GETOPT ; Go to normal checking °±¹³° ; °±¹´° RECSND CALL FNDCHR ; Get next character °±¹µ° JP NZ,GFILE ; If not CR, go get file °±¹¶° DEC HL ; HL=HL-1 °±¹·° LD (CMDPTR),HL ; Save command pointer °±¹¸° LD A,(OPTSAV) ; Get option key °±¹¹° CP 'R' ; Receive? °²°°° JR NZ,ASDMSG ; No, ask for send name °²°±° CALL ILPRNT °²°²° DEFB LF °²°³° DEFM 'Receiving' °²°´° DEFB EOL °²°µ° JR ASKNAM ; Go finish question °²°¶° ; °²°·° ASDMSG CALL ILPRNT ; Ask for send name °²°¸° DEFB LF °²°¹° DEFM 'Sending' °²±°° DEFB EOL °²±±° ASKNAM CALL ILPRNT ; Finish question °²±²° DEFM ' - Enter filename: ' °²±³° DEFB BELL °²±´° DEFB EOL °²±µ° LD B,23 ; Max of 23 characters °²±¶° LD HL,DSKBUF ; into disk buffer (temp) °²±·° CALL INPUT ; Get filename °²±¸° JP C,EXIT ; If break - exit °²±¹° LD A,(HL) ; Check for no input °²²°° CP CR ; CR only? °²²±° JP Z,EXIT ; Yes - exit °²²²° XOR A ; Set entry status °²²³° GFILE PUSH AF ; Save entry status °²²´° LD DE,FILE ; Get filename °²²µ° CALL GFSPEC ; Create filespec °²²¶° JR Z,NAMEOK ; If no error, else °²²·° LD A,ILLFNM+HIGH ; must be bad name °²²¸° CALL ERROR ; Display error °²²¹° JP EXIT ; and abort °²³°° ; °²³±° NAMEOK POP AF ; Get entry status °²³²° JR Z,XOPEN ; If asked for name °²³³° DEC HL ; HL=HL-1 °²³´° LD (CMDPTR),HL ; Save command pointer °²³µ° XOPEN PUSH DE °²³¶° LD B,23 ; Format filename for °²³·° LD HL,FNAME ; displaying later °²³¸° XOPENL LD A,(DE) °²³¹° CP EOL °²´°° JR Z,XOPENM °²´±° CP CR °²´²° JR Z,XOPENM °²´³° CP 'A' °²´´° JR C,CHROK °²´µ° OR LCTOUC °²´¶° SUB LCTOUC °²´·° CHROK LD (HL),A °²´¸° INC DE °²´¹° INC HL °²µ°° DJNZ XOPENL °²µ±° XOPENM LD (HL),CR °²µ²° POP DE °²µ³° LD B,0 ; LRL=256 °²µ´° LD HL,DSKBUF ; Sector buffer °²µµ° LD A,(OPTSAV) ; Get option key °²µ¶° CP 'R' ; Is it receive? °²µ·° JR NZ,OPENSF ; No, it is send °²µ¸° CALL OPENN ; Open new file °²µ¹° JR Z,RFOPEN ; Go if no error °²¶°° OPNERR OR HIGH ; Make it CALLable °²¶±° CALL ERROR ; Display error °²¶²° JP EXIT ; and abort °²¶³° ; °²¶´° RFOPEN JR C,RECEIV ; Go if new file created °²¶µ° CALL CLOSEF ; else close file because °²¶¶° LD A,FEXIST ; file already exists err °²¶·° JR OPNERR ; Display error and exit °²¶¸° ; °²¶¹° OPENSF CALL OPENE ; Open existing file °²·°° JP Z,SEND ; Go to send if no error °²·±° JR OPNERR ; Show error and exit °²·²° ; °²·³° RECEIV LD HL,FMSG °²·´° CALL MSGOUT °²·µ° CALL ILPRNT °²·¶° DEFB LF °²··° DEFM 'Enter ctrl-x to abort file transfer.' °²·¸° DEFB LF °²·¹° DEFB LF °²¸°° DEFM 'Ready to receive - awaiting transmission.' °²¸±° DEFB CR °²¸²° CALL INITRS ; Receive-send init °²¸³° XOR A ; Zero first block °²¸´° LD (FIRST),A ; SOH found status °²¸µ° LD A,NAK ; Send a negative °²¸¶° CALL CRSOUT ; acknowledge °²¸·° RECFIL CALL INCBLK ; Increment block count °²¸¸° CALL RECBKS ; Receive a block °²¸¹° JR C,RECEND ; Go if end of file °²¹°° LD A,(BLOCKS) ; Increment the °²¹±° INC A ; number of °²¹²° LD (BLOCKS),A ; transferred °²¹³° CP 20 ; Have there been 20? °²¹´° CALL Z,SAVBLK ; Yes, so save the blocks °²¹µ° CALL SNDACK ; Send acknowledge °²¹¶° JR RECFIL ; and go receive more °²¹·° ; °²¹¸° RECEND LD A,(BLOCKS) ; Get blocks xfered count °²¹¹° OR A ; Zero blocks? °³°°° CALL NZ,SAVBLK ; If blocks to be saved °³°±° CALL CLOSEF ; Close the file °³°²° OR A ; Any error occured? °³°³° JP NZ,ABORT ; Yes, so send cancel °³°´° CALL SNDACK ; No, so send acknowledge °³°µ° JP SUCCES ; and xfer completed °³°¶° ; °³°·° RECBKS XOR A ; Zero number of tries °³°¸° LD (TRIES),A ; counter °³°¹° RECBLK LD B,10 ; 10 seconds per attempt °³±°° CALL CRSINP ; Look for a character °³±±° JR C,RTRIES ; If no char, check tries °³±²° CP CANCEL ; Cancelled? °³±³° JP Z,ABORT ; Yes, so abort transfer °³±´° CP SOH ; Is it start of header? °³±µ° JR Z,RECBKH ; Yes, so get first block °³±¶° CP EOT ; End of transmission? °³±·° SCF ; Maybe... °³±¸° RET Z ; Yes, so return °³±¹° RTRIES CALL WNCHRS ; No, wait until no chars °³²°° LD A,NAK ; and then send negative °³²±° CALL CRSOUT ; acknowledge °³²²° BADACK LD A,(FIRST) ; Check for initial block °³²³° OR A ; Has it been started? °³²´° JR Z,CRTRYS ; No error display needed °³²µ° CALL DPYBLK ; Display error block # °³²¶° CALL ILPRNT ; Display * error status °³²·° DEFM '* ' °³²¸° DEFB EOL °³²¹° CRTRYS LD A,(TRIES) ; Get number of attempts °³³°° INC A ; and increment it by 1 °³³±° LD (TRIES),A ; Store # attempts left °³³²° CP 10 ; Have there been 10? °³³³° JR NZ,RECBLK ; If not 10, try again °³³´° JP ABORT ; else abort transfer! °³³µ° ; °³³¶° RECBKH LD A,HIGH ; Since an SOH was recvd °³³·° LD (FIRST),A ; rest of blk should come °³³¸° CALL DPYBLK ; Display current block # °³³¹° LD BC,RTRIES ; Save error return addr °³´°° PUSH BC ; for convenient exits °³´±° LD B,1 ; 1 second attempt °³´²° CALL CRSINP ; Look for a character °³´³° RET C ; If no character, exit °³´´° LD D,A ; Save first block number °³´µ° LD B,1 ; 1 second attempt °³´¶° CALL CRSINP ; Look for a character °³´·° RET C ; If no character, exit °³´¸° CPL ; Make normal block # °³´¹° CP D ; Is it the same? °³µ°° RET NZ ; No, so error exit °³µ±° LD A,(BLKCNT) ; Check block number °³µ²° CP D ; Is it the same? °³µ³° JR Z,NEWBLK ; Yes, go get block °³µ´° DEC A ; Check for bad ack char °³µµ° CP D ; Was it previous block? °³µ¶° RET NZ ; No, so error exit °³µ·° CALL WNCHRS ; Yes, so wait until all °³µ¸° CALL SNDACK ; sent, then send an ack °³µ¹° POP HL ; Fix stack °³¶°° JR BADACK ; and try block again °³¶±° ; °³¶²° NEWBLK LD HL,(BLKADR) ; Get start of block °³¶³° LD E,128 ; 128 bytes expected °³¶´° LD C,0 ; Zero checksum °³¶µ° RECBLP LD B,1 ; 1 second attempt °³¶¶° CALL CRSINP ; Look for character °³¶·° RET C ; If no character, exit °³¶¸° LD (HL),A ; Store character °³¶¹° INC HL ; Increment buffer ptr °³·°° DEC E ; Decrement # received °³·±° JR NZ,RECBLP ; and loop if not 0 °³·²° LD D,C ; Save calculated chksum °³·³° LD B,1 ; 1 second attempt °³·´° CALL CRSINP ; Look for character °³·µ° RET C ; If no character, exit °³·¶° CP D ; Do checksums match? °³··° RET NZ ; If no match, error exit °³·¸° LD (BLKADR),HL ; Save new address °³·¹° POP HL ; and pop the error addr °³¸°° RET ; and we are done °³¸±° ; °³¸²° SAVBLK LD HL,BUFFER ; Get start of buffer °³¸³° LD DE,FILE ; Open file °³¸´° LD C,A ; Number of blocks °³¸µ° SAVEBK LD B,128 ; Length of each block °³¸¶° SAVELP LD A,(HL) ; Get a byte °³¸·° CALL OUTBYT ; Write to disk file °³¸¸° JR Z,NSERR ; Go if no error °³¸¹° OR HIGH ; Make it CALLable °³¹°° CALL ERROR ; Display error °³¹±° JP ABORT ; and abort °³¹²° ; °³¹³° NSERR INC HL ; Increment buffer °³¹´° DJNZ SAVELP ; Loop until 128 written °³¹µ° DEC C ; Decrement blocks °³¹¶° JR NZ,SAVEBK ; Loop until all written °³¹·° XOR A ; Zero number of blocks °³¹¸° LD (BLOCKS),A ; transferred °³¹¹° LD HL,BUFFER ; Reset block buffer °´°°° LD (BLKADR),HL ; to the start of buffer °´°±° RET °´°²° ; °´°³° SEND LD HL,(FILE+12) ; Get # of full records °´°´° ADD HL,HL ; # of 128 byte records °´°µ° LD A,(FILE+8) ; and see if any in eof °´°¶° OR A ; Any bytes in eof sec? °´°·° JR Z,CALC ; No, so go calc °´°¸° INC HL ; Increment # of records °´°¹° CP 129 ; See how many recs, 1-2 °´±°° JR C,CALC ; If 1 record, end check °´±±° INC HL ; otherwise 2 records °´±²° CALC PUSH HL ; Save number of records °´±³° XOR A ; Zero number of °´±´° LD (BLOCKS),A ; blocks counter °´±µ° LD DE,0 ; Init seconds counter °´±¶° LD BC,5 ; Init i/o time used °´±·° LD A,132 ; Number bytes per record °´±¸° PUSH AF ; and save it to stack °´±¹° JR CALENT ; Enter calculation loop °´²°° ; °´²±° CALC1 POP AF ; Get number left in rec °´²²° SUB 30 ; 30 cps °´²³° PUSH AF ; Save number left in rec °´²´° JR C,CALC2 ; End loop if not enough °´²µ° ; °´²¶° INC DE ; Increment # of seconds °´²·° JR CALC1 ; and resume calculating °´²¸° ; °´²¹° CALC2 POP AF ; Get number left °´³°° ADD A,162 ; Add previous & next rec °´³±° PUSH AF ; Store new value °´³²° LD A,(BLOCKS) ; Get record count °´³³° INC A ; Increment it °´³´° CP 2 ; Have there been 2? °´³µ° JR NZ,CALC3 ; No, so nothing done °´³¶° ; °´³·° INC BC ; Inc i/o seconds count °´³¸° XOR A ; and zero record count °´³¹° ; °´´°° CALC3 LD (BLOCKS),A ; Store new count °´´±° DEC HL ; Decrement # of records °´´²° CALENT LD A,H ; Check for end of record °´´³° OR L ; End of records? °´´´° JR NZ,CALC1 ; No, so go get more °´´µ° ; °´´¶° POP AF ; Fix the stack °´´·° PUSH BC ; Save i/o seconds °´´¸° PUSH DE ; Save seconds for later °´´¹° ; °´µ°° EX DE,HL ; Move DE to HL °´µ±° ADD HL,BC ; Get total seconds °´µ²° LD BC,60 ; Number to divide by °´µ³° CALL DIVIDE ; Divide 60 into HL °´µ´° PUSH DE ; Save remainder °´µµ° LD B,3 ; 3 places °´µ¶° LD A,B ; Suppress leading zeroes °´µ·° LD DE,BM300 ; Where to store it °´µ¸° CALL BINASC ; Convert to ascii °´µ¹° POP HL ; Get remainder °´¶°° LD B,2 ; 2 places °´¶±° LD A,B ; Suppress leading zeroes °´¶²° LD DE,BS300 ; Where to store it °´¶³° CALL BINASC ; Convert to ascii °´¶´° POP HL ; Now to calc for 1200 °´¶µ° LD BC,4 ; Number to divide by °´¶¶° CALL DIVIDE ; Divide 4 into HL °´¶·° POP BC ; Get i/o seconds °´¶¸° ADD HL,BC ; and add for total secs °´¶¹° LD BC,60 ; Number to divide by °´·°° CALL DIVIDE ; Divide 60 into HL °´·±° PUSH DE ; Save remainder °´·²° LD B,3 ; 3 places °´·³° LD A,B ; Suppress leading zeroes °´·´° LD DE,BM1200 ; Where to store it °´·µ° CALL BINASC ; Convert to ascii °´·¶° POP HL ; Get remainder °´··° LD B,2 ; 2 places °´·¸° LD A,B ; Suppress leading zeroes °´·¹° LD DE,BS1200 ; Where to store it °´¸°° CALL BINASC ; Convert to ascii °´¸±° ; °´¸²° POP HL ; Get number of records °´¸³° PUSH HL ; and keep it saved °´¸´° LD B,5 ; 5 places °´¸µ° LD A,B ; Suppress leading zeroes °´¸¶° LD DE,NUMREC ; Where to store it °´¸·° CALL BINASC ; Convert to ascii °´¸¸° ; °´¸¹° POP HL ; Get number of records °´¹°° LD BC,8 ; Divide them by 8 to °´¹±° CALL DIVIDE ; get number of K bytes °´¹²° PUSH DE ; and save the remainder °´¹³° LD B,3 ; 3 places °´¹´° LD A,B ; Suppress leading zeroes °´¹µ° LD DE,KBYTES ; Where to store it °´¹¶° CALL BINASC ; Convert it to ascii °´¹·° ; °´¹¸° POP HL ; Get number of records °´¹¹° LD B,10 ; Number to multiply by °µ°°° CALL MULT ; Multiply by 10 °µ°±° LD BC,8 ; Get 10ths of a K °µ°²° CALL DIVIDE ; Go get it °µ°³° LD A,L ; Get value °µ°´° ADD A,'0' ; Make it ascii °µ°µ° LD (DBYTES),A ; and store it °µ°¶° ; °µ°·° LD HL,FMSG °µ°¸° CALL MSGOUT °µ°¹° CALL ILPRNT ; Show message °µ±°° DEFB LF °µ±±° DEFM 'File size in Kilobytes: ' °µ±²° KBYTES DEFM 'kkk.' °µ±³° DBYTES DEFM 'd (1 K-byte = 1024 bytes) °µ±´° DEFB LF °µ±µ° DEFM ' Block(s): ' °µ±¶° NUMREC DEFM 'nnnnn (1 Block = 128 bytes)' °µ±·° DEFB LF °µ±¸° DEFB LF °µ±¹° DEFM 'Send time at 1200 baud: ' °µ²°° BM1200 DEFM 'mmm minute(s), ' °µ²±° BS1200 DEFM 'ss second(s).' °µ²²° DEFB LF °µ²³° DEFM ' 300 baud: ' °µ²´° BM300 DEFM 'mmm minute(s), ' °µ²µ° BS300 DEFM 'ss second(s).' °µ²¶° DEFB LF °µ²·° DEFB LF °µ²¸° DEFM 'Enter ctrl-x to abort file transfer.' °µ²¹° DEFB LF °µ³°° DEFB LF °µ³±° DEFM 'Ready to send - awaiting initial NAK.' °µ³²° DEFB CR °µ³³° ; °µ³´° CALL INITRS ; Send initialization °µ³µ° ; °µ³¶° LD E,90 ; Number of tries for NAK °µ³·° ; °µ³¸° GETNAK LD B,1 ; 1 second attempt °µ³¹° CALL CRSINP ; Look for a character °µ´°° JR C,NOCHAR ; If no character °µ´±° ; °µ´²° CP NAK ; NAK received? °µ´³° JR Z,SNDFIL ; Yes, so go send file °µ´´° ; °µ´µ° CP CANCEL ; Is it cancelled? °µ´¶° JP Z,ABORT ; Yes, so go abort xfer °µ´·° ; °µ´¸° NOCHAR DEC E ; Keep looking? °µ´¹° JR NZ,GETNAK ; Yes °µµ°° JP ABORT ; No, abort transfer °µµ±° ; °µµ²° SNDFIL CALL INCBLK ; Increment block number °µµ³° LD A,(BLOCKS) ; Check number of blocks °µµ´° OR A ; More needed? °µµµ° CALL Z,GETBKS ; If we have run out °µµ¶° JR C,SNDEND ; If end of file °µµ·° CALL SNDBKS ; Send the blocks °µµ¸° JR SNDFIL ; and go get/send more °µµ¹° ; °µ¶°° SNDEND LD A,(BLOCKS) ; Check number to send °µ¶±° OR A ; Are there any left? °µ¶²° JR Z,SNDEOT ; No, so go send EOT °µ¶³° CALL SNDBKS ; Send last blocks °µ¶´° CALL INCBLK ; Increment block count °µ¶µ° JR SNDEND ; Loop if more to send °µ¶¶° ; °µ¶·° SNDEOT CALL SNDBKS ; Send EOT character °µ¶¸° CALL CLOSEF ; Close the file °µ¶¹° JP SUCCES ; and xfer completed °µ·°° ; °µ·±° GETBKS LD HL,BUFFER ; Get start of buffer °µ·²° LD (BLKADR),HL ; Store start of block °µ·³° LD DE,FILE ; Open file °µ·´° LD C,0 ; Zero blocks read °µ·µ° ; °µ·¶° LOADBK LD B,128 ; Length of each block °µ··° ; °µ·¸° LOADLP CALL INPBYT ; Read a byte °µ·¹° JR Z,NLERR ; Go if no error °µ¸°° ; °µ¸±° CP EOF ; End of file? °µ¸²° JR Z,LDEOF ; Yes, go to eof routine °µ¸³° ; °µ¸´° OR HIGH ; Make it CALLable °µ¸µ° CALL ERROR ; Display error °µ¸¶° JP ABORT ; and abort °µ¸·° ; °µ¸¸° NLERR LD (HL),A ; Store byte °µ¸¹° INC HL ; and prepare for next °µ¹°° DJNZ LOADLP ; Read rest of block °µ¹±° ; °µ¹²° INC C ; Increment blocks read °µ¹³° ; °µ¹´° LD A,20 ; Check # blocks read °µ¹µ° CP C ; Have we read 20? °µ¹¶° JR NZ,LOADBK ; No, so read more °µ¹·° ; °µ¹¸° LD (BLOCKS),A ; Store number read °µ¹¹° RET ; and return °¶°°° ; °¶°±° LDEOF LD A,128 ; Check bytes read °¶°²° CP B ; Any bytes read in? °¶°³° JR Z,LDEND ; No, so skip fill °¶°´° ; °¶°µ° XOR A ; Set fill char = 0 °¶°¶° ; °¶°·° LDFILL LD (HL),A ; Store character °¶°¸° INC HL ; Increment buffer °¶°¹° DJNZ LDFILL ; and loop until filled °¶±°° ; °¶±±° INC C ; Inc blocks read count °¶±²° ; °¶±³° LDEND LD A,C ; Get block count °¶±´° LD (BLOCKS),A ; and store it °¶±µ° SCF ; Show end of file °¶±¶° RET ; and we are done °¶±·° ; °¶±¸° SNDBKS XOR A ; Zero number of tries °¶±¹° LD (TRIES),A ; counter °¶²°° ; °¶²±° SNDBLK LD A,(BLOCKS) ; Check if any to send °¶²²° OR A ; Are there any blocks? °¶²³° JR Z,SDEOTC ; No, send EOT character °¶²´° ; °¶²µ° CALL DPYBLK ; Since not EOT block °¶²¶° ; °¶²·° LD A,SOH ; Send start of header °¶²¸° CALL CRSOUT ; character °¶²¹° ; °¶³°° LD A,(BLKCNT) ; Get block count °¶³±° CALL CRSOUT ; Send it °¶³²° CPL ; Complement it °¶³³° CALL CRSOUT ; Send it °¶³´° ; °¶³µ° LD HL,(BLKADR) ; Get start of block °¶³¶° LD B,128 ; 128 bytes / block °¶³·° LD C,0 ; Zero checksum °¶³¸° ; °¶³¹° SNDBLP LD A,(HL) ; Get character °¶´°° CALL CRSOUT ; Send it °¶´±° INC HL ; Prepare for next °¶´²° DJNZ SNDBLP ; and keep sending °¶´³° ; °¶´´° LD A,C ; Get checksum °¶´µ° CALL CRSOUT ; and send it °¶´¶° ; °¶´·° SNDAWT LD B,10 ; 10 seconds per attempt °¶´¸° CALL CRSINP ; Look for a character °¶´¹° JR C,STRIES ; If no character °¶µ°° ; °¶µ±° CP CANCEL ; Is it cancelled? °¶µ²° JP Z,ABORT ; Yes, so abort °¶µ³° ; °¶µ´° CP ACK ; Acknowledge character? °¶µµ° JR NZ,STRIES ; No, so check tries °¶µ¶° ; °¶µ·° LD A,(BLOCKS) ; Decrement number of °¶µ¸° OR A ; Is it zero? °¶µ¹° RET Z ; Yes, so end here °¶¶°° DEC A ; Decrement blocks left °¶¶±° LD (BLOCKS),A ; and store new number °¶¶²° LD (BLKADR),HL ; Store new block addr °¶¶³° RET ; and we are done °¶¶´° ; °¶¶µ° SDEOTC LD A,EOT ; Send EOT °¶¶¶° CALL CRSOUT ; character °¶¶·° JR SNDAWT ; and look for ack °¶¶¸° ; °¶¶¹° STRIES CALL WNCHRS ; Wait until no chars °¶·°° CALL ILPRNT ; Display * error status °¶·±° DEFM '* ' ; °¶·²° DEFB EOL ; °¶·³° ; °¶·´° LD A,(TRIES) ; Get number of attempts °¶·µ° INC A ; and increment it by 1 °¶·¶° LD (TRIES),A ; Store # attempts left °¶··° CP 10 ; Have there been 10? °¶·¸° JR NZ,SNDBLK ; If not 10, try again °¶·¹° JP ABORT ; else abort transfer! °¶¸°° ; °¶¸±° RSINIT LD BC,2 ; Wait for RS232 data °¶¸²° CALL DELAY ; registers to clear °¶¸³° ; °¶¸´° OUT (MR),A ; Reset the RS232 board °¶¸µ° ; °¶¸¶° INC HL °¶¸·° LD A,(HL) °¶¸¸° CP '=' °¶¸¹° JR Z,GIBAUD °¶¹°° DEC HL °¶¹±° PUSH HL °¶¹²° LD HL,BDTBL °¶¹³° IN A,(BAUD) °¶¹´° AND 7 °¶¹µ° LD B,0 °¶¹¶° LD C,A °¶¹·° ADD HL,BC °¶¹¸° LD A,(HL) °¶¹¹° JR CRS232 °·°°° GIBAUD PUSH HL °·°±° LD B,0 °·°²° FBDLEN INC HL °·°³° INC B °·°´° LD A,(HL) °·°µ° CP '0' °·°¶° JR C,FBDEND °·°·° CP '9'+1 °·°¸° JR C,FBDLEN °·°¹° FBDEND DEC B °·±°° POP DE °·±±° INC DE °·±²° LD A,B °·±³° OR A °·±´° JP Z,BADOPT °·±µ° CP 6 °·±¶° JP NC,BADOPT °·±·° CALL ASCBIN °·±¸° PUSH DE °·±¹° PUSH HL °·²°° POP BC °·²±° LD IX,BDCTBL °·²²° FIBDLP LD L,(IX+0) °·²³° LD H,(IX+1) °·²´° LD A,H °·²µ° OR L °·²¶° JP Z,BADOPT °·²·° LD A,(IX+2) °·²¸° INC IX °·²¹° INC IX °·³°° INC IX °·³±° SBC HL,BC °·³²° JR NZ,FIBDLP °·³³° CRS232 LD IX,BDCTBL-3 °·³´° GBDRLP INC IX °·³µ° INC IX °·³¶° INC IX °·³·° CP (IX+2) °·³¸° JR NZ,GBDRLP °·³¹° PUSH AF °·´°° LD L,(IX+0) °·´±° LD H,(IX+1) °·´²° LD DE,BAUDMS °·´³° LD B,5 °·´´° LD A,B °·´µ° CALL BINASC °·´¶° POP AF °·´·° OUT (BAUD),A ; Set the baud rate °·´¸° LD A,CONFIG ; 8 word, 1 stop, no par. °·´¹° OUT (RSCTRL),A ; Set the configuration °·µ°° ; °·µ±° CALL ILPRNT ; Display initialized msg °·µ²° DEFB LF °·µ³° DEFM 'The serial interface has been configured for xmodem file xfer.' °·µ´° DEFB LF °·µµ° DEFM 'Configuration is 8 bit word length, 1 stop bit, and no parity.' °·µ¶° DEFB LF °·µ·° DEFB LF °·µ¸° DEFM 'Baud rate selected: ' °·µ¹° BAUDMS DEFM 'nnnnn bps.' °·¶°° DEFB CR °·¶±° ; °·¶²° POP HL ; Get command pointer °·¶³° JP FNDOPT ; Check for more options °·¶´° ; °·¶µ° NMDMCK LD A,RETURN ; Set a bypass return °·¶¶° LD (MDMCHK),A ; to not check carrier °·¶·° PUSH HL ; Save cmd params °·¶¸° CALL ILPRNT °·¶¹° DEFB LF °··°° DEFM 'Modem carrier check disabled for direct serial to serial xfer.' °··±° DEFB CR °··²° ; °··³° POP HL °··´° JP FNDOPT ; Go check next option °··µ° ; °··¶° DELAY PUSH BC ; Save count °···° LD BC,0 ; 1 second of delay °··¸° CALL 60H ; Delay for 1 second °··¹° POP BC ; Get count °·¸°° DEC BC ; Decrement it °·¸±° LD A,B ; Is it °·¸²° OR C ; zero? °·¸³° JR NZ,DELAY ; No, so delay some more °·¸´° RET ; otherwise return °·¸µ° ; °·¸¶° MULT PUSH HL ; Move the value to DE °·¸·° POP DE ; without losing HL °·¸¸° ; °·¸¹° MULTLP ADD HL,DE ; Do the multiplying °·¹°° DJNZ MULTLP ; Until done °·¹±° RET ; and then return °·¹²° ; °·¹³° DIVIDE OR A ; Clear carry °·¹´° LD DE,0 ; To be used as a counter °·¹µ° ; °·¹¶° DIVLP SBC HL,BC ; Subtract °·¹·° JR C,DIVEND ; until carry °·¹¸° INC DE ; and increment each time °·¹¹° JR DIVLP ; Keep going til too much °¸°°° ; °¸°±° DIVEND ADD HL,BC ; Fix value °¸°²° EX DE,HL ; Flip the count and the °¸°³° RET ; remainder, then return °¸°´° ; °¸°µ° BINASC LD (BAFLAG),A ; Zero=spaces option °¸°¶° LD IX,P10TBL+10 ; Get powers of ten table °¸°·° LD A,B ; Check # of positions °¸°¸° OR A ; Zero positions? °¸°¹° JR NZ,BA0 ; No, so ok °¸±°° ; °¸±±° LD B,1 ; Set to 1 position °¸±²° LD A,B ; and in register A too! °¸±³° ; °¸±´° BA0 CP 6 ; Check for too many °¸±µ° JR C,BA1 ; Go if not too many °¸±¶° ; °¸±·° LD B,5 ; Set to 5 positions °¸±¸° LD A,B ; and in register A too! °¸±¹° ; °¸²°° BA1 DEC IX ; Get location in table °¸²±° DEC IX ; °¸²²° DJNZ BA1 ; and loop until found °¸²³° ; °¸²´° CP 5 ; Max value allowed? °¸²µ° JR Z,BA2 ; Yes, so no check needed °¸²¶° ; °¸²·° PUSH HL ; Save value °¸²¸° LD B,(IX-1) ; Get check value °¸²¹° LD C,(IX-2) ; to test for too high °¸³°° OR A ; Clear carry flag °¸³±° SBC HL,BC ; Too high? °¸³²° POP HL ; Fix HL °¸³³° JR C,BA2 ; Not too high, so skip °¸³´° ; °¸³µ° PUSH BC ; Move BC to HL °¸³¶° POP HL ; °¸³·° DEC HL ; Set highest value °¸³¸° ; °¸³¹° BA2 XOR A ; Zero leading zeroes °¸´°° LD (LEADNZ),A ; check flag °¸´±° ; °¸´²° BA3 XOR A ; Zero the A register °¸´³° LD C,(IX+0) ; Get current power of °¸´´° LD B,(IX+1) ; ten from the table °¸´µ° ; °¸´¶° BA4 SBC HL,BC ; Subtract values °¸´·° JR C,BA5 ; until too much °¸´¸° ; °¸´¹° INC A ; Increment ascii value °¸µ°° JR BA4 ; and keep going °¸µ±° ; °¸µ²° BA5 ADD HL,BC ; Fix value °¸µ³° ADD A,'0' ; Make ascii character °¸µ´° PUSH AF ; Save character °¸µµ° LD A,C ; Check for last location °¸µ¶° CP 1 ; Is it last? °¸µ·° JR Z,BA7 ; Yes, no more processing °¸µ¸° ; °¸µ¹° POP AF ; Restore AF °¸¶°° PUSH AF ; and keep it on stack °¸¶±° CP '0' ; Ascii zero? °¸¶²° JR Z,BA6 ; Yes, so go process °¸¶³° ; °¸¶´° LD A,HIGH ; Set flag to a °¸¶µ° LD (LEADNZ),A ; non-zero value °¸¶¶° ; °¸¶·° BA6 LD A,0 ; Check for storing °¸¶¸° BAFLAG EQU $-1 ; leading zeroes °¸¶¹° OR A ; Store them? °¸·°° JR Z,BA7 ; Yes °¸·±° LD A,0 ; Check for previous °¸·²° LEADNZ EQU $-1 ; non-zero value stored °¸·³° OR A ; Any found? °¸·´° JR NZ,BA7 ; Yes, so store value °¸·µ° POP AF ; Get character °¸·¶° LD A,SPACE ; Change it to a space °¸··° PUSH AF ; and restore character °¸·¸° ; °¸·¹° BA7 POP AF ; Get character from stk °¸¸°° LD (DE),A ; Store character °¸¸±° INC DE ; Prepare for next °¸¸²° LD A,C ; Check for end °¸¸³° CP 1 ; Have we done yet? °¸¸´° RET Z ; Yes, so return °¸¸µ° INC IX ; No, so get next °¸¸¶° INC IX ; power of ten position °¸¸·° JR BA3 ; and resume converting °¸¸¸° ; °¸¸¹° ASCBIN LD IX,P10TBL+10 ; Obtain powers of ten °¸¹°° LD HL,0 ; Initialize HL to zero °¸¹±° LD A,B ; Check for zero pos(s) °¸¹²° OR A ; Zero? °¸¹³° JR NZ,AB0 ; No, so skip section °¸¹´° ; °¸¹µ° LD B,1 ; Set field to 1 °¸¹¶° LD A,B ; and store new value °¸¹·° ; °¸¹¸° AB0 CP 6 ; Check for too many! °¸¹¹° JR C,AB1 ; If less than 6 °¹°°° LD B,5 ; Set to max allowed °¹°±° ; °¹°²° AB1 DEC IX ; Find place in table °¹°³° DEC IX ; °¹°´° DJNZ AB1 ; Until B=0 °¹°µ° ; °¹°¶° AB2 XOR A ; Clear flags °¹°·° LD C,(IX+0) ; Obtain power of ten °¹°¸° LD B,(IX+1) ; °¹°¹° LD A,(DE) ; Get value from buffer °¹±°° SUB '0' ; and make it 0-9 binary °¹±±° ; °¹±²° AB3 SUB 1 ; Decrement it °¹±³° JR C,AB4 ; until too many °¹±´° ADD HL,BC ; Accum value if not °¹±µ° JR AB3 ; and keep looping °¹±¶° ; °¹±·° AB4 LD A,C ; Check for end °¹±¸° CP 1 ; Are we there? °¹±¹° RET Z ; Yes, so return °¹²°° INC DE ; else get next position °¹²±° INC IX ; and next power of ten °¹²²° INC IX ; °¹²³° JR AB2 ; and keep looping °¹²´° ; °¹²µ° ILPRNT POP HL ; Get message address °¹²¶° LD A,(HL) ; and char found there °¹²·° INC HL ; Increment for next char °¹²¸° PUSH HL ; and push back on stack °¹²¹° ; °¹³°° CP EOL ; End of line? °¹³±° RET Z ; Yes, so we are done °¹³²° ; °¹³³° PUSH AF ; Save AF and DE °¹³´° PUSH DE ; °¹³µ° CALL CHROUT ; Display character °¹³¶° POP DE ; Restore DE and AF °¹³·° POP AF ; °¹³¸° ; °¹³¹° CP CR ; Was it a CR? °¹´°° RET Z ; Yes, so we are done °¹´±° ; °¹´²° JR ILPRNT ; Look for next character °¹´³° ; °¹´´° CLOSEF LD DE,FILE ; Get open file °¹´µ° CALL CLOSE ; try and close it °¹´¶° RET Z ; Done if no error °¹´·° OR HIGH ; Make it CALLable °¹´¸° JP ERROR ; and return to previous °¹´¹° ; °¹µ°° ABORT IN A,(MODEM) ; Check for carrier °¹µ±° BIT CARDET,A ; Carrier detected? °¹µ²° JR NZ,ABORT1 ; No, so skip cancel send °¹µ³° ; °¹µ´° CALL WNCHRS ; Wait until no chars °¹µµ° LD A,CANCEL ; Send the cancel char °¹µ¶° CALL CRSOUT ; to show aborting °¹µ·° ; °¹µ¸° ABORT1 CALL VIDFIX ; Fix the video output °¹µ¹° LD DE,FILE ; Get open file °¹¶°° LD A,(OPTSAV) ; Check receive or send °¹¶±° CP 'R' ; Receive? °¹¶²° JR NZ,SNDABT ; No, must be send °¹¶³° ; °¹¶´° CALL KILL ; Kill received file °¹¶µ° JR RECABT ; Exit to receive abort °¹¶¶° ; °¹¶·° SNDABT CALL CLOSEF ; Close send file °¹¶¸° RECABT JR Z,DPYABT ; Display abort message °¹¶¹° OR HIGH ; Make it CALLable °¹·°° CALL ERROR ; Display error °¹·±° ; °¹·²° DPYABT CALL ILPRNT ; Display message °¹·³° DEFB BELL °¹·´° DEFB LF °¹·µ° DEFB LF °¹·¶° DEFM '>> File transfer aborted!' °¹··° DEFB CR °¹·¸° ; °¹·¹° JP EXIT ; and take normal exit °¹¸°° ; °¹¸±° SUCCES CALL VIDFIX ; Fix video output °¹¸²° CALL ILPRNT ; Display message °¹¸³° DEFB BELL °¹¸´° DEFB LF °¹¸µ° DEFB LF °¹¸¶° DEFM '>> File transfer completed.' °¹¸·° DEFB CR °¹¸¸° ; °¹¸¹° LD HL,(CMDPTR) ; Get command pointer °¹¹°° JP FNDOPT ; and see if more waiting °¹¹±° ; °¹¹²° VIDFIX LD HL,(VIDSAV) ; Get old video driver °¹¹³° LD (VIDDCB),HL ; and store it °¹¹´° RET ; and return °¹¹µ° ; °¹¹¶° INCBLK PUSH AF ; Save AF °¹¹·° LD A,(BLKCNT) ; Get block count °¹¹¸° INC A ; and increment it °¹¹¹° LD (BLKCNT),A ; and save it ±°°°° POP AF ; Restore AF ±°°±° RET ; then return ±°°²° ; ±°°³° SNDACK LD A,ACK ; Send acknowledge ±°°´° JP CRSOUT ; character ±°°µ° ; ±°°¶° WNCHRS LD B,1 ; 1 second attempt ±°°·° CALL CRSINP ; Look for character ±°°¸° JR NC,WNCHRS ; Loop if character found ±°°¹° RET ; otherwise return ±°±°° ; ±°±±° ABTCHK LD A,(CTLVEC) ; Get control keys info ±°±²° BIT BRKKEY,A ; Break pressed? ±°±³° JR Z,CTLXCK ; No, so check ctrl-x ±°±´° ; ±°±µ° BRKLP LD A,(CTLVEC) ; Get control keys info ±°±¶° BIT BRKKEY,A ; Break still held down? ±°±·° JR NZ,BRKLP ; Yes, wait 'til released ±°±¸° ABTKEY JP ABORT ; Abort transfer ±°±¹° ; ±°²°° CTLXCK LD A,(SHIFT) ; Check shift key ±°²±° OR A ; Is it pressed? ±°²²° JR Z,MDMCHK ; No, so check modem ±°²³° LD A,(CTLVEC) ; Check down arrow ±°²´° BIT DWNARR,A ; Is it pressed? ±°²µ° JR Z,MDMCHK ; No, so check modem ±°²¶° LD A,(XYZVEC) ; Check for key X ±°²·° BIT XKEY,A ; Is it pressed? ±°²¸° JR Z,MDMCHK ; No, so check modem ±°²¹° ; ±°³°° CTLXLP LD A,(SHIFT) ; Wait 'til keys released ±°³±° OR A ; Is shift pressed? ±°³²° JR NZ,CTLXLP ; Yes, so try again ±°³³° LD A,(CTLVEC) ; Check down arrow ±°³´° BIT DWNARR,A ; Is it pressed? ±°³µ° JR NZ,CTLXLP ; Yes, so try again ±°³¶° LD A,(XYZVEC) ; Check for key X ±°³·° BIT XKEY,A ; Is it pressed? ±°³¸° JR NZ,CTLXLP ; Yes, so try again ±°³¹° JR ABTKEY ; Jump to abort routine ±°´°° ; ±°´±° MDMCHK NOP ; If bypass = return ±°´²° IN A,(MODEM) ; Check for carrier ±°´³° BIT CARDET,A ; Carrier present? ±°´´° RET Z ; Yes, so we are done ±°´µ° ; ±°´¶° CALL ILPRNT ; Display a message ±°´·° DEFB BELL ±°´¸° DEFB LF ±°´¹° DEFB LF ±°µ°° DEFM '>> No carrier detected!' ±°µ±° DEFB EOL ±°µ²° ; ±°µ³° JP ABORT1 ; Abort transfer ±°µ´° ; ±°µµ° INITRS XOR A ; Zero some counters ±°µ¶° LD (BLOCKS),A ; Blocks transferred ±°µ·° LD (BLKCNT),A ; Block count ±°µ¸° LD (DPYHDR),A ; Zero to dpy blk msg ±°µ¹° LD HL,BUFFER ; Set block address ±°¶°° LD (BLKADR),HL ; to start of buffer ±°¶±° IN A,(RSDATA) ; Clear RS232 flags/port ±°¶²° ; ±°¶³° LD HL,(VIDDCB) ; Get old video driver ±°¶´° LD (VIDSAV),HL ; and save it ±°¶µ° LD HL,0 ; Get new video driver ±°¶¶° NEWDVR EQU $-2 ; Location of driver ±°¶·° LD (VIDDCB),HL ; Store new driver ±°¶¸° ; ±°¶¹° RET ; and we are done ±°·°° ; ±°·±° DPYBLK CALL DPYHDR ; Display block message ±°·²° LD A,BCKSPC ; Move cursor back two ±°·³° CALL CHROUT ; positions by sending ±°·´° LD A,BCKSPC ; two backspace codes ±°·µ° CALL CHROUT ; to the screen ±°·¶° LD A,(BLKCNT) ; Get current block count ±°··° PUSH AF ; and save for low bits ±°·¸° CALL HIBITS ; Display high nibble ±°·¹° POP AF ; Restore for low bits ±°¸°° JP LOBITS ; and display low nibble ±°¸±° ; ±°¸²° HIBITS RRCA ; We want the high ±°¸³° RRCA ; nibble here, so rotate ±°¸´° RRCA ; the four bits into ±°¸µ° RRCA ; position ±°¸¶° ; ±°¸·° LOBITS AND 15 ; Get first 4 bits only ±°¸¸° CP 10 ; Is it > 9 ? ±°¸¹° JR C,NOTAF ; No, so it is not A - F ±°¹°° ; ±°¹±° ADD A,7 ; A-F after conversion ±°¹²° ; ±°¹³° NOTAF ADD A,'0' ; Make it ascii ±°¹´° JP CHROUT ; and display it (done) ±°¹µ° ; ±°¹¶° DPYHDR NOP ; Executes once/file xfer ±°¹·° LD A,RETURN ; Make sure only once ±°¹¸° LD (DPYHDR),A ; by storing a return ±°¹¹° ; ±±°°° LD A,(OPTSAV) ; Get option ±±°±° CP 'R' ; Is it receive? ±±°²° JR NZ,DPYSDH ; No, must be send ±±°³° ; ±±°´° CALL ILPRNT ; Display block message ±±°µ° DEFB LF ±±°¶° DEFM 'Receiving' ±±°·° DEFB EOL ±±°¸° JR ENDHDR ; End block message ±±°¹° ; ±±±°° DPYSDH CALL ILPRNT ; Display block message ±±±±° DEFB LF ±±±²° DEFM 'Sending' ±±±³° DEFB EOL ±±±´° ; ±±±µ° ENDHDR CALL ILPRNT ; Display rest of blk msg ±±±¶° DEFM ' Block: ' ±±±·° DEFB EOL ±±±¸° RET ; Now we are done ±±±¹° ; ±±²°° VIDEO1 JR C,NORMAL ; If carry, use rom ±±²±° LD L,(IX+3) ; otherwise get cursor ±±²²° LD H,(IX+4) ; screen location ±±²³° LD A,C ; and the character ±±²´° SUB 20H ; Lower it 20H ±±²µ° CP LCCHAR ; Is it lowercase? ±±²¶° LD A,C ; Obtain original again ±±²·° JP C,47DH ; Yes, it is lc so exit ±±²¸° NORMAL JP 458H ; else use normal entry ±±²¹° ; ±±³°° CRSINP PUSH DE ; Save DE ±±³±° ; ±±³²° RSINP1 LD DE,3000H ; Count = 1 second ±±³³° RSIDLY EQU $-2 ; Number of tries ±±³´° ; ±±³µ° RSINP2 CALL ABTCHK ; Check for abort ±±³¶° IN A,(STATUS) ; Check receive buffer ±±³·° BIT DRECVD,A ; Any data received? ±±³¸° JR NZ,DARECV ; Yes, so exit loop ±±³¹° ; ±±´°° DEC DE ; Decrement counter ±±´±° LD A,D ; Check for end of loop ±±´²° OR E ; End? ±±´³° JR NZ,RSINP2 ; No, so try again ±±´´° ; ±±´µ° DJNZ RSINP1 ; Loop if more secs ±±´¶° ; ±±´·° RSIERR POP DE ; Restore DE ±±´¸° IN A,(RSDATA) ; Clear the RS data reg ±±´¹° SCF ; Set carry=no char recvd ±±µ°° RET ; and we are done ±±µ±° ; ±±µ²° DARECV IN A,(STATUS) ; Check for errors ±±µ³° BIT OVRERR,A ; Overrun error? ±±µ´° JR NZ,RSIERR ; Yes, take error exit ±±µµ° ; ±±µ¶° BIT FRMERR,A ; Framing error? ±±µ·° JR NZ,RSIERR ; Yes, take error exit ±±µ¸° ; ±±µ¹° IN A,(RSDATA) ; Get character ±±¶°° POP DE ; Restore DE ±±¶±° ; ±±¶²° PUSH AF ; Save character ±±¶³° ADD A,C ; Perform ±±¶´° LD C,A ; checksum ±±¶µ° POP AF ; Restore character ±±¶¶° OR A ; Clear carry if set ±±¶·° RET ; and we are done ±±¶¸° ; ±±¶¹° CRSOUT PUSH AF ; Save character ±±·°° ADD A,C ; Perform ±±·±° LD C,A ; checksum ±±·²° ; ±±·³° RSOUT CALL ABTCHK ; Check for abort ±±·´° IN A,(STATUS) ; Check xmit buffer ±±·µ° BIT XEMPTY,A ; Is it empty? ±±·¶° JR Z,RSOUT ; No, so keep looping ±±··° ; ±±·¸° POP AF ; Restrieve character ±±·¹° OUT (RSDATA),A ; and sent it ±±¸°° RET ; and we are done ±±¸±° ; ±±¸²° BDTBL DEFB BR110 ±±¸³° DEFB BR150 ±±¸´° DEFB BR300 ±±¸µ° DEFB BR600 ±±¸¶° DEFB BR1200 ±±¸·° DEFB BR2400 ±±¸¸° DEFB BR4800 ±±¸¹° DEFB BR9600 ±±¹°° ; ±±¹±° BDCTBL DEFW 50 ±±¹²° DEFB BR50 ±±¹³° DEFW 75 ±±¹´° DEFB BR75 ±±¹µ° DEFW 110 ±±¹¶° DEFB BR110 ±±¹·° DEFW 135 ±±¹¸° DEFB BR135 ±±¹¹° DEFW 150 ±²°°° DEFB BR150 ±²°±° DEFW 300 ±²°²° DEFB BR300 ±²°³° DEFW 600 ±²°´° DEFB BR600 ±²°µ° DEFW 1200 ±²°¶° DEFB BR1200 ±²°·° DEFW 1800 ±²°¸° DEFB BR1800 ±²°¹° DEFW 2000 ±²±°° DEFB BR2000 ±²±±° DEFW 2400 ±²±²° DEFB BR2400 ±²±³° DEFW 3600 ±²±´° DEFB BR3600 ±²±µ° DEFW 4800 ±²±¶° DEFB BR4800 ±²±·° DEFW 7200 ±²±¸° DEFB BR7200 ±²±¹° DEFW 9600 ±²²°° DEFB BR9600 ±²²±° DEFW 19200 ±²²²° DEFB BR1920 ±²²³° DEFW 0 ±²²´° ; ±²²µ° FMSG DEFB LF ±²²¶° DEFM 'File = ' ±²²·° FNAME DEFS 24 ±²²¸° STKSAV DEFS 2 ; Save area for stack ptr ±²²¹° VIDSAV DEFS 2 ; Save area for video dvr ±²³°° OPTSAV DEFS 1 ; Save area for opt key ±²³±° TRIES DEFS 1 ; Number of attempts ±²³²° BLKCNT DEFS 1 ; Block counter ±²³³° BLOCKS DEFS 1 ; Number transferred ±²³´° BLKADR DEFS 2 ; Current buffer pointer ±²³µ° CMDPTR DEFS 2 ; End of current command ±²³¶° FIRST DEFS 1 ; First block flag ±²³·° FILE DEFS 50 ; Filespec work area ±²³¸° DSKBUF DEFS 256 ; Disk sector buffer ±²³¹° BUFFER DEFS 2560 ; Big buffer for blocks ±²´°° ENDPGM EQU $-1 ; Last addr used by pgm ±²´±° ; ±²´²° END START Downloaded from Guy Omer of 8/N/1 #1 at 904/377-1200 in Gainesville,FL.