1 |
3 |
zpekic |
;-------------------------------------------------------------------------
|
2 |
|
|
; ALTMON.ASM - 1K ROM monitor for the Altair 8800.
|
3 |
|
|
;
|
4 |
|
|
; This monitor is based on the 2.0C monitor from Vector Graphic. The
|
5 |
|
|
; original version has been updated to use Altair 2SIO serial ports
|
6 |
|
|
; for I/O and several commands have been added and/or modified.
|
7 |
|
|
;
|
8 |
|
|
; A typical location for this PROM in an Altair is at F800, though
|
9 |
|
|
; it can be assembled at most any address. The stack is typically
|
10 |
|
|
; placed at the top of the minimum RAM you expect to have in your
|
11 |
|
|
; system.
|
12 |
|
|
;
|
13 |
|
|
; Version Date Author
|
14 |
|
|
; ------- ---------- ---------------------------------------
|
15 |
|
|
; 1.0 01/10/2016 Mike Douglas (Original)
|
16 |
|
|
;
|
17 |
|
|
; 1.1 02/29/2016 Mike Douglas
|
18 |
|
|
; Fix bug in DUMP code that caused improper range of bytes
|
19 |
|
|
; to display. Also in DUMP, display '.' for all characters
|
20 |
|
|
; 7Fh or above.
|
21 |
|
|
;
|
22 |
|
|
; Initialize 2nd 2SIO port so that loading of Intel HEX
|
23 |
|
|
; files works over the 2nd port. Only flush hex file
|
24 |
|
|
; input on the console serial port to free up code space
|
25 |
|
|
; and because it's not really required for the 2nd port.
|
26 |
|
|
;
|
27 |
|
|
;-------------------------------------------------------------------------
|
28 |
|
|
;
|
29 |
|
|
; Following is a summary of changes from the original VG 2.0c monitor:
|
30 |
|
|
;
|
31 |
|
|
; All commands immediately echo a full command name as soon as the
|
32 |
|
|
; first command letter is typed (e.g., typing "M" immediately
|
33 |
|
|
; displays "MOVE"). This makes it easier to identify commands
|
34 |
|
|
; without a list of commands present.
|
35 |
|
|
;
|
36 |
|
|
; The ESC key can be pressed to abort input or commands as in
|
37 |
|
|
; the later 4.x monitors from VG. The original ctrl-c abort is
|
38 |
|
|
; still present as well.
|
39 |
|
|
;
|
40 |
|
|
; The B (boot) command jumps to the Altair disk boot loader PROM
|
41 |
|
|
; at FF00 instead of the North Star boot ROM.
|
42 |
|
|
;
|
43 |
|
|
; A (ASCII dump) command removed and D (hex dump) updated to display
|
44 |
|
|
; both hex and ASCII.
|
45 |
|
|
;
|
46 |
|
|
; X (exchange) command changed to the E command.
|
47 |
|
|
;
|
48 |
|
|
; H command added to load Intel hex file via either serial port
|
49 |
|
|
; on a 2SIO. The L (load and go from tape) does a hex file load
|
50 |
|
|
; as well (all tape commands eliminated).
|
51 |
|
|
;
|
52 |
|
|
; J treated as jump (i.e., go to) command instead of jump to North
|
53 |
|
|
; Star DOS.
|
54 |
|
|
;
|
55 |
|
|
; K treated as fill memory with "K"onstant instead of jump to zero
|
56 |
|
|
; (was the Z command which has been removed).
|
57 |
|
|
;
|
58 |
|
|
; R command sizes RAM (i.e., runs the N non-destructive memory test)
|
59 |
|
|
; Was previously a read from cassette command. All cassette commands
|
60 |
|
|
; have been removed.
|
61 |
|
|
;
|
62 |
|
|
; The Y command (Vector Graphic relocating loader) command has been
|
63 |
|
|
; removed.
|
64 |
|
|
;
|
65 |
|
|
; The T test memory command skips the 256 byte page the stack is on
|
66 |
|
|
; to prevent crashing the program. A "." pacifier is displayed
|
67 |
|
|
; after each cycle through the memory test range is completed
|
68 |
|
|
;
|
69 |
|
|
;-------------------------------------------------------------------------
|
70 |
|
|
;
|
71 |
|
|
; Command Summary:
|
72 |
|
|
;
|
73 |
|
|
; B jump to Altair disk boot loader (FF00)
|
74 |
|
|
; C SSSS FFFF CCCC compare blocks
|
75 |
|
|
; D SSSS FFFF dump in hex and ASCII
|
76 |
|
|
; E SSSS FFFF DDDD exchange block
|
77 |
|
|
; F SSSS FFFF DD DD find two byte sequence
|
78 |
|
|
; G SSSS go to and execute
|
79 |
|
|
; H P load Intel hex file from 2SIO port 0 or 1
|
80 |
|
|
; I PP input from I/O port
|
81 |
|
|
; J SSSS go to and execute (G)
|
82 |
|
|
; K SSSS FFFF DD fill with "K"onstant
|
83 |
|
|
; L P load Intel hex file from 2SIO port 0 or 1
|
84 |
|
|
; M SSSS FFFF DDDD move block
|
85 |
|
|
; N non destructive memory test (size RAM)
|
86 |
|
|
; O PP DD output to port
|
87 |
|
|
; P LLLL program memory
|
88 |
|
|
; Q SSSS FFFF compute checksum
|
89 |
|
|
; R non destructive memory test (size RAM)
|
90 |
|
|
; S SSSS FFFF DD search for single byte sequence
|
91 |
|
|
; T SSSS FFFF test memory
|
92 |
|
|
;
|
93 |
|
|
;-------------------------------------------------------------------------
|
94 |
|
|
;
|
95 |
|
|
; Memory location equates
|
96 |
|
|
|
97 |
|
|
org 00400h ;ROM location
|
98 |
|
|
|
99 |
|
|
SPTR equ 0ffffh ;stack pointer (use 256 byte boundary)
|
100 |
|
|
SIOPORT equ SPTR-32 ;2SIO port used for hex load
|
101 |
|
|
BOOT equ 0ff00h ;Altair disk boot loader ROM
|
102 |
|
|
|
103 |
|
|
; 88-2SIO equates
|
104 |
|
|
|
105 |
|
|
CONS equ 10h ;console status port
|
106 |
|
|
COND equ 11h ;console data port
|
107 |
|
|
TBE equ 2 ;transmit buffer entry
|
108 |
|
|
RDA equ 1 ;receive data available
|
109 |
|
|
|
110 |
|
|
; Misc Equates
|
111 |
|
|
|
112 |
|
|
CR equ 13 ;ASCII carriage return
|
113 |
|
|
LF equ 10 ;ASCII line feed
|
114 |
|
|
CTRLC equ 3 ;ASCII control-c
|
115 |
|
|
ESC equ 27 ;ASCII ESCAPE
|
116 |
|
|
|
117 |
|
|
;---------------------------------------------------------
|
118 |
|
|
; monit - monitor entry point
|
119 |
|
|
;---------------------------------------------------------
|
120 |
|
|
monit mvi a,3 ;reset 6850 uart
|
121 |
|
|
out CONS
|
122 |
|
|
out CONS+2 ;2nd 2SIO port as well
|
123 |
|
|
mvi a,11h ;8N2
|
124 |
|
|
out CONS
|
125 |
|
|
out CONS+2 ;2nd 2SIO port as well
|
126 |
|
|
|
127 |
|
|
lxi sp,SPTR
|
128 |
|
|
call dspMsg ;display welcome banner
|
129 |
|
|
db CR,LF,LF,'ALTMON 1.','1'+80h
|
130 |
|
|
|
131 |
|
|
; start - command processing loop
|
132 |
|
|
|
133 |
|
|
start lxi sp,SPTR ;re-init stack pointer
|
134 |
|
|
lxi h,start ;RET's go back to start
|
135 |
|
|
push h
|
136 |
|
|
|
137 |
|
|
call crlf ;display '*' prompt after CR/LF
|
138 |
|
|
mvi a,'*'
|
139 |
|
|
call ptcn
|
140 |
|
|
|
141 |
|
|
call getCon ;read command from keyboard
|
142 |
|
|
ani 05FH ;lower case to upper case
|
143 |
|
|
cpi 'B'
|
144 |
|
|
rc ;too small
|
145 |
|
|
cpi 'U'
|
146 |
|
|
rnc ;too large
|
147 |
|
|
|
148 |
|
|
lxi h,cmdTbl+100h-2*'B' ;'B' indexes to start of cmdtbl
|
149 |
|
|
add a ;2 bytes per entry
|
150 |
|
|
add l
|
151 |
|
|
mov l,a
|
152 |
|
|
|
153 |
|
|
mov e,m ;e=lsb of jump address
|
154 |
|
|
inx h
|
155 |
|
|
mov d,m ;d=high byte of jump address
|
156 |
|
|
xchg
|
157 |
|
|
pchl ;away we go
|
158 |
|
|
|
159 |
|
|
; Command Table
|
160 |
|
|
|
161 |
|
|
cmdTbl dw doboot ;B jump to Altair disk boot loader
|
162 |
|
|
dw compr ;C SSSS FFFF CCCC compare blocks
|
163 |
|
|
dw disp ;D SSSS FFFF dump in hex
|
164 |
|
|
dw exchg ;E SSSS FFFF DDDD exchange block
|
165 |
|
|
dw srch2 ;F SSSS FFFF DD DD two byte search
|
166 |
|
|
dw exec ;G SSSS go to and execute
|
167 |
|
|
dw hexLoad ;H P load Intel hex file from port
|
168 |
|
|
dw pinpt ;I PP input from I/O port
|
169 |
|
|
dw exec ;J SSSS jump to and execute (G)
|
170 |
|
|
dw fill ;K SSSS FFFF DD fill RAM with "k"onstant
|
171 |
|
|
dw hexLoad ;L P load Intel hex file from port
|
172 |
|
|
dw moveb ;M SSSS FFFF DDDD move block
|
173 |
|
|
dw ndmt ;N non destructive memory test (RAM size)
|
174 |
|
|
dw poutp ;O PP DD output to port
|
175 |
|
|
dw pgm ;P LLLL program memory
|
176 |
|
|
dw chksum ;Q SSSS FFFF compute checksum
|
177 |
|
|
dw ndmt ;R non destructive memory test (RAM size)
|
178 |
|
|
dw srch1 ;S SSSS FFFF DD search for single byte
|
179 |
|
|
dw tmem ;T SSSS FFFF test memory
|
180 |
|
|
|
181 |
|
|
;--------------------------------------------------------------------------
|
182 |
|
|
; exec (G or J) - execute the program at the address
|
183 |
|
|
;--------------------------------------------------------------------------
|
184 |
|
|
exec call dspMsg
|
185 |
|
|
db 'GOT','O'+80h
|
186 |
|
|
|
187 |
|
|
call ahex ;read address from keyboard
|
188 |
|
|
xchg
|
189 |
|
|
pchl
|
190 |
|
|
|
191 |
|
|
;--------------------------------------------------------------------------
|
192 |
|
|
; doBoot (B) - boot floppy disk by jumping to DBL PROM at FF00
|
193 |
|
|
;--------------------------------------------------------------------------
|
194 |
|
|
doBoot call dspMsg
|
195 |
|
|
db 'BOO','T'+80h
|
196 |
|
|
|
197 |
|
|
jmp BOOT
|
198 |
|
|
|
199 |
|
|
;--------------------------------------------------------------------------
|
200 |
|
|
; chksum (Q) - compute checksum
|
201 |
|
|
;--------------------------------------------------------------------------
|
202 |
|
|
chksum call dspMsg
|
203 |
|
|
db 'CSU','M'+80h
|
204 |
|
|
|
205 |
|
|
call tahex
|
206 |
|
|
mvi b,0 ;start checksum = 0
|
207 |
|
|
|
208 |
|
|
csloop mov a,m ;get data from memory
|
209 |
|
|
add b ;add to checksum
|
210 |
|
|
mov b,a
|
211 |
|
|
call bmp
|
212 |
|
|
jnz csloop ;repeat loop
|
213 |
|
|
|
214 |
|
|
mov a,b ;a=checksum
|
215 |
|
|
jmp pt2 ;print checksum and exit
|
216 |
|
|
|
217 |
|
|
;--------------------------------------------------------------------------
|
218 |
|
|
; tmem (T) - memory test routine
|
219 |
|
|
;--------------------------------------------------------------------------
|
220 |
|
|
tmem call dspMsg
|
221 |
|
|
db 'TES','T'+80h
|
222 |
|
|
|
223 |
|
|
call tahex ;read addresses
|
224 |
|
|
lxi b,05a5ah ;init b,c
|
225 |
|
|
|
226 |
|
|
cycl mvi a,'.' ;display '.' before each cycle
|
227 |
|
|
call ptcn
|
228 |
|
|
call rndm
|
229 |
|
|
push b ;keep all registers
|
230 |
|
|
push h
|
231 |
|
|
push d
|
232 |
|
|
|
233 |
|
|
tlop mov a,h ;on stack page?
|
234 |
|
|
cpi (SPTR shr 8)-1 ;compare to msb of stack
|
235 |
|
|
jz skipWr ;in stack, skip write
|
236 |
|
|
call rndm
|
237 |
|
|
mov m,b ;write in memory
|
238 |
|
|
skipWr call bmp
|
239 |
|
|
jnz tlop ;repeat loop
|
240 |
|
|
|
241 |
|
|
pop d
|
242 |
|
|
pop h ;restore original
|
243 |
|
|
pop b ;values
|
244 |
|
|
push h
|
245 |
|
|
push d
|
246 |
|
|
|
247 |
|
|
rlop mov a,h ;on stack page?
|
248 |
|
|
cpi (SPTR shr 8)-1 ;compare to msb of stack
|
249 |
|
|
jz skipRd ;in stack, skip the read
|
250 |
|
|
call rndm ;generate new sequence
|
251 |
|
|
mov a,m ;read memory
|
252 |
|
|
cmp b ;compare memory
|
253 |
|
|
cnz err ;call error routine
|
254 |
|
|
skipRd call bmp
|
255 |
|
|
jnz rlop
|
256 |
|
|
|
257 |
|
|
pop d
|
258 |
|
|
pop h
|
259 |
|
|
call pause
|
260 |
|
|
jmp cycl
|
261 |
|
|
|
262 |
|
|
; rndm - this routine generates random numbers
|
263 |
|
|
|
264 |
|
|
rndm mov a,b ;look at b
|
265 |
|
|
ani 0b4h ;mask bits
|
266 |
|
|
ana a ;clear carry
|
267 |
|
|
jpe peve ;jump if even
|
268 |
|
|
stc
|
269 |
|
|
peve mov a,c ;look at c
|
270 |
|
|
ral ;rotate carry in
|
271 |
|
|
mov c,a ;restore c
|
272 |
|
|
mov a,b ;look at b
|
273 |
|
|
ral ;rotate carry in
|
274 |
|
|
mov b,a ;restore b
|
275 |
|
|
ret ;return with new b,c
|
276 |
|
|
|
277 |
|
|
;--------------------------------------------------------------------------
|
278 |
|
|
; disp (D) - display memory contents
|
279 |
|
|
;--------------------------------------------------------------------------
|
280 |
|
|
disp call dspMsg
|
281 |
|
|
db 'DUM','P'+80h
|
282 |
|
|
|
283 |
|
|
call tahex ;read addresses
|
284 |
|
|
|
285 |
|
|
dmpLine push h ;save address at start of line
|
286 |
|
|
mvi c,16 ;16 locations per line
|
287 |
|
|
call ptad ;print current address
|
288 |
|
|
|
289 |
|
|
; dump line in hex
|
290 |
|
|
|
291 |
|
|
dmpHex mov a,m ;a=byte to display
|
292 |
|
|
call pt2 ;display it
|
293 |
|
|
call spce
|
294 |
|
|
inx h
|
295 |
|
|
dcr c ;decrement line byte count
|
296 |
|
|
jnz dmpHex ;loop until 16 bytes done
|
297 |
|
|
|
298 |
|
|
; dump line in ASCII
|
299 |
|
|
|
300 |
|
|
call spce
|
301 |
|
|
pop h ;hl->start of line
|
302 |
|
|
mvi c,16 ;16 locations per line
|
303 |
|
|
|
304 |
|
|
dmpAsc mov a,m ;a=byte to display
|
305 |
|
|
cpi 7Fh ;test if >= 7Fh
|
306 |
|
|
jnc dspDot ;non printable, show '.'
|
307 |
|
|
|
308 |
|
|
cpi ' ' ;displayable character?
|
309 |
|
|
jnc dspAsc ;yes, go display it
|
310 |
|
|
|
311 |
|
|
dspDot mvi a,'.' ;display '.' instead
|
312 |
|
|
|
313 |
|
|
dspAsc call ptcn ;display the character
|
314 |
|
|
call bmp ;increment hl, possibly de
|
315 |
|
|
dcr c ;decrement line byte count
|
316 |
|
|
jnz dmpAsc ;loop until 16 bytes done
|
317 |
|
|
|
318 |
|
|
call bmp ;done?
|
319 |
|
|
rz ;yes
|
320 |
|
|
dcx h ;undo extra bump of hl
|
321 |
|
|
jmp dmpLine ;do another line
|
322 |
|
|
|
323 |
|
|
;--------------------------------------------------------------------------
|
324 |
|
|
; pgm (P) - program memory
|
325 |
|
|
;--------------------------------------------------------------------------
|
326 |
|
|
pgm call dspMsg
|
327 |
|
|
db 'PG','M'+80h
|
328 |
|
|
|
329 |
|
|
call ahex ;read address
|
330 |
|
|
xchg
|
331 |
|
|
call crlf
|
332 |
|
|
|
333 |
|
|
pglp mov a,m ;read memory
|
334 |
|
|
call pt2 ;print 2 digits
|
335 |
|
|
mvi a,'-' ;load dash
|
336 |
|
|
call ptcn ;print dash
|
337 |
|
|
|
338 |
|
|
crig call rdcn ;get user input
|
339 |
|
|
cpi ' ' ;space
|
340 |
|
|
jz con2 ;skip if space
|
341 |
|
|
cpi CR ;skip if CR
|
342 |
|
|
jnz con1
|
343 |
|
|
call crlf ;print CR,LF
|
344 |
|
|
jmp crig ;back for more
|
345 |
|
|
|
346 |
|
|
con1 xchg ;HL->DE
|
347 |
|
|
lxi h,0 ;get 16 bit zero
|
348 |
|
|
mvi c,2 ;count 2 digits
|
349 |
|
|
call ahexNr ;convert to hex (no read)
|
350 |
|
|
mov m,e
|
351 |
|
|
con2 inx h
|
352 |
|
|
jmp pglp
|
353 |
|
|
|
354 |
|
|
;--------------------------------------------------------------------------
|
355 |
|
|
; fill (K) - fill memory with a constant
|
356 |
|
|
;--------------------------------------------------------------------------
|
357 |
|
|
fill call dspMsg
|
358 |
|
|
db 'FIL','L'+80h
|
359 |
|
|
|
360 |
|
|
call tahex ;read addresses
|
361 |
|
|
push h ;start addr on stack
|
362 |
|
|
mvi c,2 ;reading 2 digits
|
363 |
|
|
call ahe0 ;input fill byte
|
364 |
|
|
xchg ;byte to write from e to l
|
365 |
|
|
xthl ;hl=start addr, stack=fill byte
|
366 |
|
|
pop b ;c=fill byte from stack
|
367 |
|
|
|
368 |
|
|
zloop mov m,c ;write into memory
|
369 |
|
|
call bmp ;compare address, increment h
|
370 |
|
|
rz
|
371 |
|
|
jmp zloop
|
372 |
|
|
|
373 |
|
|
;--------------------------------------------------------------------------
|
374 |
|
|
; moveb (M) - move a block of memory
|
375 |
|
|
; exchg (E) - exhange block of memory
|
376 |
|
|
;--------------------------------------------------------------------------
|
377 |
|
|
moveb call dspMsg
|
378 |
|
|
db 'MOV','E'+80h
|
379 |
|
|
xra a ;a=0 means "move" command
|
380 |
|
|
jmp doMove
|
381 |
|
|
|
382 |
|
|
exchg call dspMsg
|
383 |
|
|
db 'EXC','H'+80h
|
384 |
|
|
;a returned <> 0 means "exchange" command
|
385 |
|
|
|
386 |
|
|
doMove mov b,a ;save move/exchange flag in b
|
387 |
|
|
call tahex ;read addresses
|
388 |
|
|
push h
|
389 |
|
|
call ahex
|
390 |
|
|
xchg
|
391 |
|
|
xthl ;HL->start, DE->end, stack has dest
|
392 |
|
|
|
393 |
|
|
mloop mov c,m ;c=byte from source
|
394 |
|
|
xthl ;hl->destination
|
395 |
|
|
|
396 |
|
|
mov a,b ;move or exchange?
|
397 |
|
|
ora a
|
398 |
|
|
jz nexch ;0 means move only
|
399 |
|
|
|
400 |
|
|
mov a,m ;a=from destination
|
401 |
|
|
xthl ;hl->source
|
402 |
|
|
mov m,a ;move destination to source
|
403 |
|
|
xthl ;hl->destination
|
404 |
|
|
|
405 |
|
|
nexch mov m,c ;move source to destination
|
406 |
|
|
inx h ;increment destination
|
407 |
|
|
xthl ;hl->source
|
408 |
|
|
call bmp ;increment source and compare to end
|
409 |
|
|
jnz mloop
|
410 |
|
|
|
411 |
|
|
pop h ;remove temp pointer from stack
|
412 |
|
|
ret ;and exit
|
413 |
|
|
|
414 |
|
|
;--------------------------------------------------------------------------
|
415 |
|
|
; ndmt (N or R) - non destructive memory test (size RAM)
|
416 |
|
|
;--------------------------------------------------------------------------
|
417 |
|
|
ndmt call dspMsg
|
418 |
|
|
db 'RAMTO','P'+80h
|
419 |
|
|
|
420 |
|
|
lxi h,0ffffh ;start at zero
|
421 |
|
|
|
422 |
|
|
ndlop inx h
|
423 |
|
|
mov a,m ;read from address in hl
|
424 |
|
|
mov b,a ;save original value in b
|
425 |
|
|
cma ;form and write inverted value
|
426 |
|
|
mov m,a
|
427 |
|
|
cmp m ;read and compare
|
428 |
|
|
mov m,b ;restore original value
|
429 |
|
|
jz ndlop ;keep going if still RAM
|
430 |
|
|
|
431 |
|
|
jmp err ;display end of RAM
|
432 |
|
|
|
433 |
|
|
;--------------------------------------------------------------------------
|
434 |
|
|
; compr (C) - compare two blocks of memory
|
435 |
|
|
;--------------------------------------------------------------------------
|
436 |
|
|
compr call dspMsg
|
437 |
|
|
db 'COM','P'+80h
|
438 |
|
|
|
439 |
|
|
call tahex ;read addresses
|
440 |
|
|
push h ;source start on stack
|
441 |
|
|
call ahex
|
442 |
|
|
xchg ;de=source end, hl=compare start
|
443 |
|
|
|
444 |
|
|
vmlop mov a,m ;a=compare byte
|
445 |
|
|
inx h
|
446 |
|
|
xthl ;hl->source byte
|
447 |
|
|
cmp m ;same?
|
448 |
|
|
mov b,m ;b=source byte
|
449 |
|
|
cnz err ;display the error
|
450 |
|
|
call bmp ;increment pointers
|
451 |
|
|
xthl ;hl->compare byte
|
452 |
|
|
jnz vmlop
|
453 |
|
|
|
454 |
|
|
pop h ;remove temp pointer from stack
|
455 |
|
|
ret ;and exit
|
456 |
|
|
|
457 |
|
|
;--------------------------------------------------------------------------
|
458 |
|
|
; srch1 (S) - search for one byte
|
459 |
|
|
; srch2 (F) - search for two bytes
|
460 |
|
|
;--------------------------------------------------------------------------
|
461 |
|
|
srch1 call dspMsg
|
462 |
|
|
db 'FIND','1'+80h
|
463 |
|
|
xra a ;zero flag means one byte search
|
464 |
|
|
jmp doSrch
|
465 |
|
|
|
466 |
|
|
srch2 call dspMsg
|
467 |
|
|
db 'FIND','2'+80h
|
468 |
|
|
;a returned <> 0 means two byte search
|
469 |
|
|
|
470 |
|
|
doSrch push psw ;save 1/2 byte flag on stack
|
471 |
|
|
call tahex
|
472 |
|
|
|
473 |
|
|
push h ;save h, getting 1st byte to find
|
474 |
|
|
mvi c,2 ;reading 2 hex digits
|
475 |
|
|
call ahe0 ;
|
476 |
|
|
xchg ;h=code, d=f
|
477 |
|
|
mov b,l ;put code in b
|
478 |
|
|
pop h ;restore h
|
479 |
|
|
|
480 |
|
|
pop psw ;a=one/two byte flag
|
481 |
|
|
ora a ;zero true if one byte search
|
482 |
|
|
push psw
|
483 |
|
|
jz cont
|
484 |
|
|
|
485 |
|
|
push h ;save h, getting 2nd byte to find
|
486 |
|
|
mvi c,2
|
487 |
|
|
call ahe0
|
488 |
|
|
xchg
|
489 |
|
|
mov c,l
|
490 |
|
|
pop h
|
491 |
|
|
|
492 |
|
|
cont mov a,m ;read memory
|
493 |
|
|
cmp b ;compare to code
|
494 |
|
|
jnz skp ;skip if no compare
|
495 |
|
|
|
496 |
|
|
pop psw ;a=one/two byte flag
|
497 |
|
|
ora a ;zero true if one byte serach
|
498 |
|
|
push psw
|
499 |
|
|
jz obcp
|
500 |
|
|
|
501 |
|
|
inx h ;two byte search
|
502 |
|
|
mov a,m
|
503 |
|
|
dcx h
|
504 |
|
|
cmp c
|
505 |
|
|
jnz skp
|
506 |
|
|
|
507 |
|
|
obcp inx h
|
508 |
|
|
mov a,m ;read next byte
|
509 |
|
|
dcx h ;decr address
|
510 |
|
|
call err ;print data found
|
511 |
|
|
|
512 |
|
|
skp call bmp ;check if done
|
513 |
|
|
jnz cont ;back for more
|
514 |
|
|
pop psw ;remove flag saved on stack
|
515 |
|
|
ret
|
516 |
|
|
|
517 |
|
|
;--------------------------------------------------------------------------
|
518 |
|
|
; poutp (O) - output data to a port
|
519 |
|
|
;--------------------------------------------------------------------------
|
520 |
|
|
poutp call dspMsg
|
521 |
|
|
db 'OU','T'+80h
|
522 |
|
|
|
523 |
|
|
mvi c,2
|
524 |
|
|
call ahe0 ;port number in e
|
525 |
|
|
|
526 |
|
|
mvi c,2
|
527 |
|
|
call ahe0 ;port to l, data in e
|
528 |
|
|
|
529 |
|
|
mov d,l ;d=port
|
530 |
|
|
lxi h,SPTR-30h ;form OUT nn, RET in memory at h
|
531 |
|
|
mvi m,0c9h ;RET opcode
|
532 |
|
|
dcx h
|
533 |
|
|
mov m,d ;output port for OUT instruction
|
534 |
|
|
dcx h
|
535 |
|
|
mvi m,0D3H ;OUT opcode
|
536 |
|
|
mov a,e
|
537 |
|
|
pchl ;call OUT, RET
|
538 |
|
|
|
539 |
|
|
;--------------------------------------------------------------------------
|
540 |
|
|
; pinpt (I) - input data from a port
|
541 |
|
|
;--------------------------------------------------------------------------
|
542 |
|
|
pinpt call dspMsg
|
543 |
|
|
db 'I','N'+80h
|
544 |
|
|
|
545 |
|
|
mvi c,2
|
546 |
|
|
call ahe0 ;port number to e
|
547 |
|
|
|
548 |
|
|
lxi h,SPTR-30H ;form IN nn, RET in memory at h
|
549 |
|
|
mvi m,0C9H ;RET opcode
|
550 |
|
|
dcx h
|
551 |
|
|
mov m,e ;input port of IN instruction
|
552 |
|
|
dcx h
|
553 |
|
|
mvi m,0DBH ;IN opcode
|
554 |
|
|
call SPTR-32H
|
555 |
|
|
jmp pt2
|
556 |
|
|
|
557 |
|
|
;---------------------------------------------------------------------
|
558 |
|
|
; hexLoad (H or L) - load intel hex through 2SIO serial port 0 or 1
|
559 |
|
|
;---------------------------------------------------------------------
|
560 |
|
|
hexload call dspMsg
|
561 |
|
|
db 'HEXLOA','D'+80h
|
562 |
|
|
|
563 |
|
|
mvi c,1 ;read one hex digit
|
564 |
|
|
call ahe0 ;digit is in e
|
565 |
|
|
lxi h,SIOPORT ;hl->location on stack to save port
|
566 |
|
|
mov m,e ;SIOPORT = 0 or 1
|
567 |
|
|
|
568 |
|
|
; rcvLine - receive a hex file line
|
569 |
|
|
|
570 |
|
|
rcvLine call crlf
|
571 |
|
|
mvi c,0 ;clear echo character flag
|
572 |
|
|
|
573 |
|
|
wtMark call getChar ;read next character
|
574 |
|
|
sui ':' ;record marker?
|
575 |
|
|
jnz wtMark ;no, keep looking
|
576 |
|
|
|
577 |
|
|
; Have start of new record. Save the byte count and load address.
|
578 |
|
|
; The load address is echoed to the screen so the user can
|
579 |
|
|
; see the file load progress.
|
580 |
|
|
|
581 |
|
|
mov d,a ;init checksum in D to zero
|
582 |
|
|
|
583 |
|
|
call iByte ;input two hex digits (byte count)
|
584 |
|
|
mov a,e ;test for zero byte count
|
585 |
|
|
ora a
|
586 |
|
|
jz flush ;count of 0 means end
|
587 |
|
|
|
588 |
|
|
mov b,e ;B = byte count on line
|
589 |
|
|
|
590 |
|
|
inr c ;set echo flag for address bytes
|
591 |
|
|
call iByte ;get MSB of address
|
592 |
|
|
mov h,e ;H = address MSB
|
593 |
|
|
call iByte ;get LSB of address
|
594 |
|
|
mov l,e ;L = address LSB
|
595 |
|
|
dcr c ;clear echo flag
|
596 |
|
|
|
597 |
|
|
call iByte ;ignore/discard record type
|
598 |
|
|
|
599 |
|
|
; Receive the data bytes of the record and move to memory
|
600 |
|
|
|
601 |
|
|
data call iByte ;read a data byte (2 hex digits)
|
602 |
|
|
mov m,e ;store in memory
|
603 |
|
|
inx h
|
604 |
|
|
dcr b
|
605 |
|
|
jnz data
|
606 |
|
|
|
607 |
|
|
; Validate checksum
|
608 |
|
|
|
609 |
|
|
call iByte ;read and add checksum
|
610 |
|
|
jz rcvLine ;checksum good, receive next line
|
611 |
|
|
|
612 |
|
|
call dspMsg ;display error message
|
613 |
|
|
db ' ER','R'+80h
|
614 |
|
|
;fall into flush
|
615 |
|
|
|
616 |
|
|
; flush - flush rest of file as it comes in until no characters
|
617 |
|
|
; received for about 1/4 second to prevent incoming file
|
618 |
|
|
; data looking like typed monitor commands. Only the console
|
619 |
|
|
; port needs to be flushed.
|
620 |
|
|
|
621 |
|
|
flush in COND ;clear possible received char
|
622 |
|
|
lxi d,10417 ;.25s timeout for 48 cycle loop
|
623 |
|
|
|
624 |
|
|
flshLp in CONS ;(10) look for character on console
|
625 |
|
|
rrc ;(4) data flag in carry
|
626 |
|
|
jc flush ;(10) data received, restart
|
627 |
|
|
|
628 |
|
|
dcx d ;(5) decrement timeout
|
629 |
|
|
mov a,d ;(5)
|
630 |
|
|
ora e ;(4)
|
631 |
|
|
jnz flshLp ;(10) loop until zero
|
632 |
|
|
ret ;done
|
633 |
|
|
|
634 |
|
|
;-----------------------------------------------------------
|
635 |
|
|
; iByte - read two ascii hex bytes and return binary
|
636 |
|
|
; value in e.
|
637 |
|
|
;-----------------------------------------------------------
|
638 |
|
|
iByte call getChar ;get a character
|
639 |
|
|
call asc2Bin ;ascii hex digit to binary
|
640 |
|
|
add a ;put in msn, zero lsn
|
641 |
|
|
add a
|
642 |
|
|
add a
|
643 |
|
|
add a
|
644 |
|
|
mov e,a ;save byte with MSN in E
|
645 |
|
|
|
646 |
|
|
; 2nd byte (LSN)
|
647 |
|
|
|
648 |
|
|
call getChar ;get a character
|
649 |
|
|
call asc2Bin ;ascii hex digit to binary
|
650 |
|
|
add e ;combine msn and lsn
|
651 |
|
|
mov e,a ;save in EH
|
652 |
|
|
add d ;add character to checksum
|
653 |
|
|
mov d,a
|
654 |
|
|
ret
|
655 |
|
|
|
656 |
|
|
;-------------------------------------------------------------
|
657 |
|
|
; asc2Bin - ASCII hex digit to binary conversion. Digit
|
658 |
|
|
; passed in a, returned in a. Errors ignored as checksum
|
659 |
|
|
; will eventually kick this out.
|
660 |
|
|
;-------------------------------------------------------------
|
661 |
|
|
asc2Bin sui '0' ;'0' to 0
|
662 |
|
|
cpi 10 ;0-9 ?
|
663 |
|
|
rc
|
664 |
|
|
|
665 |
|
|
sui 7 ;'A-F' to A-F
|
666 |
|
|
ret
|
667 |
|
|
|
668 |
|
|
;-------------------------------------------------------------
|
669 |
|
|
; getChar - read a character from the 2SIO port specified in
|
670 |
|
|
; SIOPORT. The character is also echoed to the console port
|
671 |
|
|
; if the echo flag (c) is set (non-zero)
|
672 |
|
|
;-------------------------------------------------------------
|
673 |
|
|
getChar push b ;save b,c
|
674 |
|
|
lda SIOPORT ;a=pseudo port to use
|
675 |
|
|
ora a ;port zero?
|
676 |
|
|
jnz inWait1 ;no, use port 1
|
677 |
|
|
|
678 |
|
|
; in through 1st port (0) on 2SIO
|
679 |
|
|
|
680 |
|
|
inWait0 call cntlc ;test for character from console
|
681 |
|
|
jz inWait0
|
682 |
|
|
jmp haveChr
|
683 |
|
|
|
684 |
|
|
; in through 2nd port (1) on 2SIO, check for ctrl-c on console
|
685 |
|
|
; while waiting
|
686 |
|
|
|
687 |
|
|
inWait1 call cntlc ;look for ctrl-c on console
|
688 |
|
|
in CONS+2 ;wait for character on 2nd 2SIO
|
689 |
|
|
rrc ;data flag in carry
|
690 |
|
|
jnc inWait1
|
691 |
|
|
in COND+2 ;a=character read
|
692 |
|
|
|
693 |
|
|
; process new character in a. Echo to console if c is non-zero
|
694 |
|
|
|
695 |
|
|
haveChr mov b,a ;save character in b
|
696 |
|
|
mov a,c ;echo flag (c) set?
|
697 |
|
|
ora a
|
698 |
|
|
jz noEcho ;no echo
|
699 |
|
|
|
700 |
|
|
mov a,b ;a=character to send
|
701 |
|
|
pop b ;restore b,c
|
702 |
|
|
jmp ptcn ;display character and exit
|
703 |
|
|
|
704 |
|
|
noEcho mov a,b ;a=byte read
|
705 |
|
|
pop b ;restore b,c
|
706 |
|
|
ret
|
707 |
|
|
|
708 |
|
|
;********************************************************************
|
709 |
|
|
;
|
710 |
|
|
; Type conversion, input, output subroutines
|
711 |
|
|
;
|
712 |
|
|
;********************************************************************
|
713 |
|
|
|
714 |
|
|
;------------------------------------------------------------
|
715 |
|
|
; tahex - read two 16 bit addresses. 1st returned in HL, 2nd in DE
|
716 |
|
|
;------------------------------------------------------------
|
717 |
|
|
tahex call ahex ;get first address param
|
718 |
|
|
;fall into ahex to get 2nd param
|
719 |
|
|
|
720 |
|
|
;------------------------------------------------------------
|
721 |
|
|
; ahex - read up to 4 hex digits to binary, return in de
|
722 |
|
|
;------------------------------------------------------------
|
723 |
|
|
ahex mvi c,4 ;count of 4 digits
|
724 |
|
|
ahe0 lxi h,0 ;16 bit zero
|
725 |
|
|
ahe1 call rdcn ;read a byte
|
726 |
|
|
ahexNr cpi '0'
|
727 |
|
|
jc start ;below '0', abort
|
728 |
|
|
cpi ':'
|
729 |
|
|
cnc alph
|
730 |
|
|
dad h
|
731 |
|
|
dad h
|
732 |
|
|
dad h
|
733 |
|
|
dad h
|
734 |
|
|
sui '0' ;ascii bias
|
735 |
|
|
cpi 10 ;digit 0-10
|
736 |
|
|
jc alf
|
737 |
|
|
sui 7 ;alpha bias
|
738 |
|
|
alf add l
|
739 |
|
|
mov l,a
|
740 |
|
|
dcr c
|
741 |
|
|
jnz ahe1 ;keep reading
|
742 |
|
|
xchg ;result in de
|
743 |
|
|
;fall through to print a space
|
744 |
|
|
;------------------------------------------------------------
|
745 |
|
|
; spce - print a space
|
746 |
|
|
; ptcn - print character passed in a
|
747 |
|
|
;------------------------------------------------------------
|
748 |
|
|
spce mvi a,' ' ;print space
|
749 |
|
|
ptcn push psw
|
750 |
|
|
|
751 |
|
|
ptlop in CONS ;wait for OK to transmit
|
752 |
|
|
ani TBE
|
753 |
|
|
jz ptlop
|
754 |
|
|
|
755 |
|
|
pop psw ;recover a
|
756 |
|
|
ani 07fh ;get rid of msbit
|
757 |
|
|
out COND ;and print it
|
758 |
|
|
ret ;return from ptcn
|
759 |
|
|
|
760 |
|
|
;------------------------------------------------------------
|
761 |
|
|
; alph - verify valid hex digit, abort to command loop if not
|
762 |
|
|
;------------------------------------------------------------
|
763 |
|
|
alph cpi 'A'
|
764 |
|
|
jc start
|
765 |
|
|
ani 05fh
|
766 |
|
|
cpi 'G'
|
767 |
|
|
jnc start
|
768 |
|
|
ret
|
769 |
|
|
|
770 |
|
|
;------------------------------------------------------------
|
771 |
|
|
; crlf - print CR/LF
|
772 |
|
|
;------------------------------------------------------------
|
773 |
|
|
crlf mvi a,CR
|
774 |
|
|
call ptcn
|
775 |
|
|
mvi a,LF
|
776 |
|
|
jmp ptcn
|
777 |
|
|
|
778 |
|
|
;------------------------------------------------------------
|
779 |
|
|
; err - display the address in hl followed by the value
|
780 |
|
|
; in b, then the value in a.
|
781 |
|
|
;------------------------------------------------------------
|
782 |
|
|
err push psw ;save A
|
783 |
|
|
call ptad ;print address
|
784 |
|
|
mov a,b ;print B
|
785 |
|
|
call pt2
|
786 |
|
|
call spce
|
787 |
|
|
pop psw ;print A
|
788 |
|
|
pt2 push psw
|
789 |
|
|
call binh
|
790 |
|
|
pop psw
|
791 |
|
|
jmp binl
|
792 |
|
|
|
793 |
|
|
;------------------------------------------------------------
|
794 |
|
|
; ptad - display the address in h
|
795 |
|
|
;------------------------------------------------------------
|
796 |
|
|
ptad call crlf ;print cr,lf
|
797 |
|
|
call pause
|
798 |
|
|
mov a,h ;print
|
799 |
|
|
call pt2 ;ascii
|
800 |
|
|
mov a,l ;codes
|
801 |
|
|
call pt2 ;for
|
802 |
|
|
call spce ;address
|
803 |
|
|
ret
|
804 |
|
|
|
805 |
|
|
;------------------------------------------------------------
|
806 |
|
|
; binh - print MSN of byte passed in A
|
807 |
|
|
; binl - print LSN of byte passed in A
|
808 |
|
|
;------------------------------------------------------------
|
809 |
|
|
binh rar
|
810 |
|
|
rar
|
811 |
|
|
rar
|
812 |
|
|
rar
|
813 |
|
|
binl ani 0fh ;low 4 bits
|
814 |
|
|
adi '0' ;ascii bias
|
815 |
|
|
cpi 03ah ;digit 0-9
|
816 |
|
|
jc ptcn
|
817 |
|
|
adi 7 ;digit A-F
|
818 |
|
|
jmp ptcn
|
819 |
|
|
|
820 |
|
|
;------------------------------------------------------------
|
821 |
|
|
; dspMsg - display in-line message. String terminated by byte
|
822 |
|
|
; with msbit set.
|
823 |
|
|
;------------------------------------------------------------
|
824 |
|
|
dspMsg pop h ;hl->string to display
|
825 |
|
|
|
826 |
|
|
dspLoop mov a,m ;a=next character to display
|
827 |
|
|
call ptcn ;display character
|
828 |
|
|
ora m ;MSB set? (last byte)
|
829 |
|
|
inx h ;point to next character
|
830 |
|
|
jp dspLoop ;no, keep looping
|
831 |
|
|
|
832 |
|
|
call spce ;display a trailing space
|
833 |
|
|
pchl ;return past the string
|
834 |
|
|
|
835 |
|
|
;------------------------------------------------------------
|
836 |
|
|
; rdcn - read from console to A with echo to screen
|
837 |
|
|
; getCon - read from console to A without echo
|
838 |
|
|
;------------------------------------------------------------
|
839 |
|
|
rdcn call getCon ;get character from console
|
840 |
|
|
cpi ESC ;ESC confuses smart terminals
|
841 |
|
|
rz ; so don't echo escape
|
842 |
|
|
jmp ptcn ;echo onto printer
|
843 |
|
|
|
844 |
|
|
getCon in CONS ;read keyboard status
|
845 |
|
|
rrc ;data available flag in carry
|
846 |
|
|
jnc getCon
|
847 |
|
|
|
848 |
|
|
in COND ;read from keyboard
|
849 |
|
|
ani 07fh ;strip off msb
|
850 |
|
|
ret
|
851 |
|
|
|
852 |
|
|
;------------------------------------------------------------
|
853 |
|
|
; pause - pause/resume with spacebar. Also look for a ctrl-c
|
854 |
|
|
; or ESC to abort.
|
855 |
|
|
;------------------------------------------------------------
|
856 |
|
|
pause call cntlc ;look for abort or other character
|
857 |
|
|
cpi ' '
|
858 |
|
|
rnz ;return if not space or abort
|
859 |
|
|
|
860 |
|
|
ploop call cntlc ;loop here until space or abort pressed
|
861 |
|
|
cpi ' '
|
862 |
|
|
jnz ploop
|
863 |
|
|
ret
|
864 |
|
|
|
865 |
|
|
;------------------------------------------------------------
|
866 |
|
|
; cntlc - see if a character has been typed. If not, return
|
867 |
|
|
; zero true. If ctrl-c or ESC typed, abort and return to
|
868 |
|
|
; the command loop. Otherwise, return the character typed.
|
869 |
|
|
;------------------------------------------------------------
|
870 |
|
|
cntlc in CONS ;anything typed?
|
871 |
|
|
ani RDA
|
872 |
|
|
rz ;no, exit with zero true
|
873 |
|
|
|
874 |
|
|
in COND ;get the typed character
|
875 |
|
|
ani 07fh
|
876 |
|
|
cpi CTRLC ;abort with ctrl-c (2.0 style)
|
877 |
|
|
jz start
|
878 |
|
|
cpi ESC ;or ESC (4.x style)
|
879 |
|
|
jz start
|
880 |
|
|
ret
|
881 |
|
|
|
882 |
|
|
;------------------------------------------------------------
|
883 |
|
|
; bmp - compare address and increment h. Return zero true
|
884 |
|
|
; if hl=de. Once hl=de, then de is incremented each time
|
885 |
|
|
; so the comparison remains true for subsequent calls.
|
886 |
|
|
;------------------------------------------------------------
|
887 |
|
|
bmp mov a,e ;compare lsb's of hl,de
|
888 |
|
|
sub l
|
889 |
|
|
jnz goon ;not equal
|
890 |
|
|
|
891 |
|
|
mov a,d ;compare msb's of hl,de
|
892 |
|
|
sbb h ;gives zero true if equal
|
893 |
|
|
|
894 |
|
|
goon inx h ;increment hl
|
895 |
|
|
rnz ;exit if hl <> de yet
|
896 |
|
|
|
897 |
|
|
inx d ;increase de as well so it will
|
898 |
|
|
ret ; still be equal next time
|
899 |
|
|
|
900 |
|
|
end
|