Skip to content

Commit b4337a3

Browse files
committed
Very rudimentary PBA Rez support
0 parents  commit b4337a3

9 files changed

+927
-0
lines changed

Diff for: .gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Folders for temporary files
2+
build
3+
resources
4+
unpacked
5+
converted

Diff for: CMakeLists.txt

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
set(CMAKE_C_STANDARD 11)
2+
3+
add_executable(parseRez parseRez.c)
4+
add_executable(format0001 format0001.c)
5+
add_executable(format0022 format0022.c)
6+
target_link_libraries(format0022 txc_dxtn)
7+
add_executable(format0024 format0024.c)
8+
add_executable(format002A format002A.c)
9+
add_executable(format002C format002C.c)

Diff for: convert.sh

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/bin/bash
2+
3+
4+
# Exit in case of failure
5+
set -e
6+
7+
8+
BIN_DIR=build
9+
10+
mkdir -p converted
11+
12+
# Mostly working:
13+
14+
for filename in unpacked/*.0001; do
15+
echo "$filename"
16+
$BIN_DIR/format0001 "$filename" "converted/$(basename "$filename" .0001).csv"
17+
done
18+
19+
for filename in unpacked/*.0022; do
20+
echo "$filename"
21+
$BIN_DIR/format0022 "$filename" "converted/$(basename "$filename" .0022).tga"
22+
done
23+
24+
for filename in unpacked/*.0024; do
25+
echo "$filename"
26+
$BIN_DIR/format0024 "$filename" "converted/$(basename "$filename" .0024).obj"
27+
done
28+
29+
# No conversion yet:
30+
31+
for filename in unpacked/*.002A; do
32+
echo "$filename"
33+
$BIN_DIR/format002A "$filename"
34+
done
35+
36+
# WIP Stuff:
37+
38+
mkdir -p tmp
39+
40+
for filename in unpacked/*.002C; do
41+
echo "$filename"
42+
$BIN_DIR/format002C "$filename" "tmp/$(basename "$filename" .002C).obj"
43+
done
44+
45+
echo "Success!"

Diff for: format0001.c

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Zero terminates 0001 files
2+
//FIXME: Some files are actually ROMs so the tool won't work?!
3+
4+
#include <stdint.h>
5+
#include <stdbool.h>
6+
#include <assert.h>
7+
#include <stdio.h>
8+
#include <stdlib.h>
9+
10+
int main(int argc, char* argv[]) {
11+
FILE* in = fopen(argv[1], "rb");
12+
FILE* out = fopen(argv[2], "wb");
13+
14+
while(!feof(in)) {
15+
uint8_t b;
16+
fread(&b, 1, 1, in);
17+
// Abort on zero termination
18+
if (b == 0x00) {
19+
break;
20+
}
21+
fwrite(&b, 1, 1, out);
22+
}
23+
24+
fclose(in);
25+
fclose(out);
26+
27+
return 0;
28+
}

Diff for: format0022.c

+202
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
// Converts 0022 files to tga
2+
//FIXME: Somehow store used-size + mipmaps
3+
4+
#include <assert.h>
5+
#include <stdbool.h>
6+
#include <stdint.h>
7+
#include <stdio.h>
8+
#include <stdlib.h>
9+
10+
#include <unistd.h>
11+
12+
#include "txc_dxtn.h"
13+
14+
typedef struct {
15+
char idlength;
16+
char colourmaptype;
17+
char datatypecode;
18+
short int colourmaporigin;
19+
short int colourmaplength;
20+
char colourmapdepth;
21+
short int x_origin;
22+
short int y_origin;
23+
short width;
24+
short height;
25+
char bitsperpixel;
26+
char imagedescriptor;
27+
} __attribute__((packed)) TgaHeader;
28+
29+
30+
int main(int argc, char* argv[]) {
31+
FILE* out = fopen(argv[2], "wb");
32+
TgaHeader header;
33+
header.idlength = 0;
34+
header.colourmaptype = 0;
35+
header.datatypecode = 2;
36+
header.colourmaporigin = 0;
37+
header.colourmaplength = 0;
38+
header.colourmapdepth = 0;
39+
header.x_origin = 0;
40+
header.y_origin = 0;
41+
42+
typedef struct {
43+
uint16_t width_a; // +0
44+
uint16_t height_a; // +2
45+
uint16_t stride; // +4 ?
46+
uint16_t format; // +6
47+
uint32_t unk0; // +8
48+
uint8_t always0_a[16]; // +12
49+
uint16_t mipmapCount; // +30
50+
uint8_t widthShift; // +28
51+
uint8_t heightShift; // +29
52+
float pixelWidth; // +32
53+
float pixelHeight; // +36
54+
uint8_t always0_b[20]; // +40
55+
uint16_t width_b; // +60
56+
uint16_t height_b; // +62
57+
uint8_t always0_c[8]; // +64
58+
// 72
59+
} __attribute__((packed)) Format0022;
60+
61+
FILE* in = fopen(argv[1], "rb");
62+
63+
Format0022 fmt;
64+
fread(&fmt, sizeof(fmt), 1, in);
65+
66+
printf("%d x %d (Stride: %d)\n", fmt.width_a, fmt.height_a, fmt.stride);
67+
printf("format: 0x%04X\n", fmt.format);
68+
printf("unk0: 0x%08X\n", fmt.unk0);
69+
printf("mipmapCount: 0x%04X\n", fmt.mipmapCount);
70+
printf("widthShift: 0x%02X (%d)\n", fmt.widthShift, 1 << fmt.widthShift);
71+
printf("heightShift: 0x%02X (%d)\n", fmt.heightShift, 1 << fmt.heightShift);
72+
printf("pixelWidth: %f\n", fmt.pixelWidth);
73+
printf("pixelHeight: %f\n", fmt.pixelHeight);
74+
75+
printf("usedSize: %d x %d\n", fmt.width_b, fmt.height_b);
76+
// assert(fmt.width_a == fmt.width_b);
77+
// assert(fmt.height_a == fmt.height_b);
78+
79+
80+
uint32_t o = 72;
81+
uint32_t s = fmt.stride;
82+
uint32_t w = fmt.width_a;
83+
uint32_t h = fmt.height_a;
84+
for(unsigned int i = 0; i <= fmt.mipmapCount; i++) {
85+
printf("Level %d: %d x %d at 0x%X\n", i, w, h, o);
86+
o += s * h;
87+
s /= 2;
88+
w /= 2;
89+
h /= 2;
90+
}
91+
printf("EOF at 0x%X\n", o);
92+
93+
// Padding might follow..
94+
95+
header.width = fmt.width_a;
96+
header.height = fmt.height_a;
97+
header.bitsperpixel = 32;
98+
header.imagedescriptor = 1 << 5;
99+
100+
fwrite(&header, sizeof(header), 1, out);
101+
fseek(in, 72, SEEK_SET);
102+
103+
size_t bufferSize = fmt.stride * fmt.height_a;
104+
uint8_t* buffer = malloc(bufferSize);
105+
fread(buffer, bufferSize, 1, in);
106+
107+
for(unsigned int y = 0; y < fmt.height_a; y++) {
108+
for(unsigned int x = 0; x < fmt.width_a; x++) {
109+
switch(fmt.format) {
110+
case 0x0001:
111+
fwrite(&buffer[y * fmt.stride + x * 4], 4, 1, out);
112+
break;
113+
case 0x0006: {
114+
// This is a weird format..
115+
// It can be found in ToTAN 2004-0 (0006 no-mipmaps) where the same
116+
// texture is also in 2004-5 (0009 mipmapped).
117+
// The stride suggests it's 16bpp, however, you'll get garbage then
118+
// as pixels seem to be 32bpp.
119+
// Yet, that means only half the image fits into the file..
120+
//
121+
uint32_t pixel;
122+
if (x >= fmt.width_a / 2) {
123+
pixel = 0x00FFFFFF;
124+
} else {
125+
pixel = *(uint32_t*)&buffer[y * fmt.stride + x * 4];
126+
}
127+
uint8_t texel[4];
128+
129+
// Attempts at other 16bpp formats
130+
#if 0
131+
// 565
132+
texel[0] = ((pixel >> 0) & ((1 << 5) - 1)) << 3;
133+
texel[1] = ((pixel >> 5) & ((1 << 6) - 1)) << 2;
134+
texel[2] = ((pixel >> 11) & ((1 << 5) - 1)) << 3;
135+
texel[3] = 0xFF;
136+
137+
// 1555
138+
texel[0] = ((pixel >> 0) & ((1 << 5) - 1)) << 3;
139+
texel[1] = ((pixel >> 5) & ((1 << 5) - 1)) << 3;
140+
texel[2] = ((pixel >> 10) & ((1 << 5) - 1)) << 3;
141+
texel[3] = ((pixel >> 15) & ((1 << 1) - 1)) << 7;
142+
143+
// 4444
144+
texel[0] = ((pixel >> 0) & ((1 << 4) - 1)) << 4;
145+
texel[1] = ((pixel >> 4) & ((1 << 4) - 1)) << 4;
146+
texel[2] = ((pixel >> 8) & ((1 << 4) - 1)) << 4;
147+
texel[3] = ((pixel >> 12) & ((1 << 4) - 1)) << 4;
148+
149+
// 5551
150+
texel[0] = ((pixel >> 11) & ((1 << 5) - 1)) << 3;
151+
texel[1] = ((pixel >> 6) & ((1 << 5) - 1)) << 3;
152+
texel[2] = ((pixel >> 1) & ((1 << 5) - 1)) << 3;
153+
texel[3] = ((pixel >> 0) & ((1 << 1) - 1)) << 7;
154+
#endif
155+
156+
texel[0] = (pixel >> 0) & 0xFF;
157+
texel[1] = (pixel >> 8) & 0xFF;
158+
texel[2] = (pixel >> 16) & 0xFF;
159+
texel[3] = (pixel >> 24) & 0xFF;
160+
fwrite(&texel[0], 1, 1, out);
161+
fwrite(&texel[1], 1, 1, out);
162+
fwrite(&texel[2], 1, 1, out);
163+
fwrite(&texel[3], 1, 1, out);
164+
165+
break;
166+
}
167+
case 0x0009: {
168+
uint8_t texel[4];
169+
fetch_2d_texel_rgba_dxt1(fmt.width_a, buffer, x, y, texel);
170+
fwrite(&texel[2], 1, 1, out);
171+
fwrite(&texel[1], 1, 1, out);
172+
fwrite(&texel[0], 1, 1, out);
173+
fwrite(&texel[3], 1, 1, out);
174+
break;
175+
}
176+
case 0x000D: {
177+
uint8_t texel[4];
178+
fetch_2d_texel_rgba_dxt5(fmt.width_a, buffer, x, y, texel);
179+
fwrite(&texel[2], 1, 1, out);
180+
fwrite(&texel[1], 1, 1, out);
181+
fwrite(&texel[0], 1, 1, out);
182+
fwrite(&texel[3], 1, 1, out);
183+
break;
184+
}
185+
case 0x000E: {
186+
// 4 bytes unknown
187+
// Then JPEG follows
188+
}
189+
default:
190+
assert(false);
191+
break;
192+
}
193+
}
194+
}
195+
196+
free(buffer);
197+
198+
fclose(in);
199+
fclose(out);
200+
201+
return 0;
202+
}

0 commit comments

Comments
 (0)