K
Kislinskiy
Guest
Can someone post a link to a good TIM file format description please?
TIM Graphic Formats (PSX 2D Graphics)By Klarth ([email protected])http://rpgd.emulationworld.com/klarthVersion 0.7 - January 1, 2001-- Totally rewritten for extra clarity-- Removed Opinions/Ideas on Editing Utilities SectionVersion 0.5 - August 22, 2000-- Initial ReleaseI. Table of Contents1. Introduction and Terminology2. TIM Graphic Formats (4BPP, 8BPP, 16BPP, and 24BPP)3. TIM Header Formats (4BPP, 8BPP, 16BPP, and 24BPP)4. Color Conversion Algorithms (15bit BGR <-> 24bit RGB)_______________________________________________________________________________________________1. Introduction and Terminology-----A. Introduction Hmm, I started this doc awhile ago when I first started to get interested in PSX hacking. I then concluded that many tools needed to be coded before the PSX translation "scene" could really get started. So I decided to finish it and release it so that all you coders out there can start making some graphic tools to make PSX translations remotely possible for anybody willing to try to tackle one. These formats all have headers so I decided to make a seperate document for them only since they're so different from other console graphics formats. If you wish to put this document on your site, please contact me for authorization *before* you post this file on your site. If I seem to "magically" disappear from the scene, you may post this document *only* in its original form. If you use this doc please credit me in a thanks section since I just like to see who reads and uses them.-----B. Terminology CLUT - Color LookUp Table (The Sony term for Palette) Image Org - Sets the coordinate of an image zero point, used for TIM files in the VRAM of the Playstation. Not particularly necessary from an editing point but could be useful for a program that creates TIM images and their headers. Palette Org - Sets the coordinates of a CLUT image zero point. Not particularly necessary from an editing standpoint but could be useful for a program that creates TIM images and their headers. BPP: Bits per pixel. [pA-B rC]: pixels A-B (leftmost pixel 0), row number C (topmost row 0). This won't have a bitplane value because it's a linear format. [pX rX]: The last pixel of row X. The last pixel's number is equal to the correct width of the image as defined in the header._______________________________________________________________________________________________2. TIM Graphics Data (A. 4BPP, B. 8BPP, C. 16BPP, D. 24BPP) All the graphics are stored in Big Endian order.-----A. 4BPP PSX TIM Each pair represents one byte Format: [p0-1 r0], [p2-3 r0], [p4-5 r0], [p6-7 r0], ..., [pX r0] [p0-1 r1], [p2-3 r1], [p4-5 r1], [p6-7 r1], ..., [pX r1] ... And it continues until the row number equals the height (from the header). It gets its colors from a 16 entry CLUT in the header of the file, there may be multiple CLUTs.-----B. 8BPP PSX TIM Each pair represents one byte Format: [p0 r0], [p1 r0], [p2 r0], [p3, r0], [p4, r0], [p5, r0], [p6, r0], [p7, r0], ..., [pX r0] [p0 r0], [p1 r0], [p2 r0], [p3, r0], [p4, r0], [p5, r0], [p6, r0], [p7, r0], ..., [pX r0] ... And it continues until the row number equals the height (from the header). It gets its colors from a 256 entry CLUT in the header of the file, there may be multiple CLUTs.-----C. 16BPP PSX TIM Each pair represents two bytes Format: [p0 r0], [p1 r0], [p2 r0], [p3, r0], [p4, r0], [p5, r0], [p6, r0], [p7, r0], ..., [pX r0] [p0 r0], [p1 r0], [p2 r0], [p3, r0], [p4, r0], [p5, r0], [p6, r0], [p7, r0], ..., [pX r0] ... And it continues until the row number equals the height (from the header). It doesn't need a CLUT because it's basically a type of 15bit color.-----D. 24BPP PSX TIM Each pair represents three bytes Format: [p0 r0], [p1 r0], [p2 r0], [p3, r0], [p4, r0], [p5, r0], [p6, r0], [p7, r0], ..., [pX r0] [p0 r0], [p1 r0], [p2 r0], [p3, r0], [p4, r0], [p5, r0], [p6, r0], [p7, r0], ..., [pX r0] ... Continues until the row number equals the height (from the header). It doesn't need a CLUT since it's 24bit color. I've never actually ripped a 24BPP TIM from a PSX game but I found one 24BPP TIM image and took this info from it. May or may not actually be used on the PSX._______________________________________________________________________________________________3. TIM Headers (A. 4BPP, B. 8BPP, C. 16BPP, D. 24BPP) All two byte values are in Little Endian. The rest are in Big Endian.-----A. 4BPP TIM Header: [1-4] - 10 00 00 00: ID Tag for TIM Format [5-8] - 08 00 00 00: ID Tag for 4BPP [9-10] - ? [11-12] - ? [13-14] - Palette Org X [15-16] - Palette Org Y [17-18] - ? [19-20] - Number of CLUTs [??-??] - CLUT Data. 16 Colors per CLUT, 32 bytes per CLUT. [21-22] - ? [23-24] - ? [25-26] - Image Org X [27-28] - Image Org Y [29-30] - Image Width (Multiply by 4 to get actual width) [31-32] - Image Height-----B. 8BPP TIM Header: [1-4] - 10 00 00 00: ID Tag for TIM [5-8] - 09 00 00 00: ID Tag for 8BPP [9-10] - ? [11-12] - ? [13-14] - Palette Org X [15-16] - Palette Org Y [17-18] - ? [19-20] - Number of CLUTs [??-??] - CLUT Data. 256 Colors per CLUT, 512 bytes per CLUT. [21-22] - ? [23-24] - ? [25-26] - Image Org X [27-28] - Image Org Y [29-30] - Image Width (Multiply by 2 to get actual width) [31-32] - Image Height-----C. 16BPP TIM Header: [1-4] - 10 00 00 00: ID Tag for TIM [5-8] - 02 00 00 00: ID Tag for 16BPP [9-10] - ? [11-12] - ? [13-14] - Image Org X [15-16] - Image Org Y [17-18] - Image Width (Stored as actual width) [19-20] - Image Height There is no CLUT data.-----D. 24BPP TIM Header: [1-4] - 10 00 00 00: ID Tag for TIM [5-8] - 03 00 00 00: ID Tag for 24BPP [9-10] - ? [11-12] - ? [13-14] - Image Org X [15-16] - Image Org Y [17-18] - Image Width (Divide by 1.5 to get actual height) [19-20] - Image Height There is no CLUT data._______________________________________________________________________________________________4. Color Conversion Algorithms (15bit BGR <-> 24bit RGB)-----A. 15bit BGR to 24bit RGB Color Conversion Algorithm Two bytes per 15bit BGR color, stored in Little Endian. Miscellaneous Note - Same as a SNES Palette Color. Initial 15bit BGR color in Little Endian: {ggg{rrrrr} {0}{bbbbb}gg} Swap the two bytes to change to Big Endian from Little Endian. The color order will look like this now: (b-Blue, g-Green, r-Red, 0-mystery bit) {0}{bbbbb}{gg ggg}{rrrrr} Take each of the color pairings and multiply by 8 to get a 24bit BGR color: {bbbbbbbb} {gggggggg} {rrrrrrrr} Rearrange from 15bit BGR to 24bit RGB: {rrrrrrrr} {gggggggg} {bbbbbbbb} This algorithm expands the color to 3 bytes instead of the original 2 bytes.-----B. 24bit to 15bit Color Conversion Algorithm Three bytes per 24bit RGB color, stored in Big Endian. {rrrrrrrr} {gggggggg} {bbbbbbbb} Integer Divide (DIV) each color by 8 {rrrrr}{ggg gg}{bbbbb}{0} Rearrange into 15bit BRG {0}{bbbbb}{gg ggg}{rrrrr} Swap the bytes to change from Big Endian to Little Endian (so the PSX can read it proerly) {ggg{rrrrr} {0}{bbbbb}{gg}-----C. Notes on PSX 15bit BGR Colors These are the same as the SNES 15bit BGR Colors. There is a color loss whenever converting from 24bit RGB <-> 15bit BRG. Also, there's probably a more advanced and quicker algorithm to convert the colors, however this is explaining the basic idea behind the algorithm.
typedef short int INT16;typedef unsigned short UINT16;typedef char INT8;typedef unsigned char UINT8;typedef struct{ UINT32 Magic; UINT32 Type;} base_tim_hdr;typedef struct{ UINT32 WCount; UINT16 IMGX, IMGY; // origin of image UINT16 Pitch; // in 16 bit words per horizontal line UINT16 Height; // number of lines;} base_tim_img;typedef struct{ base_tim_hdr INFO; UINT32 Bytes; UINT16 PALX, PALY; UINT16 ZZ01; UINT16 CLUT_CNT;} tim_4bpp;typedef struct{ base_tim_hdr INFO; UINT32 Bytes; UINT16 PALX, PALY; UINT16 ZZ01; UINT16 CLUT_CNT;} tim_8bpp;typedef struct{ base_tim_hdr INFO; base_tim_img IMAGEDAT;} tim_16bpp;typedef struct{ base_tim_hdr INFO; base_tim_img IMAGEDAT;} tim_24bpp;#define TIM_4BPP 8#define TIM_8BPP 9#define TIM_16BPP 2#define TIM_24BPP 3#define TIM_MAGIC 0x10// Pallette/Color Look Up Tables for TIM filestypedef UINT16 CLUT_4bpp[16];typedef UINT16 CLUT_8bpp[256];
[ 1] < 39, 52, -99>[ 2] < 0, 72, -96>[ 5] < 39, 47, -79>[ 6] < 8, 65, -68>[ 7] < 0, 69, -78>[ 12] < 37, 49, -64>[ 14] < 5, 70, -57>[ 22] < 0, 55, -29>[ 52] < -28, 48, -47>[ 57] < -5, 70, -57>[ 58] < -37, 49, -64>[ 62] < -8, 65, -68>[ 63] < -39, 47, -79>[ 64] < -39, 52, -99>
TexturedTri[11] = {[ 0] 2, 7, 62 D0080|1600 7800 2D00 390D// negative direction above nose[ 1] 7, 2, 6 D0080|2D00 7800 1600 390B// Positive direction above nose[ 2] 2, 63, 64 D0080|1600 7800 2C38 1338// positive ebrow area[ 3] 63, 2, 62 D0080|2C38 7800 1600 390D// positive eye area[ 4] 63, 62, 58 D0080|2C38 7800 390D 3E34// positive cheek area[ 5] 57, 22, 52 D0080|006D 7840 3579 1046// positive mouth/right[ 6] 57, 14, 22 D0080|006D 7840 0082 3579// mouth center[ 7] 22, 14, 21 D0080|3579 7840 0082 10A9// negative mouth/left[ 8] 6, 5, 12 D0080|390B 7800 2C38 3E34// negative cheek/left[ 9] 2, 5, 6 D0080|1600 7800 2C38 390B// negative eye/left[ 10] 5, 2, 1 D0080|2C38 7800 1600 1336// negative eye brow/left}
Textured Triangle:UINT16 Index to Coordinate 1UINT16 Index to Coordinate 2UINT16 Index to Coordinate 3 [80 00]UCHAR8 U 1UCHAR8 V 1 [00 78]UCHAR8 U 2UCHAR8 V 2UCHAR8 U 3UCHAR8 V 3Textured Plane:UINT16 Index to Coordinate 1UINT16 Index to Coordinate 2UINT16 Index to Coordinate 3UINT16 Index to Coordinate 4UCHAR8 U 1UCHAR8 V 1 [80 78]UCHAR8 U 2UCHAR8 V 2UCHAR8 U 3UCHAR8 V 3UCHAR8 U 4UCHAR8 V 4 [80 00]U/V-coords are X/Y-coords in the TIM image.To convert the U/V-coords to float[0.0f ... 1.0f] justdivide 1.0f by TIM-width/Height and multiply this with the U/V-coord:fU = (1.0f / static_cast<float>(TIM.Width)) * static_cast<float>(ucU);fV = (1.0f / static_cast<float>(TIM.Height)) * static_cast<float>(ucV);
for 1 I'll have to see if I can do that in OGLYes, it seems to be palette data between the U/V-coords. I have not checked all models but I assume black (0, 0, 0) is always transparent.
There are two options to render the models with textures:
1. Create one palettized texture (8 bit) and up to 3 palettes
2. Create a High/True-Color texture for every TIM-CLUT
fU = (1.0f / static_cast<float>(TIM.Width)) * static_cast<float>(ucU); fV = (1.0f / static_cast<float>(TIM.Height)) * static_cast<float>(ucV);
fU = (1.0f / static_cast<float>(TIM.Width + 4)) * static_cast<float>(ucU); fV = (1.0f / static_cast<float>(TIM.Height + 6)) * static_cast<float>(ucV);
My current method needs improving what I do is go through each part and check for textured triangles and quads then use the edges of where the trinagles and quads are to choose the texture information. I 'assume' anything black is transparent. This is probably wrong but I couldn't think of any more convienent wayPalettised textures are going to be a pain with OpenGL, because it doesn't (as you know) support them natively; there's an extension, which most modern cards don't support, because nobody uses paletted textures any more...
Converting them to 32-bit textures as you read them in is the best choice by a long way. When you're decoding the file format yourself, as you will be for TIM's, it's not really extra effort anyway.
The binary size requirement for OpenGL textures shouldn't give you any problems, though. If no polygon uses multiple palettes, then you can have one texture per palette, and each polygon uses one texture. If for some reason you REALLY need to have non-power-of-two-dimensioned textures (NPOTD), then there is an OpenGL extension to support that (at least one extension, maybe two), but your program isn't going to be fully portable if it uses that. Quality will suffer, too: there's good reasons why graphics cards prefer POTD textures.
Parts[35] ={//OFFSET ID UNKNOWN DATA 000000 0 FFCE ff ce 1111111111001110 000124 1 FF1F ff 1f 1111111100011111 0003C8 2 FF69 ff 69 1111111101101001 000B7C 1 FF21 ff 21 1111111100100001 000000 4 FFC4 ff c4 1111111111000100 000000 5 FF23 ff 23 1111111100100011 001A44 6 FEEC fe ec 1111111011101100 001D58 7 FFCC ff cc 1111111111001100 000000 8 FF6A ff 6a 1111111101101010 001FEC 7 FFC8 ff c8 1111111111001000 000000 10 FF6A ff 6a 1111111101101010 0020F0 7 FFC8 ff c8 1111111111001000 000000 12 FF6A ff 6a 1111111101101010 0021F4 7 FFCC ff cc 1111111111001100 000000 14 FF6A ff 6a 1111111101101010 0022F8 1 FF21 ff 21 1111111100100001 000000 16 FFC4 ff c4 1111111111000100 000000 17 FF23 ff 23 1111111100100011 0023FC 18 FEEC fe ec 1111111011101100 002710 19 FFCC ff cc 1111111111001100 000000 20 FF6A ff 6a 1111111101101010 0029A4 19 FFC8 ff c8 1111111111001000 000000 22 FF6A ff 6a 1111111101101010 002AA8 19 FFC8 ff c8 1111111111001000 000000 24 FF6A ff 6a 1111111101101010 002BAC 19 FFCC ff cc 1111111111001100 000000 26 FF6A ff 6a 1111111101101010 002CB0 0 FFD8 ff d8 1111111111011000 000000 28 FEBB fe bb 1111111010111011 002DB4 29 FF00 ff 00 1111111100000000 002F88 30 FF6E ff 6e 1111111101101110 0031EC 0 FFD8 ff d8 1111111111011000 000000 32 FEBB fe bb 1111111010111011 003670 33 FF00 ff 00 1111111100000000 003844 34 FF6E ff 6e 1111111101101110}
FF7 Object ENEMY019.LZSLOC ID PART DESCRIPTION0 0 NONE uncertain1 1 1 Waist2 2 2 Chest3 1 3 Head4 4 NONE uncertain5 5 NONE uncertain6 6 4 Right shoulder7 7 5 Right Gun Hand8 8 NONE uncertain9 7 6 Left Talon?10 10 NONE uncertain11 7 7 Middle Talon 1?12 12 NONE uncertain13 7 8 Middle Talon 2?14 14 NONE uncertain15 1 9 Right Talon?16 16 NONE uncertain17 17 NONE uncertain18 18 10 Left Shoulder19 19 11 Left Gun hand20 20 NONE uncertain21 19 12 Right Talon?22 22 NONE uncertain23 19 13 Middle Talon1?24 24 NONE uncertain25 19 14 Middle Talon2?26 26 NONE uncertain27 0 15 Left Talon?28 28 NONE uncertain29 29 16 thigh?30 30 17 shin?31 0 18 foot?32 32 NONE uncertain33 33 20 shin?34 34 21 foot?
You're right you probably shouldn't postok, i really shouldnt post because i have no idea what im talking about, but that said. what about viewing a full thingy. like all of tifa? or is that like, not possible?
Oh.. yes forgot that.. what tool does that? I forget.Desaigy Ouimate: it is possible, on FF7 PC