|
In this lesson we'll see the basics of
working in a graphics mode: How to put the 320x200x256 mode, how to exit
of it, how to draw pixels, how to use the palette,...Well, all the basics,
like i said.
Of course, most of the code is programmed
in Asm, for optimization (we need speed in graphics mode).
Before start
Basics of 320x200x256 Mode
Put some colors into your life
Vertical retrace
Behind Scenario: Virtual Screens
Source Code
Segment and offset
Memory in Intel 80x86 in real mode (MS-DOS)
use segment:offset to access to one byte. This
means that if i want to put/get a byte in memory, i must give these two
values, instead of a linear address.
Segment and offset are usually in hexadecimal.
Segment:Offset
is equivalent to (Segment*16)+Offset.
Example:A000h:0001h it's 655361 (in linear address).
MS-DOS can't take a byte above F000:FFFF->FFFFF->
nearly 1Mb. This's THE barrier. If we want to use the addresses above 1Mb,
we need to use EMS or XMS. Or protected mode. Or Win95 + DirectX.
Ports
Communications between programs and Hw
(video cards, HDD controllers,...) are done by ports. If i want to send/receive
data to/from Hw we need to use ports.
In Pascal, ports are a predefined arrays:
PORT y PORTW. One manages 8 bits ports, and the another manages 16 bits
ports.
How to start (and end) the 13h mode
For start the 320x200x256 mode (13h),
interrupts are a must. We make a call to interrupt 10h (screen services).
Inside this interrupt we use service 0h (active a graphics mode) with parameter
13h (mode 13h). And voilà!!!, we're in 320x200x256.
(If you don't know anythng of assembler,
no problem. The only important thing is to use the code, not know how are
made).
Code: [ mov ah,0; mov al,13h; int
10h ]
For exit, we use the same interrupt
and service, but with parameter 03h (text mode)
Pixels. Where are, and how to change them
In every graphics mode, screen is "mapped"
on memory. This mean that one pixel in the screen is one byte in memory.
How? in this way:
MEMORY (64000 contiguous bytes starting in DESPLZ)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SCREEN (320 columns and 200 rows)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
There's an equivalence between memory
and screen: DESPLZ:(320*row)+column<=>(row,column)
Example: one pixel in row 1, column 2, it's in DESPLZ:(320*1)+2=DESPLZ:322.
And what is DESPLZ ? Segment
A000h. So, the first position of the screen in memory is the byte A000h:0000h.
Then, If i want to draw one pixel of
color P (one pixel is a byte=[0..255] -> you know now why we have 256 colors
^_^) in row R, column C, i must make one operation:
$A000:[(320*R)+C]:=P
Now we have color P in row R, column
C of the screen.
PUT SOME COLORS INTO YOUR LIFE
RGB. Palette
As you know, one color is made by mixing
other colors.
For example: black is the mix of no colors, white is the mix of
all the colors, and violet is red+blue.
In PC, the mechanism is the same (mix
colors). Every color is the combination of some basic colors.
In 320x200x256 mode, colors are red,
el green and blue.
So RGB=R(ed)G(reen)B(lue).
These three colors
have 64 degrees of intensity (0..63) (this is cuz we use 6 bits for intensity:
26). When we join these intensities, we obtain one color (R,G,B):
Example: red (63,0,0) joins blue (0,0,63) and violet is the result (63,0,63) ^_^
(R=63,G=0,B=0) | (R=0,G=0,B=63) | (R=63,G=0,B=63) |
Palette is a set of colors (in this mode 256), and everyone is made with the method described above (combination Red.Green-Blue). We can say that we have an array of 256 elements, and one element is the result is three intensities: (R[0..63],V[0..63],A[0..63]).
DAC
Where's the palette?. Here.
DAC is a Digital to Analogic Converter.
It converts RGB intensities to colors in the screen (said fast and not
very well ^_^).
It has 256 registers of 18 bits (<-palette),
and every one of these registers has the RGB intensities. When in screen
we draw the pixel x (23, f. ex.), x is the index to one of the DAC registers.
DAC Ports
DAC has some ports, and through them we can read/write the RGB intensities of every color:
PORT | BASIC FUNCTION |
3C7h (Pel Read Address) | Index to a color to access(0..255) |
3C8h (Pel Write Address) | Index to a color to change(0..255) |
3C9h (Pel Data DAC) | Access to a DAC register |
How to use DAC ports and BIOS to change the intensity of colors.
Read a DAC register (read the RGB
components of a color):
Set in port 3C7h the color to be accessed.
Next we read three times the port 3C9h, and we obtain the RGB components
(1º red, 2º green y 3º blue).
Change a DAC register (write the RGB
components of a color):
Set in port 3C8h the color to be changed.
Next we write in 3C9h the RGB components (1º red, 2º green y
3º blue, three writes).
Change an entire palette (using BIOS
interrupts):
(I suppose we have a var. called Palette
=> Array 0..255 of r,g,b:byte).
Use interrupt 10h, service 10h, subfunction
(al) 12h (change DAC components).Bx=0 (start in the first color, 0), Cx=256
(change 256 colors), Es:Dx=Seg(Palette):Ofs(Palette) (Segment and Offset
of variable palette).
NOTE: the record r,g,b:byte is in this
order 'cause system takes the first component of the record as R, second
as G and third as B.
VERTICAL
RETRACE
(Thanks to PCActual magazine and to
Antonio Ropero)
Retrace
The image in screen bring up-to-date
its contents from video memory, $A000:0000 (this can't be saw by human
eyes, but videocameras can: try to film your monitor).
And how happens? An electron beam starts
in the first line of the upper left corner, and goes to the right. When
it arrives into the edge of the right, goes to the next line. It ends in
the lower right corner. (see that the beam starts in the start of video
memory and ends in the end of video memory. Look at tables in
Pixels.
Where are, and how to change them).
This process is iterative.
What is Vertical retrace?
When the beam arrives to the lower right corner, it goes to the upper left corner. This moment is called vertical retrace.
What problems have?
The vertical retrace have no problems
^_^. But the beam has: If we draw an sprite in the screen when the beam
is working, the sprite may flick (cuz not the entire image'll be draw,
only the part after the beam).
Example: if we draw an sprite $A000:3FF0 a $A000:4005 and the beam
is in $A000:4000, only the range of pixels $A000:4000=>$A000:4005 will
be displayed (the other pixels of the sprite must wait the next beam).
How can I avoid flickering?
Waiting the vertical retrace. In this
moment the beam will be in $A000:0000 and every pixel we draw will be put
onto screen.
And V.R. has another good thing: makes
an universal delay for every computer (cuz V.R. not depends on microprocessor
Mhz).
BEHIND SCENARIO: VIRTUAL SCREENS
What are virtual screens?
Remember that screen is mapped in memory
(1 pixel=>one byte in video memory). Well then, a virtual screen is a variable
that imitates the structure of video memory (Array[0..63999] of byte).
If we imitate the structure of video
memory, we can "draw" pixels (write bytes) onto this "screen", using the
segment of the virtual screen: SegVirtual:[(320*R)+C]. Of course every
"pixel" in this "screen" won't be wrote in the real screen.
How can i use them
If we draw the scenario and the sprites in the real screen, the gift will be a brutal flickering.
So we draw the pixel onto the virtual
screen, wait the vertical retrace and flip the contents of the virtual
screen onto memory. (We copy the 64000 bytes of v.s.to [$A000:0000,$A000:FFFF]).
Then, there'll be no flick with this
method.
In future...
Virtual screens have more uses: scrolls, backups,...etc. See the next lessons of this tutorial.
In the .zip with the game there's two
files: G320x200.pas and virtuals.pas. They have the routines
of all the things explained in this file, with more things
Well, its 3:35 am, i want to sleep,... Why i don't use a translator like everybody in this world ?. I suppose i'm a @·$%¿?!, but translators are @#!#?¡# ....^_^.