aboutsummaryrefslogtreecommitdiff
path: root/src/cpxcom.asm
blob: 7c3034e3c8eb5fdb00e7124a3ab3ed9b0039965c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
IF NOT lasm
.printx * CPXCOM.ASM *
ENDIF	; NOT lasm
;       KERMIT - (Celtic for "FREE")
;
;       This is the CP/M-80 implementation of the Columbia University
;       KERMIT file transfer protocol.
;
;       Version 4.0
;
;       Copyright June 1981,1982,1983,1984,1985
;       Columbia University
;
; Originally written by Bill Catchings of the Columbia University Center for
; Computing Activities, 612 W. 115th St., New York, NY 10025.
;
; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben,
; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many
; others.
;
;       This file contains part common code required for most if not all
;	systems.  Specifiacally, SYSINIT, INIADR, MOVER, and DELAY to name
;	the most important ones.
;
; revision history:
;
; edit 1, 21st July 1987 by OBSchou.  Regretably, I have had to include
;	some system dependent IFs, mainly for CRT, TORCH and OSI.  Inclusion
;	here means simpler family files later on. (Regrettably, the delay
;	loop for APMMDM differs too.)
;
; Set the fuzzy timeout value.  Range is 1 (VERY short) through 0ffffH to zero
; (maximum).  The actual duration is a function of the loop length and the
; processor speed.  For now, we'll make it zero for everybody, but feel free
; to change it for your system.
; [OBS] make it a little less than max, say 1000H.  More useful.
fuzval  EQU     1000H

;
;       System-dependent initialization
;       Called once at program start.
sysinit:
;
; [13]  Had to move this call to here, as the prtstr routine needs this
; before the config message is sent out.  It has only been moved.
;
	call	iniadr	;Initialize the BIOS addresses
	mvi	c,gtiob	;Get current I/O byte
	call	bdos	;From CP/M
	sta	coniob	;Remember where console is
	mvi	c,getvnm	; get the BDOS version number (e.g. 22H, 31H)
	call	bdos
	mov	a,l
	sta	bdosvr		; and store it away for future reference
	lxi	d,cfgmsg	; "configured for "
	call	prtstr
	lxi	d,sysver	; get configuration we're configured for
	call	prtstr		; print it.
