Posted: Mon May 02, 2016 6:45 am Post subject:
TMP File Format (has damaged art)
Does anyone know how this works? I thought it would be only a simple boolean switch (one bit being either 0 or 1), but noticed there are some complex numbers involved.
A TMP has a main header and a header for each tile.
This is the header for each tile that i got from the XCC code IIRC
{
__int32 x; // position
__int32 y;
__int32 unknown1[3];
__int32 x_extra; // position of extra graphics
__int32 y_extra;
__int32 cx_extra; // size of extra graphics
__int32 cy_extra;
__int32 unknown2[4];
};
unknown2[4] seems to be the one defining HasDamagedArt
I compared what TMP Studio writes in this. It writes
2 for no damaged art
6 for damaged art
however, when i checked original TS files, i got values like
-842150449
and
-842150450
on different tiles (see isotemp.mix/ovrps01.tem)
While this is a value set separately on each tile in a TMP, TMP Studio writes it to all frames, not only the currently selected tile.
So i'm not sure if TMP Studio got the implementation correct in the first place.
e.g. on ovrps01, TMP Studio says that it has damaged art, yet there are different values set on individual tiles.
HasDamagedArt works on a per cell basis, so TMP Studio's implementation is incorrect. However because of the limited way the logic works there isn't much need to use it per cell. So technically TMP Studio's implementation is more efficient XD _________________
I'd assume the per tile base of the setting is to make sure some tiles auto-LAT to adjacent tiles, while others don't.
I think I'll make TMP Shop in a way so the user can decide how and what kind of values he wanna set (for experimentation with other values/settings). _________________ SHP Artist of Twisted Insurrection: Nod buildings
Knowing Olaf's laziness of actually doing any research but instead copy pasting stuff other people found, that pad ain't no padding but actual data too. _________________ Tiberian Dawn, Red Alert, Tiberian Sun ,Red Alert 2,Renegade, Command & Conquer 3,Tiberium and Tiberium Wars and Westwood related image & video archive
https://picasaweb.google.com/113361105083292812413?noredirect=1
Skype live:tomsons26
Don't forget to state who are you otherwise i'll ignore the invite Last edited by tomsons26lv on Mon Feb 12, 2018 1:38 pm; edited 1 time in total QUICK_EDIT
Just compared, looks like it is one more if there is extra data.
XCC, vanilla / TMP Studio
No damaged art with no extra data - CA CD CD CD / 02 00 00 00
No damaged art with extra data - CB CD CD CD / 03 00 00 00
Damaged art with no extra data - CE CD CD CD / 06 00 00 00
Damaged art with extra data - CF CD CD CD / 07 00 00 00 QUICK_EDIT
@tomsons:
it's an old txt file from Olaf. It says copyright 2000.
thanks for the updated header.
@E1 Elite:
wow, why did WW made that so complex o.O
Any insight why the difference between with and without extra graphic? _________________ SHP Artist of Twisted Insurrection: Nod buildings
those marked variables are only 3 (*) byte long, but in the file between cy_extra and height are 4 byte.
So whats the 4th byte?
Is there a 4th unsigned int missing?
(*)or actually 6 byte, since isn't unsigned int in c++ a 2byte value? How can these 3 unsigned int 2 byte values work on only a 4 byte long range in the tmp?
I would expect something like this
__int32 cx_extra;
__int32 cy_extra;
__int8 has_extra_data;
__int8 has_z_data;
__int8 has_damaged_data;
__int8 unknown;
__int8 height;
__int8 terrain_type;
Quote:
unsigned int has_extra_data: 1;
What's the : 1 standing for? Is this some strange c++ range restriction setting to make unsigned int only 1 byte long, or just a default value? _________________ SHP Artist of Twisted Insurrection: Nod buildings
On
unsigned int has_extra_data: 1;
unsigned int has_z_data: 1;
unsigned int has_damaged_data: 1;
Only 3 bits from the same byte(s) is used for extra data, z data and damaged art check. So,
low nibble (least significant) can have values from 0 to F. 4 bits in it are used as - ? D Z X
where D = Has damaged art, Z = Has z data, X = Has extra data
I always thought that 'damaged art' was nothing more than hardcoded behaviour for bridge heads which used randomized tiles for damaged art.
I have never seen anything when I programmed TMP files besides the special behaviour for bridgeheads.
IIRC there's nothing in IsoMapPack5 that indicates alternative versions for tiles.
Every tile is loaded in one big list. _________________
A TileSet can contain multiple TMP files using the filename suffix a-h.
e.g. clear01.tmp, clear01a.tmp, clear01b.tmp
If i understand it correct, the random tile selection ingame doesn't work if the tmps have the value DamagedArt set.
Only when disabled, they use the random selection.
Bridges for example use
ovrps01.tmp for the normal image and
ovrps01a.tmp for the damaged version.
On these TMPs the tiles have damaged art set, so they don't randomly switch between the different TMPs.
@E1 Elite: thanks for the info. I'll try to implement it in this way, though i'm still confused about the values of the vanilla TS files.
If i understand you correct, only 1 byte should actually change.
e.g. CA CD CD CD
But on the vanilla TS files all 4 bytes constantly change the values.
See the latest version of TMP Shop and switch into "Single Frames" mode.
If you have the 4 bytes
AA BB CC DD
TMP Shop is showing
AA on "Has Extra Data"
BB on "Has Z Data"
CC on "Has Damaged Data"
DD on "unknown Data"
Following your description, only "Has Extra Data" should change, while the other 3 stay the same. _________________ SHP Artist of Twisted Insurrection: Nod buildings
@RP:
If the Has Damaged Art bit is set to 1, then game will not randomize the tiles. XCC TMP Editor 1.04
that comes with XCC utilities sets it to 1 by default if edited. So, XCC TMP Editor 1.05 should be used.
@LKO:
If the 4 bytes are say XN XX XX XX in the TMP files, we are concerned only about the nibble represented
by N. X can be anything in 0-F. Vanilla uses CD whereas TMP Studio 00 which is anyhow irrelevant.
Within the nibble also 1 bit is unused, so the 3 bit means the same when you put A or 2. It is not in 4
seperate bytes but only 3 bits within just a nibble. QUICK_EDIT
Checked TS/RA2 vanilla files, could only find - C? CD CD CD pattern. If some file is different, let me know.
On earlier post:
Even though the C Struct is kept close to file format, it need not match the bytes exactly. Actual mapping
might be happening when reading from and writing to the file.
Typical int in C is 4 bytes on 32-bit OS. (minimum is 2 bytes)
A declaration like - unsigned int x: 5; means variable x can hold 5 bits of data.
For the tool:
If the flags of extra data or z data are disabled, the related data is not shown on the UI by tools and while
saving, those related content could be removed. Game also doesn't seem to use them when these flags are
disabled, even though the related content exists. If these flags are provided as editable fields, enabling them
on a tile that doesn't have the related data, it would need more editing capability like importing images and
coordinates editing etc. QUICK_EDIT
Knowing Olaf's laziness of actually doing any research but instead copy pasting stuff other people found, that pad ain't no padding but actual data too.
Topic revival!!!
So is this the most current correct file structure for terrain tiles?
I ask because I loaded clear01.tem, and the results are shown below.
This looks more correct... I am not sure about hasExtraData & hasZData & hasDamagedData _________________ MadHQ's Graveyard - Click here!
(Permissions) - (F.A.Q.) QUICK_EDIT
In C on 32bit and 64bit platforms, int and unsigned int are 32bit. However you have missed the :1 on those 3 boolean values. Those are bitfield entries, they take up a single bit within the bitfield (which will be 32bit due to compiler alignment). The other bits in the 32bit int aren't used and so can be set to any value without consequence.
unsigned __int8 has a value between 0 and 255, __int8 is most likely signed and so has a value of -128 to 127 IIRC. QUICK_EDIT
IsoTileHeader
{
unsigned int BlockWidth; // width of blocks
unsigned int BlockHeight; // height in blocks
unsigned int BlockImageWidth; // width of each block
unsigned int BlockImageHeight; // height of each block
};
//Following the header are pointers to each Tile, count is probably gotten by BlockWidth* BlockHeight
IsoTileImageHeader
{
signed int TileX; //X offset of the tile
signed int TileY; //Y offset of the tile
unsigned int ExtraDataOffset;
unsigned int ZDataoffset;
unsigned int ExtraZDataoffset;
signed int ExtraX; //X Offset for tile "extra"
signed int ExtraY; //X Offset for tile "extra"
unsigned int ExtraWidth;
unsigned int ExtraHeight;
unsigned char Bitfield; // known bits HasExtraData, HasZData, HasDamagedData
BYTE padding[3]; // padding made by default MSVC alignment of 0x4
unsigned char Height;
unsigned char TerrainType;
unsigned char RampType;
RGB LowRadarColor; // What color to show on the radar for this set at the lowest height
RGB HighRadarColor; // What color to show on the radar for this set at the highest height
BYTE padding[3]; // padding made by default MSVC alignment of 0x4
}
//Note seems Westwood forgot to clear allocated memory so a lot of tiles have 0xCD in them(0xCD is the default value newly allocated uncleared memory is set to in MSVC)
This all is likely to be revisited as more is discovered _________________ Tiberian Dawn, Red Alert, Tiberian Sun ,Red Alert 2,Renegade, Command & Conquer 3,Tiberium and Tiberium Wars and Westwood related image & video archive
https://picasaweb.google.com/113361105083292812413?noredirect=1
Skype live:tomsons26
Don't forget to state who are you otherwise i'll ignore the invite Last edited by tomsons26lv on Thu Apr 19, 2018 6:02 pm; edited 16 times in total QUICK_EDIT
IsoTileHeader
{
unsigned int MapWidth;
unsigned int MapHeight;
unsigned int Width;
unsigned int Height;
};
//Following the header are pointers to each Tile, count is probably gotten by MapWidth* MapHeight
IsoTileFrameHeader
{
long offset; // offset of the tile in the file. Is 0 for empty tile
unsigned int TileX; //X offset of the tile
unsigned int TileY; //Y offset of the tile
unsigned int extra_offset; //offset of extra data
unsigned int z_offset; //z_data offset
unsigned int extra_z_offset; //offset of extra z_data
signed int ExtraX; //X Offset for tile "extra"
signed int ExtraY; //X Offset for tile "extra"
unsigned int cx_extra; //width of extra graphics
unsigned int cy_extra; //height of extra graphics
DWORD Bitfield; // known bits HasExtraData, HasZData, HasDamagedData
unsigned char Height;
unsigned char TerrainType;
unsigned char RampType;
unsigned char RadarRedLeft; //The C&C engine has some complex bitshifting to determine color mode by calculating Left and Right shifts of colors, these results are then used in drawing, having these in here simplifies things as the game doesn't need to calculate this then.
unsigned char RadarGreenLeft;
unsigned char RadarBlueLeft;
unsigned char RadarRedRight;
unsigned char RadarGreenRight;
unsigned char RadarBlueRight;
BYTE[3] padding;
}
Tomsons has updated his post with updates regarding the Low and High colours, what actually are for the when the tile is on the lowest cell height and highest cell height. The game then generates the remaining 10 levels from these two.
In addition to that, after spending some time looking into the IsoTile loading code it seems that by default, each tile is assigned sequence value of 1, but if there is a sequence of tiles in a set (think of clear##[a-x].tem) then they are stored in a linked list and bit 3 of the tile options controls if it randomises. So the name of "HasDamagedData" is actualy a bit that controls if it should randomise the tile data, but the logic behind this is unclear at the moment, i would need more time to look into it. QUICK_EDIT
Tomsons has updated his post with updates regarding the Low and High colours, what actually are for the when the tile is on the lowest cell height and highest cell height. The game then generates the remaining 10 levels from these two.
Are you sure that is correct. Height can go more than just 2 + 10 = 12. Though graphics glitches starts forming after height 12. But both in-game color and radar color work with height 13 and 14. Game might have certain brightness value (consider map [Lighting] section also) to multiply depending on height for both in-game and radar. Don't test in YR as its radar doesn't show contrast variation as in TS.
Calling it as lowest height and highest height also is misleading. If you look at clear*.tem tileset, those have almost same values. Some high value is even lower than low values. And in TS you can see good amount of brightness variation both in-game and in radar depending on height with clear tiles. QUICK_EDIT
I don't get what i see there.
There is no green shown in the screenshot and just some red spots like a brutal jpg compression. _________________ SHP Artist of Twisted Insurrection: Nod buildings
So if I understood correctly, the two values seem to define a gradient that the tile is represented with on the radar? Why not simply settle for one base colour...
Lin Kuei Ominae wrote:
I don't get what i see there.
There is no green shown in the screenshot and just some red spots like a brutal jpg compression.
Yes there is, the green is clearly visible next to the red pixels. Maybe you need to adjust your monitor's colour settings. _________________ Last edited by Crimsonum on Sat Apr 21, 2018 9:22 am; edited 3 times in total QUICK_EDIT
The radar image was too small. Attaching the test map as well as the modified TS clear*.tem files. Ecache08 has red/green and ecache09 has red/black for the colors.
Joined: 24 May 2004 Location: Flanders (Be) Posts:300000001
Posted: Fri Jul 27, 2018 6:52 am Post subject:
CCHyper wrote:
How certain is the "HasDamagedArt" flag? From what I see, that flag has something to do with if the tile is randomized or not...
CCHyper wrote:
In addition to that, after spending some time looking into the IsoTile loading code it seems that by default, each tile is assigned sequence value of 1, but if there is a sequence of tiles in a set (think of clear##[a-x].tem) then they are stored in a linked list and bit 3 of the tile options controls if it randomises. So the name of "HasDamagedData" is actualy a bit that controls if it should randomise the tile data, but the logic behind this is unclear at the moment, i would need more time to look into it.
This is actually interesting, since RA1 tiles also have this kind of logic; a tileset in RA has a switch to change them from "a series of tiles that make up one tileset" to "a 1x1 tileset that can randomly take one of the included tiles".
It's used a lot in the Interior theater, and I think the game's default terrain also uses that logic. _________________ QUICK_EDIT
In RA1, the variations are stored in the same terrain file like arro0001.int or clear1.tem. In TS/RA2/YR, these are stored in different files like clear01.tem, clear01a.tem to clear01g.tem. When the HasDamagedData bit is set then the variations are not used for random placing but instead used in damage logic like ovrps01.tem is non-damaged bridge section tile whereas ovrps01a.tem is damaged tile for the same bridge section.
TileSet also takes a different meaning here. Terrain INI files like temperat.ini defines a set as a collection of tiles. Like water tiles start with filename as water where TilesInSet gives the number of tiles in the set making it water01.tem to water14.tem. Game logic is coded for this tileset given in WaterSet= with water behaviour like how a missile shot from a submarine should behave etc.
Map's IsoMapPack5 doesn't store info on the variant of the tile. When loading the map, game will look into the tile and decide to use a random variant if the HasDamagedData bit is not set. Whereas, a savegame stores the tile variant info as well. QUICK_EDIT
You can post new topics in this forum You can reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum