|
Nugget
Bare-metal libraries and examples for the original PlayStation
|
A reader for Sony's TIM texture container. More...
#include <psyqo/tim.hh>
Classes | |
| struct | Section |
| One CLUT or pixel section. More... | |
Public Types | |
| enum class | Type : uint8_t { Tex4Bits = 0 , Tex8Bits = 1 , Tex16Bits = 2 , Tex24Bits = 3 , Mixed = 4 } |
| The pixel format of the data, as declared by the file. More... | |
| enum class | Error : uint8_t { None = 0 , TooSmall , BadMagic , Compressed , BadType , Truncated , BadSectionSize } |
| Why a TIM was rejected. More... | |
Public Member Functions | |
| bool | parse (const uint8_t *data, uint32_t size) |
| Parses a TIM out of a buffer, without copying or taking ownership. | |
| void | upload (GPU &gpu) const |
| Uploads the texture, and its palette if it has one, to the VRAM coordinates the file itself asks for. | |
| void | upload (GPU &gpu, Vertex texturePosition, Vertex clutPosition) const |
| Uploads to caller-chosen VRAM coordinates, ignoring the ones in the file. | |
| PrimPieces::TPageAttr | tpage (Vertex texturePosition) const |
| Builds the texture page attribute describing where the pixels landed, with the colour mode taken from the file's type. | |
| PrimPieces::ClutIndex | clutIndex (Vertex clutPosition) const |
| Builds the CLUT index for a palette uploaded at the given VRAM position. Meaningless when the file has no CLUT. | |
| bool | hasCLUT () const |
| Type | type () const |
| Error | error () const |
| const Section & | pixels () const |
| const Section & | clut () const |
| unsigned | width () const |
| The width of the image in texels rather than in VRAM units. | |
| unsigned | height () const |
A reader for Sony's TIM texture container.
TIM is the devkit's texture format, and is what most PS1 games ship. It is a thin wrapper: a short file header, then one optional CLUT section and one pixel section, each carrying a destination in VRAM and its dimensions, followed by data that is already in the layout the GPU wants. There is no compression and no decoding, so loading one is a validation pass and two transfers.
The dimensions in a TIM section are in 16-bit VRAM units rather than in texels, which happens to be exactly what GPU::uploadToVRAM wants, so the section headers drop almost directly into a Rect.
Validation is mostly a build-time concern. A TIM you produced yourself either loads or visibly does not, and paying for those checks in every shipped binary buys nothing, so define DEBUG_TIM to get them. The one exception is always compiled in: a section whose declared size disagrees with its dimensions is rejected unconditionally, because that is the only failure that is not visible. It catches a bad width, the width is what the transfer length comes from, and the result is a write past the end of the buffer rather than a wrong picture.
|
strong |
Why a TIM was rejected.
Explicit rather than a bool because the failures mean genuinely different things: a compressed TIM is a valid file this parser refuses, while a truncated one is a broken asset.
The enum keeps its shape in every configuration on purpose. All but BadSectionSize require DEBUG_TIM to be produced, but a type whose definition changes between builds is how a header and a library end up disagreeing, so the values stay put and simply go unused.
| Enumerator | |
|---|---|
| None | |
| TooSmall | The buffer cannot hold even a file header. |
| BadMagic | The file does not start with 0x10, 0x00. |
| Compressed | The reserved field is set, which marks a compressed TIM. |
| BadType | The type field is outside the range the format defines. |
| Truncated | A section claims to extend past the end of the buffer. |
| BadSectionSize | A section's declared size disagrees with its dimensions. |
|
strong |
The pixel format of the data, as declared by the file.
This is only a hint about how to view the pixels. The data is copied into VRAM the same way regardless, so treat this as the source for a texture page's colour mode rather than as something to branch on. Mixed means the file holds several formats at once.
| Enumerator | |
|---|---|
| Tex4Bits | |
| Tex8Bits | |
| Tex16Bits | |
| Tex24Bits | |
| Mixed | |
|
inline |
| psyqo::PrimPieces::ClutIndex psyqo::TIM::clutIndex | ( | Vertex | clutPosition | ) | const |
Builds the CLUT index for a palette uploaded at the given VRAM position. Meaningless when the file has no CLUT.
|
inline |
|
inline |
|
inline |
| bool psyqo::TIM::parse | ( | const uint8_t * | data, |
| uint32_t | size | ||
| ) |
Parses a TIM out of a buffer, without copying or taking ownership.
The buffer has to outlive this object. Nothing is transferred to VRAM here, so a caller can inspect the sections and decide where they should land before committing to anything.
| data | Start of the file. |
| size | Bytes available. Checked against the section extents only when DEBUG_TIM is defined. |
error() says why.
|
inline |
| psyqo::PrimPieces::TPageAttr psyqo::TIM::tpage | ( | Vertex | texturePosition | ) | const |
Builds the texture page attribute describing where the pixels landed, with the colour mode taken from the file's type.
| texturePosition | The same position passed to upload, or pixels().rect.pos when the file's own coordinates were used. |
|
inline |
| void psyqo::TIM::upload | ( | GPU & | gpu | ) | const |
Uploads the texture, and its palette if it has one, to the VRAM coordinates the file itself asks for.
Convenient for assets authored alongside the code that loads them, and the wrong choice as soon as anything decides placement at runtime, since the file wins. Prefer the overload taking explicit positions when the application owns the VRAM layout.
This is a blocking transfer with the same rules as GPU::uploadToVRAM: no other GPU transfer may be in flight. Called while a frame is running, use GPU::waitChainIdle first.
Uploads to caller-chosen VRAM coordinates, ignoring the ones in the file.
| texturePosition | Where the pixels go. Has to sit on a texture page boundary to be addressable: a multiple of 64 in x, of 256 in y. |
| clutPosition | Where the palette goes, ignored when the file has no CLUT. CLUTs are addressed in 16 pixel steps, so x should be a multiple of 16. |
Same blocking rules as the other overload.
| unsigned psyqo::TIM::width | ( | ) | const |
The width of the image in texels rather than in VRAM units.
The two differ everywhere except 16bpp, and confusing them is the classic way to end up with a sheared texture.