Previous Table of Contents Next


LISTING 32.1 L32-1.ASM

; Borland C/C++ tiny/small/medium model-callable assembler
; subroutines to:
;* Set 360×480 256-color VGA mode
;* Draw a dot in 360×480 256-color VGA mode
;* Read the color of a dot in 360×480 256-color VGA mode
;
; Assembled with TASM
;
; The 360×480 256-color mode set code and parameters were provided
; by John Bridges, who has placed them into the public domain.
;
VGA_SEGMENT     equ    0a000h      ;display memory segment
SC_INDEX        equ    3c4h        ;Sequence Controller Index register
GC_INDEX        equ    3ceh        ;Graphics Controller Index register
MAP_MASK        equ    2           ;Map Mask register index in SC
READ_MAP        equ    4           ;Read Map register index in GC
SCREEN_WIDTH    equ    360         ;# of pixels across screen
WORD_OUTS_OK    equ    1           ;set to 0 to assemble for
                                   ; computers that can’t handle
                                   ; word outs to indexed VGA registers
;
_DATAsegmentpublic byte ‘DATA’
;
; 360×480 256-color mode CRT Controller register settings.
; (Courtesy of John Bridges.)
;
vptbl   dw      06b00h  ; horz total
        dw      05901h  ; horz displayed
        dw      05a02h  ; start horz blanking
        dw      08e03h  ; end horz blanking
        dw      05e04h  ; start h sync
        dw      08a05h  ; end h sync
        dw      00d06h  ; vertical total
        dw      03e07h  ; overflow
        dw      04009h  ; cell height
        dw      0ea10h  ; v sync start
        dw      0ac11h  ; v sync end and protect cr0-cr7
        dw      0df12h  ; vertical displayed
        dw      02d13h  ; offset
        dw      00014h  ; turn off dword mode
        dw      0e715h  ; v blank start
        dw      00616h  ; v blank end
        dw      0e317h  ; turn on byte mode
vpend   label   word
_DATAends
;
; Macro to output a word value to a port.
;
OUT_WORDmacro
if WORD_OUTS_OK
      out   dx,ax
else
      out   dx,al
      inc   dx
      xchg  ah,al
      out   dx,al
      dec   dx
      xchg  ah,al
endif
      endm
;
_TEXTsegment byte public ‘CODE’
       assumecs:_TEXT, ds:_DATA
;
; Sets up 360×480 256-color mode.
; (Courtesy of John Bridges.)
;
; Call as: void Set360By480Mode()
;
; Returns: nothing
;
      public _Set360×480Mode
_Set360×480Modeprocnear
      push   si                 ;preserve C register vars
      push   di
      mov    ax,12h             ; start with mode 12h
      int    10h                ; let the BIOS clear the video memory

      mov    ax,13h             ; start with standard mode 13h
      int    10h                ; let the BIOS set the mode

      mov    dx,3c4h            ; alter sequencer registers
      mov    ax,0604h           ; disable chain 4
      out    dx,ax

      mov    ax,0100h           ; synchronous reset
      out    dx,ax              ; asserted
      mov    dx,3c2h            ; misc output
      mov    al,0e7h            ; use 28 mHz dot clock
      out    dx,al              ; select it
      mov    dx,3c4h            ; sequencer again
      mov    ax,0300h           ; restart sequencer
      out    dx,ax              ; running again

      mov    dx,3d4h            ; alter crtc registers

      mov     al,11h            ; cr11
      out     dx,al             ; current value
      inc     dx                ; point to data
      in      al,dx             ; get cr11 value
      and     al,7fh            ; remove cr0 -> cr7
      out     dx,al             ; write protect
      dec     dx                ; point to index
      cld
      mov     si,offset vptbl
      mov     cx,((offset vpend)-(offset vptbl)) shr 1
@b:   lodsw
      out     dx,ax
      loop    @b
      pop     di                ;restore C register vars
      pop     si
      ret
_Set360x480Modeendp
;
; Draws a pixel in the specified color at the specified
; location in 360×480 256-color mode.
;
; Call as: void Draw360×480Dot(int X, int Y, int Color)
;
; Returns: nothing
;
DParms     struc
      dw   ?            ;pushed BP
      dw   ?            ;return address
DrawX dw   ?            ;X coordinate at which to draw
DrawY dw   ?            ;Y coordinate at which to draw
Color dw   ?            ;color in which to draw (in the
                        ; range 0-255; upper byte ignored)
DParms     ends
;
      public _Draw360×480Dot
_Draw360×480Dotprocnear
      push  bp            ;preserve caller’s BP
      mov   bp,sp         ;point to stack frame
      push  si            ;preserve C register vars
      push  di
      mov   ax,VGA_SEGMENT
      mov   es,ax         ;point to display memory
      mov   ax,SCREEN_WIDTH/4
                          ;there are 4 pixels at each address, so
                           ; each 360-pixel row is 90 bytes wide
                           ; in each plane
      mul   [bp+DrawY] ;point to start of desired row
      mov   di,[bp+DrawX] ;get the X coordinate
      shr   di,1           ;there are 4 pixels at each address
      shr   di,1           ; so divide the X coordinate by 4
      add   di,ax          ;point to the pixel’s address
      mov   cl,byte ptr [bp+DrawX] ;get the X coordinate again
      and   cl,3           ;get the plane # of the pixel
      mov   ah,1
      shl   ah,cl          ;set the bit corresponding to the plane
                           ; the pixel is in
      mov   al,MAP_MASK
      mov   dx,SC_INDEX
      OUT_WORD             ;set to write to the proper plane for
                           ; the pixel
      mov   al,byte ptr [bp+Color] ;get the color
      stosb                ;draw the pixel
      pop   di             ;restore C register vars
      pop   si
      pop   bp             ;restore caller’s BP
      ret
_Draw360×480Dotendp
;
; Reads the color of the pixel at the specified
; location in 360×480 256-color mode.
;
; Call as: int Read360×480Dot(int X, int Y)
;
; Returns: pixel color
;
RParms     struc
      dw   ?                ;pushed BP
      dw   ?                ;return address
ReadX dw   ?                ;X coordinate from which to read
ReadY dw   ?                ;Y coordinate from which to read
RParms     ends
;
      public _Read360×480Dot
_Read360×480Dotprocnear
      push  bp              ;preserve caller’s BP
      mov   bp,sp           ;point to stack frame
      push  si              ;preserve C register vars
      push  di
      mov   ax,VGA_SEGMENT
      mov   es,ax           ;point to display memory
      mov   ax,SCREEN_WIDTH/4 ;there are 4 pixels at each address, so
                            ; each 360-pixel row is 90 bytes wide
                            ; in each plane

       mul  [bp+DrawY] ;point to start of desired row
       mov  si,[bp+DrawX] ;get the X coordinate
       shr  si,1            ;there are 4 pixels at each address
       shr  si,1            ; so divide the X coordinate by 4
       add  si,ax           ;point to the pixel’s address
       mov  ah,byte ptr [bp+DrawX] ;get the X coordinate again
       and  ah,3
                            ;get the plane # of the pixel
       mov  al,READ_MAP
       mov  dx,GC_INDEX
       OUT_WORD             ;set to read from the proper plane for
                            ; the pixel
       lods byte ptr es:[si] ;read the pixel
       sub  ah,ah           ;make the return value a word for C
       pop  di              ;restore C register vars
       pop  si
       pop  bp              ;restore caller’s BP
       ret
_Read360×480Dot  endp
_TEX   Tends
       end


Previous Table of Contents Next

Graphics Programming Black Book © 2001 Michael Abrash