home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / PROGRAMS / BKGRONDR / BGIIDRV.LBR / K83SCRN.AQM / K83SCRN.ASM
Assembly Source File  |  2000-06-30  |  26KB  |  1,364 lines

  1.     .title    "K83SCRN.ASM Kaypro '83 screen driver 11/8/86"
  2.     .sbttl    "Copyright (c) 1986  Plu*Perfect Systems"
  3.  
  4. .remark \==
  5. Source code for CDL/TDL Z80 assembler (AZM.COM).
  6.  
  7. ; production by:
  8. AZM k83scrn
  9. ZLINK
  10. *k83.com=k83scrn.rel
  11. */locate .prog.=3f80;
  12. *q
  13. ZSID k83.com
  14. m3f80 4500 100
  15. ^C
  16. SAVE 5 k83scrn.drv
  17.  
  18. ==\
  19. ; revision history:
  20. ;
  21. ; v 1.1 no scroll on line 24 in cut
  22. ;    (changes probably too long to include in '84 driver)
  23. ; v 1.0 id imbedded in string, 9/8/86
  24.  
  25. debug = 0
  26.  
  27. .ifg DEBUG, [
  28.     bios =\  'Base of bios = ?'
  29.     ]
  30.  
  31. .remark \===
  32.  
  33. The first sections of code are generic (except for some terminal equates);
  34. beginning at 'STMRKS' it is terminal-specific.
  35.  
  36. Particular features of Kaypro '83 code:
  37.  
  38. 1. The video ram is accessed by bank switching.  Active code, including
  39.    stack must be >= 4000h, and interrupts disabled.
  40. 2. There's no return-cursor function.  We read the screen, send a
  41.    test character, and find the byte that changed.
  42. 3. There's no reverse video, but we create a BLINK attribute to "hilite"
  43.    the cut region by setting bit 7 of the video-ram character.
  44. 4. Cursor-movement sequences are all single-byte control characters.
  45.  
  46. note:    If UNDERSCORE is found at cursor, we convert it to SPACE on
  47.     screen restore.  This isn't good if cursor is sitting on
  48.     a real underscore.
  49. ===\
  50.  
  51. .ifg    DEBUG, [
  52. codloc    =    100h
  53. .phex
  54. .psym
  55. .pabs
  56. consta    =    bios +06h
  57. conin    =    bios +09h
  58. conout    =    bios +0ch
  59.     ]
  60. ;
  61.     [
  62. .prel
  63. .ident    SCRK83
  64.  
  65. consta    =    0
  66. conin    =    0
  67. conout    =    0
  68. outch    =    0
  69. puts    =    0
  70. bwrch    =    0
  71. bflush    =    0
  72.     ]
  73.  
  74. .xlist
  75. .xsym
  76. .sall
  77. ;
  78.  
  79. ; ascii equates
  80. ;
  81. NUL    =    00h
  82. BELL    =    07h
  83. BS    =    08h
  84. CR    =    0dh
  85. LF    =    0ah
  86. ESC    =    1bh
  87. SPACE    =    20h
  88. DEL    =    7fh
  89. ;
  90. ; CUT command characters
  91. ;
  92. HOME    =    'H'        ;home the cursor
  93. LOHOME    =    'h'
  94. MARK    =    'X'        ;set a mark
  95. LOMARK    =    'x'
  96. PASTE    =    'P'-'@'        ;paste region at cursor
  97. CANCEL    =    'C'-'@'        ;cancel cut command
  98. ;
  99. ;
  100. ; TERMINAL-SPECIFIC EQUATES
  101. ;
  102. ; kaypro cursor controls
  103. ;
  104. LEFT    =    08H
  105. RIGHT    =    'L'-'@'
  106. UP    =    'K'-'@'
  107. DOWN    =    0AH
  108. ;
  109. LEFT8    =    82h        ;kaypro raw keypad arrow values...
  110. RIGHT8    =    83h
  111. UP8    =    80h
  112. DOWN8    =    81h
  113. ;
  114. HOMEC    =    1eh        ;home cursor
  115. ;
  116. ; Kaypro '83 screen parameters
  117. ;
  118. NCOLS    =    80
  119. NROWS    =    24
  120. NROW24    =    24        ;# rows excluding status line
  121. ;
  122. SCRSIZ    =    NCOLS*NROWS
  123. ;
  124. ;        
  125. loglin    =    128        ;length of logical screen line
  126. vidram    =    3000h        ;base of video ram
  127. bitprt    =    1ch        ; controller port
  128. ;
  129. .remark \===
  130. Kaypro '83 video ram is laid out as:
  131.  
  132.     24 80-char rows
  133.     each row begins 128 bytes after the previous one
  134. 3000:    row 0
  135. 3080:    row 1
  136. ...
  137.     ===\
  138.  
  139. ;=========================
  140.  
  141. .ifg DEBUG, [
  142.     .loc    codloc
  143.     ]
  144. ;
  145.     [
  146.     .loc    .PROG.
  147.     ]
  148. ;
  149. ;------------------------------------------------------------
  150. ;
  151. ; id sector - nul-terminated string -  at 3f80h
  152. ;
  153. sdid:    .ascii    "Kaypro '83 driver v 1.1"
  154.     db    0            ;NUL terminator
  155. idlen = . - sdid
  156.     ds    80h-idlen        ;total of 80h bytes
  157.  
  158. ;
  159. START:
  160. ;
  161. ;
  162. ; Start of Screen Module.  Assemble to run at 4000h.
  163. ;
  164. ;***** MODULE ENTRY HEADER
  165. ;
  166. ; EXTERNAL ADDRESSES, supplied by loader
  167. ;
  168. jjcons:    jmp    consta        ;bios constat
  169. jjconi:    jmp    conin        ;bios conin
  170. jjouta:    jmp    outch        ;A to conout, preserving bc,de,hl
  171. jjputs:    jmp    puts        ;hl-string to conout, NUL/bit-7 term.
  172.                 ; preserving bc,de,hl
  173. jjbrdc:    jmp    0000        ;buffered read char from cut-swp
  174. jjbwrc:    jmp    bwrch        ;buffered write char to cut-swp
  175. jjbflu:    jmp    bflush        ;flush (write) buffer
  176. ;
  177. ; INTERNAL ENTRY POINTS
  178. ;
  179. savscr:    jmp    savpag        ;save screen 
  180. resscr:    jmp    respag        ;restore saved screen
  181. lastnb:    jmp    lstnbl        ;last non-blank char in rows 1-24
  182. dmpchr:    jmp    retnch        ;return next screen char
  183. dmpcur:    jmp    retncu        ;return buffer cursor
  184. dmpatt:    jmp    retnat        ;return next screen attribute
  185. setmrk:    jmp    stmrks        ;set region marks, move cursor
  186. cutrg:    jmp    docut        ;cut region
  187. pastrg:    jmp    dopast        ;paste region
  188. ininpd:    jmp    ininot        ;initialize notepad
  189. putnpd:    jmp    putnch        ;put char to notepad
  190. ;
  191. ;========================================
  192. ; generic
  193. ;
  194. ININOT:
  195. ;
  196. ; Initiate Notepad - clear screen, print banner.
  197. ;
  198.     lxi    h,Zbanner
  199.     jr    jjputs
  200. ;
  201. ;========================================
  202. ; generic
  203. ;
  204. PUTNCH:
  205. ;
  206. ; Put char in A  to notepad (screen)
  207. ; Convert CR to CRLF, DEL to rubout.
  208. ;
  209.     cpi    CR
  210.     lxi    h,Zcrlf        ;convert CR to CR,LF
  211.     jrz    jjputs
  212.     cpi    DEL
  213.     lxi    h,Zrub
  214.     jrz    jjputs
  215.     jr    jjouta
  216.  
  217. ;========================================
  218. ; generic
  219. ;
  220. RETNCU:
  221. ;
  222. ; Return buffer cursor as row/col.
  223. ;
  224. ; ret: D = binary row, E= binary col
  225. ;      L =  ascii row, H = ascii col (for shld ...)
  226. ;
  227.     lhld    bcursor
  228. ;
  229. ; Convert offset to col/row.
  230. ; exit: D = binary row, E = binary col
  231. ;    H = ascii col,  L = ascii row <-- NOTE ORDER
  232. ;
  233.  
  234. off2cr:    mvi    b,0        ;convert to row,col
  235.     lxi    d,-NCOLS
  236. ..1:    dad    d
  237.     jrnc    ..2
  238.     inr    b        ;row count++
  239.     jr    ..1
  240. ..2:    lxi    d,NCOLS
  241.     dad    d
  242.     mov    a,l        ;col
  243.     mov    e,a        ;binary col in E
  244.     mov    d,b        ;binary row in D
  245.     adi    SPACE        ; + bias
  246.     mov    h,a        ;H = ascii col
  247.     mov    a,b        ;row
  248.     adi    SPACE        ; +bias
  249.     mov    l,a        ;L = ascii row
  250.     ret
  251. ;
  252. ;========================================
  253. ; generic
  254. ;
  255. DOPASTE:
  256. ;
  257. ; Paste the last-cut region onto active screen at the current cursor.
  258. ;
  259. ; 1. Get previously-cut region from external routine
  260. ; 2. Send chars to screen, avoiding boundary overflows. 
  261. ;
  262. ; 'savpag' not needed if terminal supports 'send cursor address'
  263. ;
  264.     call    savpag        ;get current screen,
  265.                 ;in order to find cursor
  266.     mvi    b,4        ;read 4 data bytes
  267. ..0:    push    b
  268.     call    jjbrdc
  269.     pop    b
  270.     djnz    ..0
  271. ;
  272.     mov    b,a        ;4th byte is # rows
  273.     push    b
  274.     call    crs2hl        ;current cursor's row/col to hl
  275.     pop    b
  276. ;
  277. ; loop over rows
  278. ;
  279. ..rowlp:push    b
  280.     push    h
  281.     mov    e,l        ;e = col no.
  282.     push    d
  283.     call    stcrshl        ;set cursor at h,l
  284. ..collp:call    jjbrdc        ;read char from cut-swp
  285.     cpi    CR
  286.     jrz    ..rend
  287.     mov    c,a        ;save char
  288.     pop    d        ;check for off screen
  289.     mov    a,e
  290.     cpi    NCOLS
  291.     inr    e
  292.     push    d        ;row/col to stack
  293.     cc    sendc        ;to conout, unless off edge
  294.     jr    ..collp
  295. ;
  296. ..rend:    pop    d        ;clear row/col
  297.     pop    h
  298.     pop    b
  299.     inr    h        ;bump row
  300.     mov    a,h        ;check for off bottom of screen
  301.     cpi    NROWS
  302.     jrnc    ..xit
  303.     djnz    ..rowlp
  304. ..xit:    xra    a
  305.     ret
  306. ;
  307. ;========================================
  308. ; generic
  309. ;
  310. DOCUT:
  311. ;
  312. ; Cut rectangular region defined by keypresses.
  313. ; 1. Parse keypresses to move cursor and mark corners.
  314. ;    Highlight region as cursor is moved.
  315. ; 2. Send the marked region, row-wise to external routine.
  316. ;    Append CR after each row.
  317. ;
  318. ; Data structure is:
  319. ;    size (word)
  320. ;    # columns (byte)
  321. ;    # rows (byte)
  322. ;    row 1
  323. ;    CR
  324. ;    row 2
  325. ;    CR
  326. ;    ....
  327. ;
  328. .ifg DEBUG, [
  329. ;if debugging, put output in cutbuf
  330.     lxi    h,cutbuf    ;set ptr
  331.     shld    dbgptr
  332.     ]
  333. ;
  334.     xra    a
  335.     sta    mrkcnt        ;init for next time
  336. ;
  337. ;
  338. ; set ctcols = # cols, ctrows = # rows
  339. ; (assumes mark2 is SE of mark1)
  340. ;
  341. corners:lded    mark1
  342.     lhld    mark2
  343.     mov    a,h    ;# rows = 1 + mark2row -mark1row    
  344.     inr    a
  345.     sub    d
  346.     mov    h,a
  347.     mov    a,l    ;# cols = 1 + mark2col -mark1col
  348.     inr    a
  349.     sub    e
  350.     mov    l,a
  351.     shld    ctcols
  352. ;
  353. ; cut rectangle [mark1...mark2]  & copy to buffer
  354. ; append CR at end of each row
  355. ;
  356.     xchg
  357.     push    h        ;mark1
  358.     call    wrpara        ;write parameters
  359.     pop    h        ;mark1
  360.     call    rc2off        ;convert to scr addr
  361.     lda    ctrows        ;get # rows
  362.     mov    b,a
  363. ;
  364. ; write the cut region to external buffer
  365. ;
  366. ..rowlp:push    b        ;(+1
  367.     push    h        ;(+2
  368.     lxi    d,buf        ;fetch from screen buffer
  369.     dad    d
  370. ;
  371. ; write 1 row of cut region to external buffer
  372. ;
  373.     lda    ctcols
  374.     mov    b,a        ;b = # cols
  375. ;
  376. ; write 1 row of cut region to external buffer
  377. ;
  378.     lda    ctcols
  379.     mov    b,a        ;b = # cols
  380. ;
  381. ; buffered write B chars at hl, ascii only
  382. ;
  383. ..bwrt:    push    b
  384.     push    h
  385.     mov    a,m
  386.     cpi    DEL
  387.     jrnc    ..mksp
  388.     cpi    SPACE        ;convert graphics
  389.     jrnc    ..1
  390. ..mksp:    mvi    a,SPACE        ; to space
  391. ..1:    mov    c,a
  392.     call    jjbwrch
  393.     pop    h
  394.     pop    b
  395.     inx    h
  396.     djnz    ..bwrt
  397. ;
  398.     mvi    c,CR        ;append CR to each row
  399.     call    jjbwrch
  400. ;
  401.     pop    h        ;(+1
  402.     pop    b        ;(+0
  403.     lxi    d,NCOLS        ;bump to next row
  404.     dad    d
  405.     djnz    ..rowlp        ; and loop
  406.     jmp    jjbflu        ;flush the write buffer
  407. ;
  408. ;
  409. ; write parameters: size, # cols, # rows to swp file
  410. ; de = ctcols
  411. ;
  412. wrpara:    mov    b,d        ;# rows
  413.     mvi    d,0
  414.     inr    e        ;+1 for CR
  415.     lxi    h,0        ;accum.
  416. ..0:    dad    d
  417.     djnz    ..0
  418.     call    bwhl        ;write word
  419.     lhld    ctcols        ;now #cols, # rows
  420. ;
  421. bwhl:    push    h
  422.     mov    c,l
  423.     call    jjbwrch
  424.     pop    h
  425.     mov    c,h
  426.     jmp    jjbwrch
  427. ;
  428. ;========================================
  429. ; generic
  430. ;
  431. LSTNBL:
  432. ;
  433. ; Find last non-blank line (1-24 only) in current scr buffer.
  434. ; Graphics and 8-bit characters are considered blanks.
  435. ; If B=0ff, save screen first.
  436. ;
  437. ; ret:    H=row, L=col of last non-blank char in rows 1-24
  438. ;
  439.     inr    b
  440.     cz    savpag
  441.     lxi    b,NROW24*100h + NCOLS    ;b=# rows, c=# cols
  442.     lxi    d,buf
  443.     lxi    h,0
  444. ..lp:    ldax    d
  445.     cpi    SPACE+1        ;don't count cntl chars or SPACE
  446.     jrc    ..1
  447.     cpi    DEL        ; or DEL or graphics 8-bit
  448.     jrnc    ..1
  449.     shld    savrc
  450. ..1:    inx    d
  451.     inr    l
  452.     dcr    c
  453.     jrnz    ..lp        ;loop over cols
  454.     inr    h
  455.     mov    l,c        ;0
  456.     mvi    c,NCOLS
  457.     djnz    ..lp        ;loop over rows
  458. savrc = .+1
  459.     lxi    h,0000        ;hl = last non-blank
  460.     ret        
  461.  
  462. ;----------------------------------------
  463. ;
  464. xring:    mvi    c,BELL
  465. ;
  466. ; send C to screen, exit Z, no CY
  467. ;
  468. sendc:    mov    a,c
  469.  
  470. ; send A to screen, exit Z, no CY
  471. ; (this will scroll, however!)
  472. ;
  473. send:    call    jjouta
  474.     xra    a        ;Z, no CY
  475.     ret
  476. ;========================================
  477. ;
  478. ; end of generic code
  479. ;
  480. ;========================================
  481. ; specific
  482. ;
  483. STMRKS:
  484. ;
  485. ; Move cursor and set marks. Return CY clear until exit.
  486. ;
  487. ; 1. move cursor, until:
  488. ; 2. 'X' = set 1st mark
  489. ;    turn on hiliting, set mark, keep cursor at mark
  490. ; 3. move cursor right/down only
  491. ; 4. 'X' = set 2nd mark
  492. ;    turn off hiliting, set 2nd mark
  493. ;    exit CY (done)
  494. ; 5. cntl-C = CANCEL. 
  495. ;    turn off hilighting, set CY, exit
  496. ;
  497. ;
  498.     cpi    CANCEL
  499.     jrz    abort
  500.     cpi    LEFT
  501.     jz    goleft
  502.     cpi    LEFT8
  503.     jz    golef8
  504.     cpi    UP
  505.     jz    goup
  506.     cpi    UP8
  507.     jz    goup8
  508.     cpi    RIGHT
  509.     jz    gort
  510.     cpi    RIGHT8
  511.     jz    gort8
  512.     cpi    DOWN
  513.     jz    godn
  514.     cpi    DOWN8
  515.     jz    godn8
  516.     cpi    HOME
  517.     jrz    gohome
  518.     cpi    LOHOME
  519.     jrz    gohome
  520.     cpi    CR
  521.     jrz    ..mrk
  522.     cpi    MARK
  523.     jrz    ..mrk
  524.     cpi    LOMARK
  525.     jrz    ..mrk
  526.     xra    a        ;no action
  527.     ret
  528. ..mrk:    lxi    h,mrkcnt    ;if no mark yet set
  529.     mov    a,m
  530.     ora    a
  531.     mvi    m,1
  532.     jrz    mk1        ;..set mark1
  533.     call    mk2        ;else set mark2
  534. mrkxit:    xra    a
  535.     sta    mrkcnt        ;init for next time
  536.     stc            ;CY = all done
  537.     ret
  538. ;
  539. abort:    call    normal        ;restore normal video
  540.     mvi    a,CANCEL
  541.     jr    mrkxit
  542. ;
  543. ;-------------------------------------------
  544. ;
  545. ; set 1st mark, turn on rev. video, don't move cursor
  546. ;
  547. mk1:    call    crs2hl
  548.     shld    mark1
  549.     shld    mark2
  550.     shld    curcol        ;L->curcol,H->currow
  551. ;;
  552. ;;kaypro '83 doesn't have attributes, omit:
  553. ;;    push    h
  554. ;;    call    reverse        ;reverse video on (dummy routine)
  555. ;
  556. ;;    pop    h        ;mark1
  557. ;
  558. ; Blink the marked char. Cursor may itself be off, or solid.
  559. ;
  560.     mvi    a,1        ;blink 1 char
  561.     sta    colct
  562.     sta    rowct
  563.     jmp    showro
  564. ;
  565. ; set 2nd mark, restore normal video, set CY
  566. ;
  567. mk2:    call    normal        ;dummy - restore normal video
  568.     stc            ;CY = all done
  569.     ret
  570. ;
  571. ;--------------------------------------------
  572. ;
  573. ; bump row/col  var that tracks actual cursor
  574. ; if mark not yet, send cntl char
  575. ; ret NZ if mark is set
  576. ;
  577. inrsnd:    inr    m        ;next row/col
  578.     call    anymrk
  579.     cz    sendc
  580. ;
  581. ; nz if a mark has been set
  582. ;
  583. anymrk:    lda    mrkcnt
  584.     ora    a
  585.     ret
  586. ;
  587. ; for H19, etc. that use ESC sequences,
  588. ; change these routines to send ESC, then the byte.
  589. ;
  590. gohome:    mvi    c,HOMEC        ;convert to video driver's cntl char
  591.     call    anymrk        ;if mark set,
  592.     jnz    xring        ;..error
  593.     mov    h,a        ;set row=col=0
  594.     mov    l,a
  595.     shld    bincol
  596. jjsndc:    jmp    sendc
  597. ;
  598. ; cursor left and cursor up:
  599. ;    send if not at top or left margin
  600. ;
  601. golef8:    mvi    a,LEFT        ;convert to 7-bit char
  602. ;
  603. goleft:    lxi    h,bincol    ;ck for col ==0
  604. ;
  605. zck:    mov    c,a        ;save char in c
  606.     call    anymrk
  607.     rnz
  608.     cmp    m        ;ck col/row == 0
  609.     jz    xring        ;..error
  610.     dcr    m        ;dcr col/row
  611.     jr    jjsndc
  612. ;
  613. goup8:    mvi    a,UP        ;7-bit code
  614. goup:    lxi    h,binrow    ;ck for top row and send
  615.     jr    zck
  616. ;
  617. ; cursor right and cursor down:
  618. ;    if mark is not set, move cursor
  619. ;    if mark is set, expand region and highlight
  620. ;    keep track of cursor location in both cases
  621. ;    don't move if it would scroll
  622. ;
  623. ; move cursor right
  624. ;
  625. gort8:    mvi    a,RIGHT        ;convert to 7-bit code
  626. ;
  627. gort:    mov    c,a        ;save in c
  628.     lxi    h,bincol
  629.     mvi    a,NCOLS-2
  630.     cmp    m
  631.     jc    xring
  632.     call    inrsnd        ;bump col & send if mrk not set
  633.     rz            ;rtn if mark not yet set
  634. ;
  635. ;  hilite marked column
  636. ;
  637. gort1:    lxi    h,mark2
  638.     inr    m        ;bump 2nd mark-row
  639.     lxi    h,curcol    ;bump col
  640.     inr    m
  641.     mov    l,m
  642.     lda    mark1+1        ;top row
  643.     mov    h,a        ;h=row, l=col for col to hilite
  644. rowct = .+1
  645.     mvi    b,00
  646. ;
  647. ; loop over each row in cut region
  648. ..rlp:    push    b
  649.     push    h        ;save binary row/col
  650.     mvi    a,1        ;display 1 char in each row
  651.     call    showhi
  652.     pop    h
  653.     pop    b
  654.     inr    h        ;next row
  655.     djnz    ..rlp
  656.     lxi    h,colct        ;prepare to bump col cnt & exit
  657.     jr    inrmbs
  658. ;
  659. ; move cursor down
  660. ;
  661. godn8:    mvi    a,DOWN        ;7bit code
  662. godn:    mov    c,a        ;save char
  663.     lxi    h,binrow    ;ck if already on bottom row
  664.     mvi    a,NROWS-2
  665.     cmp    m
  666.     jc    xring
  667.     call    inrsnd         ;bump row & send
  668.     rz            ;rtn if mark not yet set
  669. ;
  670. ;  hilite marked row
  671. ;
  672. godn1:    lxi    h,mark2+1    ;row
  673.     inr    m        ;bump 2nd mark-col
  674.     lxi    h,currow    ;bump row
  675.     inr    m
  676.     mov    h,m
  677.     lda    mark1        ;left col
  678.     mov    l,a        ;h=row, l=col for row to hilite
  679.     call    showro        ;display 1 cut row
  680.     lxi    h,rowct        ;bump row cnt
  681. inrmbs:    inr    m        ; and exit
  682.     ret
  683. ;
  684. ;
  685. .remark \==
  686. For Kaypro '83, write directly to screen,
  687. in order to set blink attribute.
  688.  
  689. if down:    set cur at next row, left col
  690.         send partial row
  691.         rowcnt++
  692.         BS (back up 1)
  693.  
  694. if right:    set cur at toprow, next col
  695.         send partial column
  696.         colcnt++
  697. ==\
  698. ;
  699. ; enter: H = binary row, L= binary col 
  700. ;
  701. showro:
  702. colct = .+1
  703.     mvi    a,00
  704. ;
  705. ; Fetch A chars at H=binary row, L=binary col from buffer.
  706. ; Put chars to screen, setting BLINK attribute.
  707. ;
  708. showhi:    push    psw
  709.     call    stvptr        ;set video ram ptr
  710.     call    rc2off
  711.     lxi    d,buf        ;fetch from screen buffer
  712.     dad    d    
  713.     pop    psw        ;#chars
  714.     mov    b,a
  715. ..lp:    mov    a,m        ;fetch char from buffer
  716.     cpi    SPACE
  717.     jrnz    ..set7
  718.     mvi    a,7fh        ;make displayable 'DEL' char
  719. ..set7:    set    7,a        ;set blink bit
  720.     mov    c,a
  721.     push    h
  722.     call    putv        ;put to screen
  723.     pop    h
  724.     inx    h
  725.     djnz    ..lp
  726.     ora    a        ;clear CY
  727.     ret
  728. ;
  729. ;========================================
  730. ; specific
  731. ;
  732. RETNCH:    
  733. ;
  734. ; Return next screen char from buffer.
  735. ;
  736. ; enter:
  737. ;    d = row, e = col
  738. ;    b = FF ==> read screen
  739. ;    c = FF ==> set bufptr
  740. ; exit:
  741. ;    A = char, CY set if good
  742. ;    DE -> row,col of next char, HL -> buf of next char
  743. ;    CY clear if out of range
  744. ;
  745. ; This routine can be called to get successive chars from
  746. ; buffer as long as caller preserves hl,de and sets b=c=0.
  747. ;
  748.     xra    a
  749.     call    stdump
  750.     rnc
  751.     mov    a,m        ;get char
  752.     inx    h        ;bump bufptr
  753.     ret
  754. ;
  755. ;========================================
  756. ; specific
  757. ;
  758. RETNAT:
  759. ;
  760. ; Return next screen attribute from buffer.
  761. ; THIS IS A NUL FUNCTION for Kaypro '83.
  762. ;
  763. ; enter:
  764. ;    d = row, e = col
  765. ;    b = FF ==> read screen
  766. ;    c = FF ==> set bufptr
  767. ; exit:
  768. ;    A = attr, CY set if good
  769. ;    DE -> row,col of next char, HL -> buf of next char
  770. ;    CY clear if out of range
  771. ;
  772.     xra    a        ;clear CY
  773.     ret
  774. ;
  775. ;--------------------
  776. ;
  777. ; ret:     NC if out of range
  778. ;    else hl-> buffer char
  779. ;
  780. stdump:    inr    b
  781.     jrnz    ..0
  782.     push    b        ;b == 0ff -> read screen
  783.     push    d
  784.     push    h        ;$$$ missing in k84 !!!
  785.     call    savpag
  786.     pop    h
  787.     pop    d
  788.     pop    b
  789. ..0:    inr    c
  790.     jrnz    ..4
  791. ;
  792. ; enter: D = row, E = col
  793. ; set: hl -> buffer address, cy set,    preserve de
  794. ; ret:    CY clear if  error (off screen)
  795. ;
  796. ;conv:
  797.     mov    a,d        ;c == 0ff -> set bufptr 
  798.     cpi    NROWS
  799.     jrnc    ..bad
  800.     mov    a,e
  801.     cpi    NCOLS
  802.     jrc    ..ok
  803. ..bad:    xra    a        ;out of range , ret NC
  804.     ret
  805. ..ok:    lxi    h,buf
  806.     mov    a,d
  807.     lxi    b,NCOLS        ;row*(cols per row)
  808.     inr    a
  809. ..lp:    dcr    a
  810.     jrz    ..2
  811.     dad    b
  812.     jr    ..lp
  813. ..2:    mvi    d,0        ;+ col #
  814.     dad    d
  815. ;
  816. ..4:    inx    d        ;bump col
  817.     mov    a,e
  818.     cpi    NCOLS
  819.     rc
  820.     mvi    e,0        ;end of row, set col = 0
  821.     inr    d        ;and bump row
  822.     mov    a,d    
  823.     cpi    NROWS
  824.     ret            ;NC if out of range
  825. ;
  826. ; Set video-ram pointer.
  827. ; enter: H=binary row, L=binary col
  828. ; set vptr = row*128 + col,     preserves all
  829. ;
  830. stvptr:    push    b
  831.     push    d
  832.     push    h
  833.     mov    b,h
  834.     mov    c,l
  835.     lxi    h,0
  836.     lxi    d,128
  837.     inr    b
  838.     jr    ..bot
  839. ..lp:    dad    d        ;row*128
  840. ..bot:    djnz    ..lp 
  841.     dad    b        ; + col (b=0)
  842.     lxi    b,vidram
  843.     dad    b
  844.     shld    vptr
  845.     pop    h
  846.     pop    d
  847.     pop    b
  848.     ret
  849. ;
  850. ; Initialize for screen save/restore
  851. ; enter: A=0  to save(read) screen
  852. ;     A=NZ to restore (write) screen
  853. ;
  854. iscr:    sta    putflg        ;0=save, 0ff=restore
  855. itop:    lxi    h,buf        ;init buf ptr
  856.     shld    cptr
  857.     lxi    h,vidram    ;int video ram ptr
  858.     shld    vptr
  859.     ret
  860.  
  861. vptr:    dw    0        ;ptr to video ram char
  862. ;
  863. ;========================================
  864. ; specific
  865. ;
  866. SAVPAG:
  867. ;
  868. ; Save screen to buffer.
  869. ;
  870.     xra    a        ;initialize for reading screen
  871.     call    iscr
  872.     call    doscr        ;save screen first
  873.     call    crs2off        ;THEN find screen cursor
  874.     shld    bcursor        ;and save it
  875.     call    off2cr
  876.     sded    bincol        ;save binary col/row
  877.     ret
  878. ;
  879. ;--------------------
  880. ;
  881. doscr:    lxi    b,SCRSIZ
  882. ..0:    push    b
  883.     call    vch        ;r/w char
  884.     pop    b
  885.     inx    d        ;bump ptr        USED??
  886.     dcx    b
  887.     mov    a,b
  888.     ora    c
  889.     jrnz    ..0
  890.     ret
  891. ;
  892. ;========================================
  893. ; specific
  894. ;
  895. RESPAG:
  896. ;
  897. ; Restore saved screen from buffer.
  898. ;
  899. ; Note: this sequence is necessary to be sure that the
  900. ; char in the hardware cursor register isn't written back
  901. ; to video ram after the new character has been put there.
  902.  
  903.     lhld    bcursor        ;set the new cursor position FIRST
  904.     push    h
  905.     call    stcrs
  906.     mvi    a,0ffh        ;initialize for writing screen
  907.     call    iscr
  908.     call    doscr        ;put buffer to screen
  909.     pop    h        ;get cursor offset
  910.     push    h
  911.     lxi    d,buf        ;get char at the cursor
  912.     dad    d
  913.     mov    a,m
  914.     call    jjouta        ;send it via conout
  915.     pop    h        ;reset the cursor
  916. ;
  917. ; Set cursor on screen by direct cursor addressing.
  918. ; enter: HL = cursor offset relative to 0000
  919. ;    
  920. stcrs:    call    off2cr        ;convert from offset to ascii col/row
  921. stcoro:    shld    colrow        ;put ascii col/row into string
  922.     lxi    h,Zcurs        ;send set-cursor string
  923.     jmp    jjputs
  924. ;
  925. ; Set cursor on screen.
  926. ; enter: H=binary row, L = binary col
  927. ;
  928. stcrshl:call    rc2off
  929.     jr    stcrs
  930. ;
  931. ;--------------------
  932. ;
  933. ; CONVERSION ROUTINES
  934. ;
  935. ; Get current cursor position to H=binary row, L=binary col
  936. ;
  937. crs2hl:    call    crs2off        ;get cursor by re-read of screen
  938.     call    off2cr        ;returns binary in de
  939.     xchg
  940.     ret
  941. ;
  942. ; convert H=binary row, L=binary col to hl= offset
  943. ; (hl =  row*NCOLS + col)
  944. ; uses bc,de,hl
  945. ;
  946. ; note fix from 'convhl' in k84 version !!
  947. ;
  948. rc2off:    mov    b,h        ;b=row
  949.     mov    c,l        ;c=col
  950.     lxi    h,0
  951.     inr    b
  952.     lxi    d,NCOLS
  953.     jr    ..bot
  954. ..0:    dad    d        ;rows*NCOLS
  955. ..bot:    djnz    ..0
  956.     dad    b        ;+ col
  957.     ret
  958. ;
  959. ;
  960. ; Get current screen cursor.
  961. ; ret: HL= binary offset from 0000.
  962. ;
  963. ; (Screen must already be saved into buffer).
  964. ; Send a test char via conout.  Read screen and find mismatch.
  965. ;
  966. T1CHAR    =    07Eh
  967. T2CHAR    =    07Dh
  968.  
  969. crs2off:
  970.     lxi    h,0        ;init duplicate count FIRST
  971.     shld    dupcnt
  972. ; Send a test char to the screen.  If the testchar happens to be the
  973. ; char at the cursor, bump dupcnt and repeat the loop.  Sending
  974. ; the char again puts it at cursor+1.  Repeat until there's a mismatch.
  975. ; By testing the final screen char, we ensure a mismatch will be found.
  976. ;
  977. ..nxtc:    lda    buf+SCRSIZ-1    ;set test char so it is != last char
  978.     ani    7Fh        ;kill cursor bit
  979.     cpi    T1CHAR        ; on screen
  980.     mvi    a,T1CHAR
  981.     jrnz    ..1
  982.     mvi    a,T2CHAR
  983. ..1:    sta    tstchr        ;send test char to screen at cursor
  984.     call    jjouta
  985. ;
  986.     call    itop
  987.     lxi    b,SCRSIZ
  988. ..lp:    push    b
  989.     lhld    vptr
  990.     shld    orighl
  991.     call    getv        ;get screen char to C
  992.     lhld    cptr        ;compare to buffer char
  993.     mov    a,m
  994.     sta    origc
  995.     shld    origbf
  996.     sub    c        ;hi bit has been killed
  997.     inx    h
  998.     shld    cptr
  999.     pop    b
  1000.     jrz    ..same
  1001.     adi    (7Fh-SPACE)    ;check for space converted to blink-DEL
  1002.     jrnz    ..fnd
  1003. ..same:    dcx    b
  1004.     mov    a,b
  1005.     ora    c
  1006.     jrnz    ..lp
  1007. ;
  1008. ; have a duplicate of testchar at current cursor
  1009.     lhld    dupcnt
  1010.     inx    h
  1011.     shld    dupcnt
  1012.     jr    ..nxtc
  1013. ;
  1014. ; cursor found by mismatch of buffer char, testchar
  1015. ;
  1016. ..fnd:    lxi    h,SCRSIZ    ;offset = scrsize-countleft
  1017.     ora    a
  1018.     dsbc    b
  1019.     lded    dupcnt        ;adjust for any duplicates
  1020.     ora    a
  1021.     dsbc    d        ;count - dupcnt
  1022. ..ok:    push    h        ;save offset to cursor loc.
  1023.  
  1024. origc = .+1
  1025.     mvi    a,00        ;restore original char
  1026.     res    7,a
  1027.     cpi    '_'        ;in case we picked up the cursor
  1028.     jrnz    ..2        ; at a space, put it back to space
  1029.     mvi    a,SPACE        ;(not foolproof)
  1030. ..2:    mov    c,a
  1031. origbf = .+1
  1032.     lxi    h,0000        ;and correct buffer value too
  1033.     mov    m,a
  1034. orighl = .+1
  1035.     lxi    h,0000        ;to screen
  1036.     call    putvhl
  1037.     pop    h
  1038.     push    h
  1039.     call    stcrs        ;put cursor back on screen
  1040.     pop    h
  1041.     ret            ;hl =cursor offset from 0000
  1042. ;
  1043. tstchr:    db    0        ;test char to find cursor
  1044. dupcnt:    dw    0        ;# of duplicates of test char at cursor
  1045. ;
  1046. ;--------------------
  1047. ;
  1048. ; putflg = 0:  read 1 char from screen, put into buffer
  1049. ; putflg = NZ: get 1 char from buffer, write to screen
  1050. ; ret:    c = char, if putflg != 0        ; uses A, HL
  1051. ;
  1052. vch:    lda    putflg
  1053.     ora    a
  1054.     jrnz    ..put
  1055. ;
  1056. ..get:    call    getv        ;get from video ram
  1057.     lhld    cptr        ;put into buffer
  1058.     mov    m,c
  1059.     inx    h
  1060.     shld    cptr
  1061.     ret
  1062. ;
  1063. ..put:    lhld    cptr        ;get char from buffer
  1064.     mov    c,m        ; to C
  1065.     res    7,c        ;kill any cursor bit
  1066.     inx    h
  1067.     shld    cptr
  1068. ;
  1069. putv:    lhld    vptr
  1070. putvhl:    in    bitprt        ;get port byte
  1071.     ori    80h        ;set for bank 1
  1072.     di            ;prevent interruption
  1073.     out    bitprt        ;switch to bank 1
  1074.     mov    m,c        ;put char in C into video ram
  1075. putv1:    ani    7fh        ;switch bank 0 back in
  1076.     out    bitprt
  1077.     ei
  1078. ;
  1079. ; Set pointer to next video ram char, adjusting for gap
  1080. ; at end of each line.
  1081. ;
  1082. ..bmpv:    inx    h
  1083.     mov    a,l
  1084.     cpi    80
  1085.     jrz    ..adj
  1086.     cpi    128+80
  1087.     jrnz    ..sh
  1088. ..adj:    adi    128-80
  1089.     mov    l,a
  1090.     jrnc    ..sh
  1091.     inr    h
  1092. ..sh:    shld    vptr
  1093.     ret
  1094. ;
  1095. getv:    lhld    vptr
  1096.     in    bitprt        ;get port byte
  1097.     ori    80h        ;set for bank 1
  1098.     di            ;prevent interruption
  1099.     out    bitprt        ;switch to bank 1
  1100.     mov    c,m        ;get char from video ram
  1101.     res    7,c        ;kill blinking
  1102.     jr    putv1
  1103. ;
  1104. ;******************************************
  1105. ;
  1106. ; DATA AREA
  1107. ;
  1108. putflg:    db    0        ;NZ to restore(put) screen from buf
  1109. cptr:    dw    0        ;char ptr
  1110. ;
  1111. ; cut-region data
  1112. ;
  1113. ctcols:db    0    ;# cols in cut region (excl. CR), A PAIR
  1114. ctrows:db    0    ;# rows
  1115.  
  1116. ;
  1117. ; mark-region data
  1118. ;
  1119. mrkcnt:    db    0
  1120. curcol:    db    0        ;a pair
  1121. currow:    db    0
  1122. mark1:    dw    0        ;binary row,col of upperleft mark
  1123. mark2:    dw    0        ;lower right mark
  1124. bincol:    db    0        ;a pair
  1125. binrow:    db    0
  1126. ;
  1127. Zrub:    db    BS,SPACE,BS+80H    ;rub-out previous char
  1128. ;
  1129. ;****************************************
  1130. ;
  1131. ;  TERMINAL-SPECIFIC data
  1132. ;
  1133. ; dummy routines - no attrributes for Kaypro '83
  1134. ;
  1135. normal:    
  1136. reverse:
  1137.     RET
  1138.  
  1139. ;
  1140. ; Kaypro '83 video strings
  1141. ;
  1142. Zcurs:    .ascii    [1bh]'='    ;set cursor to
  1143. colrow:    db    SPACE,SPACE    ; row,col - modified in-line
  1144.     db    NUL        ;must have following NUL
  1145. ;
  1146. .ifg DEBUG, [ 
  1147. Zclr:    db    1Ah,NUL        ;kaypro
  1148.     ]
  1149. ;
  1150. ;================================
  1151. ;
  1152. ; JOTPAD BANNER - just 2 lines' worth
  1153. ;
  1154. ; 1. Clear screen.
  1155. ; 2. Remind user of usage, to extent space is available.
  1156. ;    The editing keys are those supported by the terminal itself.
  1157. ;
  1158. Zbanner:
  1159.     db    1ah        ;clear screen KAYPRO-SPECIFIC
  1160. ;
  1161. .ascii    'JOT: <SUSPEND> = exit,  ^Paste'
  1162.     db    CR,LF
  1163. .ascii    '^X = del. rest of line, ESC E = ins. line, '    ;43
  1164. .ascii    'ESC R = del. line'                ;17
  1165. ;
  1166. ; NO ROOM FOR THIS !
  1167. ; if turborom-->
  1168. ;.ascii    'Cntl-A = insert char.  Cntl-B = delete char.         '
  1169. ;
  1170. Zcrlf:    db    CR,LF+80h
  1171.  
  1172. ;
  1173. .slist
  1174. .list
  1175. codlen = .-start        ;length of code
  1176. .rlist
  1177. ;
  1178. ;++++++++++++++++++++++++++++++
  1179. .remark \==
  1180. Debugging stragegy:
  1181.     Assemble screendriver at 100h.
  1182.     Load with Z80 debugger.
  1183.     Clear ram buffers.
  1184.     Set breakpoints as needed.
  1185.     Call these test routines and inspect buffers.
  1186. ==\
  1187.  
  1188. .ifg DEBUG, [
  1189. dbg0 = .
  1190. ;
  1191. ; these emulate the external BGii routines
  1192. ; using ram buffers for debugging
  1193. ;
  1194. bwrch:    push    h
  1195.     lhld    dbgptr        ;put to debug cut buffer
  1196.     mov    m,c
  1197.     inx    h
  1198.     shld    dbgptr
  1199.     pop    h
  1200.     ret
  1201. ;
  1202. bflush:    ret
  1203. ;
  1204.  
  1205. ;bios display-a-string
  1206. ;    nul/8-bit terminated string at hl
  1207. ;    preserves bc,de,hl
  1208. ;
  1209. puts:    push    h    ;save hl, outch save bc,de
  1210. ..0:    mov    a,m
  1211.     rlc
  1212.     srlr    a    ;shift right logical (register) A
  1213.     inx    h
  1214.     jrz    ..1
  1215.     push    psw
  1216.     call    outch
  1217.     pop    psw
  1218.     jrnc    ..0
  1219. ..1:    pop    h
  1220.     ret
  1221. ;
  1222. ; char in A to conout, preserve bc,de,hl 
  1223. ;
  1224.  
  1225. outch:    push    b
  1226.     push    d
  1227.     push    h
  1228.     mov    c,a
  1229.     call    conout
  1230.     pop    h
  1231.     pop    d
  1232.     pop    b
  1233.     ret
  1234. ;
  1235. ; Various routines for debugging in ram.
  1236. ;
  1237. TSTACK = 05000h        ;test stack, above bank-switching
  1238.  
  1239. tdump:    lxi    b,0ffffh    ;fetch scr, set ptr
  1240.     lxi    d,0        ;from row 0,col 0
  1241.     call    dmpchr
  1242. ;
  1243. tdump2:    lxi    b,0
  1244.     call    dmpchr
  1245. ;
  1246. tdump3:    lxi    d,100h + 0
  1247.     lxi    b,00ffh
  1248.     call    dmpchr
  1249. ;
  1250. tdump4:    lxi    d,3000h        ;out of range test
  1251.     lxi    b,00ffh
  1252.     call    dmpchr
  1253.     rst    7
  1254. ;
  1255. ;
  1256. clear:    lxi    h,Zclr        ;clear screen
  1257.     call    jjputs
  1258.     rst    7
  1259. ;
  1260. flood:    lxi    h,Zflood    ;write to screen
  1261.     call    jjputs
  1262.     rst    7
  1263. Zflood:    .ascii    '=======TESTING======='
  1264.     db    0
  1265. ;
  1266. tsave:    lxi    sp,TSTACK    ;save screen
  1267.     call    savscr
  1268.     rst    7
  1269.  
  1270. trest:    lxi    sp,TSTACK    ;restore screen
  1271.     call    resscr
  1272.     rst    7
  1273.  
  1274. tmark:    lxi    sp,TSTACK    ;set a mark
  1275.     call    savscr
  1276.     call    sttop        ;so debugger doesn't scroll screen
  1277. ..0:    call    conin
  1278.     call    setmrk
  1279.     jnc    ..0
  1280. ;    rst    7
  1281.     nop
  1282. ;
  1283. tcut:    lxi    h,cutbuf        ;clear buffer
  1284.     mvi    m,0
  1285.     lxi    d,cutbuf+1
  1286.     lxi    b,2*80h
  1287.     ldir
  1288.     call    cutrg            ;cut region
  1289.     call    setbot            ;put cursor out of way
  1290.     rst    7
  1291.  
  1292. ; place cursor nerar bottom or top
  1293. ;
  1294. setbot:    lxi    h,100h*(20h+18) +20h
  1295.     jr    sttop1
  1296. sttop:    lxi    h,2020h
  1297. sttop1:    shld    colrow
  1298.     lxi    h,Zcurs        ;send set-cursor string
  1299.     jmp    jjputs
  1300. ;
  1301. dbgptr:    dw    0
  1302. .slist
  1303. .list
  1304. dbglen = . - dbg0
  1305. .rlist
  1306.     ]
  1307. ;++++++++++++++++++++++++++++++
  1308. ;
  1309. .list
  1310.  
  1311. ; SCREEN BUFFER STRUCTURE
  1312. ;
  1313. ; The rest of the 4K block is available
  1314. ; for the screen image and other data.
  1315.  
  1316. xbreq    =    2 + NROWS*NCOLS
  1317. ;
  1318.  
  1319. .ifg    DEBUG, [
  1320. ;
  1321. ; put buffer on even byte ( for attributes)
  1322. bstart    =    start + 800h    ;make some room
  1323.     ]
  1324. ;
  1325.     [
  1326. ; put buffer at end of 4K area, to just fit
  1327. bstart    =    (start + 400h) + (3*400h-xbreq)
  1328.  
  1329. short =    start+codlen-bstart
  1330. xfree = - short
  1331.  
  1332. .ifg (short), [
  1333.     .prntx    '[07]Code overflows buffer!'
  1334.     ]
  1335.  
  1336.     ]
  1337.  
  1338. ;
  1339. ; addresses:
  1340. ;
  1341. bcursor =    bstart        ;cursor location in saved screen
  1342. buf    =    bcursor+2    ;start of screen buffer
  1343. ;
  1344. ;buffer uses (24 lines x 80 chars)
  1345. ;
  1346. bufend    =    buf + NROWS*NCOLS
  1347.                     
  1348. ;
  1349. .ifg DEBUG, [
  1350. ;
  1351. ; put cutbuffer in ram for debugging
  1352. ;
  1353. datcut    =    bstart+10h+3*400h
  1354. cutbuf    =    datcut
  1355.     ]
  1356.  
  1357. .xlist
  1358.     .end    jjcons
  1359. xi    h,100h*(20h+18) +20h
  1360.     jr    sttop1
  1361. sttop:    lxi    h,2020h
  1362. sttop1:    shld    c