vspacer
 
vspacer
 

Video.asm

 

ZDS Dave Goodall
 
Borders of the non-herbaceous kind

Drawing fancy borders seemed de-riguer to differentiate the TUI from the rash of other TUI's.

Windows 1.0 had just arrived on my desk and gone from box to install to the trash in five minutes.

So we drew pretty borders


video

The paint-by-numbers recipe went like this:

blue_bullet_savescreen() Save the block of video real-estate that we're about to paint the window on.

blue_bullet_fillscreen() Fill the rectangle with the solid background color.

blue_bullet_draw_wborder() Draw a border with all sorts of fancy doodads around the edge.

blue_bullet_display() Draw text strings in the foreground color(s) inside the window.

blue_bullet_restorescreen() Repaint the saved block once the window goes away.


The fun part of course was the draw border routine:

  ; ---------------------------------------------------------------------
  ; Module       : draw_wborder
  ; Function     : Draw window border.
  ; Called as    : void draw_wborder(int row1, int col1, int row2, int col2,
  ;                                  int w_battr, char * w_bd_descriptor);
  ;
  ;                static char BORDER_SINGLE[9] = "xxxxxxxx"
  ;                static char BORDER_DOUBLE[9] = "xxxxxxxx"
  ;                static char BORDER_ACTDLG[9] = "xxxxxxxx@quot;
  ;
  ; Notes        : w_border parm is consistent with SA draw_border routine.
  ;                The row2 and col2 parms must be changed if the SA routine
  ;                is to replace this routine.
  ;
                  if      bigcode
  _draw_wborder   proc    far
  w_left          equ     6[bp]           ; window left margin
  w_top           equ     8[bp]           ; window top margin
  row2            equ     10[bp]          ; window bottom row
  col2            equ     12[bp]          ; window bottom col
  w_battr         equ     14[bp]          ; border bg-fg attribute
  w_border        equ     16[bp]          ; border descriptor DS:SI pointer
                  else
  _draw_wborder proc near
  row1            equ     4[bp]
  col1            equ     6[bp]
  row2            equ     8[bp]
  col2            equ     10[bp]
  w_battr         equ     12[bp]          ; border bg-fg attribute
  w_border        equ     14[bp]          ; border descriptor DS:SI pointer
                  endif
  rows            equ     -2[bp]          ; row2 - row1
  cols            equ     -4[bp]          ; col2 - col1 - 2
  w_bd_tlhc       equ     -5[bp]          ; upper left corner border character
  w_bd_tline      equ     -6[bp]          ; top row border character
  w_bd_trhc       equ     -7[bp]          ; upper right corner border character
  w_bd_rside      equ     -8[bp]          ; right side border character
  w_bd_brhc       equ     -9[bp]          ; bottom right corner border character
  w_bd_bline      equ     -10[bp]         ; bottom row border character
  w_bd_blhc       equ     -11[bp]         ; bottom left corner border character
  w_bd_lside      equ     -12[bp]         ; left side border character
                  call _hide_mouse        ;Hide the mouse pointer
  ;
  ; Set up the stack frame
  ;
                  cmp     __cputype,0     ;Check cpu type
                  je      draw_wborder_8086
                  enter   12,0            ;Set up the stack frame
                  jmp     short draw_wborder_000
  draw_wborder_8086:
                  push    bp              ;Save BP registers
                  mov     bp,sp           ;Point it to the stack
                  sub     sp,12           ;Reserve local space
  draw_wborder_000:
                  push    di              ;Save
                  push    es              ; the
                  push    si              ;  registers
  ;
  ; Setup video variables
  ;
                  mov     ax,row1         ;Figure
                  mov     bx,col1         ; the
                  call    fig_vid_off     ;  video offset
                  mov     di,ax           ;DI=Video offset
                  mov     es,displayseg   ;ES=Video Segment
                  mov     ax,row2         ;Figure the difference
                  sub     ax,row1         ; of row2 - row1
                  mov     rows,ax         ;Save it
                  mov     ax,col2         ;Figure the
                  sub     ax,col1         ; the number
                  dec     ax              ;  of columns - 2
                  mov     cols,ax         ;Save it
  ;
  ;  Save ds and point at the border descriptor struct
  ;
                  if      bigdata
                  push    ds              ;Save DS
                  lds     si,w_border     ;DS:SI=String pointer
                  else
                  mov     si,w_border     ;DS:SI=String pointer
                  endif
  ;
  ; Unpack border descriptor
  ;
                  cld                     ;Set the direction flag forward
                  lodsb                   ;Get the next character
                  mov     w_bd_tlhc,al
                  lodsb                   ;Get the next character
                  mov     w_bd_tline,al
                  lodsb                   ;Get the next character
                  mov     w_bd_trhc,al
                  lodsb                   ;Get the next character
                  mov     w_bd_rside,al
                  lodsb                   ;Get the next character
                  mov     w_bd_brhc,al
                  lodsb                   ;Get the next character
                  mov     w_bd_bline,al
                  lodsb                   ;Get the next character
                  mov     w_bd_blhc,al
                  lodsb                   ;Get the next character
                  mov     w_bd_lside,al
  ;
  ; Draw the border
  ;
                  mov     ah,att          ;Set AH=Display attribute
                  call    disable_cga     ;Disable the CGA if necessary
                  push    di              ;Save the video offset
                  mov     al,w_bd_tlhc    ;Set AL=tlhc character
                  stosw                   ;Save the character/attribute pair
  ; Display the top line
                  mov     al,w_bd_tline   ;Set AL=Top line character
                  mov     cx,cols         ;CX=Line length
                  rep     stosw           ;Repeat ah:al save till cx = 0
                  mov     al,w_bd_trhc    ;Set AL=trhc character
                  stosw                   ;Save the character/attribute pair
  ; Draw the sides
  draw_wborder1:  pop     di              ;Restore the video pointer
                  add     di,160          ;Point it to the next row
                  dec     word ptr rows   ;Loop till the
                  jz      draw_wborder2   ; sides are complete
                  push    di              ;Save the video pointer
                  mov     al,w_bd_lside   ;Al=left side character
                  stosw                   ;Save the left hand side
                  add     di,cols         ;Point to the
                  add     di,cols         ; right hand side
                  mov     al,w_bd_rside   ;Al=right side character
                  stosw                   ;Save the right hand side
  jmp draw_wborder1                       ;Next line
  draw_wborder2:  mov     al,w_bd_blhc    ;Set Al=blhc character
                  stosw                   ;Save the video pointer
  ; Display the bottom line
                  mov     al,w_bd_bline   ;Set AL=Bot line character
                  mov     cx,cols         ;CX=Line length
                  rep     stosw           ;Repeat ah:al save till cx = 0
                  mov     al,W_bd_brhc    ;Set AL=brhc character
                  stosw                   ;Save the character/attribute pair
                  call enable_cga         ;Enable the cga if necessary
                  if bigdata
                  pop     ds              ;Restore DS
                  endif
                  pop     si              ;Restore
                  pop     es              ; the other
                  pop     di              ;  registers
                  call    _show_mouse     ;Restore the Mouse pointer
                  cmp     __cputype,0     ;Check cpu type
                  je      draw_wborder_8086x
                  leave                   ;Restore the stack
                  jmp     short draw_wborder_ret
  draw_wborder_8086x:
                   mov    sp,bp           ;Reset the stack pointer
                   pop    bp              ;Restore BP
  draw_wborder_ret:
                   ret                    ;Return
  _draw_wborder    endp

The IBM Color Graphics Adapter would display sparkly snow if you overwrote massive chunks of the video buffer to save and fill screens while it was drawing to the screen.

To avoid this you had to take the cga's sticky fingers right off of the video buffer with _disable_cga() while it was drawing and then put it back to work with _enable_cga.()

However for displaying the small numbers of characters in strings we could use the same type of interrupter type mechanism those old biplanes used to shoot bullets through a propellor disc.

We just monitor the video status register and sneak a byte or two or three into the video buffer during the vertical retrace interval when the cga is'nt reading from the video buffer.

The full file is downloadable and should come in real handy the next time you have to program for an IBM CGA adapter.


Back to top | ZDS Home | This article updated January 19 2004.