home *** CD-ROM | disk | FTP | other *** search
- MCGA Graphics Tutorial
- Lesson #7
- by Jim Cook
-
- Howdy! This is going to be semi-cool. Although, I have mentioned that
- MCGA #7 was going to address page flipping, I lied! Many of you are
- probably trying to display PCX images that were not created with the
- default palette, so this issue will address everything you ever wanted
- to know about palettes. We aren't going to mess around with those
- sweet, neat BIOS routines either! Why not? 'Cause they're slooow!
-
- But first! a couple additions to the source I have already posted. The
- DisplayPCX routine seems to work fine for PCX images with an even width,
- but (and you knew there was a but) when the PCX is saved with an odd
- numbered width, it seems the PCX format calls for an extra byte to be
- added for padding. I use Deluxe Paint II enhanced for all of my
- artwork, and it adds the pad byte. I cannot assume that it will do this
- for everyone. To fix the currrent routine add the indicated line:
-
- Procedure DisplayPCX (X,Y:Integer;Buf:Pointer);
- ...
- NumRows := Header^.YMax - Header^.YMin + 1;
- BytesWide := Header^.XMax - Header^.XMin + 1;
- >>>>>> If Odd (BytesWide) then Inc (BytesWide); <<<<<<
-
- For I := 1 to NumRows do begin
- ...
-
- I think that this should fix most problems, but let me know if it
- doesn't. Just one more thing. Those of you familiar with assembly will
- notice that my assembly routines contain rep movsw or some other
- repetitive move, store, or read command. You also know that these
- repetitive commands can work in forwards or reverse. Well, we want them
- to go forwards and I forgot the itty bitty command to do this. Add
-
- cld
-
- to the following routines:
-
- Procedure ClearScreen (Color:Byte);
- Procedure HorzLine (X1,X2,Y1:Integer;Color:Byte);
- Procedure ExtractLineASM (BytesWide:Integer;Var Source,Dest:Pointer);
- Procedure GetImageAsm (X1,Y1,X2,Y2:Integer;P:Pointer); assembler;
- Procedure PutImageAsm (X1,Y1:Integer;P:Pointer); assembler;
-
- Just put the cld command on a line by itself in each routine before a
- rep command is encountered. By the way, don't put it in a loop!
-
- OK, enough dwelling on the past. Let's put it in high gear and learn
- this palette stuff.
-
- The MCGA palette consists of 256 colors. Those 256 colors (numbered 0
- through 255) can be chosen from a total palette of 262,144 colors. How
- did they come up with this number? To understand this concept we have
- to change the way we think about color. Think of color in terms of
- Textmode. We have numbers to represent colors. For example 0 is Black,
- and 15 is white. It's similar in MCGA modes, in that, if you had a picture
- that was made up of color #15, it would probably be a screen full of white.
- Suppose we wanted to make it a screen full of Black? We could fill the
- entire screen with color #0, OR we could change the color of #15. I can
- hear the buzzing now. All color #15 means is, color #15 points to a
- lookup table (PEL) where three bytes are waiting to designate the percentage
- of red, green and blue that make up that color. Take a look at the
- sketch below. If you looked at the address in memory where the
- information is stored for color #209 it would look like this:
-
- │ 8h │
- ├─────────┤
- Red │ 8h │ < Color #209
- ├─────────┤
- Green │ 16h │
- ├─────────┤
- Blue │ 10h │
- ├─────────┤
- │ 8h │
-
- What the PEL tells us, is color #209 is made up of 8% red, 22% green,
- and 16% blue. A 50% gray is represented as $32,$32,$32. You will notice
- that the largest percentage number (63) can be represented in 6 bits
- (111111b). You may sometimes see this type of palette written as 6-6-6.
- I said that the maximum number of colors we can choose our screen colors
- from is 262,144. This comes about by considering all of the possible color
- combinations of red, green and blue yielding 64 x 64 x 64 = 262,144!
-
- If this is getting confusing, drop me a note and I will spend some more
- time on this. It really is critical to understanding smooth fades.
-
- You may think that updating a color #'s RGB value is as easy as putting
- new values into the PEL area of memory. This is true, but with one
- catch. The PEL resides on your graphics card. We cannot update it
- simply by poking a new byte into memory. Instead, we communicate to the
- VGA card via latches or IO ports. Welcome to the wonderful, wacky world
- of the VGA.
-
- To set a RGB sequence we concern ourselves with two ports. Let's say we
- want to change color #209 to the RGB values of (20h,40h,60h). First we
- send the number of the color we want to alter out port #03C8:
-
- Port [$03C8] := 209
-
- Next, we send the RGB values we want to change to out through port #03C9:
-
- Port [$03C9] := $20;
- Port [$03C9] := $40;
- Port [$03C9] := $60;
-
- After we update each red, green, and blue value, port $3C8 advances to
- the next color number and we could do that one right away. I can't
- begin to tell you how much faster this is than using the BIOS routines
- to do the same thing. It was pretty painless also.
-
- There is one thing to consider. While our palette is 6-6-6, the PCX
- format saves its palette as 8-8-8. This means that White, for example,
- is stored as ($FF,$FF,$FF), while we need it as ($63,$63,$63). This is
- very simple to fix. Simply read in the palette, and as each byte comes
- in shift it two places to the right.
-
- So much for writing a palette register. Reading the RGB values for a
- color register is just as simple. the only difference is the first port
- we call is $3C7:
-
- Port [$03C7] := 209
- Red := Port [$03C9];
- Green := Port [$03C9];
- Blue := Port [$03C9];
-
- The rest of the routine stays the same.
-
- Have you ever seen a professionaly written computer game fade to black,
- just like on the TV when a commercial comes on. I call this a
- commercial fade. What you do is gradually take all of the palette's RGB
- values slowly to a RGB value of (0,0,0). The trick is to take each
- color to Black at equal percentages. For example, if you have the color
- white ($63,$63,$63) and you want to make it approach black (0,0,0) and
- you want to do this over 10 steps, you get the following gradient:
-
-
- Before Fade: 100% $63,$63,$63 Step 4: 40% $28,$28,$28
- Step 1: 90% $5A,$5A,$5A Step 3: 30% $1E,$1E,$1E
- Step 2: 80% $50,$50,$50 Step 2: 20% $14,$14,$14
- Step 3: 70% $46,$46,$46 Step 1: 10% $0A,$0A,$0A
- Step 4: 60% $3C,$3C,$3C Final Step: 00% $00,$00,$00
- Step 5: 50% $32,$32,$32
-
- That represents a subtle change in white to black. You can apply the
- same percentages to any color combination. Due to lack of space, I do
- not want to get into the math associated with making this a general
- purpose routine, but please take the time to look closely at the
- SetupFade and FadePalette routines in the accompanying source message.
-
- Did he say "accompanying?" Yes, I am having a difficult time keeping
- these tutorials short. I do not believe in just posting code and having
- it scavenged. I think the purpose of this echo is to provoke thought
- and encourage education. Please take the time to peruse the code
- thoroughly and ask questions if you do not understand.
-
- The accompanying code contains a new unit called PALETTE. I though it
- better to separate the palette source from the rest of the code. With
- very minor tweaking the palette unit can be used in all video modes,
- including Super VGA! Once again, I have written the routine in Pascal
- for readability (as well as y'all with < TP 6.0). You may see reference
- to WritePalette in future programs. I'm going to remove the Pascal
- routines and stick with assembler for speeeed. Those of you that cannot
- due to compiler restrictions, please nix the assembler routines and
- rename the WritePalettePas procedure to WritePalette. Hope that makes
- sense.
-
- P.S.: I included a bonus procedure I call OREO. It makes a color
- picture into a black and white. A major threat to Ted Turner's
- colorization process!......NOT!
-
- jim
-
-
-
-
-
-
-
-
-