How to write your own PIX pack for C1
User avatar
Toshiba-3 created How to write your own PIX pack for C1 on Thu Apr 29, 2010 12:44 pm
(and thus prepare your custom textures)

With this article, you should be able to /write/ your own pix pack for Carmageddon 1 (C1) from scratch, and then include your bitmaps easily with CarmagEdit.
Prior to reading and trying to go on with this article. Be sure that you have a hex editor installed (Hex Workshop, FrHed, 010 Editor, etc.).

This stuff is only useful for C1 modders or for people who would like to start modding C1. It is useless for any C2 editing!
I highly recommend you totaly read this article before attempting to create a pix pack for the first time. This way you'll have a global idea of what is awaiting you.

Hexadecimal values will always be followed by a "h" and decimal values by a "d" right after them. Decimal values are what you'll calculate then turn into hexadecimal ones to write in the binary file.
Examples: 16d is your usual friendly sixteen, 16h however equals twentytwo in decimals.

(In this case) a byte will be represented by two hexadecimal characters together like 00, 6B, 1A or FF (examples). I'll often speak about them in the following.
Four bytes are called a 'word'. Data isn't always organized as formatted words though.
OK... hang on to your helmet...


So launch your /favorite/ hex editor and create a new binary file. C1 pix packs always start with two words: a type one (always 12h) then a lenght one (as in C1/C2 these first two words are always followed by eight bytes, value is always 8h). The following eight bytes are made of two words: the file type (in our case 02h) and then the last word of the header is always 02h for any file.

If you didn't understand what I explained, don't worry and just write the following in the hexadecimal part of your editor (not ascii part thus!):

