- THE OUTLAW TRIAD DEMO-SERIES -
------------------------ PART V ------------------------------------
Written by : Vulture/OT
Code in : Pascal/asm
Topic : Decoding .pcx files
---------------------- Introduction --------------------------------
Welcome to the Outlaw Triad demo-series! In these series we will be
talking about programming demo-effects in either pascal or assembler.
Theory behind the effects shall be discussed while a full sourcecode
is also provided.
We have reached the fifth release in these series already. This time
we will talk about decoding .pcx files. This is a very wellknown
graphics format and very easy to use, once you know the trick. A full
pcx-decoding routine coded in Pascal is provided. Enjoy!
------------------------- Theory -----------------------------------
Note: we will discuss how to decode a .pcx file in plain mode 13h.
This will not work in any unchained mode or high resolution modes.
Ok, let's get right down to business and start with looking at the
actual format of a .pcx file. Here it is:
- Header (128 bytes)
- Data part
- Palette (768 bytes)
Now, usually we can just ignore the header when we know we want to
display a picture in plain mode 13h. Anyhow, for those of you who
want to know how the header looks like, I'll type it down:
0 Manufacturer
1 Version
2 Encoding
3 Bits Per Pixel
4 XMin, Ymin, XMax, YMax (2 bytes each)
12 Horizontal Resolution (2 bytes)
14 Verticle Resolution (2 bytes)
16 Color pallette setting (48 bytes)
64 Reserved
65 Number of color planes
66 Bytes per line (2 bytes)
68 1 = Color 2 = Grayscale (2 bytes)
70 Blank (58 bytes)
That's it. This adds up to 128 bytes.
Ok, as you can see from the format, the palette data is situated
right at the end of the .pcx file. It's usually best to set the
palette of the .pcx file before you write the file to the screen.
To set the palette, you could do something like this:
- Seek to (end of file - 768)
- Grab values
- Divide all by 4
- Send to vga
Vga RGB values range 0..63 while the RGB values in the .pcx file are
0..255. To get the correct vga values, we divide by 4.
In the sourcecode I grabbed all 768 RGB values at once. I've set the
colors using a standard SetColor procedure. Easy stuff, once you know
what to do...
Ok, now let's start decoding, shall we? (ignore header, seek to 128th
byte)
We read a byte from the data. If the top 2 bits of the byte aren't
set, the byte can be written to the screen. If they ARE set, we go
into a loop in which we process the next byte. In pascalcode:
Temp := (read first byte from data)
If ((Temp AND 192) = 192) then { Top 2 bits set?
(192 = 11000000b) }
Begin { If so, then go write next byte }
Temp2 := (read next byte from data)
For Loop := 1 to (Temp AND 63) Do { Set loopcounter
(63 = 00111111b) }
Begin { Write next byte a number
of times }
SetPixel(VgaPos,Temp2);
Inc(VgaPos);
End;
End
Else { Top bits not set,
plot first byte }
Begin
SetPixel(VgaPos,Temp); { Temp = color }
Inc(VgaPos);
End;
So, what does all this mean? Well, like stated previously, first we
see if the top 2 bits of the FIRST byte we read are set. If the top
2 bits are set, we go and write the NEXT byte to the screen.
The number of times we write the next byte to the screen is
determined by ANDing the FIRST byte with 63. If the top two bits of
the first byte aren't set, we simply write the first byte to the
screen. That's all there is to it! In steps:
- 1. Read a byte
- 2. Check if top 2 bits of that byte are set
- 3. If they are set, go to 5
- 4. Top 2 bits aren't set, write the byte to the screen
(and back to 1)
- 5. Determine loopcounter by 'and'ing the byte with 00111111b
(63)
- 6. Read next byte
- 7. Write that byte to the screen a number of times
(then back to 1)
Pretty easy once you get the point...
For those of you who don't know much about assembler and the 'AND'
command, I will spend a few bytes extra... If you 'and' a bit with 0,
that bit will get the value 0. An example:
(original byte) 10101010b
('anding' byte) 01000001b
---------
(resulting byte) 00000000b
You see? So with the 'AND' command you can disable certain bits in a
byte!
Now what happens when we 'and' a bit with 1? In that case, the bit
will keep it's origal value. An example:
(original byte) 01010101b
('anding' byte) 10111110b
---------
(resulting byte) 00010100b
Get it? I know this all might sound pretty damn cryptic if you are
new to this. Just go and read a book on assembler and practise a lot.
And remember these two things:
- a bit 'anded' with 0, will be 0
- a bit 'anded' with 1, will keep it's original value (0 or 1)
When you keep this in mind, the pcxdecoder is a piece of cake.
Just do some experimenting and you'll get it eventually.
Trial and error rulez... ;-)
The routine provided here to decode a pcxfile is very slow. However,
you can speed it up by using more assembler code. Also, you should
implement code to write the pcx file to another destination besides
the VGA screen, like a virtual page. Hint: load the pcx into memory
at once. Don't read data byte per byte from disk. That's very slow.
And remember, this is only an example. I can give you my own routines,
but I feel that people should learn for themselves and not just use
code they found somewhere. However, if you really want more code,
write me and I'll send 'm to you. Oh, if you find this stuff usefull,
a mention in your own productions is appriciated.
Having problems? Mail me! I'd like to hear from you!
Ok, this is all for now. Happy coding!
- Vulture / Outlaw Triad -
----------------------- Distro Sites -------------------------------
Call our distrobution sites! All our releases are available at:
BlueNose World HQ +31 (0)345-619401
FireHouse Distrosite +31 (0)528-274176
The Force Distrosite +31 (0)36-5346967 More distros wanted!
Bugs'R'Us Distrosite +31 (0)252-686092 (preferably outside
MagicWare Italian HQ +39 6-52355532 of The Netherlands)
ShockWave South African HQ +27 (011)888-6345
Also check the major FTP sites for Outlaw Triad productions.
-------------------------- Contact ---------------------------------
Want to contact Outlaw Triad for some reason? You can reach us at our
distrosites in Holland. Or if you have e-mail access, mail us:
Vulture (coder/pr) comma400@tem.nhl.nl
Our internet homepage:
http://www.tem.nhl.nl/~comma400/vulture.html
These internet adresses should be valid at least till june 1996.
----------------------------------------------------------------------
Quote: There are 3 types of persons: those who can count and those
who can't!
----------------------------------------------------------------------
Note for those of you who read part 4 of these series...
I removed a small but annoying bug from the source code.
Before writing a characters scanline, you must READ the byte from the
vga position you are planning to write to. This will load the latches
and readies the vga for your WRITE command. I forgot to do this in the
source which resulted into incorrect characters (e.g. white background)
when you run the program.
Anyway, this is what you got to implement. Shouldn't be too hard...
----------------------------------------------------------------------
|