home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / screen / hercules.arc / GCHAR.ASM next >
Encoding:
Assembly Source File  |  1986-09-05  |  13.5 KB  |  530 lines

  1. ;********************************************************************
  2. ;*
  3. ;*    GRAPHIC CHARACTER HANDLING
  4. ;*
  5. ;*        Dave Tutelman - 8/86
  6. ;*
  7. ;*-------------------------------------------------------------------
  8. ;*
  9. ;*    Fn 6    Scroll up - not yet implemented
  10. ;*    Fn 7    Scroll down - not yet implemented
  11. ;*    Fn 9    Write character with attribute
  12. ;*    Fn 10    Write character normal
  13. ;*    Fn 14    Write character Teletypewriter style
  14. ;*
  15. ;*    Also includes subroutines to:
  16. ;*    get_address    convert page/row/col to display address
  17. ;*    do_char        write a character to an address on display
  18. ;*    do_attrib    change a display address to some attribute
  19. ;*    full_screen_scroll    used by Fn 14, when it needs to scroll
  20. ;*    flash        momentarily flash to reverse video and back
  21. ;*
  22. ;********************************************************************
  23. ;
  24. INCLUDE    hercbios.h
  25.  
  26. ;-----------------------------------------------
  27. extrn    exit_herc_bios:near
  28. public    writechar,scroll_up,scroll_down,tty
  29. public    scr_start,scr_length,num_rows
  30. ;------------------------------------
  31. cseg    segment    public
  32.     assume    cs:cseg,ds:bios_data
  33. ;
  34.  
  35. ;**************************************************************
  36. ;*
  37. ;*    FUNCTION 6 & 7 - SCROLL UP & DOWN
  38. ;*    (Placeholder only - not yet implemented)
  39. ;*
  40. ;*    AL = Number of rows to scroll (if 0, blank scroll area)
  41. ;*    BH = Fill attribute (we ignore, since writechar destroys old attrib)
  42. ;*    CX = Upper left corner      (CH=row, CL=col)
  43. ;*    DX = Lower right corner     (DH=row, DL=col)
  44. ;*
  45. ;****************************************************************
  46. ;
  47. scroll_up:
  48. scroll_down:
  49. ;
  50.     jmp    exit_herc_bios
  51. page
  52. ;********************************************************************
  53. ;*
  54. ;*    FUNCTION 9 & 10 - WRITE A CHARACTER AT CURRENT CURSOR
  55. ;*
  56. ;*    AL = character code to be written
  57. ;*    AH = 9 (write char with attribute) or 10 (write char normal)
  58. ;*    BL = new attribute (limited selection in graphics mode)
  59. ;*    BH = display page number
  60. ;*    CX = count of how many characters to write
  61. ;*
  62. ;********************************************************************
  63. ;
  64. writechar:    
  65. ;            ; Get the address corresponding to cursor[page]
  66.     push    bx
  67.     mov    bl,bh        ; page to BX
  68.     xor    bh,bh
  69.     shl    bx,1        ; *2 for word pointer
  70.     mov    dx,curs_pos[bx]    ; appropriate cursor position to DX
  71.     pop    bx
  72.     call    get_address    ; get display address in DI
  73. ;
  74. wrchar_loop:
  75. ;            ; Write a character to that address
  76.     call    do_char        ; arguments set up already
  77. ;
  78. ;            ; If function 9, modify the character's attributes
  79.     cmp    ah,9        ; Function 9?
  80.     jne    no_attrib    ; no, don't do attributes
  81.     call    do_attrib    ; yes, and arguments already set up
  82. no_attrib:
  83. ;
  84.     inc    di        ; move to next position, without moving
  85.                 ;    the official cursor
  86.     loop    wrchar_loop    ; continue until CX count exhausted
  87.     jmp    exit_herc_bios
  88. page
  89. ;*****************************************************************
  90. ;*
  91. ;*    FUNCTION 14 - TELETYPEWRITER-STYLE CHARACTER WRITE
  92. ;*
  93. ;*    AL = Character to be written
  94. ;*
  95. ;******************************************************************
  96. ;
  97. tty:
  98.     assume    ds:bios_data
  99.     mov    bl,active_page    ; active page to BX
  100.     xor    bh,bh
  101.     mov    dx,curs_pos[bx]    ; get cursor for active page
  102.     push    bx
  103.     mov    bh,bl        ; move page to BH
  104.     call    get_address    ; address of character to DI
  105.     pop    bx
  106. ;
  107. ;            ; process the character
  108. ;            ; check if CR
  109.     cmp    al,13        ; carriage return?
  110.     jne    not_cr
  111.     mov    dl,0        ; go to first column
  112.     jmp    fix_curs
  113. ;            ; check if LF
  114. not_cr:    cmp    al,10        ; line feed?
  115.     jne    not_lf
  116.     inc    dh        ; next line
  117.     jmp    fix_curs
  118. ;            ; check if BS
  119. not_lf:    cmp    al,8        ; backspace?
  120.     jne    not_bs
  121.     cmp    dl,0        ; already first column?
  122.     je    fix_curs    ; yup. do nothing
  123.     dec    dl        ; nope. move cursor left one
  124.     dec    di        ; also move address pointer left one
  125.     mov    al,32        ; set character to space
  126.     call    do_char        ; and write the space, but don't move
  127.     jmp    fix_curs
  128. ;            ; check if BEL
  129. not_bs:    cmp    al,7        ; bell character?
  130.     jne    not_bl
  131.     pop    es        ; restore registers
  132.     pop    di
  133.     pop    si
  134.     pop    dx
  135.     pop    cx
  136.     pop    bx
  137.     pop    ds
  138.     jmp    vid_bios    ; ... and use the normal BIOS to ring the bell
  139. ;    call    flash        ; can't do BEL standard. Blink display instead
  140. ;    jmp    fix_curs
  141. ;            ; ordinary printing character, so display it
  142. not_bl:    call    do_char        ; write it to screen
  143.     inc    dl        ; cursor one to the right
  144. ;
  145. ;            ; now look at the cursor, do what's necessary to
  146. ;            ; fix it up, and save it away.
  147. fix_curs:
  148.     cmp    dl,89        ; beyond last column?
  149.     jle    chk_scroll    ; not yet
  150.     xor    dl,dl        ; yes. do a CR
  151.     inc    dh        ; ... and a LF
  152. chk_scroll:
  153.     cmp    dh,cs:num_rows    ; now see if we're beyond last row?
  154.     jl    exit_tty    ; not yet
  155.     call    full_screen_scroll
  156.                 ; yes. Scroll the screen up one
  157.     dec    dh        ; ... and scroll cursor, too.
  158.     jmp    chk_scroll
  159. ;
  160. exit_tty:
  161.     mov    curs_pos[bx],dx    ; save cursor position
  162.     jmp    exit_herc_bios
  163. page
  164. ;--------------------------------------------------------------------
  165. ;
  166. ;    GET_ADDRESS  SUBROUTINE
  167. ;
  168. ;    BH = display page
  169. ;    DX = cursor position (DH=row, DL=col)
  170. ;
  171. ;    returns:
  172. ;    DI = displacement of top row of pixels
  173. ;
  174. ;--------------------------------------------------------------------
  175. ;
  176. get_address:
  177.     push    cx        ; save it
  178.  
  179. ;            ; compute display address from cursor_pos
  180.     mov    cl,dh        ; get row # in cx
  181.     xor    ch,ch
  182.     shl    cx,1        ; begin fast multiply by 90 (1011010 B)
  183.     mov    di,cx
  184.     shl    cx,1
  185.     shl    cx,1
  186.     add    di,cx
  187.     shl    cx,1
  188.     add    di,cx
  189.     shl    cx,1
  190.     shl    cx,1
  191.     add    di,cx        ; end fast multiply by 90
  192.     mov    cx,di        ; copy answer back to cx
  193.     shl    di,1        ; *2 for ibm graphics mode
  194.     cmp    video_mode,herc_mode
  195.     jne    ibm_ad        ; not herc mode
  196.     add    di,cx        ; *3 for herc mode
  197. ibm_ad:    xor    ch,ch        ; columns in CX
  198.     mov    cl,dl
  199.     add    di,cx        ; add in col. address in DI
  200.     cmp    bh,0        ; if page 1, set high-order bit of address
  201.     je    pg0
  202.     or    di,8000H
  203. pg0:
  204. ;            ; address now in DI
  205. ;
  206.     pop    cx        ; restore it
  207.     ret
  208. page
  209. ;--------------------------------------------------------------------
  210. ;
  211. ;    DO_CHAR  SUBROUTINE
  212. ;
  213. ;    AL = character to write
  214. ;    DI = diplacement (address) of top row of pixels
  215. ;
  216. ;    Note: SI and ES are destroyed
  217. ;
  218. ;--------------------------------------------------------------------
  219. ;
  220. do_char:
  221.     push    ax
  222.     push    bx
  223.     push    cx
  224.     push    di
  225.     push    ds
  226. ;
  227. ;            ; get scan pattern table pointer into BX
  228.     cmp    video_mode,herc_mode
  229.     je    herc_1
  230.     mov    bx,offset ibm_pattern
  231.                 ; IBM graphics mode - use appropriate table
  232.     jmp    c_1
  233. herc_1:    mov    bx,offset herc_pattern
  234.                 ; herc graphics mode - use appropriate table
  235. c_1:
  236. ;
  237. ;            ; set up source address registers
  238.     xor    ah,ah        ; character to SI
  239.     mov    si,ax
  240. IFDEF iAPX286
  241.     shl    si,3        ; *8 for 8-byte table entry
  242. ELSE
  243.     shl    si,1        ; *8 for 8-byte table entry
  244.     shl    si,1
  245.     shl    si,1
  246. ENDIF
  247.                 ; next, find beginning of table
  248.     cmp    al,7Fh        ; ROM or user table?
  249.     jg    u_tbl
  250.                 ; ROM table
  251.     add    si,charbase    ; character table base added to offset
  252.     mov    ax,mpx_bios    ; BIOS code segment to DS
  253.     mov    ds,ax
  254.     jmp    c_2
  255. u_tbl:                ; user table
  256.     xor    ax,ax        ; zero (interrupt vector) to DS
  257.     mov    ds,ax
  258.     mov    ax,si        ; save table offset in AX
  259.     assume    ds:intvec
  260.     lds    si,user_table    ; load DS:SI from interrupt vector
  261.     add    si,ax        ; add offset into table base
  262. c_2:
  263. ;
  264. ;            ; set up destination address registers
  265.     mov    ax,pixbase    ; get display segment in ES
  266.     mov    es,ax
  267.                 ; displacement already in DI
  268. ;
  269. ;
  270. ;            ; transfer the character
  271.     mov    ax,di        ; save top-row displacement in AX
  272.     mov    cx,8        ; transfer 8 rows
  273.     cld            ; direction = up
  274. c_loop:    mov    di,ax        ; top-row displacement
  275.     add    di,cs:[bx]    ; add entry from scan-pattern table
  276.     movsb            ; actually transfer a byte and bump SI & DI
  277.     add    bx,2        ; next entry in scan-pattern table
  278.     loop    c_loop
  279. ;
  280. ;            ; if hercules mode, blank the extra rows
  281.     pop    ds        ; restore DS to Bios data
  282.     assume    ds:bios_data
  283.     cmp    video_mode,herc_mode
  284.     jne    c_3
  285.                 ; Hercules mode
  286.     mov    si,ax        ; don't need SI. Save top-row displacement
  287.     xor    ax,ax        ; zero AX
  288.     mov    cx,4        ; four rows to blank
  289.     cld
  290. c_blnk: mov    di,si        ; top-row displacement
  291.     add    di,cs:[bx]    ; add entry from scan-pattern table
  292.     stosb            ; transfer a zero byte
  293.     add    bx,2        ; next entry in scan-pattern table
  294.     loop    c_blnk
  295. c_3:
  296. ;
  297. ;            ; clean up and return
  298.     pop    di
  299.     pop    cx
  300.     pop    bx
  301.     pop    ax
  302.     ret
  303. page
  304. ;---------------------------------------------------------------------
  305. ;
  306. ;    DO_ATTRIB  SUBROUTINE
  307. ;
  308. ;    BL = attribute byte
  309. ;    DI = displacement (address) of top row of pixels
  310. ;    ES is destroyed
  311. ;
  312. ;    Because attributes don't "just happen" in graphics mode, here's
  313. ;    what we have to transform them to.
  314. ;
  315. ;    CODE    USUALLY MEANS        IBM MODE    HERC MODE
  316. ;    00    invisible        invisible    invisible
  317. ;    01    underline        [normal]    underline
  318. ;    07    normal            normal        normal
  319. ;    0F    hi-intens        [rev video]    [rev video]
  320. ;    70    rev video        rev video    rev video
  321. ;
  322. ;    Anything else displays as normal
  323. ;    Note that there's no way to make blinking happen.
  324. ;
  325. ;-----------------------------------------------------------------------
  326. ;
  327. do_attrib:
  328.     assume    ds:bios_data
  329.     push    ax
  330.     mov    ax,pixbase    ; Display base to ES
  331.     mov    es,ax
  332.     pop    ax
  333. ;
  334. ;            ; which attribute, if any?
  335.     and    bl,7Fh        ; mask off blink bit
  336.     cmp    bl,0        ; invisible?
  337.     je    invisible
  338.     cmp    bl,0Fh        ; reverse video? (instead of bright)
  339.     je    reverse
  340.     cmp    bl,70H        ; reverse video?
  341.     je    reverse
  342.     cmp    bl,01        ; underline?
  343.     je    underline
  344.     ret            ; none of the above. Display normal.
  345. ;
  346. ;            ; underline the character
  347. underline:
  348.     cmp    video_mode,herc_mode
  349.     je    ul_1
  350.     ret            ; don't do it for IBM mode
  351. ul_1:    mov    byte ptr es:[di+40B4h],0FFh
  352.                 ; move ones to 11th line of pixel array
  353.                 ; 40B4h is the 11th entry in herc_pattern
  354.     ret
  355. ;
  356. ;            ; make it invisible
  357. invisible:
  358.     push    ax
  359.     push    bx
  360.     push    cx
  361.     push    dx
  362.     xor    ax,ax        ; zero the AX
  363.     cmp    video_mode,herc_mode
  364.     je    herc_3
  365.     mov    bx,offset ibm_pattern
  366.                 ; point to scan pattern
  367.     jmp    inv_1
  368. herc_3:    mov    bx,offset herc_pattern
  369.                 ; point to scan pattern
  370. inv_1:    mov    dx,di        ; save addr of top row of pixels in DX
  371.     mov    cx,8        ; 8 bytes to be moved
  372.     cld            ; direction = up
  373. invis_loop:
  374.     mov    di,dx        ; top row address
  375.     add    di,cs:[bx]    ; add scan-table offset
  376.     stosb            ; move a zero byte
  377.     add    bx,2        ; bump the scan-table pointer
  378.     loop    invis_loop
  379.     pop    dx
  380.     pop    cx
  381.     pop    bx
  382.     pop     ax
  383.     ret
  384. ;
  385. ;            ; reverse video
  386. reverse:
  387.     push    bx
  388.     push    cx
  389.     push    dx
  390.     cmp    video_mode,herc_mode
  391.     je    herc_4
  392.     mov    bx,offset ibm_pattern
  393.                 ; point to scan pattern
  394.     mov    cx,8        ; 8 scan lines for IBM mode
  395.     jmp    rev_1
  396. herc_4:    mov    bx,offset herc_pattern
  397.                 ; point to scan pattern
  398.     mov    cx,12        ; 12 scan lines for Hercules mode
  399. rev_1:    mov    dx,di        ; save addr of top row of pixels in DX
  400.     cld            ; direction = up
  401. rev_loop:
  402.     mov    di,dx        ; top row address
  403.     add    di,cs:[bx]    ; add scan-table offset
  404.     not    es:byte ptr[di]    ; invert one scan line
  405.     add    bx,2        ; bump the scan-table pointer
  406.     loop    rev_loop
  407.     pop    dx
  408.     pop    cx
  409.     pop    bx
  410.     ret
  411. page
  412. ;--------------------------------------------------------------
  413. ;
  414. ;    SUBROUTINE  FULL_SCREEN_SCROLL
  415. ;
  416. ;    This scrolls the entire screen up one print line (8 or 12 pixels).
  417. ;    Actually, we'll protect one line on the bottom (e.g.-function keys).
  418. ;
  419. ;-----------------------------------------------------------------
  420. ;
  421. ;            ; A few constants, initialized by set_mode
  422. num_rows    db    ?    ; number of rows in display
  423.                 ;   = 42 (IBM)  or 28 (Herc)
  424. scr_start    dw    ?    ; 2*90 or 3*90 depending on mode
  425. scr_length    dw    ?    ; number of words to transfer in a sweep
  426.                 ;   = 41*start /2 = 3690    (IBM)
  427.                 ;   = 27*start /2 = 3645    (Herc)
  428. ;
  429. full_screen_scroll:
  430.     assume    ds:bios_data
  431.     push    ds
  432.     push    ax
  433.     push    cx
  434.     mov    ax,pixbase    ; start getting display segment
  435.     cmp    active_page,0    ; page 0?
  436.     je    scr_pg0        
  437.     add    ax,800H        ; page 1. bump by half of 64K
  438. scr_pg0:
  439.     mov    ds,ax        ; save display segment in DS
  440.     mov    es,ax        ; ... and in ES
  441. ;
  442.     xor    ax,ax        ; zero AX
  443.     call    scr_shift
  444.     mov    ax,2000H    ; bump interlace counter
  445.     call    scr_shift
  446.     mov    ax,4000H
  447.     call    scr_shift
  448.     mov    ax,6000H
  449.     call    scr_shift
  450. ;
  451.     pop    cx
  452.     pop    ax
  453.     pop    ds
  454.     ret
  455. ;
  456. ;
  457. ; scr_shift does the actual work of scrolling, one set of interlace
  458. ;   lines at a time.
  459. ;
  460. scr_shift:
  461.     cld            ; block moves will be UP
  462.     mov    di,ax        ; interlace scan ID to DI
  463.     mov    si,ax        ; ... and to SI
  464.     add    si,cs:scr_start
  465.                 ; but bump by "start"
  466.     mov    cx,cs:scr_length
  467.                 ; set counter for transfer
  468.     rep    movsw        ; and scroll a set of lines
  469.     xor    ax,ax        ; set up a zero word
  470.     mov    cx,cs:scr_start ; set counter for one more line
  471.     shr    cx,1        ; /2 for word transfers
  472.     rep    stosw        ; and blank the line
  473.     ret
  474. page
  475. ;-----------------------------------------------------------
  476. ;
  477. ;    SUBROUTINE FLASH
  478. ;
  479. ;    Flashes the screen inverse video and back to normal.
  480. ;    Used in place of an audible bell.
  481. ;
  482. ;-------------------------------------------------------------
  483. ;
  484. flash:
  485.     push    cx
  486.     push    di
  487.     push    es
  488. ;
  489.     mov    di,pixbase    ; get display area base
  490.     cmp    active_page,0    ; page 0?
  491.     je    pg0_f
  492.     add    di,800H        ; no, page 1
  493. pg0_f:    mov    es,di        ; put resulting pointer to display in ES
  494. ;
  495. ;            ; loop to invert screen
  496.     xor    di,di        ; point to beginning of display area
  497.     mov    cx,4000H    ; number of words to invert
  498. flash_loop_1:
  499.     not    word ptr es:[di]
  500.                 ; invert one location
  501.     add    di,2        ; bump location pointer a word
  502.     loop    flash_loop_1
  503. ;
  504. ;            ; and invert it back to normal
  505.     xor    di,di        ; point to beginning of display area
  506.     mov    cx,4000H    ; number of words to invert
  507. flash_loop_2:
  508.     not    word ptr es:[di]
  509.                 ; invert one location
  510.     add    di,2        ; bump location pointer a word
  511.     loop    flash_loop_2
  512. ;
  513.     pop    es
  514.     pop    di
  515.     pop    cx
  516.     ret
  517. page
  518. ;*****************************************************
  519. ;*    Data areas for character handling
  520. ;*****************************************************
  521. ;
  522. pixels        db    12 dup(?)    ; 12 bytes for pixel pattern
  523. ibm_pattern    dw    0000h,2000h,4000h,6000h,005Ah,205Ah,405Ah,605Ah
  524. herc_pattern    dw    4000h,6000h,005Ah,205Ah,405Ah,605Ah,00B4h,20B4h
  525. blank_pattern    dw    0000h,2000h,40B4h,60B4h
  526. ;
  527. ;
  528. cseg    ends
  529.     end
  530.