]> cloudbase.mooo.com Git - kermit-80.git/blame - cpspk1.asm
Bugfix in outmdm (output buffer flush)
[kermit-80.git] / cpspk1.asm
CommitLineData
e58a7a25
L
1; CPSPK1.ASM\r
2; KERMIT - (Celtic for "FREE")\r
3;\r
4; This is the CP/M-80 implementation of the Columbia University\r
5; KERMIT file transfer protocol.\r
6;\r
7; Version 4.0\r
8;\r
9; Copyright June 1981,1982,1983,1984\r
10; Columbia University\r
11;\r
12; Originally written by Bill Catchings of the Columbia University Center for\r
13; Computing Activities, 612 W. 115th St., New York, NY 10025.\r
14;\r
15; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben,\r
16; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many\r
17; others. \r
18;\r
19; This file contains the (system-independent) routines that implement\r
20; the KERMIT protocol, and the commands that use them:\r
21; RECEIVE, SEND, FINISH, and LOGOUT.\r
22;\r
23; revision history:\r
24;\r
25;edit 23, 16-Jan-1991 by MF. The bug of (22) was not fixed (although\r
26; the error described needed to be corrected). Really fixed the bug this:\r
27; time. changed "lda 'E'" after "ptch9b" to "mvi a,'E'" -- Zilog\r
28; mnemonic thinking must've addled my brain!\r
29;edit 22, 14-Jan-1991 by MF. Fix bug in the code which sends an "E" packet\r
30; to the remote Kermit on encountering "disk full" so that\r
31; uncontrollified <CR><LF> is not copied to the packet data area (and\r
32; hence sent to the remote Kermit). This should fix a bug reported\r
33; by Russell Lang of Monash University in Australia wherein a PC\r
34; running Kermit in Server mode complained of invalid characters when\r
35; receiving the "disk full" error packet from CP/M Kermit.\r
36;edit 21 of 3-Jan-1991 by MF. Reverse part of edit 20 which flushes comm\r
37; input at EOF send: the problem of multiple copies of packets being\r
38; sent when a stream of files being sent is partially interrupted with\r
39; ^X has been fixed by modifying "inchr" in CPSPK2.ASM.\r
40;edit 20, 2-Jan-1991 by MF. Tightened up code just after "sdata1" and around\r
41; "sdat14". Added code to flush comm input after user has typed ^X\r
42; or ^Z to interrupt file sends so that duplicate packets are not\r
43; sent after the interrupt character (especially ^X) has been typed.\r
44;edit 19, 14-Dec-1990 by MF. Place "<<>>" around "F" and "X" packets coming\r
45; as replies to REMOTE commands a la VMS Bliss Kermit.\r
46; Also type each character of "X" or "F" packet explicitly in case\r
47; dollar-signs are part of the filename (as in VMS Bliss Kermit\r
48; when a REMOTE TYPE is given and SET FILE NAMING FULL is in effect).\r
49; Expanded code is at label rfil3f.\r
50;edit 18, 27-Nov-1990 by MF. Fix bug introduced with edit 17 which resulted\r
51; in "E" packet being sent twice when receiving file(s) and disk-full\r
52; occurred. Sorry about that, folks!\r
53;edit 17, 27-Nov-1990 by MF. When receiving files, make the decision as to\r
54; whether to delete a partially-received file on a "disk full"\r
55; condition subject to the setting of the SET INCOMPLETE-FILES\r
56; switch in conformity with the behavior of MSDOS Kermit.\r
57; An "E" packet is still sent to the remote Kermit. Also try to close\r
58; any incomplete file whether deleting it or not (labels rdat16 and\r
59; rdat3a). If keeping incomplete files, try to write outstanding\r
60; buffers to disk, giving an error if the disk is full.\r
61;edit 16, 23-Nov-1990 by MF. When receiving, cause the file being written\r
62; to disk to **always** be deleted and an "E" packet to be sent when a\r
63; "disk full" condition is encountered (per suggestion of\r
64; RJL@MONU1.CC.MONASH.EDU.AU).\r
65;edit 15, 15-Nov-1990 by MF. Changed code for the Receive Complete state\r
66; to always go into RECEIVE if AUTORECEIVE is on. This will happen\r
67; most of the time anyway as most mainframe Kermits issue a prompt\r
68; after a single SEND command (wild-carded or not), thus guaranteeing\r
69; that the modem status check of Kermit-80 ver. 4.09 would **always**\r
70; have characters ready for input (the mainframe Kermit's prompt),\r
71; defeating the status check and the Console input check (originally\r
72; intended to drop the user out of the loop if he/she typed a key with\r
73; no comm input present). Eliminate "any key" message there also.\r
74; the user can drop out by hitting ^C.\r
75; Of course, none of the foregoing applies if the Receive Complete\r
76; state occurs as the result of a "Get" command where Autoreceive\r
77; is meaningless and we just drop back to Kermit command-level.\r
78;edit 14, 1-Oct-1990 by MF. Added code to send an "I" packet before an\r
79; "R" packet in GET command.\r
80; Modified routine "sinit" to ignore "E" packets when sending an\r
81; "i" packet (per KPROTO.DOC).\r
82;edit 13, 14-Sep-1990 by MF. Added code to implement SET FILE COLLISION\r
83; and SET INCOMPLETE commands.\r
84;edit 12, 9-Sep-1990 by MF. Added code to prevent packet counts\r
85; from being displayed during Remote commands. Fixed\r
86; AUTORECEIVE code, file colision Rename algorithm and eliminated\r
87; multiple display of initial messages during GET/RECEIVE.\r
88; edit 11, 28 July, 1987 by OBSchou. Commented out capas etc support\r
89; (Long packets etc) as this is not worth the effort coding... but\r
90; I have left what WAS done for any enthusiast. Also set in a few\r
91; to NOT write to screen if SET TERMINAL QUIET set. Hopefully speeds\r
92; up transfers on systems taking forever to update screens.\r
93;\r
94; edit 10, 8 April, 1987 by OBSchou. Tarted up all sorts of bits n bobs\r
95; to cope with all the new aditions for Kermit-80 V 4.09\r
96; Look for the [10] for most cahnges. spar and rpar largely replaced\r
97;\r
98; edit 9, March 30th by OBSchou. Set bits for automatically receiving\r
99; another file if a remote sender sends files in seperate sessions.\r
100; The code simply checks the serial line, and if there is some\r
101; activity, assume its another SEND INIT packet. As there is no\r
102; simple way to go to receive with the control-a, just ignore the\r
103; packet. Causes one retry on the sender, but so what. Really \r
104; should make it a server gizzmo.\r
105;\r
106; edit 8: January 28, 1987 by OBSchou\r
107; Two major issues: firstly split CPSPKT.ASM into CPSPK(1 2).ASM\r
108; making it far easier to handle this file.\r
109; Second, some mode to the GET routines to correctly print the file\r
110; name instead of the fireworks. Trouble was with GET <file> <file>\r
111; and RECEIVE <file>. However, new bugs discovered...\r
112;\r
113; edit 7: August 11, 1986 Godfrey N. Nix [gnn] Nottingham University\r
114; To ignore echoed packets (ie send 'S' receive 'S' before 'A');\r
115; To allow character other than SOH for packet header (see also\r
116; updates to CP4MIT and CP4UTL for other code needed);\r
117; To permit SEND and RECEIVE to specify a host filename which\r
118; is of a different structure to that of CP/M.\r
119;\r
120; edit 6a: [OBSchou] 7 March, 1985.\r
121; Edited file with additions from MJ Carter. He writes:\r
122; 25th September 1985, M J Carter [majoc], Nottingham University\r
123; Code in gofil() amended, for exactly the same reasons to the \r
124; alteration to cmifil() in cpscmd.asm. If there is any deep\r
125; reason why gofil() has to be used instead of a call to comnd(cmofil), \r
126; I can't see it. The bug (on a British Micro Mimi 803) caused \r
127; gofil() to overwrite existing files in GET and RECEIVE, even \r
128; with file warning SET ON.\r
129;\r
130;edir 6: November 22, 1984\r
131; Change SEND's 'Unable to find file' error exit from calling\r
132; error3 to calling prtstr instead. I don't know about you, but\r
133; I greatly dislike having messages dumped into pre-existing\r
134; junk on the screen where I have to spend lots of time hunting\r
135; for them. [Hal Hostetler]\r
136;\r
137; edit 5: September 9, 1984\r
138; Call flsmdm in init to flush old input when starting transfers.\r
139; Select console before returning from inpkt.\r
140; Replace inline code with calls to makfil/clofil to set up for\r
141; multisector buffering on output.\r
142; Remove superfluous call to clrlin in error3.\r
143;\r
144; edit 4: August 21, 1984 (CJC)\r
145; Fix comment in inpkt: packet is terminated by NUL on return, not CR.\r
146; If debugging, display the outgoing packet before putting the EOL\r
147; character on, so the dumped packet doesn't get overwritten.\r
148;\r
149; edit 3: July 27, 1984\r
150; add link directive for LASM. CP4PKT is linked by CP4MIT, and links\r
151; to CP4TT. Add Toad Hall TACtrap to permit operations through a TAC.\r
152;\r
153; edit 2: June 8, 1984\r
154; formatting and documentation; remove some unused labels; move setpar\r
155; to cp4mit.m80; add module version string; make all arithmetic on\r
156; 'pktnum' modulo 64; apply defaults correctly for missing parameters\r
157; in send-init packet (and corresponding ack).\r
158;\r
159; edit 1: May, 1984\r
160; extracted from CPMBASE.M80 version 3.9; modifications are described\r
161; in the accompanying .UPD file.\r
162;\r
163pk1ver: db 'CPSPK1.ASM (23) 16-Jan-1991$' ; name, edit number, date\r
164\r
165; GET command [gnn]\r
166; here from: kermit\r
167\r
168read: mvi a,0ffh ;[obs 8] we are doing a get\r
169 sta getrxflg ;[obs 8] so set flag\r
170 lxi d,remdat ;Where to put the text (if any.)\r
171 mvi a,cmtxt\r
172 call comnd ;Get either some text or a confirm.\r
173 jmp kermt3 ; Didn't get anything.\r
174 ora a ;Get any chars?\r
175 jz kermt3 ;[gnn] GET must have a filename\r
176 sta rdl ;Store the number of chars.\r
177 xchg ;Get pointer into HL.\r
178 mvi m,'$' ;Put in a dollar sign for printing.\r
179 call init ;Clear the line and initialize the buffers.\r
180 lda quietd ; quiet display?\r
181 ana a\r
182 jz read01 ;[MF]No, go ahead and position cursor\r
183 call prcrlf ;[MF]Yes, keep from overwriting the prompt\r
184 jmp read00 ;[MF]and write filename\r
185read01: call scrfln ;Position cursor [MF]\r
186read00: lxi d,remdat ;Print the file name, in either case\r
187 call prtstr\r
188 jmp read0a ;[gnn] go get local name if any\r
189\r
190\r
191; enter here for RECEIVE command [gnn]\r
192read0: mvi a,0 ;[gnn]\r
193 sta rdl ;[gnn][MF] flag entry as receive, not get\r
194 sta getrxflg ;[obs 8] doing a receive, so reset flag\r
195 call init ;clear line, initialise buffers\r
196read0a: lxi d,remnam ;[gnn] save local name here\r
197 mvi a,cmtxt ;[gnn]\r
198 call comnd ;[gnn] read second filename if present\r
199 jmp kermt3 ;[gnn] error exit\r
200 sta remlen ;[gnn] save length of name, may be zero\r
201 sta getrxflg ;[obs 8] May also be receive <fnam> so \r
202 ;[obs 8]pretend get for printing filename\r
203 lda rdl ;[gnn] look at first name\r
204 ora a ;[gnn] receive or get?\r
205 jz read1 ;[gnn] receive\r
206\r
207 mvi a,'I' ;[MF]Set state to send "I" packet\r
208 sta state ;[MF]...\r
209\r
210; jmp read12 ;[obs] [gnn] does not want this\r
211\r
212read1: ;call init ;Clear the line and initialize the buffers.\r
213read12: xra a\r
214 sta czseen ;Clear the ^X/^Z flag initially.\r
215 lxi h,0\r
216 shld numpkt ;Set the number of packets to zero.\r
217 shld numrtr ;Set the number of retries to zero.\r
218 sta pktnum ;Set the packet number to zero.\r
219 sta numtry ;Set the number of tries to zero.\r
220 lda quietd ; quiet display?\r
221 ana a\r
222 jnz read13 ; yes, so dont write...\r
223 call scrnrt ;Position cursor\r
224 lxi h,0\r
225 call nout ;Write the number of retries.\r
226read13: lda rdl ;[MF]Get or receive?\r
227 ora a ;[MF]...\r
228 jnz read2 ;[MF]Get, don't reset state\r
229 mvi a,'R'\r
230 sta state ;Set the state to receive initiate.\r
231 ;...\r
232;\f\r
233;RECEIVE state table switcher.\r
234\r
235read2: lda quietd ; noisy display?\r
236 ana a\r
237 jnz read21 ; no, a quiet one\r
238 lda remtxt ;[MF] In Remote command?\r
239 ora a\r
240 jnz read21 ;[MF] Yes, don't write to screen\r
241 call scrnp ;Position cursor\r
242 lhld numpkt\r
243 call nout ;Write the current packet number.\r
244read21: lda state ;Get the state.\r
245 cpi 'D' ;Are we in the DATA receive state?\r
246 jnz read22\r
247 call rdata\r
248 jmp read2\r
249\r
250read22: cpi 'X' ; F packet but not an F packet?\r
251 jnz read3 ; nope, so try next one\r
252 call rfile ; 'get' the filename (but dont open it)\r
253 jmp read2\r
254\r
255read3: cpi 'F' ;Are we in the FILE receive state?\r
256 jnz read4\r
257 call rfile ;Call receive file.\r
258 jmp read2\r
259\r
260read4: cpi 'R' ;Are we in the Receive-Initiate state?\r
261 jnz read5\r
262 call rinit\r
263 lda state ;[jd] get new state\r
264 cpi 'F' ;[jd] went into receive state?\r
265 jnz read2 ;[jd] no\r
266 lxi d,inms24 ;[jd] yes, get receiving... message\r
267 call finmes ;[jd] go print it\r
268 jmp read2\r
269\r
270read5: cpi 'C' ;Are we in the Receive-Complete state?\r
271 jnz read6\r
272 lxi d,infms3 ;Put in "Complete" message.\r
273 lda czseen ;Or was it interrupted?\r
274 ora a ; . . .\r
275 jz read5a ;No.\r
276 xra a ;Yes, clear flag.\r
277 sta czseen ; ...\r
278 lxi d,inms13 ;Issue "interrupted" message.\r
279read5a: lda remtxt ;[MF] Doing a Remote command?\r
280 ora a\r
281 cz finmes ;Print completion message in right place if not\r
282;\r
283 lda rdl ;[MF]Receive or Get?\r
284 ora a ;[MF]...\r
285 jnz kermit ;[MF]Get, Autoreceive means nothing.\r
286 lda autorc ; see if we want autoreceives\r
287 ana a\r
288 jz kermit ;[MF]No autoreceives, so drop out\r
289 lxi d,autmes ;[MF]Yes, tell the user what we're doing\r
290 call prtstr ;[MF]...\r
291 jmp read1 ;[MF]Try another Receive (we get one\r
292 ;[MF]retry from the sender as the ^A is lost)\r
293\r
294read6: cpi 'Y' ;[MF]Simple ack (from remote command)?\r
295 jz kermit ;[MF]Yes\r
296\r
297 cpi 'I' ;[MF]Exchanging parameters via info packet?\r
298 jnz read7 ;[MF]No\r
299 call sinit ;[MF]Yes, send the packet\r
300 lda state ;[MF]Now see what happened\r
301 cpi 'X' ;[MF]Did we exchange parameters successfully?\r
302 jz read6a ;[MF]Yes, go send the filespec\r
303 cpi 'A' ;[MF]No, are we in abort state?\r
304 jnz read2 ;[MF]No, try again\r
305 jmp kermit ;[MF]Yes, it's a real disaster, we must stop\r
306read6a: lda rdl ;[MF]Get length of filespec\r
307 sta argblk+1 ;[MF]as length of packet\r
308 mov c,a ;[MF]We must copy the filespec\r
309 mvi b,0 ;[MF]...\r
310 lxi h,remdat ;[MF]from the temporary buffer\r
311 lxi d,data ;[MF]to the packet data area\r
312 call mover ;[MF]Do it.\r
313; for GET we must send the name of the file we want [gnn]\r
314\r
315 mvi a,'1' ;Start with single character checksum\r
316 sta curchk ;Save the type\r
317 xra a ;Start a packet zero.\r
318 sta argblk\r
319 mvi a,'R' ;Receive init packet.\r
320 call spack ;Send the packet.\r
321 jmp kermt3 ; Die!\r
322 xra a\r
323 sta czseen ;Clear the ^X/^Z flag initially.\r
324 lxi h,0\r
325 shld numpkt ;Set the number of packets to zero.\r
326 sta pktnum ;Set the packet number to zero.\r
327 sta numtry ;Set the number of tries to zero.\r
328 mvi a,'R' ;[MF]Set state to Receive-Initiate\r
329 sta state ;[MF]...\r
330 jmp read21 ;[MF]and go around again\r
331 ;[MF]without retyping packet-number\r
332\r
333read7: cpi 'A' ;Are we in the Receive-"Abort" state?\r
334 jnz read8\r
335read8: lxi d,infms4 ;Anything else is equivalent to "abort".\r
336 call finmes\r
337 jmp kermit\r
338;\f\r
339; Receive routines\r
340\r
341; Receive init\r
342; called by: read\r
343\r
344rinit: lda numtry ;Get the number of tries.\r
345 cpi imxtry ;Have we reached the maximum number of tries?\r
346 jm rinit2\r
347 lxi d,ermes4\r
348 call error3 ;Move cursor and print an error message.\r
349 jmp abort ;Change the state to abort.\r
350\r
351rinit2: inr a ;Increment it.\r
352 sta numtry ;Save the updated number of tries.\r
353 mvi a,'1' ;Reset block check type to single character\r
354 sta curchk ;Store as current type for initialization\r
355 call rpack ;Get a packet.\r
356 jmp nak ; Trashed packet: nak, retry.\r
357 cpi 'S' ;Is it a send initiate packet?\r
358 jnz rinit3 ;If not see if its an error.\r
359rini2a: lda numtry ;Get the number of tries.\r
360 sta oldtry ;Save it.\r
361 xra a\r
362 sta numtry ;Reset the number of tries.\r
363 lda argblk ;Returned packet number. (Synchronize them.)\r
364 call countp\r
365 lda argblk+1 ;Get the number of arguments received.\r
366 lxi h,data ;Get a pointer to the data.\r
367 call spar ;Get the data into the proper variables.\r
368 lxi h,data ;Get a pointer to our data block.\r
369 call rpar ;Set up the receive parameters.\r
370 sta argblk+1 ;Store the returned number of arguments.\r
371 mvi a,'Y' ;Acknowledge packet.\r
372 call spack ;Send the packet.\r
373 jmp abort ; Failed, abort.\r
374 lda inichk ;Now switch to agreed upon check-type\r
375 sta curchk ;For all future packets\r
376 mvi a,'F' ;Set the state to file send.\r
377 sta state\r
378 ret\r
379\r
380rinit3: cpi 'E' ;Is it an error packet.\r
381 jnz nak0 ;If not NAK whatever it is.\r
382 call error\r
383 jmp abort\r
384;\f\r
385; Receive file\r
386; called by: read\r
387\r
388rfile: lda numtry ;Get the number of tries.\r
389 cpi maxtry ;Have we reached the maximum number of tries?\r
390 jm rfile1\r
391 lxi d,ermes5\r
392 call error3 ;Move cursor and print an error message.\r
393 jmp abort ;Change the state to abort.\r
394\r
395rfile1: inr a ;Increment it.\r
396 sta numtry ;Save the updated number of tries.\r
397 call rpack ;Get a packet.\r
398 jmp nak ; Trashed packet: nak, retry.\r
399 cpi 'S' ;Is it a send initiate packet?\r
400 jnz rfile2 ; No, try next type.\r
401 lda oldtry ;Get the number of tries.\r
402 cpi imxtry ;Have we reached the maximum number of tries?\r
403 jm rfil12 ;If not proceed.\r
404 lxi d,ermes4\r
405 call error3 ;Move cursor and print an error message.\r
406 jmp abort ;Change the state to abort.\r
407\r
408rfil12: inr a ;Increment it.\r
409 sta oldtry ;Save the updated number of tries.\r
410 lda pktnum ;Get the present packet number.\r
411 dcr a ;Decrement\r
412 ani 3FH ; modulo 64\r
413 mov b,a\r
414 lda argblk ;Get the packet's number\r
415 cmp b ;Is the packet's number one less than now?\r
416 jnz nak0 ;No, NAK and try again.\r
417 call updrtr ;Update the retry count.\r
418 xra a\r
419 sta numtry ;Reset the number of tries.\r
420 lxi h,data ;Get a pointer to our data block.\r
421 call rpar ;Set up the parameter information.\r
422 sta argblk+1 ;Save the number of arguments.\r
423 mvi a,'Y' ;Acknowledge packet.\r
424 call spack ;Send the packet.\r
425 jmp abort ; Failed, abort.\r
426 ret\r
427\r
428rfile2: cpi 'Z' ;Is it an EOF packet?\r
429 jnz rfile3 ; No, try next type.\r
430 lda oldtry ;Get the number of tries.\r
431 cpi maxtry ;Have we reached the maximum number of tries?\r
432 jm rfil21 ;If not proceed.\r
433 lxi d,ermes6\r
434 call error3 ;Move cursor and print an error message.\r
435 jmp abort ;Change the state to abort.\r
436\r
437rfil21: call tryagn\r
438 ret\r
439\r
440rfile3: cpi 'F' ;Start of file?\r
441 jnz rfil3b\r
442 mov c,a ;[MF]Save packet type\r
443 lda remtxt ;[MF]Doing a remote server command?\r
444 ora a ;[MF]...\r
445 mov a,c ;[MF]Restore packet type\r
446 jnz rfil3d ;[MF]If yes, same as x packet\r
447 call compp\r
448 jnz nak0 ;No, NAK it and try again.\r
449 call countp\r
450 mov c,a ;[MF]\r
451 lda remtxt ;[MF]Doing a remote command?\r
452 ora a ;[MF]...\r
453 mov a,c ;[MF]\r
454 jnz rfil3a ;[MF]Yes, don't open a file\r
455 call gofil ;Get a file to write to, and init output buffer.\r
456 jmp abort\r
457rfil3a: lda numtry ;Get the number of tries.\r
458 sta oldtry ;Save it.\r
459 call ackp\r
460 mvi a,'D' ;Set the state to data receive.\r
461 sta state\r
462 lda czseen ;Check if we punted a file\r
463 cpi 'Z' ;and didn't want any more\r
464 rz ;If that was the request, keep telling other end\r
465 xra a ;Otherwise, clear flag (^X is only for one file)\r
466 sta czseen ;And store the flag back\r
467 ret\r
468\r
469rfil3b: cpi 'X' ;Start of 'file?' , but not a file?\r
470 jnz rfile4\r
471rfil3d: call compp\r
472 jnz nak0 ;No, NAK it and try again.\r
473 call countp\r
474\r
475 call selcon ;[MF]Select Console\r
476 lda argblk+1 ; get length\r
477 ora a ;[MF]Anything to write?\r
478 jz rfil3e ;[MF]No\r
479 push psw ;[MF]Yes, save character count\r
480 mvi e,'<' ;[MF]Write "<<" as in VMSKermit\r
481 push d ;[MF]...\r
482 call outcon ;[MF]...\r
483 pop d ;[MF]...\r
484 call outcon ;[MF]...\r
485 pop psw ;[MF]Restore character count\r
486 lxi h,data ; lets write the filename (?) to display\r
487rfil3f: push psw ;[MF]Save loop counter\r
488 mov e,m ;[MF]Get character to write\r
489 inx h ;[MF]and increment character pointer\r
490 push h ;[MF]Save the pointer\r
491 call outcon ;[MF]Write character to display\r
492 pop h ;[MF]Restore pointer\r
493 pop psw ;[MF]and loop counter\r
494 dcr a ;[MF]Decrement the counter\r
495 jnz rfil3f ;[MF]Display entire filename\r
496 mvi e,'>' ;[MF]Put in ">>" as in VMSKermit\r
497 push d ;[MF]...\r
498 call outcon ;[MF]...\r
499 pop d ;[MF]...\r
500 call outcon ;[MF]...\r
501 call prcrlf ;[MF]New line\r
502rfil3e: lda numtry ;Get the number of tries.\r
503 sta oldtry ;Save it.\r
504 call ackp\r
505 mvi a,'D' ; expecting a D packet\r
506 sta state\r
507 lda czseen ;Check if we punted a file\r
508 cpi 'Z' ;and didn't want any more\r
509 rz ;If that was the request, keep telling other end\r
510 xra a ;Otherwise, clear flag (^X is only for one file)\r
511 sta czseen ;And store the flag back\r
512 ret\r
513\r
514rfile4: cpi 'B' ;End of transmission.\r
515 jnz rfile5\r
516 call compp\r
517 jnz nak0 ;No, NAK it and try again.\r
518 xra a ;No data. (Packet number already in argblk).\r
519 sta argblk+1\r
520 mvi a,'Y' ;Acknowledge packet.\r
521 call spack ;Send the packet.\r
522 jmp abort\r
523 mvi a,'C' ;Set the state to complete.\r
524 sta state\r
525 ret\r
526\r
527rfile5: cpi 'E' ;Is it an error packet.\r
528 jnz abort\r
529 call error\r
530 jmp abort\r
531;\f\r
532; Receive data\r
533; called by: read\r
534\r
535rdata: lda numtry ;Get the number of tries.\r
536 cpi maxtry ;Have we reached the maximum number of tries?\r
537 jm rdata1\r
538 lxi d,erms10\r
539 call error3 ;Display error message.\r
540rdat16: lda remtxt ;[MF]Is a Remote command in progress?\r
541 ora a ;[MF]...\r
542 jnz abort ;[MF]Yes, don't worry about file disposition\r
543 lda incflg ;[MF]Are we keeping incomplete files?\r
544 ora a ;[MF]...\r
545 jnz rdat17 ;[MF]Yes\r
546 lxi d,fcb ;[MF]No, close the file, ignoring errors\r
547 push d ;[MF]while protecting the pointer\r
548 mvi c,closf ;[MF]...\r
549 call bdos ;[MF]...\r
550 pop d ;[MF]Now delete the file, ignoring errors\r
551 mvi c,delf ;[MF]...\r
552 call bdos ;[MF]...\r
553 jmp abort ;Change the state to abort.\r
554rdat17: call clofil ;[MF]Try to close the file, writing\r
555 ;[MF]outstanding buffers to disk\r
556 jmp rdat37 ;[MF]We can't, the disk is full\r
557 jmp abort ;[MF]Change the state to "abort"\r
558\r
559rdata1: inr a ;Increment it.\r
560 sta numtry ;Save the updated number of tries.\r
561 call rpack ;Get a packet.\r
562 jmp nak ; Trashed packet: nak, retry.\r
563 cpi 'D' ;Is it a data packet?\r
564 jnz rdata2 ; No, try next type.\r
565 call compp ;check for correct packet number (zero flag = ok)\r
566 jz rdat14 ;its correct\r
567 lda oldtry ;Get the number of tries.\r
568 cpi maxtry ;Have we reached the maximum number of tries?\r
569 jm rdat12 ;If not proceed.\r
570 lxi d,erms10\r
571 call error3 ;Display err msg.\r
572 jmp rdat16 ;[MF]Change the state to abort.\r
573\r
574rdat12: call tryagn\r
575 ret\r
576\r
577rdat14: call countp\r
578 lda numtry ;Get the number of tries.\r
579 sta oldtry ;Save it.\r
580 lda argblk+1 ;Get the length of the data.\r
581 call ptchr\r
582 jmp rdat3b ;[MF] Unable to write out chars;abort.\r
583 xra a\r
584 sta numtry ;Reset the number of tries.\r
585 sta argblk+1 ;No data. (Packet number still in argblk.)\r
586 mov c,a ;Assume no data\r
587 lda czseen ;Check if control-X typed\r
588 ora a ; . . .\r
589 jz rdat15 ;Zero if not typed\r
590 mov c,a ;Get the type of character typed\r
591 mvi a,1 ;One data character\r
592 sta argblk+1 ;Save the count\r
593 mov a,c ;Get the possible data character\r
594 sta data ;Store in data area\r
595rdat15: mvi a,'Y' ;Acknowledge packet.\r
596 call spack ;Send the packet.\r
597 jmp rdat16 ;[MF]\r
598 ret\r
599\r
600rdata2: cpi 'F' ;Start of file?\r
601 jnz rdata3 ; No, try next type.\r
602 lda oldtry ;Get the number of tries.\r
603 cpi maxtry ;Have we reached the maximum number of tries?\r
604 jm rdat21 ;If not proceed.\r
605 lxi d,ermes5\r
606 call error3 ;Display err msg.\r
607 jmp rdat16 ;[MF]Change the state to abort.\r
608\r
609rdat21: call tryagn\r
610 ret\r
611\r
612rdata3: cpi 'Z' ;Is it a EOF packet?\r
613 jnz rdata4 ;Try and see if its an error.\r
614 call compp\r
615 jnz nak0 ;No, NAK it and try again.\r
616 call countp\r
617 lda argblk+1 ;Get the data length\r
618 cpi 1 ;Have one item?\r
619 jnz rdat33 ;If not, ignore data\r
620 lda data ;Yes, get the character\r
621 cpi 'D' ;Is it a 'D' for discard?\r
622 jz rdat36 ;If so, punt file\r
623rdat33: lda remtxt ;[MF]Writing text to disk?\r
624 ora a ;[MF]...\r
625 jnz rdat38 ;[MF]No, don't close file\r
626 call clofil ;Finish off the file.\r
627 jmp rdat37 ; Give up if the disk is full.\r
628rdat38: xra a ;Since we kept the file,\r
629 sta czseen ;don't say it was discarded.\r
630 lda numtry ;Get the number of tries. [MF]\r
631 sta oldtry ;Save it. [MF]\r
632 call ackp ;[MF]\r
633 jmp rdat39 ;[MF]and get ready to get more files\r
634rdat36: lda numtry ;Get the number of tries.\r
635 sta oldtry ;Save it.\r
636 call ackp\r
637 lda remtxt ;[MF]Is a Remote command in progress?\r
638 ora a ;[MF]...\r
639 jnz rdat39 ;[MF]Yes, don't worry about file disposition\r
640 lda dscflg ;[MF]Is the file being punted because\r
641 ora a ;[MF]of a collision?\r
642 jnz rdat39 ;[MF]Yes, don't delete the existing file\r
643 lda incflg ;[MF]No, are we keeping incomplete files?\r
644 ora a ;[MF]...\r
645 jnz rdat3a ;[MF]Yes\r
646 lxi d,fcb ;[MF]No, close the file,\r
647 mvi c,closf ;[MF]ignoring errors\r
648 push d ;[MF]...\r
649 call bdos ;[MF]...\r
650 pop d ;[MF]Now delete the file,\r
651 mvi c,delf ;[MF]ignoring errors\r
652 call bdos ;[MF]...\r
653 jmp rdat39 ;[MF]and continue\r
654rdat3a: call clofil ;[MF]Try to close the file, writing\r
655 ;[MF]outstanding buffers to disk\r
656 jmp rdat37 ;[MF]Can't, disk is full\r
657rdat39: mvi a,'F'\r
658 sta state\r
659 ret\r
660\r
661rdat37: call ptchr9 ; Send "?Disk full" on the error line [MF]\r
662 ; and to the remote Kermit [MF]\r
663rdat3b: lda remtxt ;[MF]Doing a Remote command?\r
664 ora a ;[MF]...\r
665 jnz abort ;[MF]Yes, just abort\r
666 lxi d,fcb ;[MF]Close the file, ignoring errors\r
667 push d ;[MF]Protect fcb pointer\r
668 mvi c,closf ;[MF]...\r
669 call bdos ;[MF]...\r
670 pop d ;[MF]Restore pointer\r
671 lda incflg ;[MF]Are we keeping incomplete files?\r
672 ora a ;[MF]...\r
673 jnz abort ;[MF]Yes, just abort transfer\r
674 mvi c,delf ;[MF]No, delete the file, ignoring errors\r
675 call bdos ;[MF]...\r
676 jmp abort ;[MF] abort transfer\r
677\r
678rdata4: cpi 'E' ;Is it an error packet.\r
679 jnz rdat16 ;[MF]\r
680 call error\r
681 jmp rdat16 ;[MF]\r
682;\f\r
683; SEND command\r
684; here from: kermit\r
685\r
686send: mvi a,cmifi ;Parse an input file spec.\r
687 lxi d,fcb ;Give the address for the FCB.\r
688 call comnd\r
689 jmp kermit ; Give up on bad parse.\r
690; section to get remote filename [gnn]\r
691 lxi d,remnam ;[gnn] where to put filename\r
692 mvi a,cmtxt ;[gnn] \r
693 call comnd ;[gnn] get the text to end of the line\r
694 jmp kermt3 ;[gnn] failure in reading buffer\r
695 sta remlen ;[gnn] save length (may be zero)\r
696;\r
697 xra a\r
698 sta mfflg1 ; clear flags...\r
699 sta mfflg2\r
700 sta mfflg3 ;[gnn]\r
701 sta fcbcnt ;[gnn] clear fcbcount\r
702 lxi h,fcb0 ;[gnn] and fcb pointer\r
703 shld xfcbptr\r
704;\r
705 call mfname ;handle (multi) files\r
706 jnc send14 ;got a valid file-name\r
707 lxi d,erms15\r
708 call prtstr ;Display error msg. ([hh] where it's visible)\r
709 jmp kermit\r
710\r
711send14: call init ;Clear the line and initialize the buffers.\r
712 xra a\r
713 sta pktnum ;Set the packet number to zero.\r
714 sta numtry ;Set the number of tries to zero.\r
715 sta wrn8 ;[jd] we haven't sent the 8-bit-lost warning\r
716 lxi h,0\r
717 shld numpkt ;Set the number of packets to zero.\r
718 shld numrtr ;Set the number of retries to zero.\r
719 lda quietd ; a quiet display?\r
720 ana a\r
721 jnz send15 ; yup, dont write\r
722 call scrnrt ;Position cursor\r
723 lxi h,0\r
724 call nout ;Write the number of retries.\r
725send15: mvi a,'1' ;Reset to use single character checksum\r
726 sta curchk ;For startup\r
727 mvi a,'S'\r
728 sta state ;Set the state to receive initiate.\r
729 ;...\r
730;\f\r
731;SEND state table switcher\r
732\r
733send2: lda quietd ; a quiet display?\r
734 ana a\r
735 jnz send21 ; yes, so dont write\r
736 call scrnp ;Position cursor\r
737 lhld numpkt\r
738 call nout ;Write the packet number.\r
739send21: lda state ;Get the state.\r
740 cpi 'D' ;Are we in the data send state?\r
741 jnz send3\r
742 call sdata\r
743 jmp send2\r
744\r
745send3: cpi 'F' ;Are we in the file send state?\r
746 jnz send4\r
747 call sfile ;Call send file.\r
748 jmp send2\r
749\r
750send4: cpi 'Z' ;Are we in the EOF state?\r
751 jnz send5\r
752 call seof\r
753 jmp send2\r
754\r
755send5: cpi 'S' ;Are we in the send initiate state?\r
756 jnz send6\r
757 call sinit\r
758 lda state ;[jd] get state back\r
759 cpi 'F' ;[jd] into file send state yet?\r
760 jnz send2 ;[jd] no\r
761 lxi d,inms23 ;[jd] yes, print sending...\r
762 call finmes ;[jd] \r
763 jmp send2\r
764\r
765send6: cpi 'B' ;Are we in the eot state?\r
766 jnz send7\r
767 call seot\r
768 jmp send2\r
769\r
770send7: cpi 'C' ;Are we in the send complete state?\r
771 jnz send8 ;No...\r
772 lxi d,infms3 ;Yes, write "Complete" message.\r
773 lda czseen ;Or was it interrupted?\r
774 ora a ; . . .\r
775 jz send7a ;No.\r
776 lxi d,inms13 ;Yes, then say "Interrupted" instead.\r
777send7a: call finmes\r
778 jmp kermit\r
779\r
780send8: cpi 'A' ;Are we in the send "abort" state?\r
781 jnz send9\r
782 lxi d,infms4 ;Print message.\r
783 call finmes\r
784 jmp kermit\r
785\r
786send9: lxi d,infms4 ;Anything else is equivalent to "abort".\r
787 call finmes\r
788 jmp kermit\r
789;\f\r
790; Send routines\r
791\r
792; Send initiate\r
793; called by: send\r
794\r
795sinit: lda numtry ;Get the number of tries.\r
796 cpi imxtry ;Have we reached the maximum number of tries?\r
797 jm sinit2\r
798 lxi d,erms14\r
799 call error3 ;Display ermsg\r
800 jmp abort ;Change the state to abort.\r
801\r
802sinit2: inr a ;Increment it.\r
803 sta numtry ;Save the updated number of tries.\r
804 mvi a,'1' ;Reset to use single character checksum\r
805 sta curchk ;For startup\r
806 lda chktyp ;Get our desired block check type\r
807 sta inichk ;Store so we tell other end\r
808 lxi h,data ;Get a pointer to our data block.\r
809 call rpar ;Set up the parameter information.\r
810 sta argblk+1 ;Save the number of arguments.\r
811 lda numpkt ;Get the packet number.\r
812 sta argblk\r
813 lda state ; load state (I or S)\r
814\r
815 call spack ;Send the packet.\r
816 jmp abort ; Failed, abort.\r
817 call rpack ;Get a packet.\r
818 jmp r ; Trashed packet don't change state, retry.\r
819 cpi 'Y' ;ACK?\r
820 jnz sinit3 ;If not try next.\r
821 call compp ;compare packets. If ok, zero flag set\r
822 rnz ;If not try again.\r
823 call countp ;increment packet number modulo 64\r
824 lda argblk+1 ;Get the number of pieces of data.\r
825 lxi h,data ;Pointer to the data.\r
826 call spar ;Read in the data. (decode what they want)\r
827 lda numtry ;Get the number of tries.\r
828 sta oldtry ;Save it.\r
829 xra a\r
830 sta numtry ;Reset the number of tries.\r
831 lda state ; se if S or I state\r
832 cpi 'I' ; I state, so set X as next state\r
833 jnz sinita\r
834sinitb: mvi a,'X'\r
835 sta state\r
836 ret\r
837\r
838sinita: lda inichk ;Get the agreed upon block check type\r
839 sta curchk ;Store as type to use for packets now\r
840 mvi a,'F' ;Set the state to file send. (Assumed)\r
841 sta state\r
842 call getfil ;Open the file.\r
843 ret ; assume success; mfname thinks the file exists.\r
844\r
845sinit3: cpi 'N' ;NAK?\r
846 jnz sinit4 ;If not see if its an error.\r
847 call updrtr ;Update the number of retries.\r
848 lda pktnum ;Get the present packet number.\r
849 inr a ;Increment\r
850 ani 3FH ; modulo 64\r
851 mov b,a\r
852 lda argblk ;Get the packet's number.\r
853 cmp b ;Is the packet's number one more than now?\r
854 rnz ;If not assume its for this packet, go again.\r
855 xra a\r
856 sta numtry ;Reset number of tries.\r
857 mvi a,'F' ;Set the state to file send.\r
858 sta state\r
859 ret\r
860\r
861sinit4: cpi 'E' ;Is it an error packet.\r
862 jnz abort\r
863 lda state ;[MF]Get state\r
864 cpi 'I' ;[MF]If an "I" packet was sent,\r
865 jz sinitb ;[MF]Ignore the error, pretend success\r
866 call error ;[MF]else display the error info\r
867 jmp abort ;[MF]and abort\r
868;\f\r
869; Send file header\r
870; called by: send\r
871;[5a] Question [majoc]: Why could not the filename\r
872; parsing have been done by comnd, like all the rest?\r
873\r
874sfile: lda numtry ;Get the number of tries.\r
875 cpi maxtry ;Have we reached the maximum number of tries?\r
876 jm sfile1\r
877 lxi d,erms14\r
878 call error3\r
879 jmp abort ;Change the state to abort.\r
880\r
881sfile1: inr a ;Increment it.\r
882 sta numtry ;Save the updated number of tries.\r
883 xra a ;Clear A\r
884 sta czseen ;No control-Z or X seen\r
885 lxi h,data ;Get a pointer to our data block.\r
886 shld datptr ;Save it.\r
887; use remote name if given, else use local name [gnn]\r
888 lda remlen ;[gnn] anything given?\r
889 ora a ;[gnn] \r
890 jnz sfile4 ;[gnn] use remote name\r
891\r
892 lxi h,fcb+1 ;Pointer to the file name in the FCB.\r
893 shld fcbptr ;Save position in FCB.\r
894 mvi b,0 ;No chars yet.\r
895 mvi c,0\r
896sfil11: mov a,b\r
897 cpi 8H ;Is this the ninth char?\r
898 jnz sfil12 ;If not proceed.\r
899 mvi a,'.' ;Get a dot.\r
900 lhld datptr\r
901 mov m,a ;Put the char in the data packet.\r
902 inx h\r
903 shld datptr ;Save position in data packet.\r
904 inr c\r
905sfil12: inr b ;Increment the count.\r
906 mov a,b\r
907 cpi 0CH ;Twelve? \r
908 jp sfil13\r
909 lhld fcbptr\r
910 mov a,m\r
911 ani 7fH ;Turn off CP/M 2 or 3's high bits.\r
912 inx h\r
913 shld fcbptr ;Save position in FCB.\r
914 cpi '!' ;Is it a good character?\r
915 jm sfil11 ;If not get the next.\r
916 lhld datptr\r
917 mov m,a ;Put the char in the data packet.\r
918 inx h\r
919 shld datptr ;Save position in data packet.\r
920 inr c\r
921 jmp sfil11 ;Get another.\r
922\r
923sfil13: mov a,c ;Number of char in file name.\r
924 sta argblk+1\r
925 lhld datptr\r
926 mvi a,'$'\r
927 mov m,a ;Put in a dollar sign for printing.\r
928 lda quietd ; a quiet display\r
929 ana a\r
930 jnz sfi13a ; yes, dont write\r
931 call scrfln ;Position cursor\r
932sfi13a: lxi d,data ;Print the file name though, in either case\r
933 call prtstr\r
934 lda pktnum ;Get the packet number.\r
935 sta argblk\r
936 mvi a,'F' ;File header packet.\r
937 call spack ;Send the packet.\r
938 jmp abort ; Failed, abort.\r
939 call rpack ;Get a packet.\r
940 jmp r ; Trashed packet don't change state, retry.\r
941 cpi 'Y' ;ACK?\r
942 jnz sfile2 ;If not try next.\r
943 call compp\r
944 rnz ;If not hold out for the right one.\r
945sfil14: call countp\r
946 lda numtry ;Get the number of tries.\r
947 sta oldtry ;Save it.\r
948 xra a\r
949 sta numtry ;Reset the number of tries.\r
950 sta bytes ;[10] clear the "bytes transferred" counter\r
951 sta bytes+1 ;[10]\r
952 sta bytes+2 ;[10]\r
953 sta bytes+3 ;[10]\r
954 call gtchr ;Fill the first data packet\r
955 jmp sfil16 ;Error go see if its EOF.\r
956; ;Got the chars, proceed.\r
957 sta size ;Save the size of the data gotten.\r
958 mvi a,'D' ;Set the state to data send.\r
959 sta state\r
960 ret\r
961\r
962sfil16: cpi 0FFH ;Is it EOF?\r
963 jnz abort ;If not give up.\r
964 mvi a,'Z' ;Set the state to EOF.\r
965 sta state\r
966 ret\r
967\r
968sfile2: cpi 'N' ;NAK?\r
969 jnz sfile3 ;Try if error packet.\r
970 call updrtr ;Update the number of retries.\r
971 lda pktnum ;Get the present packet number.\r
972 inr a ;Increment\r
973 ani 3FH ; modulo 64\r
974 mov b,a\r
975 lda argblk ;Get the packet's number.\r
976 cmp b ;Is the packet's number one more than now?\r
977 rnz ;If not go try again.\r
978 jmp sfil14 ;Just as good as a ACK;go to the ACK code.\r
979\r
980sfile3: cpi 'E' ;Is it an error packet.\r
981 jnz abort\r
982 call error\r
983 jmp abort\r
984\r
985; copy remote name into packet to send [gnn]\r
986sfile4: xchg ;[gnn] keep pointer to packet\r
987 lxi h,remnam ;[gnn] set pointer to name\r
988 mov c,a ;[gnn] keep count of length\r
989 mov b,a ;[gnn] and set as loop counter\r
990sfil41: mov a,m ;[gnn] get a character\r
991 stax d ;[gnn] copy it to packet\r
992 inx h ;[gnn] \r
993 inx d ;[gnn] move pointers\r
994 dcr b ;[gnn] \r
995 mov a,b ;[gnn] \r
996 ora a ;[gnn] done them all?\r
997 jnz sfil41 ;[gnn] repeat until done\r
998 xchg ;[gnn] get final position\r
999 shld datptr ;[gnn] and save it\r
1000 jmp sfil13 ;[gnn] now go and send packet\r
1001\r
1002;\f\r
1003; Send data\r
1004; called by: send\r
1005\r
1006sdata: lda numtry ;Get the number of tries.\r
1007 cpi maxtry ;Have we reached the maximum number of tries?\r
1008 jm sdata1\r
1009 lxi d,erms14\r
1010 call error3\r
1011 jmp abort ;Change the state to abort.\r
1012\r
1013sdata1: inr a ;Increment it.\r
1014 sta numtry ;Save the updated number of tries.\r
1015 lxi h, data ;Get a pointer to our data block.\r
1016 shld datptr ;Save it.\r
1017 lxi h,filbuf ;Pointer to chars to be sent.\r
1018 shld cbfptr ;Save position in char buffer.\r
1019 mvi b,1 ;First char.\r
1020sdat11: lhld cbfptr\r
1021 mov a,m\r
1022 inx h\r
1023 shld cbfptr ;Save position in char buffer.\r
1024 mov c,a ;[jd] preserve character temporarily\r
1025 lda quot8 ;[jd] doing eighth-bit quoting?\r
1026 ora a ;[jd] \r
1027 mov a,c ;[jd] restore char\r
1028 jnz sdat4 ;[jd] using eighth-bit quoting, no warning\r
1029 lda parity ;[jd] get parity\r
1030 cpi parnon ;[jd] none?\r
1031 mov a,c ;[jd] restore character\r
1032 jz sdat4 ;[jd] no parity, leave char alone\r
1033 lda wrn8 ;[jd] look at warning flag\r
1034 ora a ;[jd] have we already given the warning?\r
1035 jnz sdat5 ;[jd] yes, skip this\r
1036 mov a,c ;[jd] restore character...\r
1037 ani 80h ;[jd] examine parity\r
1038 jz sdat5 ;[jd] no parity, no warning.\r
1039 call parwrn ;[jd] ...print warning - parity lost\r
1040 mvi a,0ffh ;[jd] remember that we sent the message\r
1041 sta wrn8 ;[jd]\r
1042sdat5: mov a,c ;[jd] restore character again\r
1043 ani 7fh ;[jd] strip parity so not checksummed\r
1044sdat4: lhld datptr\r
1045 mov m,a ;Put the char in the data packet.\r
1046 inx h\r
1047 shld datptr ;Save position in data packet.\r
1048 inr b ;Increment the count.\r
1049 lda size ;Get the number of chars in char buffer.\r
1050 cmp b ;Have we transfered that many?\r
1051 jp sdat11 ;If not get another.\r
1052 lda size ;Number of char in char buffer.\r
1053 sta argblk+1\r
1054 lda pktnum ;Get the packet number.\r
1055 sta argblk\r
1056 mvi a,'D' ;Data packet.\r
1057 call spack ;Send the packet.\r
1058 jmp abort ; Failed, abort.\r
1059 call rpack ;Get a packet.\r
1060 jmp r ; Trashed packet don't change state, retry.\r
1061 cpi 'Y' ;ACK?\r
1062 jnz sdata2 ;If not try next.\r
1063 call compp\r
1064 rnz ;If not hold out for the right one.\r
1065 lda argblk ;Get the packet number back\r
1066 call countp\r
1067 lda numtry ;Get the number of tries.\r
1068 sta oldtry ;Save it.\r
1069 xra a\r
1070 sta numtry ;Reset the number of tries.\r
1071 lda argblk+1 ;Get the data length\r
1072 cpi 1 ;Check if only 1 character?\r
1073 jnz sdat15 ;If not, just continue\r
1074 lda data ;Got one character, get it from data\r
1075 cpi 'Z' ;Want to abort entire stream?\r
1076 jnz sdat14 ;If not, check for just this file\r
1077 sta czseen ;Yes, remember it\r
1078 jmp sdat16 ;[MF] and set EOF state\r
1079sdat14: cpi 'X' ;Desire abort of current file?\r
1080 jnz sdat15 ;If not, just continue\r
1081 sta czseen ;Yes, remember that\r
1082 jmp sdat16 ;[MF] and set EOF\r
1083sdat15: lda czseen ;Also get control-Z flag\r
1084 ora a ;Check if either given\r
1085 jz sdat12 ;If neither given, continue\r
1086sdat16: mvi a,'Z' ;Change state to EOF\r
1087 sta state ; . . .\r
1088 ret ;And return\r
1089\r
1090sdat12: call gtchr\r
1091 jmp sdat13 ;Error go see if its EOF.\r
1092 sta size ;Save the size of the data gotten.\r
1093 ret\r
1094\r
1095sdat13: cpi 0FFH ;Is it EOF?\r
1096 jnz abort ;If not give up.\r
1097 mvi a,'Z' ;Set the state to EOF.\r
1098 sta state\r
1099 ret\r
1100\r
1101sdata2: cpi 'N' ;NAK?\r
1102 jnz sdata3 ;See if is an error packet.\r
1103 call updrtr ;Update the number of retries.\r
1104 lda pktnum ;Get the present packet number.\r
1105 inr a ;Increment\r
1106 ani 3FH ; modulo 64\r
1107 mov b,a\r
1108 lda argblk ;Get the packet's number.\r
1109 cmp b ;Is the packet's number one more than now?\r
1110 rnz ;If not go try again.\r
1111 jmp sdat12 ;Just as good as a ACK;go to the ACK code.\r
1112\r
1113sdata3: cpi 'E' ;Is it an error packet.\r
1114 jnz abort\r
1115 call error\r
1116 jmp abort\r
1117;\f\r
1118; Send EOF\r
1119; called by: send\r
1120\r
1121seof: lda numtry ;Get the number of tries.\r
1122 cpi maxtry ;Have we reached the maximum number of tries?\r
1123 jm seof1\r
1124 lxi d,erms14\r
1125 call error3\r
1126 jmp abort ;Change the state to abort.\r
1127\r
1128seof1: inr a ;Increment it.\r
1129 sta numtry ;Save the updated number of tries.\r
1130 lda pktnum ;Get the packet number.\r
1131 sta argblk\r
1132 xra a\r
1133 sta argblk+1 ;No data.\r
1134 lda czseen ;Check if C-Z or C-X typed\r
1135 ora a ; . . .\r
1136 jz seof14 ;If not aborted, just keep going\r
1137 mvi a,'D' ;Tell other end to discard packet\r
1138 sta data ;Store in data portion\r
1139 mvi a,1 ;One character\r
1140 sta argblk+1 ;Store the length\r
1141seof14: mvi a,'Z' ;EOF packet.\r
1142 call spack ;Send the packet.\r
1143 jmp abort ; Failed, abort.\r
1144 call rpack ;Get a packet.\r
1145 jmp r ; Trashed packet don't change state, retry.\r
1146 cpi 'Y' ;ACK?\r
1147 jnz seof2 ;If not try next.\r
1148 call compp\r
1149 rnz ;If not hold out for the right one.\r
1150seof12: call countp\r
1151 lda numtry ;Get the number of tries.\r
1152 sta oldtry ;Save it.\r
1153 xra a\r
1154 sta numtry ;Reset the number of tries.\r
1155 mvi c,closf ;Close the file.\r
1156 lxi d,fcb\r
1157 call bdos\r
1158;* Check if successful\r
1159 lda czseen ;Desire abort of entire stream?\r
1160 cpi 'Z' ;Desire abort of entire stream?\r
1161 jz seof13 ;If so, just give up now\r
1162 call mfname ;Get the next file.\r
1163 jc seof13 ; No more.\r
1164 call getfil ;and open it (assume success)\r
1165 xra a ;Clear A\r
1166 sta czseen ;Since we have not aborted this file\r
1167 mvi a,'F' ;Set the state to file send.\r
1168 sta state\r
1169 ret\r
1170\r
1171seof13: mvi a,'B' ;Set the state to EOT.\r
1172 sta state\r
1173 ret\r
1174\r
1175seof2: cpi 'N' ;NAK?\r
1176 jnz seof3 ;Try and see if its an error packet.\r
1177 call updrtr ;Update the number of retries.\r
1178 lda pktnum ;Get the present packet number.\r
1179 inr a ;Increment\r
1180 ani 3FH ; modulo 64\r
1181 mov b,a\r
1182 lda argblk ;Get the packet's number.\r
1183 cmp b ;Is the packet's number one more than now?\r
1184 rnz ;If not go try again.\r
1185 jmp seof12 ;Just as good as a ACK;go to the ACK code.\r
1186\r
1187seof3: cpi 'E' ;Is it an error packet.\r
1188 jnz abort\r
1189 call error\r
1190 jmp abort\r
1191;\f\r
1192; Send EOT\r
1193; called by: send\r
1194\r
1195seot: lda numtry ;Get the number of tries.\r
1196 cpi maxtry ;Have we reached the maximum number of tries?\r
1197 jm seot1\r
1198 lxi d,erms14\r
1199 call error3\r
1200 jmp abort ;Change the state to abort.\r
1201\r
1202seot1: inr a ;Increment it.\r
1203 sta numtry ;Save the updated number of tries.\r
1204 lda pktnum ;Get the packet number.\r
1205 sta argblk\r
1206 xra a\r
1207 sta argblk+1 ;No data.\r
1208 mvi a,'B' ;EOF packet.\r
1209 call spack ;Send the packet.\r
1210 jmp abort ; Failed, abort.\r
1211 call rpack ;Get a packet.\r
1212 jmp r ; Trashed packet don't change state, retry.\r
1213 cpi 'Y' ;ACK?\r
1214 jnz seot2 ;If not try next.\r
1215 call compp\r
1216 rnz ;If not hold out for the right one.\r
1217seot12: call countp\r
1218 lda numtry ;Get the number of tries.\r
1219 sta oldtry ;Save it.\r
1220 xra a\r
1221 sta numtry ;Reset the number of tries.\r
1222 mvi a,'C' ;Set the state to file send.\r
1223 sta state\r
1224 ret\r
1225\r
1226seot2: cpi 'N' ;NAK?\r
1227 jnz seot3 ;Is it error.\r
1228 call updrtr ;Update the number of retries.\r
1229 lda pktnum ;Get the present packet number.\r
1230 inr a ;Increment\r
1231 ani 3FH ; modulo 64\r
1232 mov b,a\r
1233 lda argblk ;Get the packet's number.\r
1234 cmp b ;Is the packet's number one more than now?\r
1235 rnz ;If not go try again.\r
1236 jmp seot12 ;Just as good as a ACK;go to the ACK code.\r
1237\r
1238seot3: cpi 'E' ;Is it an error packet.\r
1239 jnz abort\r
1240 call error\r
1241 jmp abort\r
1242;\f\r
1243; This routine sets up the data for init packet (either the\r
1244; Send_init or ACK packet).\r
1245; called by: rinit, rfile, sinit\r
1246;\r
1247; Called by rinit, rfile and sinit. See what WE want from the other fella\r
1248;\r
1249; [11] by OBS - Stripped out all the new capas code etc and reverted\r
1250; to Good Ol' Basic Kermit again!\r
1251; Those keen should study the followin gode with care, and remove\r
1252; or add semicolons as indicated.\r
1253;\r
1254; See also SPAR which decodes what comes in. It also decodes bits in \r
1255; the "capability" fields. (Two CAPAS files allowed from remote\r
1256; machines, but we will only send one at max.) Note that not all \r
1257; if any of the capability bits will be used.\r
1258;\r
1259; Definitions - init packet (data section only.. rest of header assumed OK)\r
1260; Byte 0 Maximum length I want to send\r
1261; 1 The Timeout I want you to use\r
1262; 2 Number of PAD characters I want tot use (May be null)\r
1263; 3 The PAD character I want to use (May be Null)\r
1264; 4 The End-of-Line character I will use (Carriage Return)\r
1265; 5 The control character Quote Character I will use (#)\r
1266; 6 The parity bit Quote Character I will use (&)\r
1267; 7 The Checktype I will use\r
1268; 8 The repeat prefix I will use (Null, as we cannot to repeats)\r
1269; 9 Capability Byte 0 (See SPAR for defs)\r
1270; 10 Capability byte 1 ( --- " --- but we will not send it.)\r
1271; 11 The number of packets I will send per window (not used)\r
1272; 12 MAXL1 - Long packet size, ms count\r
1273; 13 MAXL2 - Long packet size, ls count\r
1274;\r
1275;\r
1276; Enter with HL pointing to the "data" part of the packet.\r
1277\r
1278;\r
1279; older part of rpar follows...\r
1280;\r
1281;\r
1282rpar: lda rpsiz ;Get the receive packet size.\r
1283 adi space ;Add a space to make it printable.\r
1284 mov m,a ;Put it in the packet.\r
1285 inx h ;Point to the next char.\r
1286 lda rtime ;Get the receive packet time out.\r
1287 adi space ;Add a space.\r
1288 mov m,a ;Put it in the packet.\r
1289 inx h\r
1290 lda rpad ;Get the number of padding chars.\r
1291 adi space\r
1292 mov m,a\r
1293 inx h\r
1294 lda rpadch ;Get the padding char.\r
1295 adi 100O ;Uncontrol it.\r
1296 ani 7FH\r
1297 mov m,a\r
1298 inx h\r
1299 lda reol ;Get the EOL char.\r
1300 adi space\r
1301 mov m,a\r
1302 inx h\r
1303 lda rquote ;Get the quote char.\r
1304 mov m,a\r
1305 inx h\r
1306 mvi m,'Y' ;[jd] we know how to do 8-bit quoting\r
1307 lda parity ;[jd]\r
1308 cpi parnon ;[jd] parity none?\r
1309 jz rpar1 ;[jd] yes, keep going\r
1310 lda qbchr ;[jd] no, better request 8-bit quoting\r
1311 mov m,a\r
1312\r
1313rpar1:\r
1314 inx h ;Advance to next\r
1315 lda chktyp ;Get desired block check type\r
1316 mov m,a ;Store it\r
1317 inx h ;Advance pointer\r
1318\r
1319; Comment out the next two lines for capas etc. WILL require debugging\r
1320 mvi a,8 ; this id the older end for this routine. May be useful.\r
1321 ret\r
1322\r
1323; [11] Rest not needed for now, commented out\r
1324; [10] (to ret)\r
1325; New additions to rpar follows...\r
1326\r
1327; lda rcap1 ; get the first capability byte\r
1328; ani 3eh ; mask out bit 0, ie only one CAPAS byte\r
1329; adi space ; tochar it\r
1330; mov m,a\r
1331; inx h\r
1332; mvi m,space ; No windows, ie space to packet\r
1333; inx h\r
1334; push h ; we need the HL regs for maths.\r
1335; lhld rdpkt ; get receive packet length\r
1336; lxi d,95 ; we want hl div 95 and hl mod 95\r
1337; call divide ; return with divsion in hl, remainder in de\r
1338; mov a,l ; two sets of bytes\r
1339; pop h\r
1340; adi space ; tochar(maxl1)\r
1341; mov m,a\r
1342; inx h\r
1343; mov a,l\r
1344; adi space ; tochar(maxl2)\r
1345; mov m,a\r
1346;\r
1347; done all, set databytes = 12 and return\r
1348; mvi a,12 ; 12 bits of data\r
1349; ret\r
1350\r
1351;[11] End of commented out code for rpar\r
1352\r
1353\r
1354;\f\r
1355; This routine reads in all the send_init packet information.\r
1356; called by: rinit, sinit\r
1357\r
1358;[11] As for rpar, restore the "old" kermit code for non-capas Kermit.\r
1359;[10] (to ret at end)\r
1360;\r
1361; SPAR - routine to decode parameters received from the remote end\r
1362;\r
1363; Called by rinit,sinit\r
1364;\r
1365; Entry: a: Number of databytes in packet\r
1366; hl: Pointer to "data" part of packet\r
1367;\r
1368;spar: sta temp4 ; save for a while\r
1369; ; first clear some variables\r
1370; lda dspsiz ; get default "send" packet length\r
1371; sta spktl\r
1372; lda dstime ; get default time-out\r
1373; sta stimeo\r
1374; xra a ; set no pad characters by default\r
1375; sta spad\r
1376; lda dspadc ; get the default padding character\r
1377; sta spadc\r
1378; mvi a,cr ; default end of line character (CR)\r
1379; sta seol\r
1380; mvi a,dsquot ; default quote character\r
1381; sta squote\r
1382; mvi a,dsbqut ; default binary quote character\r
1383; sta qbchr\r
1384; mvi a,dschkt ; set checktype = 1 for inits\r
1385; sta inichk\r
1386; mvi a,space ; no repeat prefixing ( otherwise ~)\r
1387; sta srept\r
1388;\r
1389; Now follows the "capabilities" bits... 5 bits per capas byte.\r
1390;\r
1391; Note: Before extracting any data bits, apply unchar() to get the \r
1392; six ls bits. If bit 0 = 1 the a subsequent capaa byte follows\r
1393;\r
1394; Byte0: Bit 0: Set to 1 if there are subsequent CAPAS bytes\r
1395; 1: (Cap. 5) Set to 1 for long packets. Second byte\r
1396; AFTER the last capas byte has packet length DIV 95\r
1397; and Thire byte has length MOD 95\r
1398; 2: (Cap. 4) Sliding Windows. If used, first byte AFTER\r
1399; last capas byte has TOCHAR(no. of packets in window)\r
1400; 3: (Cap. 3) Ability to accept "A" (attribute packets)\r
1401; 4: (Cap. 2) Reserved\r
1402; 5: (Cap. 1) Reserved\r
1403; Byte 2 onward: not used in this implementation. Any capas bytes sent \r
1404; will be stored, however.\r
1405;\r
1406; lda temp4 ; get the number of bytes to test\r
1407; mov c,a ; to a count register\r
1408; mov a,m ; get first byte\r
1409; call decc ; unchar it, and decrement c\r
1410; sta spsiz ; save a send packet size\r
1411; jz sparx ; if no more, exit\r
1412;\r
1413; mov a,m ; get timout\r
1414; call decc\r
1415; sta stime ; save timeout\r
1416; jz sparx\r
1417;\r
1418; mov a,m ; get pad characters\r
1419; call decc \r
1420; sta spadc ; save it\r
1421; jz sparx\r
1422;\r
1423; mov a,m ; get pad character count\r
1424; call decc\r
1425; sta spad\r
1426; jz sparx\r
1427;\r
1428; mov a,m ; get send EOL\r
1429; call decc\r
1430; sta seol\r
1431; jz sparx\r
1432;\r
1433; mov a,m ; get control quote character\r
1434; call decc\r
1435; sta squote\r
1436; jz sparx\r
1437;\r
1438; mov a,m ; get binary (parity) quote char\r
1439; mov b,a ; this time we actually WANT accumulator\r
1440; cpi space ; are we doing 8th bit quoteing\r
1441; jz spar1 ; dont know, assume not\r
1442; cpi 'N' ; definately not?\r
1443; jz spar1\r
1444; cpi 'Y' ; definately - use &\r
1445; jz spar2\r
1446; sta squote ; else save the new character\r
1447;spar2: lda parity ; see if we are using the parity bit\r
1448; cpi parnon ; no parity => no quoting\r
1449; jz spar3 ; yup, so use the default quote character &\r
1450;\r
1451;spar1: xra a ; save not quoting\r
1452; sta squote\r
1453;spar3: call decc ; update counters etc\r
1454; jz sparx\r
1455;\r
1456; mov a,m ; get repeat prefixing\r
1457; call decc\r
1458; push psw ; save flags\r
1459; cpi space-32 ; we want it?\r
1460; jz spar4\r
1461; sta srept\r
1462;spar4: pop psw ; restore flags\r
1463; jz sparx\r
1464;\r
1465; lxi d,scapas ; point to start of capability byte(s)\r
1466; push psw ; must do this...\r
1467;spar5: pop psw ; cos we restore the spack\r
1468; mov a,m\r
1469; call decc ; get scap1 (or n)\r
1470; sta scap1\r
1471; push psw\r
1472; ani 01 ; another byte following?\r
1473; jnz spar5\r
1474; pop psw ; see if any other data bytes (Windows etc)\r
1475; jz sparx\r
1476;\r
1477; mov a,m ; get window size\r
1478; call decc\r
1479; sta swindo\r
1480; jz sparx\r
1481;\r
1482; mov a,m ; get long packets ms bits\r
1483; call decc ;\r
1484; mov d,a ; unchared ms bits-ish\r
1485; mov a,m\r
1486; call decc ; ls bits-ish\r
1487; push h ; and we are doing maths\r
1488; push b ; and an intermediate result in c\r
1489; push psw ; we want flags and the ls bits...\r
1490; mvi b,0\r
1491; mov c,d ; get ms bits-ish to bc\r
1492; push b ; get number to hl\r
1493; pop h\r
1494; now multipy by 95\r
1495; dad h ;*2\r
1496; dad h ;*4\r
1497; dad h ;*8\r
1498; dad h ;*16\r
1499; push h ; *16 to ...\r
1500; pop d ; ... de\r
1501; dad h ;*32\r
1502; dad d ; *(32+16) = *48\r
1503; dad h ; *96\r
1504; mov a,l ; *(96-1)\r
1505; sub c\r
1506; mov l,a\r
1507; mov a,0\r
1508; sbb h\r
1509; mov h,a\r
1510; pop psw ; restore ls bitsish\r
1511; mov e,a\r
1512; mvi d,0\r
1513; dad d ; *95 + ls bits. Phew.\r
1514; shld sdpkt ; save long packet length\r
1515; pop b\r
1516; pop h ; restore regs\r
1517;\r
1518;sparx: ret ; if here, (assume) no more data to read in\r
1519;[10] routines required follow\r
1520;decc: mov a,m ; get data byte\r
1521; sui space ; unchar it\r
1522; inx h ; increment input pointer\r
1523; dcr c ; decrement data counter\r
1524; ret ; return\r
1525;[10] end or spar replacement\r
1526\r
1527;[11] Restore older spar....\r
1528; Older spar follows...\r
1529spar: sta temp4 ;Save the number of arguments.\r
1530; Initialize some variables to their required default values, so we use\r
1531; the right values even if the remote Kermit doesn't send the full packet:\r
1532; ; we don't do anything with timeout values yet.\r
1533; ; no default pad count/pad character?\r
1534 mvi a,cr ; EOL character = carriage-return\r
1535 sta seol\r
1536 mvi a,'#' ; quote character = '#'\r
1537 sta squote\r
1538 mvi a,'&' ; eighth-bit quote character = '&'\r
1539 sta qbchr\r
1540 mvi a,'1' ; block-check = 1-character-checksum\r
1541 sta inichk\r
1542; \r
1543 mov a,m ;Get the max packet size.\r
1544 sbi space ;Subtract a space.\r
1545 sta spsiz ;Save it.\r
1546 lda temp4\r
1547 cpi 3 ;Fewer than three pieces?\r
1548 rm ;If so we are done.\r
1549 inx h\r
1550 inx h ;Increment past the time out info.\r
1551 mov a,m ;Get the number of padding chars.\r
1552 sbi space\r
1553 sta spad\r
1554 lda temp4\r
1555 cpi 4 ;Fewer than four pieces?\r
1556 rm ;If so we are done.\r
1557 inx h\r
1558 mov a,m ;Get the padding char.\r
1559 adi 100O ;Re-controlify it.\r
1560 ani 7FH\r
1561 sta spadch\r
1562 lda temp4\r
1563 cpi 5 ;Fewer than five pieces?\r
1564 rm ;If so we are done.\r
1565 inx h\r
1566 mov a,m ;Get the EOL char.\r
1567 sbi space\r
1568 sta seol\r
1569 lda temp4\r
1570 cpi 6 ;Fewer than six pieces?\r
1571 rm ;If so we are done.\r
1572 inx h\r
1573 mov a,m ;Get the quote char.\r
1574 sta squote\r
1575 lda temp4 ;Get the amount of data supplied\r
1576 cpi 7 ;Have an 8-bit quote?\r
1577 rm ;If not there, all done\r
1578 inx h ;Yes, get the character\r
1579 mvi a,0 ;[jd] \r
1580 sta quot8 ;[jd] assume not quoting\r
1581 mov a,m ;Get the supplied character\r
1582 cpi 'N' ;[jd] No?\r
1583 jz spar1 ;[jd] then don't try to do it\r
1584 cpi space ;[jd] maybe they don't know about it...\r
1585 jz spar1 ;[jd] then don't try to do it.\r
1586 cpi 'Y' ;[jd] Yes?\r
1587 jnz spar2 ;[jd] if not 'Y', assume it's a quote char.\r
1588 lda parity ;[jd] using parity?\r
1589 cpi parnon ;[jd] no, don't need quoting...\r
1590 jz spar1 ;[jd] \r
1591 mvi a,0ffh ;[jd] else turn on...\r
1592 sta quot8 ;[jd] ...quote flag\r
1593 jmp spar1\r
1594\r
1595;[11] Note: If capas etc required, beware of the next two lables, as these \r
1596; are used elswhere.\r
1597\r
1598spar2: sta qbchr ;[jd] use their quote char (should validate)\r
1599 mvi a,0ffh\r
1600 sta quot8 ;[jd] turn quote flag and fall thru...\r
1601\r
1602spar1: lda temp4 ;Determine if block check type given\r
1603 cpi 8 ;Is the field there?\r
1604 rm ;If not, all done\r
1605 inx h ;Point to the character\r
1606 mov a,m ;Get the value\r
1607 mov b,a ;Copy value\r
1608 lda chktyp ;Get our type\r
1609 cmp b ;Is it our desired type?\r
1610 rnz ; If not, use default (1-character-checksum)\r
1611 sta inichk ; Match, store as type to use after init\r
1612 ret ; and return\r
1613;[10] end of replacement\r
1614;[11] end of replacement of replacement (ie back to original code)\r
1615;\f\r
1616\r
1617; Copy characters from packet to disk (or screen)\r
1618; called by: rdata\r
1619\r
1620ptchr: sta temp1 ;Save the size.\r
1621 lda remtxt ;[MF]Get remote command flag\r
1622 ora a ;[MF]Remote command in progress?\r
1623 jnz ptchr0 ;[MF]Yes, don't check for file collisions\r
1624 lda flwflg ;[MF]Get File Warning (Set Collision) flag\r
1625 cpi 3 ;[MF]SET COLLISION DISCARD?\r
1626 jnz ptchr0 ;[MF]No\r
1627 lda dscflg ;[MF]Yes, get "discard" flag\r
1628 ora a ;[MF]Discarding file?\r
1629 jz ptchr0 ;[MF]No\r
1630 mvi a,'X' ;[MF]Yes, simulate a user rejection\r
1631 sta czseen ;[MF]...\r
1632 jmp rskp ;[MF]and pretend success\r
1633ptchr0: ;[MF]\r
1634 lxi h,data ;Beginning of received packet data.\r
1635 shld outpnt ;Remember where we are.\r
1636 lda rquote\r
1637 mov b,a ;Keep the quote char in b.\r
1638 mvi c,0 ;[jd] assume no 8-bit quote char\r
1639 lda quot8 ;[jd] doing 8-bit quoting?\r
1640 ora a\r
1641 jz ptchr1 ;[jd] no, keep going\r
1642 lda qbchr ;[jd] else get 8-bit quote char\r
1643 mov c,a ;[jd] keep this in c\r
1644ptchr1: lxi h,temp1\r
1645 dcr m ;Decrement # of chars in packet.\r
1646 jm rskp ;Return successfully if done.\r
1647 lda remtxt ; to screen only?\r
1648 ana a\r
1649 jnz ptchr2 ; dont do any disk stuff\r
1650 lxi h,chrcnt ;Number of chars remaining in dma.\r
1651 dcr m ;Decrement.\r
1652 jp ptchr2 ;Continue if space left.\r
1653 call outbuf ;Output it if full.\r
1654 jmp ptchr9 ; Error return if disk is full.\r
1655ptchr2: lhld outpnt ;Get position in output buffer.\r
1656 mov a,m ;Grab a char.\r
1657 inx h\r
1658 shld outpnt ;and bump pointer.\r
1659 mvi e,0 ;[jd] assume nothing to OR in.\r
1660 cmp c ;[jd] is it the binary quote char?\r
1661 jnz ptch2a ;[jd] no, keep going\r
1662 mvi e,80h ;[jd] include parity bit\r
1663 lda temp1\r
1664 dcr a\r
1665 sta temp1 ;[jd] decrement character count\r
1666 mov a,m ;[jd] get next character\r
1667 inx h\r
1668 shld outpnt\r
1669ptch2a: cmp b ;Is it the quote char?\r
1670 jnz ptchr3 ;[jd] changed to ptchr3 so includes parity\r
1671 mov a,m ;Get the quoted character\r
1672 inx h\r
1673 shld outpnt ;and bump pointer.\r
1674 lxi h,temp1\r
1675 dcr m ;Decrement # of chars in packet.\r
1676 mov d,a ;Save the char.\r
1677 ani 80H ;Turn off all but the parity bit.\r
1678 ora e ;[jd] let parity come from either (???)\r
1679 mov e,a ;Save the parity bit.\r
1680 mov a,d ;Get the char.\r
1681 ani 7FH ;Turn off the parity bit.\r
1682 cmp b ;Is it the quote char?\r
1683 jz ptchr3 ;If so just go write it out.\r
1684 cmp c ;[jd] maybe it's the 8-bit prefix character?\r
1685 jz ptchr3 ;[jd] then don't controllify.\r
1686 mov a,d ;Get the char.\r
1687 adi 40H ;Make the character a control char again.\r
1688 ani 7FH ;Modulo 128.\r
1689ptchr3: ora e ;Or in the parity bit.\r
1690 sta temp3 ; save for a while\r
1691 lda remtxt ; to screen or disk?\r
1692 ana a\r
1693 lda temp3\r
1694 jz ptch31 ; to disk\r
1695 push h\r
1696 push d\r
1697 push b\r
1698 mov e,a ; to display\r
1699 mvi c,dconio\r
1700 call bdos\r
1701 pop b\r
1702 pop d\r
1703 pop h\r
1704 jmp ptchr1 ; continue\r
1705\r
1706ptch31: lhld bufpnt ;Destination buffer.\r
1707 mov m,a ;Store it.\r
1708 inx h\r
1709 shld bufpnt ;Update the pointer\r
1710 jmp ptchr1 ;and loop to next char.\r
1711\r
1712ptchr9: lxi d,erms11 ; "?Disk full"\r
1713 push d ;[MF] Save pointer\r
1714 call error3 ; put it on the error line\r
1715 pop d ;[MF] Restore pointer\r
1716 lxi h,data ;[MF] Where to put the message for "e" packet\r
1717 lda argblk ;[MF] Get packet-number\r
1718 call countp ;[MF]Increment it\r
1719 sta argblk ;[MF] as packet to send\r
1720 xra a ;[MF] Zero length of packet data\r
1721 sta temp1 ;[MF] ...\r
1722ptch9a: ldax d ;[MF] Get a character to copy\r
1723 cpi cr ;[MF] No more to copy?\r
1724 jz ptch9b ;[MF] Yes, we can send the packet\r
1725 mov m,a ;[MF] No, copy the character\r
1726 inx d ;[MF] and increment source/dest pointers\r
1727 inx h ;[MF] ...\r
1728 lda temp1 ;[MF] Get character count\r
1729 inr a ;[MF] and increment it\r
1730 sta temp1 ;[MF] ...\r
1731 jmp ptch9a ;[MF] Copy entire error message\r
1732ptch9b: mvi m,0 ;[MF]Put in a zero\r
1733 lda temp1 ;[MF] Get number of characters in the message\r
1734 sta argblk+1 ;[MF] and store as number of packet data chars\r
1735 mvi a,'E' ;[MF] Make it an error packet\r
1736 call spack ;[MF] Send the error packet\r
1737 nop ;[MF] Don't really care if\r
1738 nop ;[MF] the send fails since we're\r
1739 nop ;[MF] bombing off anyway\r
1740 ret ; take error return.\r
1741;\f\r
1742; Fill a data packet from file\r
1743; called by: sfile, sdata\r
1744\r
1745gtchr: lda squote ;Get the quote char.\r
1746 mov c,a ;Keep quote char in c.\r
1747 lda curchk ;Get current block check type\r
1748 sui '1' ;Get the extra overhead\r
1749 mov b,a ;Get a copy\r
1750 lda spsiz ;Get the maximum packet size.\r
1751 sui 5 ;Subtract the overhead.\r
1752 sub b ;Determine max packet length\r
1753 sta temp1 ;This is the number of chars we are to get.\r
1754 lxi h,filbuf ;Where to put the data.\r
1755 shld cbfptr ;Remember where we are.\r
1756 mvi b,0 ;No chars.\r
1757gtchr1: lda temp1\r
1758 dcr a ;Decrement the number of chars left.\r
1759 jp gtchr2 ;Go on if there is more than one left.\r
1760 mov a,b ;Return the count in A.\r
1761 jmp rskp\r
1762\r
1763gtchr2: sta temp1\r
1764 lda chrcnt ;Space left in the DMA.\r
1765 dcr a\r
1766;* Can improve order here.\r
1767 jm gtchr3\r
1768 sta chrcnt\r
1769 jmp gtchr4\r
1770\r
1771gtchr3: call inbuf ;Get another buffer full.\r
1772 jmp gtch30 ; If no more return what we got.\r
1773 jmp gtchr4 ;If we got some, proceed.\r
1774\r
1775gtch30: mov a,b ;Return the count in A.\r
1776 ora a ;Get any chars?\r
1777 jnz rskp ;If so return them.\r
1778 jmp gtceof ;If not, say we found the end of the file.\r
1779\r
1780gtchr4: lhld bufpnt ;Position in DMA.\r
1781 mov a,m ;Get a char from the file.\r
1782 inx h\r
1783 shld bufpnt\r
1784 mov d,a ;Save the char.\r
1785 ani 80H ;Turn off all but parity.\r
1786 mov e,a ;Save the parity bit.\r
1787 jz gtch4a ;[jd] no parity, skip this check...\r
1788 lda quot8 ;[jd] doing eighth-bit quoting?\r
1789 ora a\r
1790 jz gtch4a ;[jd] no, just proceed normally\r
1791 lda temp1 ;[jd] get space remaining\r
1792 cpi 2 ;[jd] 3 chrs left (one cnted already)?\r
1793 jm gtchr9 ;[jd] no, skip this\r
1794 dcr a ;[jd] decrement space remaining\r
1795 sta temp1 ;[jd] put back.\r
1796 lhld cbfptr ;[jd] Position in character buffer.\r
1797 lda qbchr ;[jd] get quote character\r
1798 mov m,a ;]jd] Put the quote char in the buffer.\r
1799 inx h ;[jd] increment destination buffer pointer\r
1800 shld cbfptr ;[jd] store the pointer back\r
1801 inr b ;[jd] Increment the char count.\r
1802 mvi e,0 ;[jd] no parity bit to OR in.\r
1803;[jd] fall thru...\r
1804\r
1805gtch4a: mov a,d ;Restore the char.\r
1806 ani 7FH ;Turn off the parity.\r
1807 mov d,a ;[jd] save here for later...\r
1808 cpi space ;Compare to a space.\r
1809 jm gtchr5 ;If less then its a control char, handle it.\r
1810 cpi del ;Is the char a delete?\r
1811 jz gtchr5 ;Go quote it.\r
1812 lda quot8 ; Are we doing 8th-bit quoting?\r
1813 ora a\r
1814 jz gtch4c ; if not, skip this test and restore character.\r
1815 lda qbchr ; get 8th-bit quote character\r
1816 cmp d ; same as current character?\r
1817 jz gtch4b ; yes, have to quote it...\r
1818gtch4c: mov a,d ; no. get character back again.\r
1819 cmp c ;Is it the quote char?\r
1820 jnz gtchr8 ;If not proceed.\r
1821gtch4b: lxi h,temp1 ;[jd] point to char count\r
1822 dcr m ;[jd] decrement (know room for at least one)\r
1823 lhld cbfptr ;Position in character buffer.\r
1824 mov m,c ;Put the (quote) char in the buffer.\r
1825 inx h\r
1826 shld cbfptr\r
1827 inr b ;Increment the char count.\r
1828 mov a,d ;[jd] restore character again\r
1829 jmp gtchr8\r
1830\r
1831gtchr5: \r
1832 ;[gnn] ignore parity for checking\r
1833; ora e ;Turn on the parity bit.\r
1834\r
1835 cpi ('Z'-100O) ;Is it a ^Z?\r
1836 jnz gtchr7 ;If not just proceed.\r
1837 lda cpmflg ;Was the file created by CPM...\r
1838 cpi 1 ;in ASCII-mode ?\r
1839 jz gtch52 ;Control-Z stops text\r
1840 cpi 2 ;in BINARY mode?\r
1841 jz gtchr6 ;Yes, pass the ^Z\r
1842;At this point file-mode is DEFAULT.\r
1843;If the rest of the record is filled with ^Zs, we're at EOF, otherwise\r
1844;its a regular character.\r
1845 lhld bufpnt ;since CHRCNT is ZERO at EOF-time\r
1846 lda chrcnt ;(set by INBUF5 B.G.E)\r
1847 mov d,a ;Get the number of chars left in the DMA.\r
1848gtch51: dcr d\r
1849 mov a,d\r
1850 jp gtch53 ;Any chars left?\r
1851gtch52: xra a ;If not, get a zero.\r
1852 sta chrcnt ;Say no more chars in buffer.\r
1853 mov a,b ;Return the count in A.\r
1854 jmp rskp\r
1855\r
1856;Scan rest of buffer for non ^Z -- If we find a non ^Z, fall into gtchr6.\r
1857;If we get to the end of the buffer before finding a non ^Z, fall into gtch52.\r
1858gtch53: mov a,m ;Get the next char.\r
1859 inx h ;Move the pointer.\r
1860 cpi ('Z'-100O) ;Is it a ^Z?\r
1861 jz gtch51 ;If so see if the rest are.\r
1862\r
1863gtchr6: mvi a,('Z'-100O) ;Restore the ^Z.\r
1864gtchr7: sta temp2 ;Save the char.\r
1865 lxi h,temp1 ;Point to the char total remaining.\r
1866 dcr m ;Decrement it.\r
1867 lhld cbfptr ;Position in character buffer.\r
1868 mov m,c ;Put the quote in the buffer.\r
1869 inx h\r
1870 shld cbfptr\r
1871 inr b ;Increment the char count.\r
1872 lda temp2 ;Get the control char back.\r
1873 adi 40H ;Make the non-control.\r
1874 ani 7fH ;Modulo 200 octal.\r
1875gtchr8: lhld cbfptr ;Position in character buffer.\r
1876 ora e ;Or in the parity bit.\r
1877 mov m,a ;Put the char in the buffer.\r
1878 inx h\r
1879 shld cbfptr\r
1880 inr b ;Increment the char count.\r
1881 jmp gtchr1 ;Go around again.\r
1882\r
1883gtchr9: ;[jd] not enough room left in buffer...\r
1884 lhld bufpnt\r
1885 dcx h\r
1886 shld bufpnt ;[jd] back up over last character\r
1887 lxi h,chrcnt ;[jd] point to character count\r
1888 inr m ;[jd] increment it\r
1889 mov a,b ;[jd] count of chars transferred\r
1890 jmp rskp ;[jd] return it\r
1891\r
1892gtceof: mvi a,0FFH ;Get a minus one.\r
1893 ret\r
1894;\f\r
1895\r
1896; Little code to allow some expansion of code without changing\r
1897; every futher address, only up to the end of this file.\r
1898; TO BE REMOVED FRO RELEASE!\r
1899\r
1900; org ($+100h) AND 0FF00H\r
1901\r
1902IF lasm\r
1903 LINK CPSPK2 ;[obs] Link to part two of the packet file\r
1904ENDIF ;lasm\r