Say Goodbye Seq/Frame
...And hello Reference/Slot.
Windemere PAK Files
29 December 2004
After analyzing the formats used for graphics in the Dink Smallwood engine I determined it was necessary to work up a new system. Seq and frame, as they are commonly called, are ways to reference a particular image. This system is very confusing and one wrong mistake can cause the engine to come crashing down hard.
And then the creator created the PAK file.
PAK files are similar to FastFiles. The two are both single-file archives and have similar file layouts. However, PAK files are designed to be quick – no memory mappings are necessary and the code is based upon the C++ STL, a proven platform. Let's first take a look at the file format.
The first four bytes of the file contain the letters “WPAK”, for Windemere PAK. This is to ensure not only that the file is a PAK file, but mainly that the file is not compressed. If the file does not contain “WPAK” as the first four bytes it will be passed through the decompressor.
The next four bytes contain the number of files in the PAK.
The next amount of bytes are variable so that there are no name length restrictions. If your name is 13 characters long, 13 bytes will be used. If your name is 281 characters long, 281 bytes will be used. So, for as many files as there are in the PAK, these bytes are filled:
4 – The length of the file header
4 – The length of the name
x – The actual name
4 – The size of the file
File data follows after each header.
Now the question: What is a PAK good for? The main purpose is to store image files in one place. Earlier in this article I stated that the seq/frame system was confusing. I have instead implemented a better system which I call the File Reference System. There are two components to this system (Kind of like Seq and Frame): Reference and Slot. Let's see a real-life example (yes – it's actually already coded)...
PAK.Define(“Trees.pak”, “Trees”);
PAK.DefineFile(“Trees”, “Tree1.png”, 0);
PAK.DefineFile(“Trees”, “Tree2.png”, 1);
PAK.DefineFile(“Trees”, “Tree3.png”, 2);
PAK.DefineFile(“Trees”, “Tree4.png”, 3);
PAK.DefineFile(“Trees”, “Tree5.png”, 4);
PAK.DefineFile(“Trees”, “Tree6.png”, 6);
This is placed in the main.c file (or whatever I may change the name to) in a function that is called at program startup). In the scripting engine, <something><dot> indicates either a Nil Reference or a Library Reference. In this case it is referencing the PAK library (Nils will be covered in a later scripting article). So, the first line calls the Define function from the PAK library. Let's go through it one-by-one.
PAK.Define(“Trees.pak”, “Trees”);
The first argument to this function is a path to the actual PAK file. The second argument is a user-defined string to reference the PAK with. I could've called it “SabreIsfabulous”, for instance, but I thought “Trees” was a little better-fitting.
After assigning your string you can now tell the engine that the PAK file has other files.
PAK.DefineFile(“Trees”, “Tree1.png”, 0);
This assigns the “Tree1.png” file to slot 0 in the “Trees” PAK.
PAK.DefineFile(“Trees”, “Tree2.png”, 1);
PAK.DefineFile(“Trees”, “Tree3.png”, 2);
PAK.DefineFile(“Trees”, “Tree4.png”, 3);
PAK.DefineFile(“Trees”, “Tree5.png”, 4);
Ditto for these four.
PAK.DefineFile(“Trees”, “Tree6.png”, 6);
Now, on this one, Tree6.png is assigned to slot 6. Notice how slot 5 was skipped. You can assign a file to any positive integer you wish, even 123456789, as long as:
1)That number does not exceed 4294967296.
2)That number is not negative.
If you were to tell the engine to use a negative number it would be casted positive and you would, for say -1, probably get a number like 4294967295. Stay positive.
Now that this is done, how is it referenced? In a function, either:
Draw(“Trees”, 6, Xpos, Ypos);
OR
Draw(“Trees:6”, Xpos, Ypos);
Finally, one last function:
PAK.Remove(“Trees”, 0);
Great, that removes the PAK file, but what is the 0 for? If you specify 1 the loaded images in the PAK will be unloaded but the PAK will stay referenced. If you specify a 0 the engine will never have known a PAK even existed. I will probably remove this later but it's kinda fun to have it now.
What's to come:
* Sprites will reference these PAKs. You could specify Dink's Left Walk Sequence as “Dink”, {12, 13, 14, 15, 16}; or maybe you would rather do “DinkLeft”, {0, 1, 2, 3, 4}. It's up to you.
* You can stuff other things in the PAKs, like music or scripts. Well, you can already do that, but it's not coded for DinkC++.
Windemere PAK Files
29 December 2004
After analyzing the formats used for graphics in the Dink Smallwood engine I determined it was necessary to work up a new system. Seq and frame, as they are commonly called, are ways to reference a particular image. This system is very confusing and one wrong mistake can cause the engine to come crashing down hard.
And then the creator created the PAK file.
PAK files are similar to FastFiles. The two are both single-file archives and have similar file layouts. However, PAK files are designed to be quick – no memory mappings are necessary and the code is based upon the C++ STL, a proven platform. Let's first take a look at the file format.
The first four bytes of the file contain the letters “WPAK”, for Windemere PAK. This is to ensure not only that the file is a PAK file, but mainly that the file is not compressed. If the file does not contain “WPAK” as the first four bytes it will be passed through the decompressor.
The next four bytes contain the number of files in the PAK.
The next amount of bytes are variable so that there are no name length restrictions. If your name is 13 characters long, 13 bytes will be used. If your name is 281 characters long, 281 bytes will be used. So, for as many files as there are in the PAK, these bytes are filled:
4 – The length of the file header
4 – The length of the name
x – The actual name
4 – The size of the file
File data follows after each header.
Now the question: What is a PAK good for? The main purpose is to store image files in one place. Earlier in this article I stated that the seq/frame system was confusing. I have instead implemented a better system which I call the File Reference System. There are two components to this system (Kind of like Seq and Frame): Reference and Slot. Let's see a real-life example (yes – it's actually already coded)...
PAK.Define(“Trees.pak”, “Trees”);
PAK.DefineFile(“Trees”, “Tree1.png”, 0);
PAK.DefineFile(“Trees”, “Tree2.png”, 1);
PAK.DefineFile(“Trees”, “Tree3.png”, 2);
PAK.DefineFile(“Trees”, “Tree4.png”, 3);
PAK.DefineFile(“Trees”, “Tree5.png”, 4);
PAK.DefineFile(“Trees”, “Tree6.png”, 6);
This is placed in the main.c file (or whatever I may change the name to) in a function that is called at program startup). In the scripting engine, <something><dot> indicates either a Nil Reference or a Library Reference. In this case it is referencing the PAK library (Nils will be covered in a later scripting article). So, the first line calls the Define function from the PAK library. Let's go through it one-by-one.
PAK.Define(“Trees.pak”, “Trees”);
The first argument to this function is a path to the actual PAK file. The second argument is a user-defined string to reference the PAK with. I could've called it “SabreIsfabulous”, for instance, but I thought “Trees” was a little better-fitting.
After assigning your string you can now tell the engine that the PAK file has other files.
PAK.DefineFile(“Trees”, “Tree1.png”, 0);
This assigns the “Tree1.png” file to slot 0 in the “Trees” PAK.
PAK.DefineFile(“Trees”, “Tree2.png”, 1);
PAK.DefineFile(“Trees”, “Tree3.png”, 2);
PAK.DefineFile(“Trees”, “Tree4.png”, 3);
PAK.DefineFile(“Trees”, “Tree5.png”, 4);
Ditto for these four.
PAK.DefineFile(“Trees”, “Tree6.png”, 6);
Now, on this one, Tree6.png is assigned to slot 6. Notice how slot 5 was skipped. You can assign a file to any positive integer you wish, even 123456789, as long as:
1)That number does not exceed 4294967296.
2)That number is not negative.
If you were to tell the engine to use a negative number it would be casted positive and you would, for say -1, probably get a number like 4294967295. Stay positive.
Now that this is done, how is it referenced? In a function, either:
Draw(“Trees”, 6, Xpos, Ypos);
OR
Draw(“Trees:6”, Xpos, Ypos);
Finally, one last function:
PAK.Remove(“Trees”, 0);
Great, that removes the PAK file, but what is the 0 for? If you specify 1 the loaded images in the PAK will be unloaded but the PAK will stay referenced. If you specify a 0 the engine will never have known a PAK even existed. I will probably remove this later but it's kinda fun to have it now.
What's to come:
* Sprites will reference these PAKs. You could specify Dink's Left Walk Sequence as “Dink”, {12, 13, 14, 15, 16}; or maybe you would rather do “DinkLeft”, {0, 1, 2, 3, 4}. It's up to you.
* You can stuff other things in the PAKs, like music or scripts. Well, you can already do that, but it's not coded for DinkC++.
Well, there is the obvious question of what happend when there are too many images in one pak file, but then again, if you have 65535 frames in a single sequence, well, there either is a problem, or there will be a problem. Now, since there is a limit to how many images can go into a pak file, why not limit the slot variable to a xxxx variable instead of a xxxxxxxx variable? Would that make much difference in the performance anyway? Also, I think you mean that the slot variable can't exceed 4294967295, cause, er, you didn't count zero.
Also, a pressing question, how do hardboxes fall in line with all this? Is there gonna be a certian couple bytes at the start of the wpak file letting the engine know that the file contains hardbox-images, background-images, music-files, etc? Because, I was thinking, that if you put a single hardbox for a sequence, isn't that easier than multiple hardboxes? That would make it easier, except for the misc. hardbox-image file(s). Or am I completely off tangent, and dink either already does this, or there are not even gonna be hardboxs in Windemere?
G'nite.
Also, a pressing question, how do hardboxes fall in line with all this? Is there gonna be a certian couple bytes at the start of the wpak file letting the engine know that the file contains hardbox-images, background-images, music-files, etc? Because, I was thinking, that if you put a single hardbox for a sequence, isn't that easier than multiple hardboxes? That would make it easier, except for the misc. hardbox-image file(s). Or am I completely off tangent, and dink either already does this, or there are not even gonna be hardboxs in Windemere?
G'nite.
If someone puts 65535 fames in a sequence they need their ass kicked. Plain and simple.
Let's piece this bit by bit...
Well, there is the obvious question of what happend when there are too many images in one pak file, but then again, if you have 65535 frames in a single sequence, well, there either is a problem, or there will be a problem. Now, since there is a limit to how many images can go into a pak file, why not limit the slot variable to a xxxx variable instead of a xxxxxxxx variable?
Where did I say there was a limit? There is no limit (aside from the theoretical limit of 2^32 on 32-bit machines).
Would that make much difference in the performance anyway?
Yes. Definitely. See, if I limited it to xxxx (maximum 9999) I would have to create 9999 * who-knows-how many bytes (let's say 50) because I would have to use a C Array. So, there's 500 KB allocated on the stack. With my current method using a C++ Vector you only allocate what you need. So, say you only need 7 of those 9999 slots. That's only 300 bytes, ~499.5 KB of wasted space. Not to mention that the entire 9999 slots would need to be iterated through each time instead of just the seven.
So, not having a limit is much more beneficial.
Also, I think you mean that the slot variable can't exceed 4294967295, cause, er, you didn't count zero.
Yes.
Also, a pressing question, how do hardboxes fall in line with all this? Is there gonna be a certian couple bytes at the start of the wpak file letting the engine know that the file contains hardbox-images, background-images, music-files, etc?
No. That would be wasting 4 bytes of memory. All you would need to do is use the appropriate DinkC++ command in the appropriate library and you essentially tell the engine what is in the file.
...Or am I completely off tangent, and dink either already does this, or there are not even gonna be hardboxs in Windemere?
There will not be hardboxes in Windemere. There will be hard maps, though. They will be integrated into the map file. Or are you referring to the same thing?
Well, there is the obvious question of what happend when there are too many images in one pak file, but then again, if you have 65535 frames in a single sequence, well, there either is a problem, or there will be a problem. Now, since there is a limit to how many images can go into a pak file, why not limit the slot variable to a xxxx variable instead of a xxxxxxxx variable?
Where did I say there was a limit? There is no limit (aside from the theoretical limit of 2^32 on 32-bit machines).
Would that make much difference in the performance anyway?
Yes. Definitely. See, if I limited it to xxxx (maximum 9999) I would have to create 9999 * who-knows-how many bytes (let's say 50) because I would have to use a C Array. So, there's 500 KB allocated on the stack. With my current method using a C++ Vector you only allocate what you need. So, say you only need 7 of those 9999 slots. That's only 300 bytes, ~499.5 KB of wasted space. Not to mention that the entire 9999 slots would need to be iterated through each time instead of just the seven.
So, not having a limit is much more beneficial.
Also, I think you mean that the slot variable can't exceed 4294967295, cause, er, you didn't count zero.
Yes.
Also, a pressing question, how do hardboxes fall in line with all this? Is there gonna be a certian couple bytes at the start of the wpak file letting the engine know that the file contains hardbox-images, background-images, music-files, etc?
No. That would be wasting 4 bytes of memory. All you would need to do is use the appropriate DinkC++ command in the appropriate library and you essentially tell the engine what is in the file.
...Or am I completely off tangent, and dink either already does this, or there are not even gonna be hardboxs in Windemere?
There will not be hardboxes in Windemere. There will be hard maps, though. They will be integrated into the map file. Or are you referring to the same thing?
No hardboxes? Then a sprite has no hardness? Or will it draw the hard map at runtime according to where the sprites are placed?
Ahh, my bad. I misinterpreted the question. Hardboxes will be drawn according to the commands given when the sprite is assigned to the slot. It's not coded yet, but it will be something like:
Sprite.Assign("Reference", Slot, x1, y1, x2, y2, xcenter = 0, ycenter = 0);
Sprite.Assign("Reference", Slot, x1, y1, x2, y2, xcenter = 0, ycenter = 0);
'No memory mapping necessary'
Will we ever need to preload_seq() anymore?
Will we ever need to preload_seq() anymore?
By no memory mapping necesssary I meant that mmap didn't need to be used. But no, you won't need to preload_seq. It's done automatically.
Bah, I got confused thinking that the slot number would be in the name variable. My SNAFU.
Oh, and ps, I should have mentioned, the xxx's were hex placeholders.
Oh, and ps, I should have mentioned, the xxx's were hex placeholders.
So... If I try to understand this (it was quite a long read, mind you) I've come to the following conclusion:
Basically, a lot of
PAK.DefineFile("Reference", "Name", Slot);
and
Sprite.Assign("Reference", Slot, x1, y1, x2, y2, xcenter = 0, ycenter = 0);
Will be something that acts like ye good ol' dink.ini
Basically, a lot of
PAK.DefineFile("Reference", "Name", Slot);
and
Sprite.Assign("Reference", Slot, x1, y1, x2, y2, xcenter = 0, ycenter = 0);
Will be something that acts like ye good ol' dink.ini
December 30th 2004, 05:54 PM
MiloBones
Advantage being that you don't have to remember all of those annoying seq numbers...
Exactly. The main difference is that it's done in a WASP file and that you no longer have to remember numbers: you get strings. And that there is no limit to the number of strings you can use. The strings will be CaSE SEnsiTivE, mind you.
Nice!
I'd better make sure all graphics files have logical names and follow a standard.
I'd better make sure all graphics files have logical names and follow a standard.
Like that's gonna happen.
Will it be possible to use numbers anyway? Some weapon scripts manipulate sequence numbers based on Dink's direction. I know there are other ways do do the same, but they are longer to write.
This article is out of date now. I should update it...
Short answer: since everything is user-definable, yes.
Short answer: since everything is user-definable, yes.
Yeah I assume you could make dinkmoving left referenced to a string like "1-2" 1 being dink and 2 being the left direction. It looks nice but we need new info to satisfy my lust for knowledge on the new engine
I'll get on it after my AP test and SAT in 2 weeks. Until then, I can't/won't do much.
I'd still prefer the numpad numbers for directions now that I'm used to that
well you still can use the number system if you want since you can set it to whatever you want. oh an merlin what ap tests you taking. Last year I took the european, calc and physics ap tests, physics and european was near impossible but calc was kinda easy
American History.
My friend got a 5 on AP European History. lol. Can't be too hard.
My friend got a 5 on AP European History. lol. Can't be too hard.