00000012 00000008 00000002 00000002 (don't pay attention to the spaces ofcourse)

This part must only be written once per pix pack file (at the very start thus). The rest of the file will be the texture entries.
You'll notice that the word values are always written starting with the last byte. It will always be like that for any C1/C2 file.
You'll also notice that this header has no value as to how many texture entries the pix pack has. This means you'll be able to add/remove entries easily without having to change the header or any value.
This was the header, thank you very much, see you next week!


What I mean by 'entries' is the textures. These entries are divided in two parts: the texture infos and the actual texture data.
The texture infos is the most important part and will probably make you rage from time to time. This part always start with two words. The first is always the same and its value is 03h. The second one is a bit mysterious as its value varies from 15h to 18h and I don't have a clue why, especialy as changing this value seems to have no effect in any way. I'm used to set 15h for small textures and 18h for large ones but I'm pretty sure it's incoherent. Oh well. Let's always write 16h.

So now (directly after the header) write this:
00000003 00000016

Now the entry isn't organized in words anymore. What comes next is an 'image type' byte followed by a series of integers using two bytes each.
In order: image type byte, width, width again, height, half of the width, half of the height.
In C1 the image type is always 03h (it means 8bit color depth). Width and height are ofcourse the ones of the texture we are written the entry for. They will most probably not be the same for every texture so the entries will have to be rewritten (or at least modified) for the other textures.

You must pay attention to the dimensions of your textures! Even if C1 seems to be able to support weirdo sizes ala 51*76px, these can get very complicated to calculate (in order to write the correct values in each entry I mean). Power of two are the best bet (32*32px, 128*256px, 2*1024px, 16*64px, etc.), but if you want very specific dimension here's what I suggest: the half of the dimension shouldn't finish with five (example: don't choose 70d because its half is 35d) ; what's even better is to choose a dimension that can be divided by four and still be an integer (like 12d) or then choosing two dimensions whose multiplication can be divided by sixteen (56*26px for example) but then the width must always be the one divisible by four at least. So you guessed it, stay with even numbers and make sure they can be divided by two a few times (if the first dimension can only be divided by two one time, the second dimension must be divisible by two three times and chosen as width, etc.).

Let's try to resume that: the width must be the most divisible dimension, avoid a dimension whose half ends with five (or then choose it as height), the multiplication of both dimensions must be divisible by sixteen.

Ok so let's get back at writing that chunk. In this article I'll use 56*26px as dimensions. What is their equal in hexadecimal?...

In order the chunk is thus:
03 0038 0038 001A 001C 000D

If your dimension is larger even in hexadecimal simply fill the two bytes. If your decimal dimension is 1234d for example, hex is 4D2h so write 04D2h. Got it?

Now what directly follows this chunk is the texture name, I suggest you write it in the ascii part of your editor. Here I choosed to name the file TEST1.PIX. There's probably the same name lenght limit as in C2 (14 chars) but I highly recommend sticking to the good ol' 8.3 format maximum and in all caps!
The filename is always followed by a null byte (the game uses it to notice when the name ends). In my case the hexadecimal chunk looks like this:
54455354312E504958 00

We are almost done! The final part of the texture infos starts with a word whose value is always 21h. Then two similar words containing the division by sixteen of both dimensions multiplication. And finally the closing word (always 01h).

If my english doesn't make enough sense, what I meant with the division is this: (WIDTHxHEIGHT)/16
In my example I already wrote it up there: 56dx26d=1456d | 1456d/16d=91d | 91d=5Bh
5Bh is the value we are seeking (in this example, your division result will most probably be different). However the word composition is a bit different in this case as we'll have to keep the very last half byte of each word to put exclusively 8h and 0h. Let me show you.

So we know both words must contain 5Bh (in this article uh) but there's a forced half byte offset filled with 8h for the first byte and 0h for the second. If I had the first and last words it looks like this:
00000021 000005B8 000005B0 00000001 (I guess it's explicit enough)

Feww! I'll write everything again to have a good look at it:
00000012 00000008 00000002 00000002 (pix pack header)
00000003 00000016 (texture entry header)
03 0038 0038 001A 001C 000D (image type and dimensions)
54455354312E504958 00 (name.ext and null byte)
00000021 000005B8 000005B0 00000001 (kind of coefficient)

This all without spaces or carriage return obviously. The hardest part is done. Let's put the bytes CarmagEdit will later edit. To achieve that simple get back the multiplication of the width and height (in this case 1456d) and insert the same amount of bytes. Yes, your hex editor is supposed to have this feature. Make sure you place your cursor at the end (in the hex part, not ascii!), use the insert function, make sure that this tool will read the amount of bytes to insert as a decimal value (hex workshop might insert 1456h bytes (=5206d!) instead of 1456d for example), and if you can set the byte value choose/write FFh (this way you can easily see where the texture bitmap data starts and ends). And finally insert eight null bytes (00000000 00000000) to finish this entry.

At this point you should have the header and one complete entry. I suggest you save your file (as PACKTEST.PIX for example, don't forget the extension uh) and try to open it in CarmagEdit. If everything went well it should display one white texture with the correct dimensions ready to import your 8bit bitmap!


Ok so you got the file header right and one first entry to insert your texture. Ofcourse your car/track is probably not made out of one single texture. There are few chances that all your textures have different sizes. Logically you should even stick with as many power of two dimensions as possible (btw using these dimensions speeds up the loading a little). So imagine we have five 32*64px textures, one 64*64px, one 128*64px and one non-power of two ala 216*68px. Well you'll write the first texture entry with the correct dimensions etc., fill it with the right amount of FFh bytes to insert the bitmap and finish it with the eight null bytes. Now select the hex part of the chunk starting with 00000003h and stop after the eight null bytes. This is a complete chunk, copy it and paste it four more times (in the hex part, remember to never work in the ascii part of your editor but for text editing). Your five 32*64px texture entries are already there! You just have to change their name, remember that the name lenght doesn't matter much, just try not to have filenames longer than eight characters (the extension not counting) and don't forget to finish it with a null byte. Now write your 64*64px entry but stop right before inserting the lot of FFh bytes. Select your new chunk from 00000003h and stop after the closing 00000001h word, and copy it. Insert the correct amount of FFh bytes and then the eight null bytes. The 64*64px texture is done. Now paste your previous hex selection, change the height, then the half of the height, the name and finaly the kind of ratio. Fill in the right amount of FFh bytes again (should be double as last time) then the eight bytes and so your 64*128px texture is done. Now for that bigger texture with unusual dimensions it's better to start the last chunk from scratch again just to make sure you don't miss a thing.

I suggest you save your file often and test it with CarmagEdit (chunks must be complete uh! including the eight null bytes).
When you are done there's nothing to add at the end of the file. The last texture entry will finish the file with its eight null bytes.
You'll notice that I started with the smaller textures and ended up with the bigger ones. This is a more convenient order as the bigger the textures will be the more bitmap data (the FFh bytes) they'll require, and thus it becomes easier to get lost in your file. At some point if you have too much big textures it'd be wise to skip the FFh bytes filling and do it when you're done creating all the entries.

Voilà! Seems like we are done! Good luck!
Pages: 1

Extra information
It is currently Wed Feb 20, 2019 11:52 am,

Please Register a username.
In total there is 1 user online :: 0 registered, 0 hidden and 1 guest
Users browsing this forum: No registered users and 1 guest
Moderators: coffeycup, Toshiba-3

Powered by phpBB :: Hosted by n3wton :: Molested by goats
CWA Links