1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-01 02:40:43 +02:00

#368 GBA data packer (PKD & WAD)

This commit is contained in:
XProger
2022-11-26 01:24:19 +03:00
parent a311245b81
commit 9418492ad7
5 changed files with 457 additions and 214 deletions

View File

@@ -547,9 +547,11 @@ enum ItemType {
#define MAX_ITEMS 240
#define MAX_NODES 32
#define MAX_TEXTURES 1536 * 2
#define MAX_ANIM_TEX 128
#define TEX_ATTR_AKILL 0x0001
#define FACE_TEXTURE 0x07FF
#define TEX_ATTR_AKILL 0x0001
#define TEX_ATTR_ANIM 0x0002
#define FACE_TEXTURE 0x3FFF
struct vec3s
{

View File

@@ -4,10 +4,49 @@
#include "TR1_PSX.h"
#include "out_GBA.h"
#include "out_3DO.h"
#include "out_32X.h"
TR1_PC* pc[LVL_MAX];
TR1_PSX* psx[LVL_MAX];
void dumpLightmap(const char* fileName, TR1_PC* level)
{
uint32 data[34 * 256];
uint32 *ptr = data;
for (int32 i = 0; i < 256; i++)
{
int32 idx = i * 3;
uint8 r = level->palette.colors[idx + 0] << 2;
uint8 g = level->palette.colors[idx + 1] << 2;
uint8 b = level->palette.colors[idx + 2] << 2;
*ptr++ = (b | (g << 8) | (r << 16) | 0xFF000000);
}
for (int32 i = 0; i < 256; i++) {
*ptr++ = 0;
}
for (int32 j = 0; j < 32; j++)
{
for (int32 i = 0; i < 256; i++)
{
int32 idx = level->lightmap[j * 256 + i] * 3;
uint8 r = level->palette.colors[idx + 0] << 2;
uint8 g = level->palette.colors[idx + 1] << 2;
uint8 b = level->palette.colors[idx + 2] << 2;
*ptr++ = (b | (g << 8) | (r << 16) | 0xFF000000);
}
}
saveBitmap(fileName, (uint8*)data, 256, 32 + 2, 32);
}
int main(int argc, char** argv)
{
if (argc < 3) {
@@ -34,6 +73,8 @@ int main(int argc, char** argv)
}
}
dumpLightmap("lightmap.bmp", pc[LVL_TR1_1]);
if (strcmp(argv[1], "gba") == 0)
{
out_GBA* out = new out_GBA();
@@ -48,6 +89,13 @@ int main(int argc, char** argv)
delete out;
}
if (strcmp(argv[1], "32x") == 0)
{
out_32X* out = new out_32X();
out->process(argv[2], pc, NULL);
delete out;
}
for (int32 i = 0; i < LVL_MAX; i++)
{
delete pc[i];

View File

@@ -16,7 +16,14 @@ struct out_GBA
enum {
FACE_TYPE_SHIFT = 14,
FACE_TRIANGLE = (1 << 13)
};
struct Remap {
int32 meshes[MAX_MESHES];
int32 models[MAX_MODELS];
int32 animFrames[MAX_ANIMS];
int16 textures[MAX_TEXTURES];
int16 sprites[MAX_TEXTURES];
};
struct Header
@@ -471,6 +478,27 @@ struct out_GBA
uint32 uv01;
uint32 uv23;
ObjectTexture(const TR1_PC::ObjectTexture* tex)
{
tile = (tex->tile & 0x3FFF) << 16;
uint32 uv0 = ((tex->uv0 << 16) | (tex->uv0 >> 16)) & 0xFF00FF00;
uint32 uv1 = ((tex->uv1 << 16) | (tex->uv1 >> 16)) & 0xFF00FF00;
uint32 uv2 = ((tex->uv2 << 16) | (tex->uv2 >> 16)) & 0xFF00FF00;
uint32 uv3 = ((tex->uv3 << 16) | (tex->uv3 >> 16)) & 0xFF00FF00;
fixTexCoord(uv0, uv1);
fixTexCoord(uv0, uv3);
fixTexCoord(uv1, uv2);
uv01 = uv0 | (uv1 >> 8);
uv23 = uv2 | (uv3 >> 8);
}
bool isEqual(const ObjectTexture* tex)
{
return memcmp(this, tex, sizeof(*tex)) == 0;
}
void write(FileStream &f) const
{
f.write(tile);
@@ -485,6 +513,25 @@ struct out_GBA
uint32 uwvh;
int16 l, t, r, b;
SpriteTexture(const TR1_PC::SpriteTexture* spr)
{
uint32 u = spr->u;
uint32 v = spr->v;
uint32 w = (spr->w + 255) >> 8;
uint32 h = (spr->h + 255) >> 8;
tile = spr->tile << 16;
uwvh = (u << 24) | (w << 16) | (v << 8) | h;
l = spr->l;
t = spr->t;
r = spr->r;
b = spr->b;
}
bool isEqual(const SpriteTexture* spr)
{
return memcmp(this, spr, sizeof(*spr)) == 0;
}
void write(FileStream &f) const
{
f.write(tile);
@@ -607,10 +654,26 @@ struct out_GBA
}
}
void write(FileStream &f) const
void write(FileStream &f, const Remap *remap) const
{
ASSERT(vCount < 256);
#if 0 // TODO proper center/radius calc?
vec3s bmin = vertices[0];
vec3s bmax = bmin;
for (int32 j = 0; j < vCount; j++)
{
const vec3s* v = vertices + j;
if (v->x < bmin.x) bmin.x = v->x;
if (v->y < bmin.y) bmin.y = v->y;
if (v->z < bmin.z) bmin.z = v->z;
if (v->x > bmax.x) bmax.x = v->x;
if (v->y > bmax.y) bmax.y = v->y;
if (v->z > bmax.z) bmax.z = v->z;
}
#endif
f.write(center.x);
f.write(center.y);
f.write(center.z);
@@ -641,14 +704,16 @@ struct out_GBA
for (int32 j = 0; j < rCount; j++)
{
TR1_PC::Quad q = rFaces[j];
uint16 texIndex = q.flags & FACE_TEXTURE;
MeshQuad comp;
comp.indices[0] = uint8(q.indices[0]);
comp.indices[1] = uint8(q.indices[1]);
comp.indices[2] = uint8(q.indices[2]);
comp.indices[3] = uint8(q.indices[3]);
comp.flags = q.flags & FACE_TEXTURE;
if (level->objectTextures[comp.flags].attribute & TEX_ATTR_AKILL) {
comp.flags = remap ? remap->textures[texIndex] : texIndex;
if (level->objectTextures[texIndex].attribute & TEX_ATTR_AKILL) {
comp.flags |= (FACE_TYPE_FTA << FACE_TYPE_SHIFT);
} else {
comp.flags |= (FACE_TYPE_FT << FACE_TYPE_SHIFT);
@@ -675,19 +740,20 @@ struct out_GBA
for (int32 j = 0; j < tCount; j++)
{
TR1_PC::Triangle t = tFaces[j];
uint16 texIndex = t.flags & FACE_TEXTURE;
MeshTriangle comp;
comp.indices[0] = uint8(t.indices[0]);
comp.indices[1] = uint8(t.indices[1]);
comp.indices[2] = uint8(t.indices[2]);
comp.indices[3] = 0;
comp.flags = t.flags & FACE_TEXTURE;
if (level->objectTextures[comp.flags].attribute & TEX_ATTR_AKILL) {
comp.flags = remap ? remap->textures[texIndex] : texIndex;
if (level->objectTextures[texIndex].attribute & TEX_ATTR_AKILL) {
comp.flags |= (FACE_TYPE_FTA << FACE_TYPE_SHIFT);
} else {
comp.flags |= (FACE_TYPE_FT << FACE_TYPE_SHIFT);
}
comp.flags |= FACE_TRIANGLE;
comp.write(f);
}
@@ -703,7 +769,6 @@ struct out_GBA
comp.indices[3] = 0;
comp.flags = t.flags & FACE_TEXTURE;
comp.flags |= (FACE_TYPE_F << FACE_TYPE_SHIFT);
comp.flags |= FACE_TRIANGLE;
comp.write(f);
}
@@ -769,6 +834,9 @@ struct out_GBA
int32 akill;
uint8* indices;
uint32 indexSum;
int32 tile;
int32 x, y;
int32 minX, minY, maxX, maxY;
Texture(const TR1_PC* level, TR1_PC::ObjectTexture* tex, int32 uid)
{
@@ -777,13 +845,14 @@ struct out_GBA
this->spr = NULL;
this->link = NULL;
this->uid = uid;
this->tile = -1;
TR1_PC::Tile *tile = level->tiles + (tex->tile & 0x3FFF);
int32 minX = MIN(MIN(tex->x0, tex->x1), tex->x2);
int32 minY = MIN(MIN(tex->y0, tex->y1), tex->y2);
int32 maxX = MAX(MAX(tex->x0, tex->x1), tex->x2);
int32 maxY = MAX(MAX(tex->y0, tex->y1), tex->y2);
minX = MIN(MIN(tex->x0, tex->x1), tex->x2);
minY = MIN(MIN(tex->y0, tex->y1), tex->y2);
maxX = MAX(MAX(tex->x0, tex->x1), tex->x2);
maxY = MAX(MAX(tex->y0, tex->y1), tex->y2);
if (tex->isQuad)
{
@@ -825,13 +894,14 @@ struct out_GBA
this->tex = NULL;
this->spr = spr;
this->link = NULL;
this->tile = -1;
TR1_PC::Tile *tile = level->tiles + (spr->tile & 0x3FF);
int32 minX = spr->u;
int32 minY = spr->v;
int32 maxX = spr->u + (spr->w >> 8);
int32 maxY = spr->v + (spr->h >> 8);
minX = spr->u;
minY = spr->v;
maxX = spr->u + (spr->w >> 8);
maxY = spr->v + (spr->h >> 8);
width = maxX - minX + 1;
height = maxY - minY + 1;
@@ -866,7 +936,14 @@ struct out_GBA
static int cmp(const Texture* a, const Texture* b)
{
int32 i = b->akill - a->akill;
int32 animA = a->tex ? a->tex->attribute & TEX_ATTR_ANIM : 0;
int32 animB = b->tex ? b->tex->attribute & TEX_ATTR_ANIM : 0;
int32 i = animB - animA;
if (i == 0)
{
i = b->akill - a->akill;
}
if (i == 0)
{
@@ -887,7 +964,7 @@ struct out_GBA
}
};
struct Tile24
struct Atlas
{
struct Node
{
@@ -925,8 +1002,11 @@ struct out_GBA
if (nw < tw || nh < th)
return NULL;
if (nw == tw && nh == th) {
if (nw == tw && nh == th)
{
this->tex = tex;
tex->x = l;
tex->y = t;
return this;
}
@@ -1004,12 +1084,12 @@ struct out_GBA
Node* root;
Tile24()
Atlas()
{
root = new Node(0, 0, 256, 256);
}
~Tile24()
~Atlas()
{
delete root;
}
@@ -1024,7 +1104,7 @@ struct out_GBA
root->fill8(data);
}
static int cmp(const Tile24* a, const Tile24* b)
static int cmp(const Atlas* a, const Atlas* b)
{
return 0;
}
@@ -1033,81 +1113,16 @@ struct out_GBA
RoomVertex* roomVertices;
int32 roomVerticesCount;
struct Remap {
int32 meshes[MAX_MESHES];
int32 models[MAX_MODELS];
int32 animFrames[MAX_ANIMS];
int32 textures[MAX_TEXTURES];
int32 sprites[MAX_TEXTURES];
};
Remap remap[LVL_MAX];
Remap remaps[LVL_MAX];
Array<Mesh> meshes;
Array<Model> models;
Array<AnimFrames> animFrames;
Array<ObjectTexture> objectTextures;
Array<SpriteTexture> spriteTextures;
Array<Texture> textures;
Array<Tile24> tiles;
void packTiles(FileStream &f)
{
for (int32 i = 0; i < textures.count; i++)
{
Texture* tex = textures[i];
if (tex->link)
continue;
bool placed = false;
for (int32 j = 0; j < tiles.count; j++)
{
if (tiles[j]->root->insert(tex)) {
placed = true;
break;
}
}
if (!placed)
{
Tile24* tile = new Tile24();
tiles.add(tile);
if (!tile->root->insert(tex))
{
printf("Can't pack texture %d x %d", tex->width, tex->height);
break;
}
}
}
uint8* data = new uint8[256 * 256 * 3 * tiles.count];
// save bitmap (debug)
for (int32 i = 0; i < 256 * 256 * tiles.count; i++)
{
data[i * 3 + 0] = 255;
data[i * 3 + 1] = 0;
data[i * 3 + 2] = 255;
}
for (int32 i = 0; i < tiles.count; i++)
{
tiles[i]->fill24(data + i * 256 * 256 * 3);
}
saveBitmap("tiles.bmp", data, 256, 256 * tiles.count);
memset(data, 0, 256 * 256 * tiles.count);
for (int32 i = 0; i < tiles.count; i++)
{
tiles[i]->fill8(data + i * 256 * 256);
}
f.write(data, 256 * 256 * tiles.count);
delete[] data;
}
Array<Atlas> tiles;
void addTextures(TR1_PC* level)
{
@@ -1164,6 +1179,10 @@ struct out_GBA
textures.add(tex);
}
static int32 maxSprites = 0;
maxSprites += level->spriteTexturesCount;
printf("%d\n", maxSprites);
delete[] used;
}
@@ -1214,22 +1233,195 @@ struct out_GBA
}
}
}
}
//remap.textures[i] = textures.add(tex);
//remap.sprites[i] = textures.add(tex);
void packTiles(FileStream &f)
{
int32 texPacked = 0;
for (int32 i = 0; i < textures.count; i++)
{
Texture* tex = textures[i];
if (tex->link)
continue;
bool placed = false;
for (int32 j = 0; j < tiles.count; j++)
{
if (tiles[j]->root->insert(tex))
{
placed = true;
tex->tile = j;
break;
}
}
if (!placed)
{
Atlas* tile = new Atlas();
tex->tile = tiles.add(tile);
placed = tile->root->insert(tex);
}
if (!placed)
{
tex->tile = -1;
printf("Can't pack texture %d x %d", tex->width, tex->height);
break;
}
if (placed) {
texPacked++;
}
}
printf("textures packed: %d\n", texPacked);
uint8* data = new uint8[256 * 256 * 3 * tiles.count];
// save bitmap (debug)
for (int32 i = 0; i < 256 * 256 * tiles.count; i++)
{
data[i * 3 + 0] = 255;
data[i * 3 + 1] = 0;
data[i * 3 + 2] = 255;
}
for (int32 i = 0; i < tiles.count; i++)
{
tiles[i]->fill24(data + i * 256 * 256 * 3);
}
saveBitmap("tiles.bmp", data, 256, 256 * tiles.count);
memset(data, 0, 256 * 256 * tiles.count);
for (int32 i = 0; i < tiles.count; i++)
{
tiles[i]->fill8(data + i * 256 * 256);
}
f.write(data, 256 * 256 * tiles.count);
delete[] data;
}
void remapTextures()
{
int32 animated = -1;
int32 maxAnimatedTex = 0;
for (int32 i = 0; i < textures.count; i++)
{
const Texture* texture = textures[i];
const Texture* instance = texture->link ? texture->link : texture;
int32 dx = instance->x - instance->minX;
int32 dy = instance->y - instance->minY;
ASSERT(instance->tile >= 0);
Remap &remap = remaps[texture->level->id];
if (texture->tex) // is ObjectTexture
{
if (texture->tex->attribute & TEX_ATTR_ANIM)
{
ASSERT(animated == -1 || animated == 1);
animated = 1;
} else {
// add dummy textures as padding between animated and static textures
int32 padding = MAX_ANIM_TEX - objectTextures.count;
for (int32 j = 0; j < padding; j++)
{
TR1_PC::ObjectTexture tmp;
memset(&tmp, 0, sizeof(tmp));
objectTextures.add(new ObjectTexture(&tmp));
}
animated = 0;
}
TR1_PC::ObjectTexture tmp;
memset(&tmp, 0, sizeof(tmp));
tmp.attribute = texture->tex->attribute; // old attribute
tmp.tile = instance->tile; // new tile index
tmp.x0 = texture->tex->x0 + dx;
tmp.y0 = texture->tex->y0 + dy;
tmp.x1 = texture->tex->x1 + dx;
tmp.y1 = texture->tex->y1 + dy;
tmp.x2 = texture->tex->x2 + dx;
tmp.y2 = texture->tex->y2 + dy;
if (texture->tex->isQuad)
{
tmp.x3 = texture->tex->x3 + dx;
tmp.y3 = texture->tex->y3 + dy;
}
ObjectTexture* comp = new ObjectTexture(&tmp);
int32 texIndex = int32(texture->tex - texture->level->objectTextures);
int32 index = objectTextures.find(comp);
if (index <= 0) {
index = objectTextures.add(comp);
} else {
delete comp;
}
remap.textures[texIndex] = index;
if (texture->tex->attribute & TEX_ATTR_ANIM) {
maxAnimatedTex = i;
}
}
else // is SpriteTexture
{
ASSERT(animated == 0);
TR1_PC::SpriteTexture tmp;
memset(&tmp, 0, sizeof(tmp));
tmp.tile = instance->spr->tile;
tmp.u = texture->spr->u + dx;
tmp.v = texture->spr->v + dy;
tmp.w = texture->spr->w;
tmp.h = texture->spr->h;
tmp.l = texture->spr->l;
tmp.t = texture->spr->t;
tmp.r = texture->spr->r;
tmp.b = texture->spr->b;
SpriteTexture* comp = new SpriteTexture(&tmp);
int32 sprIndex = int32(texture->spr - texture->level->spriteTextures);
int32 index = spriteTextures.find(comp);
if (index <= 0) {
index = spriteTextures.add(comp);
} else {
delete comp;
}
remap.sprites[sprIndex] = index;
}
}
printf("animated textures: %d\n", maxAnimatedTex + 1);
ASSERT(maxAnimatedTex < MAX_ANIM_TEX);
}
int32 addRoomVertex(int32 yOffset, const TR1_PC::Room::Vertex &v)
{
RoomVertex comp;
int32 px = v.pos.x >> 10;
int32 px = v.pos.x >> 8;
int32 py = (v.pos.y - yOffset) >> 8;
int32 pz = v.pos.z >> 10;
int32 pz = v.pos.z >> 8;
ASSERT(py >= 0);
ASSERT(px < 32);
ASSERT(px < (32 << 2));
ASSERT(py < 64);
ASSERT(pz < 32);
ASSERT(pz < (32 << 2));
comp.x = px;
comp.y = py;
@@ -1302,21 +1494,6 @@ struct out_GBA
return animFrames.add(anim);
}
void fixObjectTexture(ObjectTexture &tex, int32 idx)
{
uint32 uv0 = tex.uv01 & 0xFF00FF00;
uint32 uv1 = (tex.uv01 << 8) & 0xFF00FF00;
uint32 uv2 = tex.uv23 & 0xFF00FF00;
uint32 uv3 = (tex.uv23 << 8) & 0xFF00FF00;
fixTexCoord(uv0, uv1);
fixTexCoord(uv0, uv3);
fixTexCoord(uv1, uv2);
tex.uv01 = uv0 | (uv1 >> 8);
tex.uv23 = uv2 | (uv3 >> 8);
}
uint32 writePalette(FileStream &f, TR1_PC* level)
{
uint32 offset = f.align4();
@@ -1342,16 +1519,26 @@ struct out_GBA
uint32 writeLightmap(FileStream &f, TR1_PC* level)
{
uint32 offset = f.align4();
#if 1
for (int32 i = 0; i < 32; i++) {
level->lightmap[i * 256] = 0;
}
f.write(level->lightmap, 32 * 256);
f.write(level->lightmap, 256 * 32);
#else
uint8 lmap[256 * 32];
for (int32 i = 0; i < 32; i++)
{
for (int32 j = 0; j < 256; j++)
{
lmap[j * 32 + i] = level->lightmap[i * 256 + j];
}
}
f.write(lmap, 256 * 32);
#endif
return offset;
}
uint32 writeRooms(FileStream &f, TR1_PC* level)
uint32 writeRooms(FileStream &f, TR1_PC* level, const Remap* remap)
{
uint32 offset = f.align4();
@@ -1371,6 +1558,7 @@ struct out_GBA
ASSERT(room->info.yTop >= -32768 && room->info.yTop <= 32767);
info.x = room->info.x / 256;
info.z = room->info.z / 256;
info.yBottom = -32768;
info.yTop = 32767;
@@ -1413,14 +1601,16 @@ struct out_GBA
for (int32 i = 0; i < room->qCount; i++)
{
TR1_PC::Quad q = room->quads[i];
uint16 texIndex = q.flags & FACE_TEXTURE;
RoomQuad comp;
comp.indices[0] = addRoomVertex(info.yTop, room->vertices[q.indices[0]]);
comp.indices[1] = addRoomVertex(info.yTop, room->vertices[q.indices[1]]);
comp.indices[2] = addRoomVertex(info.yTop, room->vertices[q.indices[2]]);
comp.indices[3] = addRoomVertex(info.yTop, room->vertices[q.indices[3]]);
comp.flags = remap ? remap->textures[texIndex] : texIndex;
comp.flags = q.flags & FACE_TEXTURE;
if (level->objectTextures[comp.flags].attribute & TEX_ATTR_AKILL) {
if (level->objectTextures[texIndex].attribute & TEX_ATTR_AKILL) {
comp.flags |= (FACE_TYPE_FTA << FACE_TYPE_SHIFT);
} else {
comp.flags |= (FACE_TYPE_FT << FACE_TYPE_SHIFT);
@@ -1433,19 +1623,19 @@ struct out_GBA
for (int32 i = 0; i < room->tCount; i++)
{
TR1_PC::Triangle t = room->triangles[i];
RoomTriangle comp;
uint16 texIndex = t.flags & FACE_TEXTURE;
RoomTriangle comp;
comp.indices[0] = addRoomVertex(info.yTop, room->vertices[t.indices[0]]);
comp.indices[1] = addRoomVertex(info.yTop, room->vertices[t.indices[1]]);
comp.indices[2] = addRoomVertex(info.yTop, room->vertices[t.indices[2]]);
comp.flags = t.flags & FACE_TEXTURE;
if (level->objectTextures[comp.flags].attribute & TEX_ATTR_AKILL) {
comp.flags = remap ? remap->textures[texIndex] : texIndex;
if (level->objectTextures[texIndex].attribute & TEX_ATTR_AKILL) {
comp.flags |= (FACE_TYPE_FTA << FACE_TYPE_SHIFT);
} else {
comp.flags |= (FACE_TYPE_FT << FACE_TYPE_SHIFT);
}
comp.flags |= FACE_TRIANGLE;
comp.write(f);
}
@@ -1638,11 +1828,34 @@ struct out_GBA
}
}
uint32 writeAnimTex(FileStream &f, TR1_PC* level)
uint32 writeAnimTex(FileStream &f, TR1_PC* level, const Remap* remap)
{
uint32 offset = f.align4();
f.write(level->animTexData, level->animTexDataSize);
const uint16* data = level->animTexData;
int16 rangesCount = *data++;
f.write(rangesCount);
for (int32 i = 0; i < rangesCount; i++)
{
int16 texCount = *data++;
f.write(texCount);
for (int32 j = 0; j <= texCount; j++)
{
uint16 texIndex = *data++;
if (remap)
{
texIndex = remap->textures[texIndex];
}
f.write(texIndex);
}
}
return offset;
}
@@ -1711,7 +1924,7 @@ struct out_GBA
header.tiles = f.align4();
f.write((uint8*)pc->tiles, header.tilesCount * 256 * 256);
header.rooms = writeRooms(f, pc);
header.rooms = writeRooms(f, pc, NULL);
header.floors = writeFloors(f, pc);
header.meshData = f.align4();
@@ -1731,7 +1944,7 @@ struct out_GBA
const uint8* ptr = (uint8*)pc->meshData + pc->meshOffsets[i];
Mesh* mesh = new Mesh(pc, ptr);
mesh->write(f);
mesh->write(f, NULL);
delete[] mesh;
for (int32 j = i + 1; j < pc->meshOffsetsCount; j++)
@@ -1813,40 +2026,14 @@ struct out_GBA
header.objectTextures = f.align4();
for (int32 i = 0; i < pc->objectTexturesCount; i++)
{
const TR1_PC::ObjectTexture* objectTexture = pc->objectTextures + i;
ObjectTexture comp;
comp.tile = (objectTexture->tile & 0x3FFF) << 16;
uint32 uv0 = ((objectTexture->uv0 << 16) | (objectTexture->uv0 >> 16)) & 0xFF00FF00;
uint32 uv1 = ((objectTexture->uv1 << 16) | (objectTexture->uv1 >> 16)) & 0xFF00FF00;
uint32 uv2 = ((objectTexture->uv2 << 16) | (objectTexture->uv2 >> 16)) & 0xFF00FF00;
uint32 uv3 = ((objectTexture->uv3 << 16) | (objectTexture->uv3 >> 16)) & 0xFF00FF00;
comp.uv01 = uv0 | (uv1 >> 8);
comp.uv23 = uv2 | (uv3 >> 8);
// GBA rasterizer doesn't support UV deltas over 127
fixObjectTexture(comp, i);
ObjectTexture comp(pc->objectTextures + i);
comp.write(f);
}
header.spriteTextures = f.align4();
for (int32 i = 0; i < pc->spriteTexturesCount; i++)
{
const TR1_PC::SpriteTexture* spriteTexture = pc->spriteTextures + i;
SpriteTexture comp;
comp.tile = spriteTexture->tile << 16;
uint32 u = spriteTexture->u;
uint32 v = spriteTexture->v;
uint32 w = (spriteTexture->w + 255) >> 8;
uint32 h = (spriteTexture->h + 255) >> 8;
comp.uwvh = (u << 24) | (w << 16) | (v << 8) | h;
comp.l = spriteTexture->l;
comp.t = spriteTexture->t;
comp.r = spriteTexture->r;
comp.b = spriteTexture->b;
SpriteTexture comp(pc->spriteTextures + i);
comp.write(f);
}
@@ -1858,7 +2045,7 @@ struct out_GBA
header.boxes = writeBoxes(f, pc);
header.overlaps = writeOverlaps(f, pc);
writeZones(f, pc, header.zones[0]);
header.animTexData = writeAnimTex(f, pc);
header.animTexData = writeAnimTex(f, pc, NULL);
header.items = writeItems(f, pc);
header.cameraFrames = writeCameraFrames(f, pc);
@@ -2077,6 +2264,23 @@ struct out_GBA
delete[] indices;
}
void markAnimatedTextures(TR1_PC* level)
{
const uint16* data = level->animTexData;
int16 rangesCount = *data++;
for (int32 i = 0; i < rangesCount; i++)
{
int16 texCount = *data++;
for (int32 j = 0; j <= texCount; j++)
{
level->objectTextures[*data++].attribute |= TEX_ATTR_ANIM;
}
}
}
void convertWAD(FileStream &f, TR1_PC** pc, TR1_PSX** psx)
{
TR1_PC* level;
@@ -2093,6 +2297,7 @@ struct out_GBA
// collect unique textures
LEVELS_LOOP()
{
markAnimatedTextures(level);
addTextures(level);
}
@@ -2100,7 +2305,12 @@ struct out_GBA
packTiles(f);
printf("textures: %d\n", textures.count);
remapTextures();
printf("textures: %d\n", objectTextures.count);
printf("sprites: %d\n", spriteTextures.count);
ASSERT(objectTextures.count < (1 << FACE_TYPE_SHIFT));
// collect unique meshes
LEVELS_LOOP()
@@ -2112,7 +2322,7 @@ struct out_GBA
const uint8* ptr = (uint8*)level->meshData + level->meshOffsets[i];
Mesh* mesh = new Mesh(level, ptr);
remap[id].meshes[i] = addMesh(mesh);
remaps[id].meshes[i] = addMesh(mesh);
}
}
@@ -2141,7 +2351,7 @@ struct out_GBA
}
AnimFrames* af = new AnimFrames(startPtr, endPtr);
remap[id].animFrames[i] = addAnimFrames(af);
remaps[id].animFrames[i] = addAnimFrames(af);
}
}
@@ -2154,42 +2364,60 @@ struct out_GBA
{
Model model;
model.init(level, level->models[i]);
remap[id].models[i] = addModel(model);
remaps[id].models[i] = addModel(model);
}
}
// collect unique object textures
LEVELS_LOOP()
{
// TODO
}
printf("Meshes: %d\n", meshes.count);
printf("Models: %d\n", models.count);
printf("Animations: %d\n", animFrames.count);
// write objectTextures
headers[0].objectTextures = f.align4();
for (int32 i = 0; i < objectTextures.count; i++)
{
objectTextures[i]->write(f);
}
// write spriteTextures
headers[0].spriteTextures = f.align4();
for (int32 i = 0; i < spriteTextures.count; i++)
{
spriteTextures[i]->write(f);
}
// write meshes
//header.meshes = f.align4();
headers[0].meshData = f.align4();
for (int32 i = 0; i < meshes.count; i++)
{
meshes[i]->offset = f.align4();
meshes[i]->write(f);
meshes[i]->write(f, &remaps[meshes[i]->level->id]);
}
// write models
//header.models = f.align4();
headers[0].models = f.align4();
for (int32 i = 0; i < models.count; i++)
{
models[i]->write(f);
}
// write anims
//header.frames = f.align4();
headers[0].frameData = f.align4();
for (int32 i = 0; i < animFrames.count; i++)
{
animFrames[i]->write(f);
}
// set global array pointers
LEVELS_LOOP()
{
headers[id].objectTextures = headers[0].objectTextures;
headers[id].spriteTextures = headers[0].spriteTextures;
headers[id].meshData = headers[0].meshData;
headers[id].models = headers[0].models;
headers[id].frameData = headers[0].frameData;
}
// palette
LEVELS_LOOP()
{
@@ -2205,7 +2433,7 @@ struct out_GBA
// rooms
LEVELS_LOOP()
{
headers[id].rooms = writeRooms(f, level);
headers[id].rooms = writeRooms(f, level, &remaps[id]);
}
// floors data
@@ -2221,7 +2449,7 @@ struct out_GBA
headers[id].meshOffsets = f.align4();
for (int32 i = 0; i < level->meshOffsetsCount; i++)
{
f.write(meshes[remap[id].meshes[i]]->offset);
f.write(meshes[remaps[id].meshes[i]]->offset);
}
}
@@ -2295,48 +2523,11 @@ struct out_GBA
{
headers[id].staticMeshes = writeStaticMeshes(f, level);
}
/*
header.objectTextures = f.align4();
for (int32 i = 0; i < pc->objectTexturesCount; i++)
{
const TR1_PC::ObjectTexture* objectTexture = pc->objectTextures + i;
ObjectTexture comp;
comp.attribute = objectTexture->attribute;
comp.tile = objectTexture->tile & 0x3FFF;
comp.uv0 = ((objectTexture->uv0 << 16) | (objectTexture->uv0 >> 16)) & 0xFF00FF00;
comp.uv1 = ((objectTexture->uv1 << 16) | (objectTexture->uv1 >> 16)) & 0xFF00FF00;
comp.uv2 = ((objectTexture->uv2 << 16) | (objectTexture->uv2 >> 16)) & 0xFF00FF00;
comp.uv3 = ((objectTexture->uv3 << 16) | (objectTexture->uv3 >> 16)) & 0xFF00FF00;
// GBA rasterizer doesn't support UV deltas over 127, due performance reason, so we clamp it
fixObjectTexture(comp, i);
comp.write(f);
}
header.spriteTextures = f.align4();
for (int32 i = 0; i < pc->spriteTexturesCount; i++)
{
const TR1_PC::SpriteTexture* spriteTexture = pc->spriteTextures + i;
SpriteTexture comp;
comp.tile = spriteTexture->tile;
comp.u = spriteTexture->u;
comp.v = spriteTexture->v;
comp.w = spriteTexture->w >> 8;
comp.h = spriteTexture->h >> 8;
comp.l = spriteTexture->l;
comp.t = spriteTexture->t;
comp.r = spriteTexture->r;
comp.b = spriteTexture->b;
comp.write(f);
}
/*
header.spriteSequences = f.align4();
f.writeObj(pc->spriteSequences, pc->spriteSequencesCount);
*/
*/
// fixed cameras
LEVELS_LOOP()
@@ -2371,7 +2562,7 @@ struct out_GBA
// animated textures
LEVELS_LOOP()
{
headers[id].animTexData = writeAnimTex(f, level);
headers[id].animTexData = writeAnimTex(f, level, &remaps[id]);
}
// items

View File

@@ -156,6 +156,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="IMA.h" />
<ClInclude Include="out_32X.h" />
<ClInclude Include="out_3DO.h" />
<ClInclude Include="out_GBA.h" />
<ClInclude Include="common.h" />

View File

@@ -17,5 +17,6 @@
<ClInclude Include="out_3DO.h" />
<ClInclude Include="out_GBA.h" />
<ClInclude Include="IMA.h" />
<ClInclude Include="out_32X.h" />
</ItemGroup>
</Project>