home *** CD-ROM | disk | FTP | other *** search
/ Graphics Programming Black Book (Special Edition) / BlackBook.bin / disk1 / source / chapter31 / l31-1.asm next >
Encoding:
Assembly Source File  |  1997-06-18  |  8.2 KB  |  330 lines

  1. ; *** Listing 9.1 ***
  2. ;
  3. ; Program to demonstrate pixel drawing in 320x400 256-color
  4. ; mode on the VGA. Draws 8 lines to form an octagon, a pixel
  5. ; at a time. Draws 8 octagons in all, one on top of the other,
  6. ; each in a different color set. Although it's not used, a
  7. ; pixel read function is also provided.
  8. ;
  9. ; Assembled with TASM 4.0, linked with TLINK 6.10
  10. ; Checked by Jim Mischel 11/21/94
  11. ;
  12. VGA_SEGMENT    equ    0a000h
  13. SC_INDEX        equ    3c4h    ;Sequence Controller Index register
  14. GC_INDEX        equ    3ceh    ;Graphics Controller Index register
  15. CRTC_INDEX    equ    3d4h    ;CRT Controller Index register
  16. MAP_MASK        equ    2    ;Map Mask register index in SC
  17. MEMORY_MODE    equ    4    ;Memory Mode register index in SC
  18. MAX_SCAN_LINE    equ    9    ;Maximum Scan Line reg index in CRTC
  19. START_ADDRESS_HIGH equ    0ch    ;Start Address High reg index in CRTC
  20. UNDERLINE    equ    14h    ;Underline Location reg index in CRTC
  21. MODE_CONTROL    equ    17h    ;Mode Control register index in CRTC
  22. READ_MAP        equ    4    ;Read Map register index in GC
  23. GRAPHICS_MODE    equ    5    ;Graphics Mode register index in GC
  24. MISCELLANEOUS    equ    6    ;Miscellaneous register index in GC
  25. SCREEN_WIDTH    equ    320    ;# of pixels across screen
  26. SCREEN_HEIGHT    equ    400    ;# of scan lines on screen
  27. WORD_OUTS_OK    equ    1    ;set to 0 to assemble for
  28.                 ; computers that can't handle
  29.                 ; word outs to indexed VGA registers
  30. ;
  31. stack    segment para stack 'STACK'
  32.         db    512 dup (?)
  33. stack    ends
  34. ;
  35. Data    segment    word 'DATA'
  36. ;
  37. BaseColor    db    0
  38. ;
  39. ; Structure used to control drawing of a line.
  40. ;
  41. LineControl    struc
  42. StartX        dw    ?
  43. StartY        dw    ?
  44. LineXInc        dw    ?
  45. LineYInc        dw    ?
  46. BaseLength    dw    ?
  47. LineColor    db    ?
  48. LineControl    ends
  49. ;
  50. ; List of descriptors for lines to draw.
  51. ;
  52. LineList    label    LineControl
  53.     LineControl    <130,110,1,0,60,0>
  54.     LineControl    <190,110,1,1,60,1>
  55.     LineControl    <250,170,0,1,60,2>
  56.     LineControl    <250,230,-1,1,60,3>
  57.     LineControl    <190,290,-1,0,60,4>
  58.     LineControl    <130,290,-1,-1,60,5>
  59.     LineControl    <70,230,0,-1,60,6>
  60.     LineControl    <70,170,1,-1,60,7>
  61.     LineControl    <-1,0,0,0,0,0>
  62. Data    ends
  63. ;
  64. ; Macro to output a word value to a port.
  65. ;
  66. OUT_WORD    macro
  67. if WORD_OUTS_OK
  68.     out    dx,ax
  69. else
  70.     out    dx,al
  71.     inc    dx
  72.     xchg    ah,al
  73.     out    dx,al
  74.     dec    dx
  75.     xchg    ah,al
  76. endif
  77.     endm
  78. ;
  79. ; Macro to output a constant value to an indexed VGA register.
  80. ;
  81. CONSTANT_TO_INDEXED_REGISTER    macro    ADDRESS, INDEX, VALUE
  82.     mov    dx,ADDRESS
  83.     mov    ax,(VALUE shl 8) + INDEX
  84.     OUT_WORD
  85.     endm
  86. ;
  87. Code    segment
  88.     assume    cs:Code, ds:Data
  89. Start    proc    near
  90.     mov    ax,Data
  91.     mov    ds,ax
  92. ;
  93. ; Set 320x400 256-color mode.
  94. ;
  95.     call    Set320By400Mode
  96. ;
  97. ; We're in 320x400 256-color mode. Draw each line in turn.
  98. ;
  99. ColorLoop:
  100.     mov    si,offset LineList ;point to the start of the
  101.                 ; line descriptor list
  102. LineLoop:
  103.     mov    cx,[si+StartX]    ;set the initial X coordinate
  104.     cmp    cx,-1
  105.     jz    LinesDone    ;a descriptor with a -1 X
  106.                 ; coordinate marks the end
  107.                 ; of the list
  108.     mov    dx,[si+StartY]       ;set the initial Y coordinate,
  109.     mov    bl,[si+LineColor]  ; line color,
  110.     mov    bp,[si+BaseLength] ; and pixel count
  111.     add    bl,[BaseColor]    ;adjust the line color according
  112.                 ; to BaseColor
  113. PixelLoop:
  114.     push    cx        ;save the coordinates
  115.     push    dx
  116.     call    WritePixel    ;draw this pixel
  117.     pop    dx        ;retrieve the coordinates
  118.     pop    cx
  119.     add    cx,[si+LineXInc] ;set the coordinates of the
  120.     add    dx,[si+LineYInc] ; next point of the line
  121.     dec    bp        ;any more points?
  122.     jnz    PixelLoop    ;yes, draw the next
  123.     add    si,size LineControl ;point to the next line descriptor
  124.     jmp    LineLoop    ; and draw the next line
  125. LinesDone:
  126.     call    GetNextKey    ;wait for a key, then
  127.     inc    [BaseColor]    ; bump the color selection and
  128.     cmp    [BaseColor],8    ; see if we're done
  129.     jb    ColorLoop    ;not done yet
  130. ;
  131. ; Wait for a key and return to text mode and end when
  132. ; one is pressed.
  133. ;
  134.     call    GetNextKey
  135.     mov    ax,0003h
  136.     int    10h    ;text mode
  137.     mov    ah,4ch
  138.     int    21h    ;done
  139. ;
  140. Start    endp
  141. ;
  142. ; Sets up 320x400 256-color modes.
  143. ;
  144. ; Input: none
  145. ;
  146. ; Output: none
  147. ;
  148. Set320By400Mode    proc    near
  149. ;
  150. ; First, go to normal 320x200 256-color mode, which is really a
  151. ; 320x400 256-color mode with each line scanned twice.
  152. ;
  153.     mov    ax,0013h ;AH = 0 means mode set, AL = 13h selects
  154.               ; 256-color graphics mode
  155.     int    10h     ;BIOS video interrupt
  156. ;
  157. ; Change CPU addressing of video memory to linear (not odd/even,
  158. ; chain, or chain 4), to allow us to access all 256K of display
  159. ; memory. When this is done, VGA memory will look just like memory
  160. ; in modes 10h and 12h, except that each byte of display memory will
  161. ; control one 256-color pixel, with 4 adjacent pixels at any given
  162. ; address, one pixel per plane.
  163. ;
  164.     mov    dx,SC_INDEX
  165.     mov    al,MEMORY_MODE
  166.     out    dx,al
  167.     inc    dx
  168.     in    al,dx
  169.     and    al,not 08h    ;turn off chain 4
  170.     or    al,04h        ;turn off odd/even
  171.     out    dx,al
  172.     mov    dx,GC_INDEX
  173.     mov    al,GRAPHICS_MODE
  174.     out    dx,al
  175.     inc    dx
  176.     in    al,dx
  177.     and    al,not 10h    ;turn off odd/even
  178.     out    dx,al
  179.     dec    dx
  180.     mov    al,MISCELLANEOUS
  181.     out    dx,al
  182.     inc    dx
  183.     in    al,dx
  184.     and    al,not 02h    ;turn off chain
  185.     out    dx,al
  186. ;
  187. ; Now clear the whole screen, since the mode 13h mode set only
  188. ; cleared 64K out of the 256K of display memory. Do this before
  189. ; we switch the CRTC out of mode 13h, so we don't see garbage
  190. ; on the screen when we make the switch.
  191. ;
  192.     CONSTANT_TO_INDEXED_REGISTER SC_INDEX,MAP_MASK,0fh
  193.                 ;enable writes to all planes, so
  194.                 ; we can clear 4 pixels at a time
  195.     mov    ax,VGA_SEGMENT
  196.     mov    es,ax
  197.     sub    di,di
  198.     mov    ax,di
  199.     mov    cx,8000h    ;# of words in 64K
  200.     cld
  201.     rep    stosw        ;clear all of display memory
  202. ;
  203. ; Tweak the mode to 320x400 256-color mode by not scanning each
  204. ; line twice.
  205. ;
  206.     mov    dx,CRTC_INDEX
  207.     mov    al,MAX_SCAN_LINE
  208.     out    dx,al
  209.     inc    dx
  210.     in    al,dx
  211.     and    al,not 1fh    ;set maximum scan line = 0
  212.     out    dx,al
  213.     dec    dx
  214. ;
  215. ; Change CRTC scanning from doubleword mode to byte mode, allowing
  216. ; the CRTC to scan more than 64K of video data.
  217. ;
  218.     mov    al,UNDERLINE
  219.     out    dx,al
  220.     inc    dx
  221.     in    al,dx
  222.     and    al,not 40h    ;turn off doubleword
  223.     out    dx,al
  224.     dec    dx
  225.     mov    al,MODE_CONTROL
  226.     out    dx,al
  227.     inc    dx
  228.     in    al,dx
  229.     or    al,40h    ;turn on the byte mode bit, so memory is
  230.             ; scanned for video data in a purely
  231.             ; linear way, just as in modes 10h and 12h
  232.     out    dx,al
  233.     ret
  234. Set320By400Mode    endp
  235. ;
  236. ; Draws a pixel in the specified color at the specified
  237. ; location in 320x400 256-color mode.
  238. ;
  239. ; Input:
  240. ;    CX = X coordinate of pixel
  241. ;    DX = Y coordinate of pixel
  242. ;    BL = pixel color
  243. ;
  244. ; Output: none
  245. ;
  246. ; Registers altered: AX, CX, DX, DI, ES
  247. ;
  248. WritePixel    proc    near
  249.     mov    ax,VGA_SEGMENT
  250.     mov    es,ax    ;point to display memory
  251.     mov    ax,SCREEN_WIDTH/4
  252.             ;there are 4 pixels at each address, so
  253.             ; each 320-pixel row is 80 bytes wide
  254.             ; in each plane
  255.     mul    dx    ;point to start of desired row
  256.     push    cx    ;set aside the X coordinate
  257.     shr    cx,1    ;there are 4 pixels at each address
  258.     shr    cx,1    ; so divide the X coordinate by 4
  259.     add    ax,cx    ;point to the pixel's address
  260.     mov    di,ax
  261.     pop    cx    ;get back the X coordinate
  262.     and    cl,3    ;get the plane # of the pixel
  263.     mov    ah,1
  264.     shl    ah,cl    ;set the bit corresponding to the plane
  265.             ; the pixel is in
  266.     mov    al,MAP_MASK
  267.     mov    dx,SC_INDEX
  268.     OUT_WORD            ;set to write to the proper plane for
  269.             ; the pixel
  270.     mov    es:[di],bl    ;draw the pixel
  271.     ret
  272. WritePixel    endp
  273. ;
  274. ; Reads the color of the pixel at the specified location in 320x400
  275. ; 256-color mode.
  276. ;
  277. ; Input:
  278. ;    CX = X coordinate of pixel to read
  279. ;    DX = Y coordinate of pixel to read
  280. ;
  281. ; Output:
  282. ;    AL = pixel color
  283. ;
  284. ; Registers altered: AX, CX, DX, SI, ES
  285. ;
  286. ReadPixel    proc    near
  287.     mov    ax,VGA_SEGMENT
  288.     mov    es,ax    ;point to display memory
  289.     mov    ax,SCREEN_WIDTH/4
  290.             ;there are 4 pixels at each address, so
  291.             ; each 320-pixel row is 80 bytes wide
  292.             ; in each plane
  293.     mul    dx    ;point to start of desired row
  294.     push    cx    ;set aside the X coordinate
  295.     shr    cx,1    ;there are 4 pixels at each address
  296.     shr    cx,1    ; so divide the X coordinate by 4
  297.     add    ax,cx    ;point to the pixel's address
  298.     mov    si,ax
  299.     pop    ax    ;get back the X coordinate
  300.     and    al,3    ;get the plane # of the pixel
  301.     mov    ah,al
  302.     mov    al,READ_MAP
  303.     mov    dx,GC_INDEX
  304.     OUT_WORD        ;set to read from the proper plane for
  305.             ; the pixel
  306.     lods    byte ptr es:[si] ;read the pixel
  307.     ret
  308. ReadPixel    endp
  309. ;
  310. ; Waits for the next key and returns it in AX.
  311. ;
  312. ; Input: none
  313. ;
  314. ; Output:
  315. ;    AX = full 16-bit code for key pressed
  316. ;
  317. GetNextKey    proc    near
  318. WaitKey:
  319.     mov    ah,1
  320.     int    16h
  321.     jz    WaitKey    ;wait for a key to become available
  322.     sub    ah,ah
  323.     int    16h    ;read the key
  324.     ret
  325. GetNextKey    endp
  326. ;
  327. Code    ends
  328. ;
  329.     end    Start
  330.