home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
programs
/
bkgrondr
/
bgk84scr.lbr
/
K84SCRN.AZM
/
K84SCRN.ASM
Wrap
Assembly Source File
|
1987-02-27
|
26KB
|
1,438 lines
.title "K84SCRN.ASM Kaypro '83 screen driver 11/8/86"
.sbttl "Copyright (c) 1986 Plu*Perfect Systems"
noatt = 1 ;nul return-attribute function to save space
DEBUG = 0
.remark \==
Source code for CDL/TDL Z80 assembler (AZM.COM).
; production by:
;
AZM k84scrn
ZLINK
*k84.com=k84scrn.rel
*/locate .prog.=3f80;
*q
ZSID k84.com
m3f80 4500 100
^C
SAVE 5 k84scrn.drv
==\
; revision history:
;
; v 1.0: no scroll on line 24 in cut
; id imbedded in string
; most data put in-line to save bytes
.XLIST
.ifg DEBUG, [
bios =\ 'Base of bios = ?'
]
.remark \===
The first sections of code are generic (except for some terminal equates);
beginning at 'STMRKS' it is terminal-specific.
Particular features of Kaypro '84 code:
1. Video ram must be accessed via video controller.
2. We store screen attributes as nybbles.
3. Cursor-movement sequences are all single-byte control characters.
Space is very tight; in-line data used extensively.
===\
.ifg DEBUG, [
codloc = 100h
.phex
.psym
.pabs
consta = bios +06h
conin = bios +09h
conout = bios +0ch
]
;
[
.prel
.ident SCRK84
consta = 0
conin = 0
conout = 0
outch = 0
puts = 0
bwrch = 0
bflush = 0
]
.xsym
.sall
;
; ascii equates
;
NUL = 00h
BELL = 07h
BS = 08h
CR = 0dh
LF = 0ah
ESC = 1bh
SPACE = 20h
DEL = 7fh
;
; CUT command characters
;
HOME = 'H' ;home the cursor
LOHOME = 'h'
MARK = 'X' ;set a mark
LOMARK = 'x'
PASTE = 'P'-'@' ;paste region at cursor
CANCEL = 'C'-'@' ;cancel cut command
;
;
; TERMINAL-SPECIFIC EQUATES
;
; kaypro cursor controls
;
LEFT = 08H
RIGHT = 'L'-'@'
UP = 'K'-'@'
DOWN = 0AH
;
LEFT8 = 82h ;kaypro raw keypad arrow values...
RIGHT8 = 83h
UP8 = 80h
DOWN8 = 81h
;
HOMEC = 1eh ;home cursor
;
; Kaypro '84 screen parameters
;
NCOLS = 80
NROWS = 25
NROW24 = 24 ;# rows excluding status line
;
SCRSIZ = NCOLS*NROWS
;
; Kaypro '84 controller ports
;
vcbase = 1ch
vccmd = vcbase
vcstat = vcbase
vcrdat = vcbase+1
vcdata = vcbase+3
;
; controller register numbers
;
cstart = 10 ;cursor start
cstop = 11 ;cursor stop
hiadd = 18 ;hi address byte - update register
loadd = 19 ;lo ""
;
scrcmd = 12 ;"scroll" set home addr
curcmd = 14 ;place cursor
rwcmd = 18 ;read/write
strcmd = 31 ;strobe
;
;=========================
.ifg DEBUG, [
.loc codloc
]
;
[
.loc .PROG.
]
;
;------------------------------------------------------------
;
; id sector - nul-terminated string - at 3f80h
;
sdid: .ascii "Kaypro '84 driver v 1.0"
db 0 ;NUL terminator
idlen = . - sdid
ds 80h-idlen ;total of 80h bytes
;
START:
;
;
; Start of Screen Module. Assemble to run at 4000h.
;
;***** MODULE ENTRY HEADER
;
; EXTERNAL ADDRESSES, supplied by loader
;
jjcons: jmp consta ;bios constat
jjconi: jmp conin ;bios conin
jjouta: jmp outch ;A to conout, preserving bc,de,hl
jjputs: jmp puts ;hl-string to conout, NUL/bit-7 term.
; preserving bc,de,hl
jjbrdc: jmp 0000 ;buffered read char from cut-swp
jjbwrc: jmp bwrch ;buffered write char to cut-swp
jjbflu: jmp bflush ;flush (write) buffer
;
; INTERNAL ENTRY POINTS
;
savscr: jmp savpag ;save screen
resscr: jmp respag ;restore saved screen
lastnb: jmp lstnbl ;last non-blank char in rows 1-24
dmpchr: jmp retnch ;return next screen char
dmpcur: jmp retncu ;return buffer cursor
dmpatt: jmp retnat ;return next screen attribute
setmrk: jmp stmrks ;set region marks, move cursor
cutrg: jmp docut ;cut region
pastrg: jmp dopast ;paste region
ininpd: jmp ininot ;initialize notepad
putnpd: jmp putnch ;put char to notepad
;
;========================================
; generic
;
ININOT:
;
; Initiate Notepad - clear screen, print banner.
;
lxi h,Zbanner
jr jjputs
;
;========================================
; generic
;
PUTNCH:
;
; Put char in A to notepad (screen)
; Convert CR to CRLF, DEL to rubout.
;
cpi CR
lxi h,Zcrlf ;convert CR to CR,LF
jrz jjputs
cpi DEL
lxi h,Zrub
jrz jjputs
jr jjouta
;========================================
; generic
;
RETNCU:
;
; Return buffer cursor as row/col.
;
; ret: D = binary row, E= binary col
; L = ascii row, H = ascii col (for shld ...)
;
lhld bcursor
;
; Convert offset to col/row.
; exit: D = binary row, E = binary col
; H = ascii col, L = ascii row <-- NOTE ORDER
;
off2cr: mvi b,0 ;convert to row,col
lxi d,-NCOLS
..1: dad d
jrnc ..2
inr b ;row count++
jr ..1
..2: lxi d,NCOLS
dad d
mov a,l ;col
mov e,a ;binary col in E
mov d,b ;binary row in D
adi SPACE ; + bias
mov h,a ;H = ascii col
mov a,b ;row
adi SPACE ; +bias
mov l,a ;L = ascii row
ret
;
;========================================
; generic
;
DOPASTE:
;
; Paste the last-cut region onto active screen at the current cursor.
;
; 1. Get previously-cut region from external routine
; 2. Send chars to screen, avoiding boundary overflows.
;
; 'savpag' not needed if terminal supports 'send cursor address'
;;-- call savpag ;get current screen,
;in order to find cursor
mvi b,4 ;read 4 data bytes
..0: push b
call jjbrdc
pop b
djnz ..0
;
mov b,a ;4th byte is # rows
push b
call crs2hl ;current cursor's row/col to hl
pop b
;
; loop over rows
;
..rowlp:push b
push h
mov e,l ;e = col no.
push d
call stcrshl ;set cursor at h,l
..collp:call jjbrdc ;read char from cut-swp
cpi CR
jrz ..rend
mov c,a ;save char
pop d ;check for off screen
mov a,e
cpi NCOLS
inr e
push d ;row/col to stack
cc sendc ;to conout, unless off edge
jr ..collp
;
..rend: pop d ;clear row/col
pop h
pop b
inr h ;bump row
mov a,h ;check for off bottom of screen
cpi NROWS
jrnc ..xit
djnz ..rowlp
..xit: xra a
ret
;
;========================================
; generic
;
DOCUT:
;
; Cut rectangular region defined by keypresses.
; 1. Parse keypresses to move cursor and mark corners.
; Highlight region as cursor is moved.
; 2. Send the marked region, row-wise to external routine.
; Append CR after each row.
;
; Data structure is:
; size (word)
; # columns (byte)
; # rows (byte)
; row 1
; CR
; row 2
; CR
; ....
;
.ifg DEBUG, [
;for debugging, use cutbuf for output
lxi h,cutbuf ;set ptr
shld dbgptr
]
;
xra a
sta mrkcnt ;init for next time
;
;
; set ctcols = # cols, ctrows = # rows
; (assumes mark2 is SE of mark1)
;
mark1 = .+1
mark1r = .+2
corners:lxi d,0000 ;binary col, then row of upperleft mark
;
mark2 = .+1
mark2r = .+2
lxi h,0000 ;lower right mark
mov a,h ;# rows = 1 + mark2row -mark1row
inr a
sub d
mov h,a
mov a,l ;# cols = 1 + mark2col -mark1col
inr a
sub e
mov l,a
shld ctcols
;
; cut rectangle [mark1...mark2] & copy to buffer
; append CR at end of each row
;
xchg
push h ;mark1
call wrpara ;write parameters
pop h ;mark1
call rc2off ;convert to scr addr
lda ctrows ;get # rows
mov b,a
;
; write the cut region to external buffer
;
..rowlp:push b ;(+1
push h ;(+2
lxi d,buf ;fetch from screen buffer
dad d
;
; write 1 row of cut region to external buffer
;
lda ctcols
mov b,a ;b = # cols
;
; buffered write B chars at hl, ascii only
;
..bwrt: push b
push h
mov a,m
cpi DEL
jrnc ..mksp
cpi SPACE ;convert graphics
jrnc ..1
..mksp: mvi a,SPACE ; to space
..1: mov c,a
call jjbwrch
pop h
pop b
inx h
djnz ..bwrt
;
mvi c,CR ;append CR to each row
call jjbwrch
pop h ;(+1
pop b ;(+0
lxi d,NCOLS ;bump to next row
dad d
djnz ..rowlp ; and loop
jmp jjbflu ;flush the write buffer
;
;
; write parameters: size, # cols, # rows to swp file
; de = ctcols
;
wrpara: mov b,d ;# rows
mvi d,0
inr e ;+1 for CR
lxi h,0 ;accum.
..0: dad d
djnz ..0
call bwhl ;write word
ctcols = .+1
ctrows = .+2
lxi h,0000 ;now #cols, # rows
;
bwhl: push h
mov c,l
call jjbwrch
pop h
mov c,h
jmp jjbwrch
;========================================
; generic
;
LSTNBL:
;
; Find last non-blank line (1-24 only) in current scr buffer.
; Graphics and 8-bit characters are considered blanks.
; If B=0ff, save screen first.
;
; ret: H=row, L=col of last non-blank char in rows 1-24
;
inr b
cz savpag
lxi b,NROW24*100h + NCOLS ;b=# rows, c=# cols
lxi d,buf
lxi h,0
..lp: ldax d
cpi SPACE+1 ;don't count cntl chars or SPACE
jrc ..1
cpi DEL ; or DEL or graphics 8-bit
jrnc ..1
shld savrc
..1: inx d
inr l
dcr c
jrnz ..lp ;loop over cols
inr h
mov l,c ;0
mvi c,NCOLS
djnz ..lp ;loop over rows
savrc = .+1
lxi h,0000 ;hl = last non-blank
ret
;----------------------------------------
;
xring: mvi c,BELL
;
; send C to screen, exit Z, no CY
;
sendc: mov a,c
; send A to screen, exit Z, no CY
; (this will scroll, however!)
;
send: call jjouta
xra a ;Z, no CY
ret
;========================================
;
; end of generic code
;
;========================================
; specific
;
; bump row/col var that tracks actual cursor
; if mark not yet, send cntl char
; ret NZ if mark is set
;
inrsnd: inr m ;next row/col
call anymrk
cz sendc
;
; nz if a mark has been set
;
mrkcnt = .+1
anymrk: mvi a,00
ora a
ret
;
STMRKS:
;
; Move cursor and set marks. Return CY clear until exit.
;
; 1. move cursor, until:
; 2. 'X' = set 1st mark
; turn on hiliting, set mark, keep cursor at mark
; 3. move cursor right/down only
; 4. 'X' = set 2nd mark
; turn off hiliting, set 2nd mark
; exit CY (done)
; 5. cntl-C = CANCEL.
; turn off hilighting, set CY, exit
;
;
lxi h,bincol ;load ptr to actual col/row
cpi CANCEL
jrz abort
cpi LEFT
jrz jjlef8 ;;jz golef8
cpi LEFT8
jjlef8: jz golef8
;
cpi UP
jrz jjup8 ;;jz goup
cpi UP8
jjup8: jz goup8
;
cpi RIGHT
jrz jjrt8 ;;jz gort
cpi RIGHT8
jjrt8: jz gort8
;
cpi DOWN
jrz jjdn8 ;;jz godn
cpi DOWN8
jjdn8: jz godn8
;
cpi CR
jrz ..mrk
;
ani 5fh ;convert rest to uppercase
cpi HOME
jrz gohome
;
cpi MARK
jrz ..mrk
xra a ;no action
ret
..mrk: lxi h,mrkcnt ;if no mark yet set
mov a,m
ora a
mvi m,1
jrz mk1 ;..set mark1
call mk2 ;else set mark2
mrkxit: xra a
sta mrkcnt ;init for next time
stc ;CY = all done
ret
;
abort: call normal ;restore normal video
jr mrkxit
;-------------------------------------------
;
; set 1st mark, turn on rev. video, don't move cursor
;
mk1: call crs2hl
shld mark1
shld mark2
shld curcol ;L->curcol,H->currow
push h
call reverse ;reverse video on
;
; Hilite the marked char.
;
pop h ;mark1
mvi a,1 ;blink 1 char
sta colct
sta rowct
call showro
jmp sendbs
;
; set 2nd mark, restore normal video, set CY
;
mk2: call normal ;dummy - restore normal video
stc ;CY = all done
ret
;
;======================
; for H19, etc that use ESC sequences,
; change these routines to send ESC, then the byte.
;
gohome: mvi c,HOMEC ;convert to video driver's cntl char
call anymrk ;if mark set,
jnz xring ;..error
mov h,a ;set row=col=0
mov l,a
shld bincol
jjsndc: jmp sendc
;
; cursor left and cursor up:
; send if not at top or left margin
;
golef8: mvi a,LEFT ;convert to 7-bit char
;
goleft: ;hl = bincol
;
zck: mov c,a ;save char in c
call anymrk
rnz
cmp m ;ck col/row == 0
jz xring ;..error
dcr m ;dcr col/row
jr jjsndc
;
goup8: mvi a,UP ;7-bit code
goup: inx h ;binrow
jr zck ;ck for top row and send
;
; cursor right and cursor down:
; if mark is not set, move cursor
; if mark is set, expand region and highlight
; keep track of cursor location in both cases
; don't move if it would scroll
;
; move cursor right
;
gort8: mvi a,RIGHT ;convert to 7-bit code
;
gort: mov c,a ;save in c
mvi a,NCOLS-2
cmp m
jcxrng: jc xring
call inrsnd ;bump col & send if mrk not set
rz ;rtn if mark not yet set
;
; hilite marked column
;
gort1: lxi h,mark2
inr m ;bump 2nd mark-row
lxi h,curcol ;bump col
inr m
mov l,m
lda mark1r ;top row
mov h,a ;h=row, l=col for col to hilite
rowct = .+1
mvi b,00
;
; loop over each row in cut region
;
..rlp: push b
push h ;save binary row/col
mvi a,1 ;display 1 char in each row
call showhi
pop h
pop b
inr h ;next row
djnz ..rlp
lxi h,colct ;prepare to bump col cnt & exit
jr inrmbs
;
; move cursor down
;
godn8: mvi a,DOWN ;7bit code
godn: mov c,a ;save char
inx h ;binrow
mvi a,NROW24-2 ;ck if already on bottom row
cmp m
jc jcxrng
call inrsnd ;bump row & send
rz ;rtn if mark not yet set
;
; hilite marked row
;
godn1: lxi h,mark2r ;row
inr m ;bump 2nd mark-col
lxi h,currow ;bump row
inr m
mov h,m
lda mark1 ;left col
mov l,a ;h=row, l=col for row to hilite
call showro ;display 1 cut row
lxi h,rowct ;bump row cnt
inrmbs: inr m ; and exit
sendbs: mvi a,BS ;back up cursor
jmp send
;
.remark \====
For Kaypro '84, use bios conout.
if down: set cur at next row, left col
send partial row
rowcnt++
BS (back up 1)
if right: set cur at toprow, next col
send partial column
colcnt++
====\
;
; enter: H = binary row, L= binary col
;
showro:
colct = .+1
mvi a,00
;
; Fetch A chars at H=binary row, L=binary col from buffer.
; Put chars to screen, setting BLINK attribute.
;
showhi: push psw
push h
call stcrshl ;set cursor at h,l
pop h
call rc2off
lxi d,buf ;fetch from screen buffer
dad d
pop psw ;#chars
mov b,a
..lp: mov a,m
inx h
call jjouta
djnz ..lp
ora a
ret
;
;========================================
;
RETNCH:
;
; Return next screen char.
;
; enter:
; d = row, e = col
; b = FF ==> read screen
; c = FF ==> set bufptr
; exit:
; A = char, CY set if good
; DE -> row,col of next char, HL -> buf of next char
; CY clear if out of range
;
xra a
call stdump
rnc
mov a,m ;get char
inx h ;bump bufptr
ret
;
;========================================
;
.slist
.list
RETNAT:
;
.ifg noatt, [
; save space with a NUL FUNCTION
xra a ;clear CY
ret
]
[
;
;--------------------
; Return next screen attribute.
;
; enter:
; d = row, e = col
; b = FF ==> read screen
; c = FF ==> set bufptr
; exit:
; A = attr, CY set if good
; DE -> row,col of next char, HL -> buf of next char
; CY clear if out of range
;
mvi a,0ffh
call stdump
rnc
;
; fetch attr from buffer, advance hl every 2
;
mov a,m ;fetch attr byte from buffer
bit 0,e
jrnz ..podd ;DE here is CHAR addr, not attr +1
rar
rar
rar
rar
jr ..done
..podd: inx h ;bump hl
..done: ani 0fh
ret
;
]
.rlist
;--------------------
;
; ret: NC if out of range
;
stdump: sta attflg
inr b
jrnz ..0
push b
push d
call savpag
pop d
pop b
..0: inr c
jrnz ..1
call conv
rnc ;out of range
..1: inx d ;col++
mov a,e
cpi NCOLS
rc
mvi e,0 ;col = 0
inr d ;row++
mov a,d
cpi NROWS
ret ;NC if out of range
;
; enter: d = row, e = col
; exit: hl -> buffer address, cy set
; de preserved
; CY clear if error (off screen)
;
conv: mov a,d
cpi NROWS
jrnc cnvbad
mov a,e
cpi NCOLS
jrnc cnvbad
lxi h,buf
mov a,d
lxi b,NCOLS ;row*(cols per row)
inr a
..lp: dcr a
jrz ..2
dad b
jr ..lp
..2: mvi d,0 ;+ col #
dad d
attflg = .+1
mvi a,00
ora a
stc
rz
lxi b,SCRSIZ ;bump ptr to attributes
dad b
stc
ret
cnvbad: xra a
ret
;
;========================================
;
SAVPAG:
;
; Save screen to buffer.
;
xra a
call iscr
call crs2off ;find screen cursor
shld bcursor
push h
push d
call off2cr
sded bincol ;save binary col/row
pop d
pop h
;
;--------------------
;
doscr: lxi b,SCRSIZ
push b ;save count
push d ;save addr
;
; first the characters
;
..0: call datadr ;set addr
call vch ;r/w char
inx d
dcx b
mov a,b
ora c
jrnz ..0
pop d ;addr
pop b ;count
;
; now the attributes
;
inx d ;attributes lead 1 byte
..2: call attadr
call vat
inx d
dcx b
mov a,b
ora c
jrnz ..2
ret
;
;========================================
;
RESPAG:
;
; Restore saved screen from buffer.
;
; First, set any attribute so we undo the effect of a clearscreen.
; This ensures that the restored screen, if it has
; attributes set, will get cleared by a clearscreen or ^X or whatever.
;
;put1att:
call svcrsor
lxi h,Zoneat
call jjputs
call cursbak
;
mvi a,0ffh
call iscr
call gethome ;get current top of screen
xchg ; to de
call doscr ;put buffer to screen
lhld bcursor ;and set the cursor
;
; Set cursor on screen by direct cursor addressing.
; enter: HL = cursor offset relative to 0000
;
stcrs: call off2cr ;convert from offset to ascii col/row
stcoro: shld colrow ;put ascii col/row into string
lxi h,Zcurs ;send set-cursor string
jmp jjputs
;
; Set cursor on screen.
; enter: H=binary row, L = binary col
;
stcrshl:call rc2off
jr stcrs
;
;--------------------
;
; CONVERSION ROUTINES
;
; Get current cursor position to H=binary row, L=binary col
;
crs2hl: call crs2off ;get cursor by ...84 method
call off2cr ;returns binary in de
xchg
ret
;
; convert H=binary row, L=binary col to hl= offset
; (hl = row*NCOLS + col)
; uses bc,de,hl
;
rc2off: mov b,h ;b=row
mov c,l ;c=col
lxi h,0
inr b
lxi d,NCOLS
jr ..bot
..0: dad d ;rows*NCOLS
..bot: djnz ..0
dad b ;+ col
ret
;
; get raw relative cursor to HL
;
crs2off:
call gethome ;get top of scr addr
xchg ;keep in de
call gcur ;get cursor addr
;
mod800: ora a
dsbc d
mod8ck: rnc
lxi d,800h
dad d
ret
;
;--------------------
;initialize for screen
;
iscr: sta putflg ;0=save, 0ff=restore
lxi h,buf ;init char ptr
jr shcptr
;
;
; read/write 1 char from video controller, to/from buffer
; status must already be checked and ok
;
vch: lhld cptr
lda putflg
ora a
jrnz vchput
in vcdata ;get char from screen
mov m,a ; & put into buffer
inxcpt: inx h
shcptr: shld cptr
ret
;
vchput: mov a,m ;fetch char from buffer
call inxcpt
out vcdata ; & put to screen
ret
;
; read/write 1 attribute nybble to/from buffer
; stored: upper nybble = 00, lower nybble = 01, upper = 02,...
;
cptr = .+ 1
vat: lxi h,0000 ;char ptr
;
putflg = .+1
mvi a,00 ;NZ to restore(put) screen from buf
ora a
jrnz ..put
;
; get attribute from screen, store in buffer
;
..get: bit 0,e ;test for even col (de leads 1 )
jrz ..odd
rld ;a->lo, lo->hi
in vcdata ;get char from screen
rrd ;a->hi, hi back to lo
ret
..odd: rrd ;do low nybble, a->hi, hi->lo
in vcdata
rld
jr inxcpt ;and bump ptr
;
; fetch attr from buffer, advance hl every 2, put to screen
;
..put: mov a,m ;fetch attr byte from buffer
bit 0,e
jrz ..podd ;DE leads 1
rar
rar
rar
rar
jr ..done
..podd: inx h ;bump hl
shld cptr
..done: ani 0fh
out vcdata ; & put to screen
ret
;
;
gethome:call svcrsor ;save cursor in bios rom
mvi a,HOMEC ;home it
call jjouta
call gcur
;
cursbak:push h
lxi h,Zrestc ;restore bios copy of cursor addr
call jjputs
pop h ;ret home addr in hl
;
; v 1.4a FIX turborom v2.6. Restore cursor calls ldcursor
; w/o waiting for good status. The next controller read cause
; cursor-type byte to be written to screen.
;---
fixtrb: push h
lxi d,SCRSIZ
dad d ;point at 1st char in gap
xchg
call datadr ;set addr
in vcdata ;read the controller to flush
pop h ;the cursor-type byte.
;---
ret
;
; HL = raw cursor read from video controller
; uses h,l,a
;
gcur: mvi a,curcmd
out vccmd ;to get scrolling address
call vwait ; may be unnecessary ??
in vcrdat
mov h,a
mvi a,curcmd+1 ;get low byte
out vccmd
call vwait
in vcrdat
mov l,a
ret
;
;--------------------
;
; wait, set DE attribute addr, stroke
;
attadr: mov a,d ;qualify D for attribute space
ani 07h
ori 08h
jr xadr1
;
; wait, set DE data address, stroke
;
datadr: mov a,d ;qualify DE for data space
ani 07h
xadr1: mov d,a
xadr2: in vcstat
ral
jrnc xadr2
;
;send DE to reg A, A+1, stroke & wait
;
;setrw:
mvi a,hiadd
out vccmd
mov a,d
out vcrdat
mvi a,loadd
out vccmd
mov a,e
out vcrdat
mvi a,strcmd ;stroke chip
out vccmd
vwait: in vcstat
ral
jrnc vwait
ret
;----------------------------------------
;
; DATA AREA
bincol: db 0 ;pair
binrow: db 0
;
curcol: db 0
currow: db 0
;
Zrub: db BS,SPACE,BS+80H ;rub-out previous char
;
;****************************************
;
; TERMINAL-SPECIFIC data
;
svcrsor:lxi h,Zsavec ;save cursor & push state in bios rom
jr jputs
;
; turn on normal video
;
normal: lxi h,Znorm
jputs: call jjputs
ora a ;clr CY
ret
;
; turn on reverse video
;
reverse:lxi h,Zrev
jr jputs
;
; Kaypro '84 video strings
;
Zsavec: .ascis [1bh]'B6' ;save cursor location
Zrestc: .ascis [1bh]'C6' ;restore it
;
Zcurs: .ascii [1bh]'=' ;set cursor to
colrow: db SPACE,SPACE ; row,col - modified in-line
db NUL ;must have following NUL
;
Zrev: .ascii [1bh]'B0' ; reverse video
.ascis [1bh]'B1' ; with 1/2 intensity
Znorm: .ascii [1bh]'C0' ; normal video
.ascis [1bh]'C1' ; with full intensity
;
; !! this causes momentary flashing, can we do it elsewhere?
;
Zoneat: .ascii [1bh]'B3 '
.ascis [1bh]'C3'
;
.ifg DEBUG, [
Zclr: db 1Ah,NUL ;kaypro
]
;
;
;================================
;
; JOTPAD BANNER - just 2 lines' worth
;
; 1. Clear screen.
; 2. Remind user of usage, to extent space is available.
; The editing keys are those supported by the terminal itself.
;
Zbanner:
db 1ah ;clear screen KAYPRO-SPECIFIC
;
.ascii 'JOT: <SUSPEND>=exit, ^Paste'
db CR,LF
.ascii 'ESC E/ESC R=ins/del line'
; NO ROOM FOR THIS !
; if turborom-->
;.ascii 'Cntl-A = insert char. Cntl-B = delete char. '
;
Zcrlf: db CR,LF+80h
;
.slist
.list
codlen = .-start ;length of code
.rlist
;
;++++++++++++++++++++++++++++++
.remark \==
Debugging stragegy:
Assemble screendriver at 100h.
Load with Z80 debugger.
Clear ram buffers.
Set breakpoints as needed.
Call these test routines and inspect buffers.
==\
.ifg DEBUG, [
dbg0 = .
;
; these emulate the external BGii routines
; using ram buffers for debugging
;
bwrch: push h
lhld dbgptr ;put to debug cut buffer
mov m,c
inx h
shld dbgptr
pop h
ret
;
bflush: ret
;
;bios display-a-string
; nul/8-bit terminated string at hl
; preserves bc,de,hl
;
puts: push h ;save hl, outch save bc,de
..0: mov a,m
rlc
srlr a ;shift right logical (register) A
inx h
jrz ..1
push psw
call outch
pop psw
jrnc ..0
..1: pop h
ret
;
; char in A to conout, preserve bc,de,hl
;
outch: push b
push d
push h
mov c,a
call conout
pop h
pop d
pop b
ret
;
; Various routines for debugging in ram.
;
TSTACK = 05000h ;test stack, above bank-switching
tdump: lxi b,0ffffh ;fetch scr, set ptr
lxi d,0 ;from row 0,col 0
call dmpchr
;
tdump2: lxi b,0
call dmpchr
;
tdump3: lxi d,100h + 0
lxi b,00ffh
call dmpchr
;
tdump4: lxi d,3000h ;out of range test
lxi b,00ffh
call dmpchr
rst 7
;
;
clear: lxi h,Zclr ;clear screen
call jjputs
rst 7
;
flood: lxi h,Zflood ;write to screen
call jjputs
rst 7
Zflood: .ascii '=======TESTING======='
db 0
;
tsave: lxi sp,TSTACK ;save screen
call savscr
rst 7
trest: lxi sp,TSTACK ;restore screen
call resscr
rst 7
tmark: lxi sp,TSTACK ;set a mark
call savscr
call sttop ;so debugger doesn't scroll screen
..0: call conin
call setmrk
jnc ..0
; rst 7
nop
;
tcut: lxi h,cutbuf ;clear buffer
mvi m,0
lxi d,cutbuf+1
lxi b,2*80h
ldir
call cutrg ;cut region
call setbot ;put cursor out of way
rst 7
; place cursor nerar bottom or top
;
setbot: lxi h,100h*(20h+18) +20h
jr sttop1
sttop: lxi h,2020h
sttop1: shld colrow
lxi h,Zcurs ;send set-cursor string
jmp jjputs
;
dbgptr: dw 0
.slist
.list
dbglen = . - dbg0
.rlist
]
;++++++++++++++++++++++++++++++
;
.list
; SCREEN BUFFER STRUCTURE
;
; The rest of the 4K block is available
; for the screen image and other data.
xbreq = 2 + NROWS*NCOLS + (NROWS*NCOLS)/2 ;required space
;
.ifg DEBUG, [
;
; put buffer on even byte ( for attributes)
bstart = start + 800h ;make some room
]
;
[
; put buffer at end of 4K area, to just fit
bstart = (start + 400h) + (3*400h-xbreq)
short = start+codlen-bstart
xfree = - short
.ifg (short), [
.prntx '[07]Code overflows buffer!'
]
]
;
; addresses:
;
bcursor = bstart ;cursor location in saved screen
buf = bcursor+2 ;start of screen buffer
;
;buffer uses (25 lines x 80 chars) + 1/2 that for attributes
;
bufend = buf + 25*80 + (25*80)/2
;
.ifg DEBUG, [
;
; put cutbuffer in ram for debugging
;
datcut = bstart+10h+3*400h
cutbuf = datcut
]
.xlist
.remark \======================
This routine is needed to calculate locations of mark1, mark2
if cursor movements are not restricted to DOWN and RIGHT after
1st mark is set. Not used in current implementation.
;
; Code for minimum calc::
;
; stored row, col
; set mark1(row,col) = min row,min col
; mark2(row,col) = max row,max col
; ctcols = #cols, ctrows = # rows
;
corners:lxi d,mark1
lxi h,mark2
ldax d ;col 1 = min(col1,col2)
mov b,m
cmp b
jrc ..1 ;cy if 1 < 2
mov m,a ;exchange
mov a,b
stax d
..1: inx h ;row 1...
inx d
ldax d ;row 1 = min(row1,row2)
mov b,m
cmp b
jrc ..2
mov m,a
mov a,b
stax d
..2: ldax d ;row1
sub m ; - row2
cma ; gives (row2 - row1 - 1)
inr a
inr a
sta ctrows
dcx h
dcx d
ldax d
sub m
cma
inr a
inr a
sta ctcols
ret
;
=========================\
.end jjcons
0 + (25*80)/2
;
.ifg DEBUG, [
;
; put c