Initial conversion to markdown
This commit is contained in:
parent
a96a114403
commit
5e10794a24
362 changed files with 67353 additions and 0 deletions
116
31-04.md
Normal file
116
31-04.md
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](31-03.html) [Table of Contents](index.html) [Next](31-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
The interesting aspects of Listing 31.1 are three. First, the
|
||||
**Set320x400Mode** subroutine selects 320x400 256-color mode. This is
|
||||
accomplished by performing a mode 13H mode set followed by then putting
|
||||
the VGA into standard planar byte mode. **Set320x400Mode** zeros display
|
||||
memory as well. It’s necessary to clear display memory even after a mode
|
||||
13H mode set because the mode 13H mode set clears only the 64K of
|
||||
display memory that can be accessed in that mode, leaving 192K of
|
||||
display memory untouched.
|
||||
|
||||
The second interesting aspect of Listing 31.1 is the **WritePixel**
|
||||
subroutine, which draws a colored pixel at any *x,y* addressable
|
||||
location on the screen. Although it may not be obvious because I’ve
|
||||
optimized the code a little, the process of drawing a pixel is
|
||||
remarkably simple. First, the pixel’s display memory address is
|
||||
calculated as
|
||||
|
||||
*address*=(*y* \* (SCREEN\_WIDTH / 4)) + (*x* / 4)
|
||||
|
||||
which might be more recognizable as:
|
||||
|
||||
*address*=((*y* \* SCREEN\_WIDTH) + *x*) / 4
|
||||
|
||||
(There are 4 pixels at each display memory address in 320x400 mode,
|
||||
hence the division by 4.) Then the pixel’s plane is calculated as
|
||||
|
||||
*plane*=*x* and 3
|
||||
|
||||
which is equivalent to:
|
||||
|
||||
*plane*=*x* modulo 4
|
||||
|
||||
The pixel’s color is then written to the addressed byte in the addressed
|
||||
plane. That’s all there is to it!
|
||||
|
||||
The third item of interest in Listing 31.1 is the **ReadPixel**
|
||||
subroutine. **ReadPixel** is virtually identical to **WritePixel**, save
|
||||
that in **ReadPixel** the Read Map register is programmed with a plane
|
||||
number, while **WritePixel** uses a plane *mask* to set the Map Mask
|
||||
register. Of course, that difference merely reflects a fundamental
|
||||
difference in the operation of the two registers. (If that’s Greek to
|
||||
you, refer back to Chapters 23-30 for a refresher on VGA programming.)
|
||||
**ReadPixel** isn’t used in Listing 31.1, but I’ve included it because,
|
||||
as I said above, the read and write pixel functions together can support
|
||||
a whole host of more complex graphics functions.
|
||||
|
||||
How does 320x400 256-color mode stack up as regards performance? As it
|
||||
turns out, the programming model of 320x400 mode is actually pretty good
|
||||
for pixel drawing, pretty much on a par with the model of mode 13H. When
|
||||
you run Listing 31.1, you’ll no doubt notice that the lines are drawn
|
||||
quite rapidly. (In fact, the drawing could be considerably faster still
|
||||
with a dedicated line-drawing subroutine, which would avoid the
|
||||
multiplication associated with each pixel in Listing 31.1.)
|
||||
|
||||
In 320x400 mode, the calculation of the memory address is not
|
||||
significantly slower than in mode 13H, and the calculation and selection
|
||||
of the target plane is quickly accomplished. As with mode 13H, 320x400
|
||||
mode benefits tremendously from the byte-per-pixel organization of
|
||||
256-color mode, which eliminates the need for the time-consuming
|
||||
pixel-masking of the 16-color modes. Most important, byte-per-pixel
|
||||
modes never require read-modify-write operations (which can be extremely
|
||||
slow due to display memory wait states) in order to clip and draw
|
||||
pixels. To draw a pixel, you just store its color in display memory—what
|
||||
could be simpler?
|
||||
|
||||
More sophisticated operations than pixel drawing are less easy to
|
||||
accomplish in 320x400 mode, but with a little ingenuity it is possible
|
||||
to implement a reasonably efficient version of just about any useful
|
||||
graphics function. A fast line draw for 320x400 256-color mode would be
|
||||
simple (although not as fast as would be possible in mode 13H). Fast
|
||||
image copies could be implemented by copying one-quarter of the image to
|
||||
one plane, one-quarter to the next plane, and so on for all four planes,
|
||||
thereby eliminating the **OUT** per pixel that sequential processing
|
||||
requires. If you’re really into performance, you could store your images
|
||||
with all the bytes for plane 0 grouped together, followed by all the
|
||||
bytes for plane 1, and so on. That would allow a single **REP MOVS**
|
||||
instruction to copy all the bytes for a given plane, with just four
|
||||
**REP MOVS** instructions copying the whole image. In a number of cases,
|
||||
in fact, 320x400 256-color mode can actually be much faster than mode
|
||||
13H, because the VGA’s hardware can be used to draw four or even eight
|
||||
pixels with a single access; I’ll return to the topic of
|
||||
high-performance programming in 256-color modes other than mode 13H
|
||||
(“non-chain 4” modes) in Chapter 47.
|
||||
|
||||
It’s all a bit complicated, but as I say, you should be able to design
|
||||
an adequately fast—and often *very* fast—version for 320x400 mode of
|
||||
whatever graphics function you need. If you’re not all that concerned
|
||||
with speed, **WritePixel** and **ReadPixel** should meet your needs.
|
||||
|
||||
### Two 256-Color Pages {#Heading7}
|
||||
|
||||
Listing 31.2 demonstrates the two pages of 320x400 256-color mode by
|
||||
drawing slanting color bars in page 0, then drawing color bars slanting
|
||||
the other way in page 1 and flipping to page 1 on the next key press.
|
||||
(Note that page 1 is accessed starting at offset 8000H in display
|
||||
memory, and is—unsurprisingly—displayed by setting the start address to
|
||||
8000H.) Finally, Listing 31.2 draws vertical color bars in page 0 and
|
||||
flips back to page 0 when another key is pressed.
|
||||
|
||||
The color bar routines don’t use the **WritePixel** subroutine from
|
||||
Listing 31.1; they go straight to display memory instead for improved
|
||||
speed. As I mentioned above, better speed yet could be achieved by a
|
||||
color-bar algorithm that draws all the pixels in plane 0, then all the
|
||||
pixels in plane 1, and so on, thereby avoiding the overhead of
|
||||
constantly reprogramming the Map Mask register.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](31-03.html) [Table of Contents](index.html) [Next](31-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
Loading…
Reference in a new issue