0x30 Width (2 bytes)
0x32 Height (2 bytes)
0x3c Data Offset (4 bytes)
0x4c Pallet Offset (4 bytes)
Data is 8BPP, pallet is stored as RGBA. Alpha value is usually 128.
If I use "Console Texture Explorer" the textures are viewable, but that tool doesn't like width/height values that aren't powers of 2. My tool produces lots of noise not present in the original image... have I swizzled the texture properly?
from Console Texture Explorer (width should be 448, had to use 256):

from my tool:

Original GIM file: http://rghost.net/51608656
Here's the source for my broken tool. png.h is located here: http://nothings.org/stb/stb_image_write.h. It's a little messy
Code: Select all
#define STB_IMAGE_WRITE_IMPLEMENTATION 1
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include "png.h"
// Based on https://github.com/neko68k/rtftool/blob/master/RTFTool/rtfview/p6t_v2.cpp
// which looks like a port from puyotools.
void deswizzle(uint8_t *inpixels, uint8_t *outpixels, size_t width, size_t height)
{
int i = 0;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
int block_location = (y & (~0xf)) * width + (x & (~0xf)) * 2;
int swap_selector = (((y + 2) >> 2) & 0x1) * 4;
int posY = (((y & (~3)) >> 1) + (y & 1)) & 0x7;
int column_location = posY * width * 2 + ((x + swap_selector) & 0x7) * 4;
int byte_num = ((y >> 1) & 1) + ((x >> 2) & 2); // 0,1,2,3
outpixels[(y * width) + x] = inpixels[block_location + column_location + byte_num];
}
}
}
int main(int argc, char* argv[])
{
FILE* fGim = NULL;
FILE* fPng = NULL;
unsigned char* gimData;
uint32_t* pngData;
uint32_t* imageData;
size_t gimLength;
size_t pngLength;
/* Parts of GIM header */
uint16_t width;
uint16_t height;
uint8_t* dataPtr;
uint32_t* cltPtr;
printf("gim2png - Converts Initial D Special Stage GIM textures to PNG files.\n");
assert(argc >= 3);
fGim = fopen(argv[1], "rb");
printf("Reading GIM to memory...\n");
/* Read GIM into memory */
fseek(fGim, 0, SEEK_END);
gimLength = ftell(fGim);
fseek(fGim, 0, SEEK_SET);
gimData = malloc(gimLength);
assert(gimData != NULL);
fread(gimData, 1, gimLength, fGim);
fclose(fGim);
/* Read parts of the header for relevant values */
width = *((uint16_t *)(gimData+0x30));
height = *((uint16_t *)(gimData+0x32));
dataPtr = gimData + *((uint32_t *)(gimData+0x3c));
cltPtr = gimData + *((uint32_t *)(gimData+0x4c));
printf("Data starts at 0x%x, CLT is at 0x%x\n", dataPtr, cltPtr);
unsigned char *original = malloc(width*height);
memcpy(original, dataPtr, width*height);
printf("Un-Swizzling...\n");
deswizzle(original, dataPtr, width, height);
printf("Converting to RGBA...\n");
/* Read the image as RGBA (4 bytes per pixel) */
imageData = malloc(width * height * 4);
for(int i = 0; i < (width*height); i++)
{
uint8_t pixel = *(dataPtr + i);
imageData[i] = cltPtr[pixel] | (0xFF << 24);
}
printf("Saving PNG...\n");
int ret = stbi_write_png(argv[2], width, height, 4, imageData, width*4);
//int ret = stbi_write_tga(argv[2], width, height, 4, imageData);
if(ret == 0)
{
printf("Error writing PNG...\n");
return EXIT_FAILURE;
}
else
{
printf("Saved to %s.\n", argv[2]);
return EXIT_SUCCESS;
}
return 0;
}



