]> cloudbase.mooo.com Git - kermit-80.git/blame - cpxcom.asm
Bugfix in outmdm (output buffer flush)
[kermit-80.git] / cpxcom.asm
CommitLineData
e58a7a25
L
1IF NOT lasm\r
2.printx * CPXCOM.ASM *\r
3ENDIF ; NOT lasm\r
4; KERMIT - (Celtic for "FREE")\r
5;\r
6; This is the CP/M-80 implementation of the Columbia University\r
7; KERMIT file transfer protocol.\r
8;\r
9; Version 4.0\r
10;\r
11; Copyright June 1981,1982,1983,1984,1985\r
12; Columbia University\r
13;\r
14; Originally written by Bill Catchings of the Columbia University Center for\r
15; Computing Activities, 612 W. 115th St., New York, NY 10025.\r
16;\r
17; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben,\r
18; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many\r
19; others.\r
20;\r
21; This file contains part common code required for most if not all\r
22; systems. Specifiacally, SYSINIT, INIADR, MOVER, and DELAY to name\r
23; the most important ones.\r
24;\r
25; revision history:\r
26;\r
27; edit 1, 21st July 1987 by OBSchou. Regretably, I have had to include\r
28; some system dependent IFs, mainly for CRT, TORCH and OSI. Inclusion\r
29; here means simpler family files later on. (Regrettably, the delay\r
30; loop for APMMDM differs too.)\r
31;\r
32; Set the fuzzy timeout value. Range is 1 (VERY short) through 0ffffH to zero\r
33; (maximum). The actual duration is a function of the loop length and the\r
34; processor speed. For now, we'll make it zero for everybody, but feel free\r
35; to change it for your system.\r
36; [OBS] make it a little less than max, say 1000H. More useful.\r
37fuzval EQU 1000H\r
38\r
39;\r
40; System-dependent initialization\r
41; Called once at program start.\r
42sysinit:\r
43;\r
44; [13] Had to move this call to here, as the prtstr routine needs this\r
45; before the config message is sent out. It has only been moved.\r
46;\r
47 call iniadr ;Initialize the BIOS addresses\r
48 mvi c,gtiob ;Get current I/O byte\r
49 call bdos ;From CP/M\r
50 sta coniob ;Remember where console is\r
51 mvi c,getvnm ; get the BDOS version number (e.g. 22H, 31H)\r
52 call bdos\r
53 mov a,l\r
54 sta bdosvr ; and store it away for future reference\r
55 lxi d,cfgmsg ; "configured for "\r
56 call prtstr\r
57 lxi d,sysver ; get configuration we're configured for\r
58 call prtstr ; print it.\r
59;\r
60; If we're set up to do special terminal handling, say what kind\r
61; of terminal we expect... (unless it's the generic 'crt')\r
62IF termin\r
63 lxi d,witmsg ; " with "\r
64 call prtstr\r
65 lxi d,ttytyp ; terminal type\r
66 call prtstr\r
67ENDIF;termin\r
68 call prcrlf ; print CR/LF\r
69;\r
70; now, to work...\r
71;\r
72; locate large buffer for multi-sector I/O\r
73; What we want to do here is find the ccp. Space between ovlend and the ccp\r
74; is available for buffering, except we don't want to use more than maxsec\r
75; buffers (if we use too many, the remote end could time out while we're\r
76; writing to disk). maxsec is system-dependent, but for now we'll just\r
77; use 8Kbytes. If you get retransmissions and other protocol errors after\r
78; transferring the first maxsec sectors, lower maxsec.\r
79\r
80maxsec EQU (8*1024)/bufsiz ; 8K / number of bytes per sector\r
81\r
82 lxi h,ovlend ; get start of buffer\r
83 shld bufadr ; store in linkage section\r
84 mvi a,maxsec ; get size of buffer, in sectors\r
85 sta bufsec ; store that, too.\r
86\r
87 call sysxin ; call system specific init code\r
88\r
89 ret ; return from system-dependent routine\r
90\r
91bdosvr: ds 1 ; space to save the BDOS version number\r
92IF NOT iobyt\r
93coniob: ds 1 ; space to save copy of IO byte\r
94ENDIF ;NOT iobyt\r
95;\f\r
96; This one is hopefully the last "improvement" in view of GENERIC\r
97;Kermit. It uses for Character-I/O the BIOS-routines ( instead of the\r
98;"normal" BDOS routines. What does it give us (hopefully) : More speed,\r
99;higher chance of success ( I/O byte implemented in BIOS [if at all]),\r
100;but no "extra" device handling - that's done by BDOS.\r
101;\r
102; How do we "get" the call-adresses? Location 0 has a JMP Warm-Boot\r
103;in CP/M which points into the second location of the BIOS JMP-Vector. The\r
104;next three locations of the JMP-Vector point to the CONSTAT,CONIN,CONOUT\r
105;BIOS-routines. CONOUT wants the character in C.\r
106;\r
107;- Bernie Eiben\r
108\r
109iniadr: lhld 1 ;get BIOS Warmstart-address\r
110 lxi d,3 ;next adress is CONSTAT in BIOS\r
111 dad d\r
112 shld bconst+1 ;stuff it into the call-instruction\r
113 lxi d,3 ;next adress is CONIN in BIOS\r
114 dad d\r
115 shld bconin+1 ;\r
116 lxi d,3 ;next adress is CONOUT in BIOS\r
117 dad d\r
118 shld bcnout+1\r
119 lxi d,3 ;next address is LIST in BIOS\r
120 dad d\r
121 shld blsout+1\r
122 lxi d,10*3 ; get printer status routine\r
123 dad d\r
124 shld bprtst\r
125 ret ;And return\r
126\r
127bconst: jmp $-$ ;Call BIOS directly (filled in by iniadr)\r
128\r
129bconin: jmp $-$ ;Call BIOS directly (filled in by iniadr)\r
130\r
131bcnout: jmp $-$ ;Call BIOS directly (filled in by iniadr)\r
132\r
133blsout: jmp $-$ ; ....\r
134\r
135bprtst: jmp $-$ ; Call BIOS directly for printer status\r
136\r
137IF NOT apmmdm ; Shame about this, but the Apple needs a different delay\r
138;\r
139;[cjc] Delay routine. Called with time (hundredths of seconds) in A.\r
140; The inner loop delays 1001 T-states, assuming no wait states are\r
141; inserted; this is repeated CPUSPD times, for a total delay of just\r
142; over 0.01 second. (CPUSPD should be set to the system clock rate,\r
143; in units of 100KHz: for an unmodified Kaypro II, that's 25 for\r
144; 2.5 MHz. Some enterprising soul could determine whether or not the\r
145; Kaypro actually inserts a wait state on instruction fetch (a common\r
146; practice); if so, the magic number at delay2 needs to be decreased.\r
147; (We also neglect to consider time spent at interrupt level).\r
148;\r
149; called by: sendbr\r
150; destroys BC\r
151\r
152delay: mvi c,cpuspd ; Number of times to wait 1000 T-states to\r
153 ; make .01 second delay\r
154delay2: mvi b,70 ; Number of times to execute inner loop to\r
155 ; make 1000 T-state delay\r
156delay3: dcr b ; 4 T-states (* 70 * cpuspd)\r
157 jnz delay3 ; 10 T-states (* 70 * cpuspd)\r
158 dcr c ; 4 T-states (* cpuspd)\r
159 jnz delay2 ; 10 T-states (* cpuspd)\r
160 ; total delay: ((14 * 70) + 14) * cpuspd\r
161 ; = 1001 * cpuspd\r
162 dcr a ; 4 T-states\r
163 jnz delay ; 10 T-states\r
164 ret ; grand total: ((1001 * cpuspd) + 14) * a\r
165ENDIF ; NOT apmmdm\r
166;\f\r
167;\r
168; Set up screen display for file transfer\r
169; called with kermit version in DE\r
170;\r
171sysscr: push d ; save version for a bit\r
172 lxi d,outlin ; clear screen, position cursor\r
173 call prtstr ; do it\r
174 pop d ; get Kermit's version\r
175IF NOT (osi OR crt) ; got cursor control?\r
176 call prtstr ; print it\r
177 mvi e,'[' ; open bracket\r
178 call outcon ; print it (close bracket is in outln2)\r
179 lxi d,sysver ; get name and version of system module\r
180 call prtstr\r
181 lxi d,outln2 ; yes, print field names\r
182 call prtstr\r
183 lda dbgflg ; is debugging enabled?\r
184 ora a\r
185 rz ; finished if no debugging\r
186 lxi d,outln3 ; set up debugging fields\r
187 call prtstr\r
188ENDIF;NOT (osi OR crt)\r
189 ret\r
190;\f\r
191; Calculate free space for current drive\r
192; returns value in HL\r
193sysspc:\r
194 lda bdosvr ;cpm3's alloc vect may be in another bank\r
195 cpi 30H ;cpm3 or later?\r
196 jm cp2spc ;no: use cp/m 2 algorithm\r
197 lda fcb ;If no drive, get\r
198 ora a ; logged in drive\r
199 jz dir180\r
200 dcr a ;FCB drive A=1 normalize to be A=0\r
201 jmp dir18a\r
202\r
203dir180: mvi c,rddrv\r
204 call bdos\r
205dir18a: mov e,a ;drive in e\r
206 mvi c,getfs ;get free space BDOS funct\r
207 call bdos ;returns free recs (3 bytes in buff..buff+2)\r
208 mvi b,3 ;conv recs to K by 3 bit shift\r
209dir18b: xra a ;clear carry\r
210 mvi c,3 ;for 3 bytes\r
211 lxi h,buff+3 ;point to addr + 1\r
212dir18c: dcx h ;point to less sig. byte\r
213 mov a,m ;get byte\r
214 rar ;carry -> A -> carry\r
215 mov m,a ;put back byte\r
216 dcr c ;for all bytes (carry not mod)\r
217 jnz dir18c\r
218 dcr b ;shift 1 bit 3 times\r
219 jnz dir18b\r
220 mov e,m ;get least sig byte\r
221 inx h\r
222 mov d,m ;get most sig byte\r
223 xchg ;get K free in HL\r
224 ret\r
225\r
226; the rest are CP/M 2.2 systems, so use the alloc vector\r
227cp2spc: mvi c,getalv ;Address of CP/M Allocation Vector\r
228 call bdos\r
229 xchg ;Get its length\r
230 lhld bmax\r
231 inx h\r
232 lxi b,0 ;Initialize Block count to zero\r
233dir19: push d ;Save allocation address\r
234 ldax d\r
235 mvi e,8 ;set to process 8 blocks\r
236dir20: ral ;Test bit\r
237 jc dir20a\r
238 inx b\r
239dir20a: mov d,a ;Save bits\r
240 dcx h\r
241 mov a,l\r
242 ora h\r
243 jz dir21 ;Quit if out of blocks\r
244 mov a,d ;Restore bits\r
245 dcr e ;count down 8 bits\r
246 jnz dir20 ;do another bit\r
247 pop d ;Bump to next count of Allocation Vector\r
248 inx d\r
249 jmp dir19 ;process it\r
250\r
251dir21: pop d ;Clear Allocation vector from stack\r
252 mov l,c ;Copy block to 'HL'\r
253 mov h,b\r
254 lda bshiftf ;Get Block Shift Factor\r
255 sui 3 ;Convert from records to thousands\r
256 rz ;Skip shifts if 1K blocks\r
257dir22: dad h ;Multiply blocks by 'K per Block'\r
258 dcr a\r
259 jnz dir22\r
260 ret\r
261\r
262; +----|----|----|----|----|----|----|...\r
263; 1 |\r
264; 2 | Kermit-80 v4.0 [system]\r
265; 3 |\r
266; 4 |Number of packets: ____\r
267; 5 |Number of retries: ____\r
268; 6 |File name: ____________\r
269; 7 |<error>...\r
270; 8 |<status>...\r
271; 9 |RPack: ___(if debugging)...\r
272; 10 |\r
273; 11 |SPack: ___(if debugging)...\r
274; 12 |\r
275; 13 |Kermit-80 A:> (when finished)\r
276;\r
277; For the PX-8, the display looks like:\r
278; 5 10 15 20 25 30 35 40 45 50 55\r
279; +----|----|----|----|----|----|----|----|----|----|----|----|----\r
280; 1 |Kermit-80 v4.05 [Epson PX-8] Number of retries: ____\r
281; 2 |Number of packets: ____ File name: ________.___\r
282; 3 |<error>...\r
283; 4 |<status>...\r
284; 5 |RPack: ___ (if debugging)...\r
285; 6 |\r
286; 7 |SPack: ___ (if debugging)...\r
287; 8 |\r
288; 9 |Kermit-80 A:> (when finished)\r
289;\r
290\r
291IF NOT px8 ; [29]\r
292nppos EQU 4*100h+20\r
293rtpos EQU 5*100h+20\r
294fnpos EQU 6*100h+12\r
295errlin EQU 7\r
296stlin EQU 8\r
297rplin EQU 9\r
298splin EQU 11\r
299prplin EQU 13\r
300ENDIF ; NOT px8\r
301\r
302IF px8\r
303nppos EQU 2*100h+20\r
304rtpos EQU 1*100h+59\r
305fnpos EQU 2*100h+51\r
306errlin EQU 3\r
307stlin EQU 4\r
308rplin EQU 5\r
309splin EQU 7\r
310prplin EQU 9\r
311ENDIF ; px8 [29]\r
312\r
313\r
314IF NOT (osi OR crt );[26]\r
315scrnp: lxi b,nppos\r
316 jmp csrpos\r
317\r
318scrnrt: lxi b,rtpos\r
319 jmp csrpos\r
320\r
321scrfln: lxi b,fnpos\r
322 call csrpos\r
323clreol:\r
324 lxi d,tk\r
325 jmp prtstr\r
326\r
327screrr: lxi b,errlin*100H+1\r
328 call csrpos\r
329 jmp clreol\r
330\r
331scrst: lxi b,stlin*100H+1\r
332 call csrpos\r
333 jmp clreol\r
334\r
335rppos: lxi b,rplin*100H+8\r
336 call csrpos\r
337 jmp clreol\r
338\r
339sppos: lxi b,splin*100H+8\r
340 call csrpos\r
341 jmp clreol\r
342\r
343; [29] Modify scrend to make the cursor line conditional on use of debugging\r
344; This means that in most cases the entire file transfer will fit on PX-8 lcd\r
345scrend: lda dbgflg\r
346 ora a\r
347 jz scr1nd\r
348 lxi b,prplin*100H+1 ; debugging in use [29]\r
349 jmp scr2nd\r
350scr1nd: lxi b,rplin*100H+1 ; no debugging\r
351scr2nd: call csrpos\r
352clreos: lxi d,tj\r
353 jmp prtstr\r
354; [29] and nop out the rest for now...\r
355;\r
356;scrend: lxi b,prplin*100H+1\r
357; call csrpos\r
358;clreos: lxi d,tj\r
359; jmp prtstr\r
360ENDIF;NOT (osi OR crt ) [26]\r
361\r
362\r
363IF osi OR crt ; no cursor control\r
364scrnp: mvi e,' '\r
365 jmp outcon\r
366\r
367scrnrt: mvi e,' '\r
368 call outcon\r
369 mvi e,'%'\r
370 jmp outcon\r
371\r
372scrfln:\r
373screrr:\r
374scrst:\r
375scrend: jmp prcrlf ;Print CR/LF [Toad Hall]\r
376\r
377rppos: lxi d,prpack\r
378 jmp prtstr\r
379\r
380sppos: lxi d,pspack\r
381 jmp prtstr\r
382ENDIF;osi OR crt\r
383\r
384; Some frequently-used routines (duplicates of those in CPSMIT):\r
385; prcrlf - output a CR/LF\r
386; prtstr - output string in DE\r
387; rskp - return, skipping over error return\r
388prcrlf: lxi d,crlf\r
389prtstr:\r
390; [17] added this to avoid prtstr.. emulate function 9 call.\r
391; Works on most machines.\r
392IF (torch OR px8 OR z80mu)\r
393;\r
394; Modified print string as the CP/N (for Nut) system traps control\r
395; characters in a function 9 call.. rot its cotton socks.\r
396 push h\r
397 push d\r
398 push b\r
399prtst1:\r
400 ldax d\r
401 inx d\r
402 cpi '$' ; if a dollar then end of string\r
403 jz prtst2\r
404 push d\r
405 mov e,a\r
406 mov c,a ; also to c if its via conout in BIOS\r
407 call outcon ; send it to the screen\r
408 pop d\r
409 jmp prtst1\r
410\r
411prtst2: pop b\r
412 pop d\r
413 pop h\r
414 ret ; regs restored.. just in case\r
415ENDIF ;(torch OR px8 OR z80mu)\r
416\r
417IF NOT (torch OR px8 or z80mu) ;ie any machine that can send ctrl chrs via dos call 9\r
418 PUSH H\r
419 PUSH D\r
420 push b\r
421 mvi c,9 ; Dos call 9 (print a string)\r
422 call bdos\r
423 pop b\r
424 POP D\r
425 POP H\r
426 ret ; all done for good machines\r
427ENDIF ;NOT (torch OR px8 OR z80mu)\r
428\r
429;\r
430; rskp - return to calling address + 3.\r
431rskp: pop h ; Get the return address\r
432 inx h ; Increment by three\r
433 inx h\r
434 inx h\r
435 pchl\r
436\r
437; Copy block of data\r
438; source in HL, destination in DE, byte count in BC\r
439; called by: cpxsys, mfname\r
440;\r
441mover:\r
b0db0839 442IF NOT z80 ; 8080's have to do it the hard way\r
e58a7a25
L
443;OBS assume its an 8080 for now - this will work on Z80s anyway.\r
444 mov a,m\r
445 stax d\r
446 inx h\r
447 inx d\r
448 dcx b\r
449 mov a,b\r
450 ora c\r
451 jnz mover\r
b0db0839
L
452ENDIF;NOT z80\r
453IF z80\r
454 db 0EDh,0B0h ; Z80 LDIR instruction\r
455ENDIF;z80\r
e58a7a25
L
456 ret\r
457\r
458;\r
459; Miscellaneous messages\r
460;\r
461crlf: db cr,lf,'$'\r
462cfgmsg: db 'configured for $'\r
463witmsg: db ' with $' ; Its included if we get here ('with terminal')\r
464\r
465IF NOT (osi OR crt OR px8) ; [29] got cursor control?\r
466outln2: db ']',cr,lf,cr,lf,'Number of packets:'\r
467 db cr,lf,'Number of retries:'\r
468 db cr,lf,'File name:$'\r
469ENDIF;NOT (osi OR crt OR px8)\r
470\r
471IF px8 ; [29]\r
472outln2: db '] Number of retries:', cr, lf\r
473 db 'Number of packets: File name:$'\r
474ENDIF ; px8 [29]\r
475\r
476IF NOT (osi OR crt) ; [29]\r
477outln3: db cr,lf,cr,lf ; debugging messages\r
478 db cr,lf,'Rpack:'\r
479 db cr,lf ; Blank line in case of long packet\r
480 db cr,lf,'Spack:$'\r
481ENDIF ; NOT (osi OR crt) [29]\r
482\r
483IF lasm\r
484LINK CPXSWT.ASM\r
485ENDIF ;lasm\r
486\r