Updated Splashpack structure, added imhex project
This commit is contained in:
@@ -62,13 +62,17 @@ namespace SplashEdit.RuntimeCode
|
|||||||
int totalFaces = 0;
|
int totalFaces = 0;
|
||||||
|
|
||||||
// Lists for mesh data offsets.
|
// Lists for mesh data offsets.
|
||||||
List<long> offsetPlaceholderPositions = new List<long>();
|
List<long> meshOffsetPlaceholderPositions = new List<long>();
|
||||||
List<long> meshDataOffsets = new List<long>();
|
List<long> meshDataOffsets = new List<long>();
|
||||||
|
|
||||||
// Lists for atlas data offsets.
|
// Lists for atlas data offsets.
|
||||||
List<long> atlasOffsetPlaceholderPositions = new List<long>();
|
List<long> atlasOffsetPlaceholderPositions = new List<long>();
|
||||||
List<long> atlasDataOffsets = new List<long>();
|
List<long> atlasDataOffsets = new List<long>();
|
||||||
|
|
||||||
|
// Lists for clut data offsets.
|
||||||
|
List<long> clutOffsetPlaceholderPositions = new List<long>();
|
||||||
|
List<long> clutDataOffsets = new List<long>();
|
||||||
|
|
||||||
int clutCount = 0;
|
int clutCount = 0;
|
||||||
|
|
||||||
// Cluts
|
// Cluts
|
||||||
@@ -86,18 +90,21 @@ namespace SplashEdit.RuntimeCode
|
|||||||
using (BinaryWriter writer = new BinaryWriter(File.Open(path, FileMode.Create)))
|
using (BinaryWriter writer = new BinaryWriter(File.Open(path, FileMode.Create)))
|
||||||
{
|
{
|
||||||
// Header
|
// Header
|
||||||
writer.Write('S');
|
writer.Write('S'); // 1 byte
|
||||||
writer.Write('P');
|
writer.Write('P'); // 1 byte
|
||||||
writer.Write((ushort)1);
|
writer.Write((ushort)1); // 2 bytes - version
|
||||||
writer.Write((ushort)_exporters.Length);
|
writer.Write((ushort)_exporters.Length); // 2 bytes
|
||||||
writer.Write((ushort)_atlases.Length);
|
writer.Write((ushort)_atlases.Length); // 2 bytes
|
||||||
writer.Write((ushort)clutCount);
|
writer.Write((ushort)clutCount); // 2 bytes
|
||||||
writer.Write((ushort)0);
|
for (int i = 0; i < 3; i++) writer.Write((ushort)0);
|
||||||
// Start of Metadata section
|
|
||||||
|
|
||||||
// GameObject section (exporters)
|
// GameObject section (exporters)
|
||||||
foreach (PSXObjectExporter exporter in _exporters)
|
foreach (PSXObjectExporter exporter in _exporters)
|
||||||
{
|
{
|
||||||
|
// Write placeholder for mesh data offset and record its position.
|
||||||
|
meshOffsetPlaceholderPositions.Add(writer.BaseStream.Position);
|
||||||
|
writer.Write((int)0); // 4-byte placeholder for mesh data offset.
|
||||||
|
|
||||||
// Write object's transform
|
// Write object's transform
|
||||||
writer.Write((int)PSXTrig.ConvertCoordinateToPSX(exporter.transform.localToWorldMatrix.GetPosition().x, GTEScaling));
|
writer.Write((int)PSXTrig.ConvertCoordinateToPSX(exporter.transform.localToWorldMatrix.GetPosition().x, GTEScaling));
|
||||||
writer.Write((int)PSXTrig.ConvertCoordinateToPSX(-exporter.transform.localToWorldMatrix.GetPosition().y, GTEScaling));
|
writer.Write((int)PSXTrig.ConvertCoordinateToPSX(-exporter.transform.localToWorldMatrix.GetPosition().y, GTEScaling));
|
||||||
@@ -114,12 +121,8 @@ namespace SplashEdit.RuntimeCode
|
|||||||
writer.Write((int)rotationMatrix[2, 1]);
|
writer.Write((int)rotationMatrix[2, 1]);
|
||||||
writer.Write((int)rotationMatrix[2, 2]);
|
writer.Write((int)rotationMatrix[2, 2]);
|
||||||
|
|
||||||
|
writer.Write((ushort)exporter.Mesh.Triangles.Count);
|
||||||
// Write placeholder for mesh data offset and record its position.
|
writer.Write((ushort) 0);
|
||||||
offsetPlaceholderPositions.Add(writer.BaseStream.Position);
|
|
||||||
writer.Write((int)0); // 4-byte placeholder for mesh data offset.
|
|
||||||
|
|
||||||
writer.Write((int)exporter.Mesh.Triangles.Count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Atlas metadata section
|
// Atlas metadata section
|
||||||
@@ -142,18 +145,12 @@ namespace SplashEdit.RuntimeCode
|
|||||||
{
|
{
|
||||||
if (texture.ColorPalette != null)
|
if (texture.ColorPalette != null)
|
||||||
{
|
{
|
||||||
foreach (VRAMPixel clutPixel in texture.ColorPalette)
|
clutOffsetPlaceholderPositions.Add(writer.BaseStream.Position);
|
||||||
{
|
writer.Write((int)0); // 4-byte placeholder for clut data offset.
|
||||||
writer.Write((ushort)clutPixel.Pack());
|
writer.Write((ushort)texture.ClutPackingX); // 2 bytes
|
||||||
}
|
writer.Write((ushort)texture.ClutPackingY); // 2 bytes
|
||||||
for (int i = texture.ColorPalette.Count; i < 256; i++)
|
writer.Write((ushort)texture.ColorPalette.Count); // 2 bytes
|
||||||
{
|
writer.Write((ushort) 0); // 2 bytes
|
||||||
writer.Write((ushort)0);
|
|
||||||
}
|
|
||||||
writer.Write((ushort)texture.ClutPackingX);
|
|
||||||
writer.Write((ushort)texture.ClutPackingY);
|
|
||||||
writer.Write((ushort)texture.ColorPalette.Count);
|
|
||||||
writer.Write((ushort)0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -249,12 +246,31 @@ namespace SplashEdit.RuntimeCode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clut data section
|
||||||
|
foreach (TextureAtlas atlas in _atlases)
|
||||||
|
{
|
||||||
|
foreach (var texture in atlas.ContainedTextures)
|
||||||
|
{
|
||||||
|
if (texture.ColorPalette != null)
|
||||||
|
{
|
||||||
|
AlignToFourBytes(writer);
|
||||||
|
long clutDataOffset = writer.BaseStream.Position;
|
||||||
|
clutDataOffsets.Add(clutDataOffset);
|
||||||
|
|
||||||
|
foreach(VRAMPixel color in texture.ColorPalette) {
|
||||||
|
writer.Write((ushort) color.Pack());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Backfill the mesh data offsets into the metadata section.
|
// Backfill the mesh data offsets into the metadata section.
|
||||||
if (offsetPlaceholderPositions.Count == meshDataOffsets.Count)
|
if (meshOffsetPlaceholderPositions.Count == meshDataOffsets.Count)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < offsetPlaceholderPositions.Count; i++)
|
for (int i = 0; i < meshOffsetPlaceholderPositions.Count; i++)
|
||||||
{
|
{
|
||||||
writer.Seek((int)offsetPlaceholderPositions[i], SeekOrigin.Begin);
|
writer.Seek((int)meshOffsetPlaceholderPositions[i], SeekOrigin.Begin);
|
||||||
writer.Write((int)meshDataOffsets[i]);
|
writer.Write((int)meshDataOffsets[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -276,6 +292,20 @@ namespace SplashEdit.RuntimeCode
|
|||||||
{
|
{
|
||||||
Debug.LogError("Mismatch between atlas offset placeholders and atlas data blocks!");
|
Debug.LogError("Mismatch between atlas offset placeholders and atlas data blocks!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Backfill the clut data offsets into the metadata section.
|
||||||
|
if (clutOffsetPlaceholderPositions.Count == clutDataOffsets.Count)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < clutOffsetPlaceholderPositions.Count; i++)
|
||||||
|
{
|
||||||
|
writer.Seek((int)clutOffsetPlaceholderPositions[i], SeekOrigin.Begin);
|
||||||
|
writer.Write((int)clutDataOffsets[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError("Mismatch between clut offset placeholders and clut data blocks!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Debug.Log(totalFaces);
|
Debug.Log(totalFaces);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ All numeric values are stored in little‐endian format. All offsets are counted
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1. File Header (12 bytes)
|
## 1. File Header (16 bytes)
|
||||||
|
|
||||||
| Offset | Size | Type | Description |
|
| Offset | Size | Type | Description |
|
||||||
| ------ | ---- | ------ | ----------------------------------- |
|
| ------ | ---- | ------ | ----------------------------------- |
|
||||||
@@ -13,7 +13,7 @@ All numeric values are stored in little‐endian format. All offsets are counted
|
|||||||
| 0x04 | 2 | uint16 | Number of Exporter descriptors |
|
| 0x04 | 2 | uint16 | Number of Exporter descriptors |
|
||||||
| 0x06 | 2 | uint16 | Number of Texture Atlas descriptors |
|
| 0x06 | 2 | uint16 | Number of Texture Atlas descriptors |
|
||||||
| 0x08 | 2 | uint16 | Number of CLUT descriptors |
|
| 0x08 | 2 | uint16 | Number of CLUT descriptors |
|
||||||
| 0x0A | 2 | uint16 | Reserved (always 0) |
|
| 0x0A | 3*2 | uint16 | Reserved (always 0) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -21,18 +21,19 @@ All numeric values are stored in little‐endian format. All offsets are counted
|
|||||||
|
|
||||||
The metadata section comprises three groups of descriptors.
|
The metadata section comprises three groups of descriptors.
|
||||||
|
|
||||||
### 2.1 Exporter Descriptors (56 bytes each)
|
### 2.1 GameObject Descriptors (56 bytes each)
|
||||||
|
|
||||||
Each exporter descriptor stores the transform and mesh metadata for one GameObject.
|
Each gameobject descriptor stores the transform and mesh metadata for one GameObject.
|
||||||
|
|
||||||
| Offset (per entry) | Size | Type | Description |
|
| Offset (per entry) | Size | Type | Description |
|
||||||
| ------------------ | ---- | ------ | --------------------------------- |
|
| ------------------ | ---- | ------ | --------------------------------- |
|
||||||
| 0x00 | 4 | int | X coordinate (Fixed-point) |
|
| 0x00 | 4 | int | **Mesh Data Offset** |
|
||||||
| 0x04 | 4 | int | Y coordinate (Fixed-point) |
|
| 0x04 | 4 | int | X coordinate (Fixed-point) |
|
||||||
| 0x08 | 4 | int | Z coordinate (Fixed-point) |
|
| 0x08 | 4 | int | Y coordinate (Fixed-point) |
|
||||||
| 0x0C | 36 | int[9] | 3×3 Rotation matrix (Fixed-point) |
|
| 0x0C | 4 | int | Z coordinate (Fixed-point) |
|
||||||
| 0x30 | 4 | int | **Mesh Data Offset Placeholder** |
|
| 0x10 | 36 | int[9] | 3×3 Rotation matrix (Fixed-point) |
|
||||||
| 0x34 | 4 | int | Triangle count in the mesh |
|
| 0x28 | 4 | uint16 | Triangle count in the mesh |
|
||||||
|
| 0x2A | 2 | uint16 | Reserved |
|
||||||
|
|
||||||
### 2.2 Texture Atlas Descriptors (12 bytes each)
|
### 2.2 Texture Atlas Descriptors (12 bytes each)
|
||||||
|
|
||||||
@@ -46,18 +47,18 @@ Each texture atlas descriptor holds atlas layout data and a placeholder for the
|
|||||||
| 0x08 | 2 | uint16 | Atlas position X – relative to VRAM origin |
|
| 0x08 | 2 | uint16 | Atlas position X – relative to VRAM origin |
|
||||||
| 0x0A | 2 | uint16 | Atlas position Y – relative to VRAM origin |
|
| 0x0A | 2 | uint16 | Atlas position Y – relative to VRAM origin |
|
||||||
|
|
||||||
### 2.3 CLUT Descriptors (520 bytes each)
|
### 2.3 CLUT Descriptors (12 bytes each)
|
||||||
|
|
||||||
CLUTs are the only data which is stored in the Metadata section.
|
CLUTs are the only data which is stored in the Metadata section.
|
||||||
For each CLUT (Color Lookup Table) associated with an atlas texture that has a palette:
|
For each CLUT (Color Lookup Table) associated with an atlas texture that has a palette:
|
||||||
|
|
||||||
| Offset (per entry) | Size | Type | Description |
|
| Offset (per entry) | Size | Type | Description |
|
||||||
| ------------------ | ---- | ----------- | --------------------------------------------------------------------------------- |
|
| ------------------ | ---- | ------ | ----------------------------------------------------- |
|
||||||
| 0x00 | 512 | uint16[256] | Color palette entries (each entry is 2 bytes 16bpp). If unused, entries are zero. |
|
| 0x00 | 4 | int | **Clut Data Offset Placeholder** |
|
||||||
| 0x200 | 2 | uint16 | CLUT packing X coordinate - already in 16 pixel steps |
|
| 0x04 | 2 | uint16 | CLUT packing X coordinate - already in 16 pixel steps |
|
||||||
| 0x202 | 2 | uint16 | CLUT packing Y coordinate |
|
| 0x06 | 2 | uint16 | CLUT packing Y coordinate |
|
||||||
| 0x204 | 2 | uint16 | Palette count (number of valid palette entries) |
|
| 0x08 | 2 | uint16 | Palette count (number of valid palette entries) |
|
||||||
| 0x206 | 2 | uint16 | Reserved (always 0) |
|
| 0x0A | 2 | uint16 | Reserved (always 0) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -72,22 +73,31 @@ For each exporter, a mesh data block is written at the offset specified in its d
|
|||||||
#### **Triangle Data Layout (per triangle – 52 bytes total):**
|
#### **Triangle Data Layout (per triangle – 52 bytes total):**
|
||||||
|
|
||||||
| Field | Size | Description |
|
| Field | Size | Description |
|
||||||
| ----------------------------- | -------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ----------------------------- | -------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
|
||||||
| **Vertex Coordinates** | 3 vertices × 3 × 2 bytes = 18 bytes | For each vertex (v0, v1, v2): X, Y, Z coordinates (int16) |
|
| **Vertex Coordinates** | 3 vertices × 3 × 2 bytes = 18 bytes | For each vertex (v0, v1, v2): X, Y, Z coordinates (int16) |
|
||||||
| **Vertex Normal** | 3 × 2 bytes = 6 bytes | Normal vector for vertex v0 (int16: nx, ny, nz) |
|
| **Vertex Normal** | 3 × 2 bytes = 6 bytes | Normal vector for vertex v0 (int16: nx, ny, nz) |
|
||||||
| **Vertex Colors** | 3 vertices × (3 bytes color + 1 byte padding) = 12 bytes | For each vertex (v0, v1, v2): Red, Green, Blue (uint8) plus 1 byte padding |
|
| **Vertex Colors** | 3 vertices × (3 bytes color + 1 byte padding) = 12 bytes | For each vertex (v0, v1, v2): Red, Green, Blue (uint8) plus 1 byte padding |
|
||||||
| **Texture Coordinates (UVs)** | 3 vertices × 2 bytes = 6 bytes | For each vertex (v0, v1, v2): U and V coordinates (uint8), adjusted by texture packing factors |
|
| **Texture Coordinates (UVs)** | 3 vertices × 2 bytes = 6 bytes | For each vertex (v0, v1, v2): U and V coordinates (uint8), adjusted by texture packing factors |
|
||||||
| **UV Padding** | 2 bytes | Padding (uint16, set to zero) |
|
| **UV Padding** | 2 bytes | Padding (uint16, set to zero) |
|
||||||
| **Texture Attributes** | 2 + 2 + 2 + 2 = 8 bytes | Contains: <br> • Texture page attributes (uint16 – encoded from page X/Y, bit depth, dithering)<br> • Texture CLUT packing X (uint16)<br> • Texture CLUT packing Y (uint16)<br> • Reserved (uint16, set to zero) |
|
| **Texture Attributes** | 2 bytes | The TPage attribute for the given polygon |
|
||||||
|
| **Clut X** | 2 bytes | Clut position within VRAM (already predivided by 16) |
|
||||||
|
| **Clut Y** | 2 bytes | Clut position within VRAM |
|
||||||
|
| **Padding** | 2 bytes | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*Triangles are written sequentially. Prior to writing each mesh data block, the file pointer is aligned to a 4-byte boundary.*
|
|
||||||
|
|
||||||
### 3.2 Atlas Data Blocks
|
### 3.2 Atlas Data Blocks
|
||||||
|
|
||||||
For each atlas, a raw texture data block is written at the offset specified in its descriptor. Before writing, the file pointer is aligned to a 4-byte boundary.
|
For each atlas, a raw texture data block is written at the offset specified in its descriptor
|
||||||
|
|
||||||
- **Raw Texture Data:**
|
- **Raw Texture Data:**
|
||||||
The atlas data is written pixel by pixel as returned by the pixel packing function. The total size equals
|
The atlas data is written pixel by pixel as returned by the pixel packing function. The total size equals
|
||||||
*(Atlas Width × Atlas Height)* The data is prepared for a DMA transfer to the VRAM.
|
*(Atlas Width × Atlas Height)* The data is prepared for a DMA transfer to the VRAM.
|
||||||
|
|
||||||
|
|
||||||
|
### 3.3 Clut Data Blocks
|
||||||
|
|
||||||
|
For each clut, a raw pixel data block is written at the offset specified in its descriptor as an array of `uint16` colors already formatted for the VRAM.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
8
tools.meta
Normal file
8
tools.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: cf7149f85c29d3f4d9a7f968d8825ffa
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
BIN
tools/imhex.hexproj
Normal file
BIN
tools/imhex.hexproj
Normal file
Binary file not shown.
7
tools/imhex.hexproj.meta
Normal file
7
tools/imhex.hexproj.meta
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 871e1f08910e9f329ad3fce5d77c8785
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Reference in New Issue
Block a user