;
;       If we're set up to do special terminal handling, say what kind
;       of terminal we expect... (unless it's the generic 'crt')
IF termin
	lxi	d,witmsg	; " with "
	call	prtstr
	lxi	d,ttytyp	; terminal type
	call	prtstr
ENDIF;termin
	call	prcrlf		; print CR/LF
;
; now, to work...
;
; locate large buffer for multi-sector I/O
; What we want to do here is find the ccp.  Space between ovlend and the ccp
; is available for buffering, except we don't want to use more than maxsec
; buffers (if we use too many, the remote end could time out while we're
; writing to disk).  maxsec is system-dependent, but for now we'll just
; use 8Kbytes.  If you get retransmissions and other protocol errors after
; transferring the first maxsec sectors, lower maxsec.

maxsec	EQU	(8*1024)/bufsiz	; 8K / number of bytes per sector

	lxi	h,ovlend	; get start of buffer
	shld	bufadr		; store in linkage section
	mvi	a,maxsec	; get size of buffer, in sectors
	sta	bufsec		; store that, too.

	call	sysxin		; call system specific init code

	ret			; return from system-dependent routine

bdosvr:	ds	1		; space to save the BDOS version number
IF NOT iobyt
coniob:	ds	1		; space to save copy of IO byte
ENDIF	;NOT iobyt
;
;       This one is hopefully the last "improvement" in view of GENERIC
;Kermit. It uses for Character-I/O the BIOS-routines ( instead of the
;"normal" BDOS routines. What does it give us (hopefully) : More speed,
;higher chance of success ( I/O byte implemented in BIOS [if at all]),
;but no "extra" device handling - that's done by BDOS.
;
;       How do we "get" the call-adresses?  Location 0 has a JMP Warm-Boot
;in CP/M which points into the second location of the BIOS JMP-Vector.  The
;next three locations of the JMP-Vector point to the CONSTAT,CONIN,CONOUT
;BIOS-routines.  CONOUT wants the character in C.
;
;- Bernie Eiben

iniadr:	lhld	1		;get BIOS Warmstart-address
	lxi	d,3		;next adress is CONSTAT in BIOS
	dad	d
	shld	bconst+1	;stuff it into the call-instruction
	lxi	d,3		;next adress is CONIN in BIOS
	dad	d
	shld	bconin+1	;
	lxi	d,3		;next adress is CONOUT in BIOS
	dad	d
	shld	bcnout+1
	lxi	d,3		;next address is LIST in BIOS
	dad	d
	shld	blsout+1
	lxi	d,10*3		; get printer status routine
	dad	d
	shld	bprtst
	ret			;And return

bconst:	jmp	$-$		;Call BIOS directly (filled in by iniadr)

bconin:	jmp	$-$		;Call BIOS directly (filled in by iniadr)

bcnout:	jmp	$-$		;Call BIOS directly (filled in by iniadr)

blsout:	jmp	$-$		; ....

bprtst:	jmp	$-$		; Call BIOS directly for printer status

IF NOT apmmdm	; Shame about this, but the Apple needs a different delay
;
;[cjc]  Delay routine.  Called with time (hundredths of seconds) in A.
;       The inner loop delays 1001 T-states, assuming no wait states are
;       inserted; this is repeated CPUSPD times, for a total delay of just
;       over 0.01 second. (CPUSPD should be set to the system clock rate,
;       in units of 100KHz: for an unmodified Kaypro II, that's 25 for
;       2.5 MHz.  Some enterprising soul could determine whether or not the
;       Kaypro actually inserts a wait state on instruction fetch (a common
;       practice); if so, the magic number at delay2 needs to be decreased.
;       (We also neglect to consider time spent at interrupt level).
;
;       called by: sendbr
;       destroys BC

delay:	mvi	c,cpuspd	; Number of times to wait 1000 T-states to
				;  make .01 second delay
delay2:	mvi	b,70		; Number of times to execute inner loop to
				;  make 1000 T-state delay
delay3:	dcr	b		; 4 T-states (* 70 * cpuspd)
	jnz	delay3		; 10 T-states (* 70 * cpuspd)
	dcr	c		; 4 T-states (* cpuspd)
	jnz	delay2		; 10 T-states (* cpuspd)
				; total delay: ((14 * 70) + 14) * cpuspd
				;  = 1001 * cpuspd
	dcr	a		; 4 T-states
	jnz	delay		; 10 T-states
	ret			; grand total: ((1001 * cpuspd) + 14) * a
ENDIF	; NOT apmmdm
;
;
;       Set up screen display for file transfer
;       called with kermit version in DE
;
sysscr: push    d               ; save version for a bit
        lxi     d,outlin        ; clear screen, position cursor
        call    prtstr          ; do it
        pop     d               ; get Kermit's version
IF NOT (osi OR crt)             ; got cursor control?
        call    prtstr          ; print it
        mvi     e,'['           ; open bracket
        call    outcon          ; print it (close bracket is in outln2)
        lxi     d,sysver        ; get name and version of system module
        call    prtstr
        lxi     d,outln2        ; yes, print field names
        call    prtstr
        lda     dbgflg          ; is debugging enabled?
        ora     a
        rz                      ; finished if no debugging
        lxi     d,outln3        ; set up debugging fields
        call    prtstr
ENDIF;NOT (osi OR crt)
        ret
;
;       Calculate free space for current drive
;       returns value in HL
sysspc:
        lda     bdosvr          ;cpm3's alloc vect may be in another bank
        cpi     30H             ;cpm3 or later?
        jm      cp2spc          ;no: use cp/m 2 algorithm
        lda     fcb             ;If no drive, get
        ora     a               ; logged in drive
        jz      dir180
        dcr     a               ;FCB drive A=1 normalize to be A=0
        jmp     dir18a

dir180: mvi     c,rddrv
        call    bdos
dir18a: mov     e,a             ;drive in e
        mvi     c,getfs         ;get free space BDOS funct
        call    bdos            ;returns free recs (3 bytes in buff..buff+2)
        mvi     b,3             ;conv recs to K by 3 bit shift
dir18b: xra     a               ;clear carry
        mvi     c,3             ;for 3 bytes
        lxi     h,buff+3        ;point to addr + 1
dir18c: dcx     h               ;point to less sig. byte
        mov     a,m             ;get byte
        rar                     ;carry -> A -> carry
        mov     m,a             ;put back byte
        dcr     c               ;for all bytes (carry not mod)
        jnz     dir18c
        dcr     b               ;shift 1 bit 3 times
        jnz     dir18b
        mov     e,m             ;get least sig byte
        inx     h
        mov     d,m             ;get most sig byte
        xchg                    ;get K free in HL
        ret

; the rest are CP/M 2.2 systems, so use the alloc vector
cp2spc: mvi     c,getalv        ;Address of CP/M Allocation Vector
        call    bdos
        xchg                    ;Get its length
        lhld    bmax
        inx     h
        lxi     b,0             ;Initialize Block count to zero
dir19:  push    d               ;Save allocation address
        ldax    d
        mvi     e,8             ;set to process 8 blocks
dir20:  ral                     ;Test bit
        jc      dir20a
        inx     b
dir20a: mov     d,a             ;Save bits
        dcx     h
        mov     a,l
        ora     h
        jz      dir21           ;Quit if out of blocks
        mov     a,d             ;Restore bits
        dcr     e               ;count down 8 bits
        jnz     dir20           ;do another bit
        pop     d               ;Bump to next count of Allocation Vector
        inx     d
        jmp     dir19           ;process it

dir21:  pop     d               ;Clear Allocation vector from stack
        mov     l,c             ;Copy block to 'HL'
        mov     h,b
        lda     bshiftf         ;Get Block Shift Factor
        sui     3               ;Convert from records to thousands
        rz                      ;Skip shifts if 1K blocks
dir22:  dad     h               ;Multiply blocks by 'K per Block'
        dcr     a
        jnz     dir22
        ret

;      +----|----|----|----|----|----|----|...
;    1 |
;    2 |                Kermit-80 v4.0 [system]
;    3 |
;    4 |Number of packets: ____
;    5 |Number of retries: ____
;    6 |File name: ____________
;    7 |<error>...
;    8 |<status>...
;    9 |RPack: ___(if debugging)...
;   10 |
;   11 |SPack: ___(if debugging)...
;   12 |
;   13 |Kermit-80  A:>  (when finished)
;
; For the PX-8, the display looks like:
;           5    10   15   20   25   30   35   40   45   50   55
;      +----|----|----|----|----|----|----|----|----|----|----|----|----
;    1 |Kermit-80 v4.05 [Epson PX-8]            Number of retries: ____
;    2 |Number of packets: ____                 File name: ________.___
;    3 |<error>...
;    4 |<status>...
;    5 |RPack: ___ (if debugging)...
;    6 |
;    7 |SPack: ___ (if debugging)...
;    8 |
;    9 |Kermit-80 A:> (when finished)
;

IF NOT px8 ; [29]
nppos   EQU     4*100h+20
rtpos   EQU     5*100h+20
fnpos   EQU     6*100h+12
errlin  EQU     7
stlin   EQU     8
rplin   EQU     9
splin   EQU     11
prplin  EQU     13
ENDIF ; NOT px8

IF px8
nppos   EQU     2*100h+20
rtpos   EQU     1*100h+59
fnpos   EQU     2*100h+51
errlin  EQU     3
stlin   EQU     4
rplin   EQU     5
splin   EQU     7
prplin  EQU     9
ENDIF ; px8 [29]


IF NOT (osi OR crt );[26]
scrnp:  lxi     b,nppos
        jmp     csrpos

scrnrt: lxi     b,rtpos
        jmp     csrpos

scrfln: lxi     b,fnpos
        call    csrpos
clreol:
        lxi     d,tk
        jmp     prtstr

screrr: lxi     b,errlin*100H+1
        call    csrpos
        jmp     clreol

scrst:  lxi     b,stlin*100H+1
        call    csrpos
        jmp     clreol

rppos:  lxi     b,rplin*100H+8
        call    csrpos
        jmp     clreol

sppos:  lxi     b,splin*100H+8
        call    csrpos
        jmp     clreol

; [29] Modify scrend to make the cursor line conditional on use of debugging
; This means that in most cases the entire file transfer will fit on PX-8 lcd
scrend: lda     dbgflg
        ora     a
        jz      scr1nd
        lxi     b,prplin*100H+1 ; debugging in use [29]
        jmp     scr2nd
scr1nd: lxi     b,rplin*100H+1  ; no debugging
scr2nd: call    csrpos
clreos: lxi     d,tj
        jmp     prtstr
; [29]  and nop out the rest for now...
;
;scrend:        lxi     b,prplin*100H+1
;       call    csrpos
;clreos:        lxi     d,tj
;       jmp     prtstr
ENDIF;NOT (osi OR crt ) [26]


IF osi OR crt   ; no cursor control
scrnp:  mvi     e,' '
        jmp     outcon

scrnrt: mvi     e,' '
        call    outcon
        mvi     e,'%'
        jmp     outcon

scrfln:
screrr:
scrst:
scrend: jmp     prcrlf          ;Print CR/LF    [Toad Hall]

rppos:  lxi     d,prpack
        jmp     prtstr

sppos:  lxi     d,pspack
        jmp     prtstr
ENDIF;osi OR crt

; Some frequently-used routines (duplicates of those in CPSMIT):
;       prcrlf - output a CR/LF
;       prtstr - output string in DE
;       rskp - return, skipping over error return
prcrlf: lxi     d,crlf
prtstr:
;  [17] added this  to avoid prtstr.. emulate function 9 call.
;	Works on most machines.
IF (torch OR px8 OR z80mu)
;
;       Modified print string as the CP/N (for Nut) system traps control
;       characters in a function 9 call.. rot its cotton socks.
        push    h
        push    d
        push    b
prtst1:
        ldax    d
        inx     d
        cpi     '$'             ; if a dollar then end of string
        jz      prtst2
        push    d
        mov     e,a
	mov	c,a		; also to c if its via conout in BIOS
        call    outcon          ; send it to the screen
        pop     d
        jmp     prtst1

prtst2: pop     b
        pop     d
        pop     h
        ret                     ; regs restored.. just in case
ENDIF	;(torch OR px8 OR z80mu)

IF NOT (torch OR px8 or z80mu)		;ie any machine that can send ctrl chrs via dos call 9
	PUSH	H
	PUSH	D
        push    b
        mvi     c,9     ; Dos call 9 (print a string)
        call    bdos
        pop     b
	POP	D
	POP	H
        ret             ; all done for good machines
ENDIF   ;NOT (torch OR px8 OR z80mu)

;
;	rskp - return to calling address + 3.
rskp:   pop     h               ; Get the return address
        inx     h               ; Increment by three
        inx     h
        inx     h
        pchl

;       Copy block of data
;       source in HL, destination in DE, byte count in BC
;       called by: cpxsys, mfname
;
mover:
;IF NOT z80              ; 8080's have to do it the hard way
;OBS assume its an 8080 for now - this will work on Z80s anyway.
        mov     a,m
        stax    d
        inx     h
        inx     d
        dcx     b
        mov     a,b
        ora     c
        jnz     mover
;ENDIF;NOT z80
;IF z80
;       db      0EDh,0B0h       ; Z80 LDIR instruction
;ENDIF;z80
        ret

;
;       Miscellaneous messages
;
crlf:   db      cr,lf,'$'
cfgmsg: db      'configured for $'
witmsg:	db	' with $'	; Its included if we get here ('with terminal')

IF NOT (osi OR crt OR px8)	; [29] got cursor control?
outln2:	db	']',cr,lf,cr,lf,'Number of packets:'
	db	cr,lf,'Number of retries:'
	db	cr,lf,'File name:$'
ENDIF;NOT (osi OR crt OR px8)

IF px8	; [29]
outln2:	db	']           Number of retries:', cr, lf
	db	'Number of packets:                     File name:$'
ENDIF ; px8 [29]

IF NOT (osi OR crt) ; [29]
outln3:	db	cr,lf,cr,lf	; debugging messages
	db	cr,lf,'Rpack:'
	db	cr,lf		; Blank line in case of long packet
	db	cr,lf,'Spack:$'
ENDIF ; NOT (osi OR crt) [29]

IF lasm
LINK CPXSWT.ASM
ENDIF	;lasm