home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR13 / OS2ASM.ZIP / DISP.ASM < prev    next >
Assembly Source File  |  1991-07-06  |  29KB  |  1,204 lines

  1. ;_ disp.asm
  2. ; Phar Lap support added by G. Eric Engstrom Oct 1990
  3. ; Overlapping window support added by G. Eric Engstrom Oct 1989
  4. ; Copyright (C) 1986-1990 by Northwest Software
  5. ; All Rights Reserved
  6. ; Written by Walter Bright
  7. ;
  8. ; Fast screen display package
  9. ;
  10.  
  11. include    macros.asm
  12.  
  13. video_io macro
  14.     int    10h
  15.     endm
  16.  
  17. ;ASCII values
  18. DEL    equ    07Fh        ;DEL character
  19.  
  20. TIMEOUT equ        6
  21. RETRACE equ        250
  22.  
  23.     begdata
  24.  
  25.     public    _disp_numrows,_disp_numcols
  26. _disp_numrows    dd    25    ;# of rows in display
  27. _disp_numcols    dd    0    ;# of columns in display
  28.  
  29. scrnrowcol    label    word    ;row,col of actual screen cursor
  30. scrncol    db    ?
  31. scrnrow    db    ?
  32.  
  33.     public    _disp_cursorrow,_disp_cursorcol
  34. _disp_cursorrow    dd    0    ;row,col of where we want the cursor to be
  35. _disp_cursorcol    dd    0
  36.  
  37.     public    _disp_cursortype
  38. _disp_cursortype  dd    0    ;start/end scan line of cursor
  39. _disp_cursorcount dd    0    ;if 0, cursor is shown
  40.  
  41. normatt    equ    07h    ;white chars on black background
  42. stndatt    equ    070h    ;inverse video
  43. att    db    normatt    ;current attribute
  44.  
  45.     public    _disp_mono,_disp_base,_disp_snowycga,_disp_mode,_disp_inited
  46.     public    _disp_ega,_disp_activepage,_disp_base
  47. _disp_mono    db    1    ;0 for color, 1 for monochrome
  48. _disp_snowycga    db    1    ;if 1, then the display is an IBM snowy CGA
  49. _disp_mode    db    ?    ;what is the current display mode?
  50. _disp_inited    db    0    ;1 if display package is opened
  51. _disp_ega    db    0    ;1 if IBM EGA
  52. _disp_activepage  db    0    ;which page to read/write
  53. _disp_displaypage db    0    ;which page is displayed
  54. _disp_offset    dd    0    ;offset portion of far ptr into display
  55. _disp_base      dw      0b000h  ;monochrome is default
  56.  
  57. cursortype    dw    ?    ;where we save the cursor type
  58.  
  59.     enddata
  60.  
  61.     begcode    disp
  62.  
  63. extrn    __get_video_selector:near
  64.  
  65.     c_public    disp_open
  66. func    disp_open
  67.     _ifs    _disp_inited e 0, Q4    ;if not already initialized
  68.       ret
  69.  
  70. Q4:     mov     _disp_inited,1
  71.         push    EBP
  72.         uses    <EAX,EBX,EDX,EDI>
  73.  
  74.     ;Determine number of rows, also if we have an EGA
  75.     clr    EDX        ;default value
  76.     clr    EBX
  77.     mov    AX,01130h    ;inquire info from EGA BIOS
  78.     video_io
  79.     tst    DL        ;Check if DL is still zero
  80.     jz    L3        ;if so, no EGA
  81.  
  82.       mov     _disp_ega,1     ;flag that we have an EGA
  83.       mov     _disp_snowycga,0        ;EGAs don't snow
  84.       inc     DL
  85.       mov     word ptr _disp_numrows,DX       ;number of rows
  86.  
  87. L3:    mov    AH,15
  88.     video_io
  89.     mov    byte ptr _disp_numcols,AH    ;set number of columns
  90.     mov    _disp_mode,AL        ;save display mode
  91.     _ifs    AL ne 7, Q2        ;if not mono mode
  92.  
  93.       mov     _disp_snowycga,0                ;mono displays don't snow
  94.  
  95.       ;Do an equipment check to see if this is really a mono card.
  96.       ;Note that the COMPAQ can be in mode 7, but still be a color card!
  97.       int     11h                     ;Equipment Determination BIOS call
  98.       and     AX,  00110000b          ;isolate initial video mode bits
  99.       _ifs    AX e 00110000b, L1      ;yes, it is a real mono card
  100.  
  101.         mov     AL,7                    ;mode 7
  102.         jmps    L51
  103.  
  104. Q2:         _ifs    AL e 15, L51            ;if EGA monochrome graphics mode
  105.               mov     _disp_mono,0          ;else color display
  106.  
  107. L51:
  108.       mov     _disp_base,0b800h     ;base of color adapter
  109.       _ifs    AL be 3, L1     ;if color text mode
  110.       _ifs    AL e 7, L1      ; or mono text mode
  111.       mov     _disp_base,0    ;use BIOS instead of direct access to video ram
  112.                   ; for all graphics and other unrecognized modes
  113.       jmps    L50
  114. L1:
  115.     ;Find out if we are running under DESQview.
  116.     ;This section provided by Erik Lindberg.
  117.     mov    AX,2B01h    ; Get DESQview version (set date)
  118.     mov    CX,'DE'        ;     if CX,DX = 'DESQ', is invalid
  119.     mov    DX,'SQ'        ;     setdate call.
  120.     int    21h        ; DOS interrupt.
  121.     cmp    AL,0FFh        ; check for invalid return.
  122.     jz    L2        ;   then DESQview is not running.
  123.       mov     _disp_base,0    ;use BIOS when running under DESQview
  124. L2:
  125.     ;determine where cursor is
  126. L50:    mov    AH,3
  127.     video_io
  128.     mov    cursortype,CX        ;save original cursor type
  129.     mov    word ptr _disp_cursortype,CX    ;current cursor type
  130.     mov    scrnrow,DH
  131.     mov    scrncol,DL
  132.     mov    AL,DH
  133.     cbw
  134.     mov    word ptr _disp_cursorrow,AX
  135.     clr    DH
  136.     mov    word ptr _disp_cursorcol,DX
  137.         mov     ax,_disp_base                   ;real mode segment
  138.         call    __get_video_selector            ;convert segment to selector
  139.         mov     _disp_base,ax                   ;protected mode selector
  140.         unuse   <EDI,EDX,EBX,EAX>
  141.         pop     EBP
  142.         ret
  143. c_endp    disp_open
  144.  
  145. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  146. ; Close things up
  147.  
  148.     c_public    disp_close
  149. func    disp_close
  150.     _ifs    _disp_inited e 0, Q3    ;quit if never opened
  151.       push    EBP
  152.       uses    <ECX>
  153.       callm   disp_flush
  154.       mov     AH,1
  155.       mov     CX,cursortype   ;restore original cursor type
  156.       video_io
  157.       mov     _disp_inited,0
  158.       unuse   <ECX>
  159.       pop     EBP
  160. Q3:    ret
  161. c_endp    disp_close
  162.  
  163. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  164. ; Be BIOS compatible, instead of poking directly into the screen
  165. ; memory.
  166.  
  167.     c_public    disp_usebios
  168. func    disp_usebios
  169.     mov    _disp_base,0
  170.     ret
  171. c_endp    disp_usebios
  172.  
  173. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  174. ; Set cursor type.
  175. ; If the cursor is hidden (via calls to disp_hidecursor()), the
  176. ; new cursor type will show up when the cursor is redisplayed.
  177. ; Use:
  178. ;    disp_setcursortype(startline*256 + endline);
  179.  
  180.     c_public    disp_setcursortype
  181. func    disp_setcursortype
  182.     push    EBP
  183.     mov    EBP,ESP
  184.     uses    <ECX>
  185.     mov    CX,P[EBP]
  186.     mov    word ptr _disp_cursortype,CX
  187.     _ifs    _disp_cursorcount ne 0, SCT1    ;if cursor is not displayed
  188.       mov      AH,1
  189.       video_io
  190. SCT1:    unuse    <ECX>
  191.     pop    EBP
  192.     ret
  193. c_endp    disp_setcursortype
  194.  
  195. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  196. ; Hide/show hardware cursor on screen. Calls can be nested.
  197.  
  198.     c_public    disp_hidecursor,disp_showcursor
  199.  
  200. func    disp_hidecursor
  201.     inc    _disp_cursorcount
  202.     _ifs    _disp_cursorcount ne 1, HC1
  203.       mov     CX,02000h               ;non-displaying combination
  204. HC2:      push    EBP
  205.       mov     AH,1
  206.       video_io
  207.       pop     EBP
  208. HC1:    ret
  209. c_endp    disp_hidecursor
  210.  
  211. func    disp_showcursor
  212.     dec    _disp_cursorcount
  213.     jnz    HC1            ;nested, not ready to show yet
  214.       mov      CX,word ptr _disp_cursortype
  215.       jmp     HC2
  216. c_endp    disp_showcursor
  217.  
  218. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  219. ; Put a character into the display.
  220. ; Behave as a dumb terminal.
  221. ; Returns character passed.
  222.  
  223.     c_public    disp_putc
  224. func    disp_putc
  225.         push    EBP
  226.         mov    EBP,ESP
  227.     uses    <EBX,EDX>
  228.     clr    EAX
  229.     mov    AL,P[EBP]
  230.     _ifs    AL b ' ',docntl        ;control char
  231.     _ifs    AL z DEL,zip1        ;ignore rubouts
  232. doout:    call    near ptr outchr        ;display character
  233.     mov    EAX,_disp_cursorcol
  234.     inc    EAX            ;next column
  235.     _ifs    EAX ae _disp_numcols, L19    ;if on or past right edge
  236. L20:    mov    _disp_cursorcol,EAX
  237. zip1:    unuse    <EDX,EBX>
  238.     clr    EAX
  239.     mov    AL,P[EBP]
  240.         pop    EBP
  241.     ret
  242.  
  243. L19:    clr    EAX
  244.     mov    EBX,_disp_cursorrow        ;get row and column
  245.     inc    EBX            ;start of next row
  246.     _ifs    EBX b _disp_numrows, L18    ;if not past bottom
  247.     call    near ptr scrollup    ;scroll up 1 line
  248.     clr    EAX
  249.     mov    EBX,_disp_numrows        ;lower left corner
  250.     dec    EBX
  251. L18:    mov    _disp_cursorrow,EBX
  252.     jmp    L20
  253.  
  254. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  255. ; Handle control characters
  256.  
  257. docntl:    movzx    EAX,AL
  258.     mov    EBX,EAX
  259.     shl    EBX,2
  260.     jmp    dword ptr CS:(offset cntltab)[EBX]
  261.  
  262. cntltab:
  263.     dd    offset _TEXT:doout
  264.     dd    offset _TEXT:doout
  265.     dd    offset _TEXT:doout
  266.     dd    offset _TEXT:doout
  267.     dd    offset _TEXT:doout
  268.     dd    offset _TEXT:doout
  269.     dd    offset _TEXT:doout
  270.     dd    offset _TEXT:beep,offset _TEXT:dobs    ;BEL,BS
  271.     dd    offset _TEXT:dotab,offset _TEXT:donl    ;TAB,LF
  272.     dd    offset _TEXT:donl,offset _TEXT:donl    ;VT,FF
  273.     dd    offset _TEXT:docr            ;CR
  274.     dd    offset _TEXT:doout,offset _TEXT:doout
  275.     dd    offset _TEXT:doout,offset _TEXT:doout        ;P,XON,R,XOFF
  276.     dd    offset _TEXT:doout
  277.     dd    offset _TEXT:doout
  278.     dd    offset _TEXT:doout
  279.     dd    offset _TEXT:doout
  280.     dd    offset _TEXT:doout
  281.     dd    offset _TEXT:doout
  282.     dd    offset _TEXT:doout
  283.     dd    offset _TEXT:doout                ;escape
  284.     dd    offset _TEXT:doout
  285.     dd    offset _TEXT:doout
  286.     dd    offset _TEXT:doout
  287.     dd    offset _TEXT:doout
  288.     dd    offset _TEXT:doout
  289.     dd    offset _TEXT:doout
  290.  
  291. ;;;;;;;;;;;;;;;;;;;;;;
  292. ; Bell
  293.  
  294. beep:
  295.     mov    DL,7
  296.     bdos    2            ;send a bell to DOS
  297.     clr    EAX
  298.     mov    AL,7
  299.     jmp    short L140
  300.  
  301. ;;;;;;;;;;;;;;;;;;;;
  302. ; Backspace (non-destructive)
  303.  
  304. dobs:    mov    EBX,_disp_cursorcol
  305.     dec    EBX            ;backup 1 column
  306.     js    L140            ;oops! already in column 0
  307.       mov      _disp_cursorcol,EBX
  308. L140:    unuse    <EDX,EBX>
  309.     pop    EBP
  310.     ret
  311.  
  312. ;;;;;;;;;;;;;;;;;;;;
  313. ; Carriage return
  314.  
  315. docr:    mov    _disp_cursorcol,0        ;reset column
  316.     jmp    short L140
  317.  
  318. ;;;;;;;;;;;;;;;;;;;
  319. ; Line feed
  320.  
  321. donl:    mov    _disp_cursorcol,0        ;reset column to start of line
  322.  
  323. dolf:    mov    EDX,_disp_cursorrow
  324.     inc    EDX
  325.     _ifs    EDX b _disp_numrows, L101
  326.       call      near ptr scrollup
  327.       clr      EAX
  328.       mov     AL,0Ah
  329.       jmp      short L140
  330. L101:    mov    _disp_cursorrow,EDX
  331.     jmp    short L140
  332.  
  333. ;;;;;;;;;;;;;;;;;;;
  334. ; Tab (non-destructive)
  335.  
  336. dotab:
  337.     mov    AX,word ptr _disp_cursorcol
  338.     or    AX,7
  339.     inc    EAX        ;advance to next tab stop
  340.     _ifs    AX b <word ptr _disp_numcols>, D1
  341.     mov    AX,word ptr _disp_numcols
  342.     dec    EAX
  343. D1:    mov    word ptr _disp_cursorcol,AX
  344.     clr    EAX
  345.     mov    AL,9
  346.     jmp    short L140
  347. c_endp    disp_putc
  348.  
  349. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  350. ; Scroll a region of the display.
  351. ;    void disp_scroll(lines,ulrow,ulcol,lrrow,lrcol,att);
  352. ;    lines > 0:    scroll up
  353. ;    lines == 0:    blank window
  354. ;    lines < 0:    scroll down
  355.  
  356. PSC_LINECOUNT    EQU 0
  357. PSC_LINE    EQU PSC_LINECOUNT+4
  358. PSC_COLUMN    EQU PSC_LINE+4
  359. PSC_BOTTOMLINE    EQU PSC_COLUMN+4
  360. PSC_RIGHTCOLUMN    EQU PSC_BOTTOMLINE+4
  361. PSC_ATTRIBUTE    EQU PSC_RIGHTCOLUMN+4
  362.  
  363.     c_public    disp_scroll
  364. func    disp_scroll
  365.     push    EBP
  366.     mov    EBP,ESP
  367.     uses    <EAX,EBX,ECX,EDX>
  368.     mov    AL,P+PSC_LINECOUNT[EBP]
  369.     mov    CH,P+PSC_LINE[EBP]
  370.     mov    CL,P+PSC_COLUMN[EBP]
  371.     mov    DH,P+PSC_BOTTOMLINE[EBP]
  372.     mov    DL,P+PSC_RIGHTCOLUMN[EBP]
  373.     mov    BH,P+PSC_ATTRIBUTE[EBP]
  374.     mov    AH,6
  375.     tst    AL
  376.     jns    scroll1
  377.       neg      AL
  378.       inc      AH
  379. scroll1:
  380.     video_io
  381.     unuse    <EDX,ECX,EBX,EAX>
  382.     pop    EBP
  383.     ret
  384. c_endp    disp_scroll
  385.  
  386. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  387. ; Poke att/char into display at row,column.
  388. ;    void disp_pokew(row,col,attchr);
  389.  
  390. POKE_ROW    equ    0
  391. POKE_COL    equ    POKE_ROW+4
  392. POKE_ATTCHR    equ    POKE_COL+4
  393.  
  394.     c_public    disp_pokew
  395. func    disp_pokew
  396.     push    EBP
  397.     mov    EBP,ESP
  398.     uses    <EBX,ECX,EDX,ES>
  399.  
  400.     clr    EAX
  401.     movzx    ECX,word ptr P+POKE_ATTCHR[EBP]    ;save att/char
  402.     movzx    EDX,byte ptr P+POKE_COL[EBP]    ;column
  403.     mov    DH,P+POKE_ROW[EBP]    ;row
  404.     _ifs    _disp_base e 0, W7
  405.  
  406.       movzx   EAX,word ptr _disp_numcols
  407.       mul     DH
  408.       clr     DH
  409.       add     EAX,EDX         ;add in column
  410.       shl     EAX,1           ;compute offset into screen
  411.       mov     EBX,EAX
  412.       mov     ES,_disp_base
  413.       _ifs    _disp_snowycga ne 0, W1A        ;if dont skip snow check
  414.  
  415. W1:         mov     ES:[EBX],CX           ;poke it
  416.         sti                           ;enable interrupts
  417. W8:         unuse   <ES,EDX,ECX,EBX>
  418.         pop     EBP
  419.         ret
  420.  
  421. W1A:      mov     DX,03DAh                ;color card status port
  422.       mov     AH,1
  423.  
  424. W5:       in      AL,DX                   ;wait for retrace low
  425.       test    AL,AH
  426.       jnz     W5
  427.       cli                             ;turn off interrupts
  428. W6:       in      AL,DX                   ;wait for retrace high
  429.       test    AL,AH
  430.       jz      W6
  431.       jmp     short W1
  432.  
  433. W7:    mov    scrnrowcol,DX
  434.     mov    BH,_disp_activepage    ;page number
  435.     mov    AH,2
  436.     video_io        ;set cursor position (BP is destroyed)
  437.     mov    AL,CL        ;char
  438.     mov    BL,CH        ;attribute to use
  439.     mov    AH,9        ;write att/char at current cursor position
  440.     mov    CX,1        ;write one character
  441.     video_io
  442.     jmp    short W8
  443. c_endp    disp_pokew
  444.  
  445. LBP_COLUMN    EQU    0
  446. LBP_ROW        EQU    LBP_COLUMN+4
  447. LBP_X        EQU    LBP_ROW+4
  448. LBP_Y        EQU    LBP_X+4
  449. LBP_LEVEL    EQU    LBP_Y+4
  450. LBP_LEVELMAP    EQU    LBP_LEVEL+4
  451. LBP_LEVELMAPX    EQU    LBP_LEVELMAP+SIZEPTR
  452. LBP_VIEWARRAY    EQU    LBP_LEVELMAPX+4
  453. LBP_VIEWARRAYX    EQU    LBP_VIEWARRAY+SIZEPTR
  454.  
  455.     c_public    disp_levelblockpoke
  456. func    disp_levelblockpoke
  457.     _ifs    _disp_inited ne 0,lbp0
  458.       ret
  459. lbp0:    push    EBP
  460.     mov    EBP,ESP
  461.     uses    <EBX,ECX,EDX,ESI,EDI,ES>
  462.  
  463.     movzx    EDX,byte ptr P+LBP_ROW[EBP]    ;row
  464.     mov    EAX,_disp_numcols
  465.     mul    DX
  466.     movzx    EDX,byte ptr P+LBP_COLUMN[EBP]    ;column
  467.     add    EAX,EDX        ;add in column
  468.     shl    EAX,1        ;xlat from bytes to words
  469.     mov    EDI,EAX
  470.     mov    ES,_disp_base    ;es:edi is screen ram
  471.  
  472.         mov     EAX,_disp_numcols
  473.         sub     AX,P+LBP_X[EBP]
  474.         shl     EAX,17                  ;compute video ptr offset to next line
  475.  
  476.         mov     ESI,P+LBP_LEVELMAP[EBP]        ;esi points at level map
  477.         mov     EBX,P+LBP_VIEWARRAY[EBP]    ;ebx points to data being transferred
  478.         mov     CX,P+LBP_Y[EBP]            ;lines in block being transferred
  479.         mov     DX,P+LBP_LEVEL[EBP]        ;dx = level being transferred
  480.         cld
  481.  
  482.     mov     AX,word ptr P+LBP_X[EBP]        ;columns in block being transferred
  483.     push    EAX        ;create local variable used by this loop
  484. E_1:      mov      EAX,[ESP]
  485.       shl      ECX,16
  486.       mov      CX,DX
  487.       mov      EDX,ECX    ;save line count in upper 16bits of EDX
  488.       movzx   ECX,AX    ;restore loop counter for columns
  489. E_2:        lodsw
  490.             cmp     AX,DX         ;if levelMap <= level being transferred
  491.             ja      E_3
  492.               mov     AX,[EBX]      ;get char & attr to be displayed
  493.           stosw                 ;update video
  494.               mov     -2[ESI],DX    ;update level map
  495.           inc     EBX
  496.               inc     EBX           ;advance data ptr to next char
  497.           loop    E_2
  498.           jmp     short E_5
  499. E_3:        inc     EBX
  500.         inc     EBX
  501.             inc     EDI
  502.         inc     EDI
  503.             loop    E_2
  504. E_5:      mov     EAX,[ESP]
  505.       shr      EAX,16
  506.  
  507.       add     EDI,EAX
  508.           movzx   EAX,word ptr P+LBP_VIEWARRAYX[EBP]    ;advance data ptr to next data line
  509.       add      EBX,EAX
  510.       movzx   EAX,word ptr P+LBP_LEVELMAPX[EBP]    ;advance level map ptr to next levelmap line
  511.       add     ESI,EAX
  512.  
  513.       mov     ECX,EDX
  514.       shr      ECX,16    ;restore loop ctr for lines in block
  515.       loop    E_1
  516.     pop    EAX        ;destroy local variable
  517.     unuse    <ES,EDI,ESI,EDX,ECX,EBX>
  518.     pop    EBP
  519.     ret
  520. c_endp    disp_levelblockpoke
  521.  
  522. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  523. ; Read att/char from display at row,column.
  524. ;    unsigned disp_peekw(row,col);
  525.  
  526. PK_LINE     EQU 0
  527. PK_COLUMN    EQU PK_LINE+4
  528.  
  529.     c_public    disp_peekw
  530. func    disp_peekw
  531.     push    EBP
  532.     mov    EBP,ESP
  533.     uses    <EBX,EDX,ES>
  534.  
  535.     mov    DH,P+PK_LINE[EBP]        ;row
  536.     mov    DL,P+PK_COLUMN[EBP]        ;column
  537.     _ifs    _disp_base e 0, W8A
  538.  
  539.     clr    EBX
  540.     mov    AX,word ptr _disp_numcols
  541.     mul    DH
  542.     clr    DH
  543.     add    AX,DX        ;add in column
  544.     shl    AX,1        ;compute offset into screen
  545.     mov    BX,AX
  546.     mov    ES,_disp_base
  547.     _ifs    _disp_snowycga ne 0, W9A ;if dont skip snow check
  548.  
  549. W9:      mov      AX,ES:[EBX]        ;read it
  550.       sti                ;enable interrupts
  551.       unuse      <ES,EDX,EBX>
  552.       pop      EBP
  553.       ret
  554.  
  555. W9A:    mov    DX,03DAh        ;color card status port
  556.     mov    AH,1
  557.  
  558. W10:    in    AL,DX            ;wait for retrace low
  559.     test    AL,AH
  560.     jnz    W10
  561.     cli                ;turn off interrupts
  562. W11:    in    AL,DX            ;wait for retrace high
  563.     test    AL,AH
  564.     jz    W11
  565.     jmp    short W9
  566.  
  567. W8A:    mov    scrnrowcol,DX
  568.     mov    BH,_disp_activepage    ;page number
  569.     mov    AH,2
  570.     video_io        ;set cursor position (BP is destroyed)
  571.     mov    AH,8        ;read att/char at current cursor position
  572.     video_io
  573.     unuse    <ES,EDX,EBX>
  574.     pop    EBP
  575.     ret
  576. c_endp    disp_peekw
  577.  
  578. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  579. ; Display character in AL.
  580.  
  581. outchr    proc    near
  582.     _ifs    _disp_base e 0, P7
  583.  
  584.     mov    CL,AL
  585.     mov    CH,att        ;attribute to use
  586.     mov    EAX,_disp_numcols
  587.     mul    _disp_cursorrow
  588.     add    AX,word ptr _disp_cursorcol
  589.     shl    EAX,1        ;compute offset into screen
  590.     mov    EBX,EAX
  591.     mov    ES,_disp_base
  592.     _ifs    _disp_snowycga ne 0, P1A;if dont skip snow check
  593.  
  594. P1:      mov      ES:[EBX],CX        ;poke it
  595.       sti                ;enable interrupts
  596.       ret
  597.  
  598. P1A:    mov    DX,03DAh        ;color card status port
  599.     mov    AH,1
  600. P5:    in    AL,DX            ;wait for retrace low
  601.     test    AL,AH
  602.     jnz    P5
  603.     cli                ;turn off interrupts
  604. P6:    in    AL,DX            ;wait for retrace high
  605.     test    AL,AH
  606.     jz    P6
  607.     jmp    short P1
  608.  
  609. P7:    push    EAX
  610.     callm    disp_flush    ;bring cursor up to date
  611.     pop    EAX
  612.     mov    AH,9        ;write att/char at current cursor position
  613.     mov    BH,_disp_activepage    ;page number
  614.     mov    BL,att        ;attribute to use
  615.     mov      CX,1        ;write one character
  616.     video_io
  617.     ret
  618. outchr    endp
  619.  
  620.  
  621. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  622. ; Set cursor position
  623. ;    void disp_move(unsigned row,unsigned col);
  624.  
  625.     c_public    disp_move
  626. func    disp_move
  627.     mov    EAX,PS[ESP]
  628.     mov    _disp_cursorrow,EAX
  629.     mov    EAX,PS+4[ESP]
  630.     mov    _disp_cursorcol,EAX
  631.     ret
  632. c_endp    disp_move
  633.  
  634. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  635. ; Flush output.
  636. ; What this does is set the hardware cursor (scrnxxx) to be where
  637. ; the software cursor (disp_cursorxxx) is. This is only done when
  638. ; disp_flush() is called because it is a relatively slow operation.
  639.  
  640.     c_public    disp_flush
  641. func    disp_flush
  642.     uses    <EBX,EDX>
  643.     mov    DH,byte ptr _disp_cursorrow
  644.     mov    DL,byte ptr _disp_cursorcol
  645.     _ifs    DX e scrnrowcol, F1
  646.  
  647.       mov     scrnrowcol,DX
  648.       mov     BH,_disp_activepage
  649.       mov     AH,2            ;set cursor function
  650.       push    EBP
  651.       video_io
  652.       pop     EBP
  653.  
  654. F1:    unuse    <EDX,EBX>
  655.     ret
  656. c_endp    disp_flush
  657.  
  658.  
  659. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  660. ; Delete to end of line (including cursor position)
  661.  
  662.     c_public    disp_eeol
  663. func    disp_eeol
  664.     uses    <ECX>
  665.     mov    ECX,_disp_numcols
  666.     sub    ECX,_disp_cursorcol    ;CX = # of spaces left in line
  667.     mov    EAX,_disp_numcols
  668.     mul    _disp_cursorrow
  669.     add    EAX,_disp_cursorcol
  670.     jmps    clear1
  671. c_endp    disp_eeol
  672.  
  673. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  674. ; Delete to end of screen (including cursor position)
  675.  
  676.     c_public    disp_eeop
  677. func    disp_eeop
  678.     uses    <ECX>
  679.     mov    EAX,_disp_numcols
  680.     mul    _disp_numrows
  681.     mov    ECX,EAX        ;CX = # of chars on screen
  682.     mov    EAX,_disp_numcols
  683.     mul    _disp_cursorrow
  684.     add    EAX,_disp_cursorcol
  685.     sub    ECX,EAX
  686. clear1:
  687.     uses    <EDI>
  688.     shl    AX,1
  689.     movzx    EDI,AX
  690.     jmps    aclear
  691. c_endp    disp_eeop
  692.  
  693. ;;;;;;;;;;;;;;;;;;;;;;;;
  694. ; Send CX spaces to screen starting at DI.
  695. ; expect EDI,ECX <USED> on stack
  696. ; i.e. this routine will unuse them in that order
  697.  
  698.         c_public aclear
  699. func    aclear
  700.     uses    <EBX,EDX,ES>
  701.     _ifs    _disp_base e 0, C7
  702.       mov      ES,_disp_base
  703.       cld
  704.       mov      AL,' '
  705.       mov      AH,att
  706.  
  707.       _ifs      _disp_snowycga ne 0, C1
  708.         rep     stosw
  709.         jmp     short C8        ;exit tail merge
  710.  
  711. C1:    _ifs    _disp_base e 0, C7
  712.       mov      DX,03DAh          ;color card status port
  713.       mov      BX,AX
  714.  
  715. C5:          in      AL,DX            ;wait for retrace low
  716.           test    AL,1
  717.           jnz     C5
  718.  
  719.         cli                  ;turn off interrupts
  720.  
  721. C6:          in      AL,DX            ;wait for retrace high
  722.           test    AL,1
  723.           jz      C6
  724.  
  725.         mov        AX,BX
  726.         stosw                  ;poke it
  727.         sti                  ;enable interrupts
  728.         loop    C5
  729.       jmp      short C8        ;exit tail merge
  730.  
  731. C7:    callm    disp_flush    ;bring cursor up to date
  732.     mov    AX,9*256+' '    ;write att/char at current cursor position
  733.     mov    BH,_disp_activepage    ;page number
  734.     mov    BL,att        ;attribute to use
  735.     push    EBP
  736.     video_io
  737.     pop    EBP
  738.  
  739. C8:    unuse   <ES,EDX,EBX,EDI,ECX>
  740.     ret
  741. c_endp    aclear
  742.  
  743. ;;;;;;;;;;;;;;;;;;;;;;;;
  744. ; Start/end standout mode.
  745. ; Set attribute for subsequent writes.
  746.  
  747.     c_public    disp_startstand,disp_endstand
  748.     c_public    disp_setattr,disp_getattr
  749.  
  750. func    disp_startstand
  751.     mov    att,stndatt
  752.     ret
  753. c_endp    disp_startstand
  754.  
  755. func    disp_endstand
  756.     mov    att,normatt
  757.     ret
  758. c_endp    disp_endstand
  759.  
  760. func    disp_setattr
  761.     mov    AL,PS[ESP]
  762.     mov    att,AL
  763.     ret
  764. c_endp    disp_setattr
  765.  
  766. func    disp_getattr
  767.     clr    EAX
  768.     mov    AL,att
  769.     ret
  770. c_endp    disp_getattr
  771.  
  772. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  773. ; Scroll up 1 line
  774.  
  775. scrollup proc    near
  776.     _ifs    _disp_snowycga ne 0, biosway    ;give up and use bios
  777.     _ifs    _disp_base e 0, biosway
  778.  
  779.       uses    <EBX,ECX,EDX,ESI,EDI>
  780.       mov     EAX,_disp_numcols
  781.       mov     ESI,EAX
  782.       mov     EBX,EAX
  783.       mul     _disp_numrows
  784.       sub     EAX,ESI
  785.       mov     ECX,EAX                 ;CX = # of words to scroll
  786.       shl     ESI,1                   ;source is 1 row in
  787.       clr     EDI
  788.       push      ES
  789.       push      DS
  790.       mov     ES,_disp_base           ;point to video segment
  791.       mov     DS,_disp_base
  792.       cld                             ;increment
  793.       rep movsw                       ;do the scroll
  794.       pop      DS
  795.       pop      ES
  796.       mov     ECX,EBX                 ;# of words in bottom row
  797.       mov     AL,' '                  ;char for blank row
  798.       mov     AH,att                  ;attribute for blank row
  799.       rep stosw                       ;blank bottom row
  800.       unuse   <EDI,ESI,EDX,ECX,EBX>
  801.           ret
  802.  
  803. biosway:
  804.     clr    ECX            ;row,col of upper left corner
  805.     mov    EDX,_disp_numcols    ;col of lower right corner
  806.     dec    EDX
  807.     mov    DH,24
  808.     mov    BH,att            ;att for blank
  809.     mov    AX,0601h        ;scroll up 1 line
  810.     video_io
  811.     ret
  812. scrollup endp
  813.  
  814. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  815. ; Get and return the current video mode.
  816.  
  817.     c_public    disp_getmode
  818. func    disp_getmode
  819.     push    EBP
  820.     mov    AH,15
  821.     video_io
  822.     movzx    EAX,AL
  823.     pop    EBP
  824.     ret
  825. c_endp    disp_getmode
  826.  
  827. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  828. ; Set the video mode.
  829. ; Do not use while disp package is open.
  830.  
  831.     c_public    disp_setmode
  832. func    disp_setmode
  833.     movzx    AX,byte ptr PS[ESP]
  834.     push    EBP
  835.     video_io
  836.     pop    EBP
  837.     ret
  838. c_endp    disp_setmode
  839.  
  840. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  841. ; Set into 43 line mode.
  842. ; Do not use while disp package is open.
  843.  
  844.     c_public    disp_set43
  845. func    disp_set43
  846.     _ifs    _disp_ega ne 1, S1
  847.     _ifs    _disp_numrows ne 25, S1
  848.     uses    <EBX,ECX,EDX>
  849.     push    EBP        ;some BIOS's trash BP
  850.     mov    AX,0003h    ;set color mode, 80x43
  851.     _ifs    _disp_mono e 0, S2
  852.     mov    AL,07h        ;set monochrome mode, 80x43
  853. S2:    mov    _disp_mode,AL        ;save display mode
  854.     video_io
  855.     mov    AX,01112h    ;character generator BIOS routine
  856.     mov    BL,0        ;8x8 double dot character font
  857.     video_io
  858.     mov    AX,01200h    ;alternate screen routine
  859.     mov    BL,020h        ;alternate print screen routine
  860.     video_io
  861.     ;Must set cursor to be a block else it will disappear
  862.     mov    AX,0100h
  863.     mov    CX,0007h    ;block cursor
  864.     video_io        ;set cursor type
  865.  
  866. S3:    mov    AX,01130h    ;inquire info from EGA BIOS
  867.     mov    BH,2
  868.     video_io
  869.     pop    EBP
  870.     movzx    EDX,DL
  871.     _ifs    EDX ae _disp_cursorrow, S4
  872.     mov    _disp_cursorrow,EDX    ;reset cursor so it's on the screen
  873. S4:    inc    EDX
  874.     mov    _disp_numrows,EDX    ;set new # of rows
  875.     unuse    <EDX,ECX,EBX>
  876. S1:    ret
  877. c_endp    disp_set43
  878.  
  879. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  880. ; Switch from 43 line mode back to 25 line mode.
  881.  
  882.     c_public    disp_reset43
  883. func    disp_reset43
  884.     _ifs    _disp_ega ne 1, S1
  885.     _ifs    _disp_numrows be 25, S1
  886.     uses    <EBX,EDX>
  887.     push    EBP
  888.     mov    AX,0003        ;color, 80x25
  889.     _ifs    _disp_mono e 0, R2
  890.     mov    AX,0007        ;mono, 80x25
  891. R2:    mov    _disp_mode,AL    ;save display mode
  892.     video_io
  893.     mov    AX,01101h    ;character generator BIOS routine
  894.     mov    BL,0
  895.     video_io
  896.     mov    AX,01200h
  897.     mov    BL,020h
  898.     video_io
  899.     mov    BH,2
  900.     mov    AX,01130h    ;inquire info from EGA BIOS
  901.     video_io
  902.     movzx    EDX,DL
  903.     _ifs    EDX ae _disp_cursorrow, R3
  904.     mov    _disp_cursorrow,EDX    ;reset cursor so it's on the screen
  905. R3:     inc    EDX
  906.     mov    _disp_numrows,EDX    ;set new # of rows
  907.         mov     AH,0
  908.         mov     AL,_disp_mode   ;reset video mode to clean up odd characters
  909.         video_io                ;gee 5-20-90
  910.     pop    EBP
  911.     unuse    <EDX,EBX>
  912.         ret
  913. c_endp    disp_reset43
  914.  
  915. ;parameter list for disp_peekbox & disp_pokebox
  916. ;
  917.  
  918. PBX_BUFFER    EQU    0
  919. PBX_LINE    EQU    PBX_BUFFER+SIZEPTR
  920. PBX_COLUMN    EQU    PBX_LINE+4
  921. PBX_BOTTOMLINE    EQU    PBX_COLUMN+4
  922. PBX_RIGHTCOLUMN    EQU    PBX_BOTTOMLINE+4
  923.  
  924. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  925. ;    disp_peekbox        Assembly language routine by Dave Mansell
  926. ;                February, 18th 1989
  927. ;  Synopsis:
  928. ;
  929. ;    void disp_peekbox(unsigned *buffer,
  930. ;        unsigned trow,unsigned lcol,unsigned brow,unsigned rcol);
  931. ;
  932. ;    Moves char/attr pairs from screen memory to buf avoiding screen snow if a
  933. ;    cga is present, uses both horizontal and vertical retrace intervals.
  934. ;  Where:
  935. ;    buffer    Pointer to array of unsigneds. Into each unsigned
  936. ;        will be placed the corresponding attr/char word.
  937. ;        The words are stored sequentially from left to right
  938. ;        and top to bottom. The number of unsigneds required
  939. ;        is ((brow - trow + 1) * (rcol - lcol + 1)).
  940. ;    trow,lcol    Top left corner
  941. ;    brow,rcol    Bottom right corner
  942.  
  943.     c_public disp_peekbox
  944. func  disp_peekbox
  945.     push    EBP
  946.     mov    EBP,ESP
  947.     uses    <EBX,ECX,EDX,ESI,EDI,ES,DS>
  948.     clr    EDX
  949.     mov    DH,P+PBX_LINE[EBP]            ;top row
  950.     mov    DL,P+PBX_COLUMN[EBP]            ;left column
  951.     mov    EBX,P+PBX_BOTTOMLINE[EBP]        ;bottom row
  952.     sub    BL,DH                    ;BX = no of rows
  953.     inc    EBX
  954.     mov    ECX,P+PBX_RIGHTCOLUMN[EBP]        ;right column
  955.     sub    CL,DL                ;CX = no of columns
  956.     inc    ECX
  957.     mov    EDI,P+PBX_BUFFER[EBP]        ;pointer to buf in EDI
  958.     _ifs _disp_base e 0,pkk            ;use bios
  959.     mov    EAX,_disp_numcols
  960.     push    EAX
  961.     mul    DH
  962.     xor    DH,DH
  963.     add    EAX,EDX
  964.     shl    EAX,1
  965.     mov    ESI,EAX
  966.     pop    EDX
  967.     sub    EDX,ECX
  968.     shl    EDX,1
  969.     mov    DH,_disp_snowycga
  970. ife ESeqDS
  971.     push    DS
  972.     pop    ES
  973. endif
  974.     mov    DS,_disp_base            ;screen segment
  975.  
  976. pkb0:    push    EBX                ;no of rows
  977.     push    EDX                ;offset to next row (and snow flag)
  978.     push    ECX                ;no of cols
  979.     _ifs DH e 1,pkb1                ;if snow is a problem jump
  980.     rep    movsw                ;otherwise just do copy
  981.     jmp    short pkb99
  982. pkk:    jmp    peekbios
  983. pkb1:    mov    DX,3DAh                ;CGA status port
  984. pkb2:    mov    EBX,ECX
  985.     mov    ECX,TIMEOUT
  986.     cli    ;clear interrupts
  987. pkb3:    in    AL,DX                ;read the port
  988.     test    AL,1                ;loop while display enable
  989.     loopnz    pkb3                ;is not active
  990.     jz    pkb4                ;jump if not timed out
  991.     movsw                    ;copy one word (char & attr)
  992.     sti                    ;re-enable interrupts
  993.     mov    ECX,EBX                ;restore CX = no of bytes
  994.     loop    pkb2                ;no more bytes so exit
  995.     jmp    short pkb99
  996. pkb4:    sti
  997.     mov    ECX,EBX                ;restore CX = no of bytes
  998. pkb5:    push    ECX                ;save loop counter
  999.     mov    ECX,TIMEOUT            ;timeout loop limit
  1000.     cli                    ;clear interrupts
  1001. pkb6:    in    AL,DX
  1002.     test    AL,1
  1003.     loopnz    pkb6
  1004.     jnz    pkb8
  1005. pkb7:    in    AL,DX
  1006.     test    AL,1
  1007.     jz    pkb7
  1008.     lodsw                    ;AL = char   AH = attr
  1009.     sti
  1010.     stosw
  1011.     pop    ECX
  1012.     loop    pkb5
  1013.     jmp short pkb99
  1014. pkb8:    pop    EBX
  1015.     mov    ECX,RETRACE
  1016.     cmp    EBX,ECX
  1017.     jnb    pkb9
  1018.     mov    ECX,EBX
  1019.     xor    EBX,EBX
  1020.     jmp    short pkb10
  1021. pkb9:    sub    EBX,ECX
  1022. pkb10:    rep    movsw
  1023.     mov    ECX,EBX
  1024.     test    ECX,ECX
  1025.     jnz    pkb2
  1026.  
  1027. pkb99:    pop    ECX
  1028.     pop    EDX
  1029.     mov    EBX,EDX
  1030.     xor    DH,DH
  1031.     add    ESI,EDX
  1032.     mov    EDX,EBX
  1033.     pop    EBX
  1034.     dec    EBX
  1035.     jnz    pkb0
  1036.     cld
  1037.     jmp    short peekend
  1038. peekbios:
  1039.     mov    BH,_disp_displaypage
  1040. peeklp1:
  1041.     push    ECX                ;save the # of columns
  1042.     push    EDX
  1043. peeklp2:
  1044.     mov    AX,0200h
  1045.     video_io                ;position the cursor
  1046.     mov    AX,0800h
  1047.     video_io                ;read one word (char & attr)
  1048.     stosw                    ;store in ES:DI
  1049.     inc    DL                ;next column
  1050.     loop    peeklp2                ;loop until row finished
  1051.     pop    EDX
  1052.     pop    ECX
  1053.     inc    DH                ;next row
  1054.     dec    BL                ;all rows done?
  1055.     jnz    peeklp1                ;go and do the next row
  1056. peekend:
  1057.     unuse    <DS,ES,EDI,ESI,EDX,ECX,EBX>
  1058.     pop    EBP
  1059.     ret
  1060. c_endp disp_peekbox
  1061.  
  1062. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1063. ;  Name:
  1064. ;    disp_pokebox        Assembly language routine by Dave Mansell
  1065. ;                February, 18th 1989
  1066. ;  Synopsis:
  1067. ;
  1068. ;    void disp_pokebox(unsigned *buffer,
  1069. ;        unsigned trow,unsigned lcol,unsigned brow,unsigned rcol);
  1070. ;
  1071. ;  Description
  1072. ;    Moves char/attr pairs from buf to screen memory avoiding screen snow if a
  1073. ;    cga is present, uses both horizontal and vertical retrace intervals.
  1074.  
  1075.     c_public disp_pokebox
  1076.  
  1077. func disp_pokebox
  1078.     push    EBP
  1079.     mov    EBP,ESP
  1080.     uses    <EBX,ECX,EDX,ESI,EDI,ES>
  1081.     clr    EDX
  1082.     mov    DH,P+PBX_LINE[EBP]            ;top row
  1083.     mov    DL,P+PBX_COLUMN[EBP]            ;left column
  1084.     movzx    EBX,word ptr P+PBX_BOTTOMLINE[EBP]    ;bottom row
  1085.     sub    BL,DH                    ;BX = no of rows
  1086.     inc    EBX
  1087.     movzx    ECX,word ptr P+PBX_RIGHTCOLUMN[EBP]    ;right column
  1088.     sub    CL,DL                    ;CX = no of columns
  1089.     inc    ECX
  1090.     mov    ESI,P+PBX_BUFFER[EBP]            ;pointer to buf in ESI
  1091.     _ifs _disp_base e 0,pbk                ;use bios
  1092.     mov    EAX,_disp_numcols
  1093.     push    EAX
  1094.     mul    DH
  1095.     xor    DH,DH
  1096.     add    EAX,EDX
  1097.     shl    EAX,1
  1098.     mov    EDI,EAX
  1099.     pop    EDX
  1100.     sub    EDX,ECX
  1101.     shl    EDX,1
  1102.     mov    DH,_disp_snowycga
  1103.     mov    ES,_disp_base            ;screen segment
  1104. pb0:    push    EBX
  1105.     push    EDX
  1106.     push    ECX
  1107.     _ifs DH e 1,pb1                ;if snow is a problem jump
  1108.     rep    movsw                ;otherwise just do copy
  1109.     jmp short pb99
  1110. pbk:    jmp    pokebios
  1111. pb1:    mov    DX,3DAh                ;CGA status port
  1112. pb2:    mov    EBX,ECX
  1113.     mov    ECX,TIMEOUT
  1114.     cli                    ;clear interrupts
  1115. pb3:    in    AL,DX                ;read the port
  1116.     test    AL,1                ;loop while display enable
  1117.     loopnz    pb3                ;is not active
  1118.     jz    pb4                ;jump if not timed out
  1119.     movsw                    ;copy one word (char & attr)
  1120.     sti                    ;re-enable interrupts
  1121.     mov    ECX,EBX                ;restore CX = no of bytes
  1122.     loop    pb2                ;no more bytes so exit
  1123.     jmp short pb99
  1124. pb4:    sti
  1125.     mov    ECX,EBX                ;restore CX = no of bytes
  1126. pb5:    lodsw                    ;AL = char   AH = attr
  1127.     mov    EBX,EAX                ;get into BX
  1128.     push    ECX                ;save loop counter
  1129.     mov    ECX,TIMEOUT            ;timeout loop limit
  1130.     cli                    ;clear interrupts
  1131. pb6:    in    AL,DX
  1132.     test    AL,1
  1133.     loopnz    pb6
  1134.     jnz    pb8
  1135. pb7:    in    AL,DX
  1136.     test    AL,1
  1137.     jz    pb7
  1138.     xchg    EAX,EBX
  1139.     stosw
  1140.     sti
  1141.     pop    ECX
  1142.     loop    pb5
  1143.     jmp short pb99
  1144. pb8:    pop    EBX
  1145.     dec    ESI
  1146.     dec    ESI
  1147.     mov    ECX,RETRACE
  1148.     cmp    EBX,ECX
  1149.     jnb    pb9
  1150.     mov    ECX,EBX
  1151.     xor    EBX,EBX
  1152.     jmp short pb10
  1153. pb9:    sub    EBX,ECX
  1154. pb10:    rep    movsw
  1155.     mov    ECX,EBX
  1156.     test    ECX,ECX
  1157.     jnz    pb2
  1158.  
  1159. pb99:    pop    ECX
  1160.     pop    EDX
  1161.     mov    EBX,EDX
  1162.     xor    DH,DH
  1163.     add    EDI,EDX
  1164.     mov    EDX,EBX
  1165.     pop    EBX
  1166.     dec    EBX
  1167.     jnz    pb0
  1168.     cld
  1169.     jmp    short pokeend
  1170. pokebios:
  1171.     mov    BH,_disp_displaypage    ;display page
  1172. pokelp1:
  1173.     push    ECX            ;save the # of columns
  1174.     push    EBX
  1175.     push    EDX
  1176. pokelp2:push    ECX
  1177.     mov    AX,0200h
  1178.     video_io            ;position the cursor
  1179.     mov    AX,[ESI]        ;get character and attribute
  1180.     mov    BL,AH            ;attribute
  1181.     mov    ECX,1
  1182.     mov    AH,09h
  1183.     video_io            ;write one word (char & attr)
  1184.     inc    DL            ;next column
  1185.     inc    ESI            ;next char/attr
  1186.     inc    ESI
  1187.     pop    ECX
  1188.     loop    pokelp2            ;loop until row finished
  1189.     pop    EDX
  1190.     pop    EBX
  1191.     pop    ECX
  1192.     inc    DH            ;next row
  1193.     dec    BL            ;all rows done?
  1194.     jnz    pokelp1            ;go and do the next row
  1195. pokeend:
  1196.     unuse    <ES,EDI,ESI,EDX,ECX,EBX>
  1197.     pop    EBP
  1198.     ret
  1199. c_endp disp_pokebox
  1200.  
  1201.     endcode    disp
  1202.  
  1203.     end
  1204.