dquakeplus/source/psp/wad3.cpp

508 lines
12 KiB
C++

/*
Copyright (C) 2009 Crow_bar.
Used code from "Fuhquake" modify by Crow_bar
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
extern "C"
{
#include "../quakedef.h"
}
#include <pspgu.h>
#include <malloc.h>
#include <list>
std::list<FILE*> UnloadFileList;
#define TEXWAD_MAXIMAGES 16384
typedef struct
{
char name[16];
FILE *file;
int position;
int size;
} texwadlump_t;
texwadlump_t texwadlump[TEXWAD_MAXIMAGES];
int numwadtextures;
//By Crow_bar
void UnloadWads (void)
{
FILE *files;
while (UnloadFileList.size() > 0)
{
files = UnloadFileList.front();
UnloadFileList.pop_front();
fclose(files);
}
numwadtextures = 0;
}
void WAD3_LoadTextureWadFile (char *filename)
{
lumpinfo_t *lumps, *lump_p;
wadinfo_t header;
int i, j, infotableofs, numlumps, lowmark;
FILE *file;
if (FS_FOpenFile (va("textures/wad3/%s", filename), &file) != -1)
goto loaded;
if (FS_FOpenFile (va("textures/halflife/%s", filename), &file) != -1)
goto loaded;
if (FS_FOpenFile (va("textures/%s", filename), &file) != -1)
goto loaded;
if (FS_FOpenFile (filename, &file) != -1)
goto loaded;
Host_Error ("Couldn't load halflife wad \"%s\"\n", filename);
loaded:
if (fread(&header, 1, sizeof(wadinfo_t), file) != sizeof(wadinfo_t))
{
Con_Printf ("WAD3_LoadTextureWadFile: unable to read wad header");
fclose(file);
return;
}
if (memcmp(header.identification, "WAD3", 4))
{
Con_Printf ("WAD3_LoadTextureWadFile: Wad file %s doesn't have WAD3 id\n",filename);
fclose(file);
return;
}
numlumps = LittleLong(header.numlumps);
if (numlumps < 1 || numlumps > TEXWAD_MAXIMAGES)
{
Con_Printf ("WAD3_LoadTextureWadFile: invalid number of lumps (%i)\n", numlumps);
fclose(file);
return;
}
infotableofs = LittleLong(header.infotableofs);
if (fseek(file, infotableofs, SEEK_SET))
{
Con_Printf ("WAD3_LoadTextureWadFile: unable to seek to lump table");
fclose(file);
return;
}
lowmark = Hunk_LowMark();
if (!(lumps = static_cast<lumpinfo_t*>(Hunk_Alloc(sizeof(lumpinfo_t) * numlumps))))
{
Con_Printf ("WAD3_LoadTextureWadFile: unable to allocate temporary memory for lump table");
fclose(file);
return;
}
if (fread(lumps, 1, sizeof(lumpinfo_t) * numlumps, file) != sizeof(lumpinfo_t) * numlumps)
{
Con_Printf ("WAD3_LoadTextureWadFile: unable to read lump table");
fclose(file);
Hunk_FreeToLowMark(lowmark);
return;
}
UnloadFileList.push_back(file); //Crow_bar. UnloadWads code
for (i = 0, lump_p = lumps; i < numlumps; i++,lump_p++)
{
W_CleanupName (lump_p->name, lump_p->name);
for (j = 0;j < numwadtextures;j++)
{
if (!strcmp(lump_p->name, texwadlump[j].name)) // name match, replace old one
break;
}
if (j >= TEXWAD_MAXIMAGES)
break; // abort loading
if (j == numwadtextures)
{
W_CleanupName (lump_p->name, texwadlump[j].name);
texwadlump[j].file = file;
texwadlump[j].position = LittleLong(lump_p->filepos);
texwadlump[j].size = LittleLong(lump_p->disksize);
numwadtextures++;
}
}
Hunk_FreeToLowMark(lowmark);
//leaves the file open
}
//converts paletted to rgba
int ConvertWad3ToRGBA(miptex_t *tex)
{
// Check that texture has data
if (!tex->offsets[0]) {
Sys_Error("ConvertWad3ToRGBA: tex->offsets[0] == 0");
}
// Get pointers to WAD3 data and palette
byte* wadData = ((byte*)tex) + tex->offsets[0];
byte* palette = ((byte*)tex) + tex->offsets[3] + (tex->width>>3)*(tex->height>>3) + 2;
//byte* palette = wadData + tex->offsets[MIPLEVELS]; // Palette starts 2 bytes after the last mipmap
// Allocate buffer for RGBA data
int imageSize = tex->width * tex->height;
byte* rgbaData = (byte*)Q_malloc(imageSize * 4);
// Convert WAD3 data to RGBA format
for (int i = 0; i < imageSize; i++) {
byte colorIndex = wadData[i];
rgbaData[i * 4] = palette[colorIndex * 3 + 0];
rgbaData[i * 4 + 1] = palette[colorIndex * 3 + 1];
rgbaData[i * 4 + 2] = palette[colorIndex * 3 + 2];
rgbaData[i * 4 + 3] = 255; // Set alpha to opaque
if (rgbaData[i * 4] == 0 && rgbaData[i * 4 + 1] == 0 && rgbaData[i * 4 + 2] == 255) {
rgbaData[i * 4] = rgbaData[i * 4 + 1] = rgbaData[i * 4 + 2] = 128;
rgbaData[i * 4 + 3] = 0;
}
}
int index = GL_LoadImages(tex->name, tex->width, tex->height, rgbaData, qtrue, GU_LINEAR, 0, 4);
free(rgbaData);
return index;
}
int ConvertWad3ToClut4(miptex_t *tex)
{
// Check that texture has data
if (!tex->offsets[0]) {
Sys_Error("ConvertWad3ToRGBA: tex->offsets[0] == 0");
}
// Get pointers to WAD3 data and palette
const byte* wadData = ((byte*)tex) + tex->offsets[0];
const byte* palette = ((byte*)tex) + tex->offsets[3] + (tex->width>>3)*(tex->height>>3) + 2;
return GL_LoadTexture8to4(tex->name, tex->width, tex->height, wadData, palette, GU_LINEAR);
}
int WAD3_LoadTexture(miptex_t *mt)
{
char texname[MAX_QPATH];
int i, j, lowmark = 0;
FILE *file;
miptex_t *tex;
int index;
if (mt->offsets[0])
return ConvertWad3ToClut4(mt); // ConvertWad3ToRGBA(mt);
texname[sizeof(texname) - 1] = 0;
W_CleanupName (mt->name, texname);
for (i = 0;i < numwadtextures;i++)
{
if (!texwadlump[i].name[0])
break;
if (strcmp(texname, texwadlump[i].name))
continue;
file = texwadlump[i].file;
if (fseek(file, texwadlump[i].position, SEEK_SET))
{
fclose(file);
Con_Printf("WAD3_LoadTexture: corrupt WAD3 file");
return 0;
}
lowmark = Hunk_LowMark();
tex = static_cast<miptex_t*>(Hunk_Alloc(texwadlump[i].size));
if (fread(tex, 1, texwadlump[i].size, file) < texwadlump[i].size)
{
Con_Printf("WAD3_LoadTexture: corrupt WAD3 file");
Hunk_FreeToLowMark(lowmark);
return 0;
}
tex->width = LittleLong(tex->width);
tex->height = LittleLong(tex->height);
if (tex->width != mt->width || tex->height != mt->height)
{
Hunk_FreeToLowMark(lowmark);
return 0;
}
for (j = 0;j < MIPLEVELS;j++)
tex->offsets[j] = LittleLong(tex->offsets[j]);
index = ConvertWad3ToClut4(mt); // ConvertWad3ToRGBA(tex);
Hunk_FreeToLowMark(lowmark);
return index;
}
return 0;
}
int WAD3_LoadTextureName(char *name)
{
char texname[MAX_QPATH];
int i, j, lowmark = 0;
FILE *file;
miptex_t *tex;
int index;
texname[sizeof(texname) - 1] = 0;
W_CleanupName (name, texname);
for (i = 0;i < numwadtextures;i++)
{
if (!texwadlump[i].name[0])
break;
if (strcmp(texname, texwadlump[i].name))
continue;
file = texwadlump[i].file;
if (fseek(file, texwadlump[i].position, SEEK_SET))
{
fclose(file);
Con_Printf("WAD3_LoadTexture: corrupt WAD3 file");
return 0;
}
lowmark = Hunk_LowMark();
tex = static_cast<miptex_t*>(Hunk_Alloc(texwadlump[i].size));
if (fread(tex, 1, texwadlump[i].size, file) < texwadlump[i].size)
{
Con_Printf("WAD3_LoadTexture: corrupt WAD3 file");
fclose(file);
Hunk_FreeToLowMark(lowmark);
return 0;
}
tex->width = LittleLong(tex->width);
tex->height = LittleLong(tex->height);
#if 0
if (tex->width != mt->width || tex->height != mt->height)
{
fclose(file);
Hunk_FreeToLowMark(lowmark);
return 0;
}
#endif
for (j = 0;j < MIPLEVELS;j++)
tex->offsets[j] = LittleLong(tex->offsets[j]);
index = ConvertWad3ToRGBA(tex);
UnloadFileList.push_back(file); //Crow_bar. UnloadWads code
/*
fclose(file);
*/
Hunk_FreeToLowMark(lowmark);
return index;
}
return 0;
}
//Other wad3 loaders
void W_LoadTextureWadFileHL (char *filename, int complain)
{
lumpinfo_t *lumps, *lump_p;
wadinfo_t header;
unsigned i, j;
int infotableofs;
FILE *file;
int numlumps;
FS_FOpenFile (filename, &file);
if (!file)
{
if (complain)
Con_Printf ("W_LoadTextureWadFile: couldn't find %s\n", filename);
return;
}
if (fread(&header, sizeof(wadinfo_t), 1, file) != 1)
{Con_Printf ("W_LoadTextureWadFile: unable to read wad header");return;}
if(header.identification[0] != 'W'
|| header.identification[1] != 'A'
|| header.identification[2] != 'D'
|| header.identification[3] != '3')
{
fclose(file);
Con_Printf ("W_LoadTextureWadFile: Wad file %s doesn't have WAD3 id\n",filename);
return;
}
numlumps = LittleLong(header.numlumps);
if (numlumps < 1 || numlumps > TEXWAD_MAXIMAGES)
{
fclose(file);
Con_Printf ("W_LoadTextureWadFile: invalid number of lumps (%i)\n", numlumps);
return;
}
infotableofs = LittleLong(header.infotableofs);
if (fseek(file, infotableofs, SEEK_SET))
{
fclose(file);
Con_Printf ("W_LoadTextureWadFile: unable to seek to lump table");
return;
}
if (!(lumps = static_cast<lumpinfo_t*>(Q_malloc(sizeof(lumpinfo_t)*numlumps))))
{
fclose(file);
Con_Printf ("W_LoadTextureWadFile: unable to allocate temporary memory for lump table");
return;
}
if (fread(lumps, sizeof(lumpinfo_t), numlumps, file) != (unsigned)numlumps)
{
fclose(file);
Con_Printf ("W_LoadTextureWadFile: unable to read lump table");
return;
}
for (i=0, lump_p = lumps ; i<(unsigned)numlumps ; i++,lump_p++)
{
W_CleanupName (lump_p->name, lump_p->name);
for (j = 0;j < TEXWAD_MAXIMAGES;j++)
{
if (texwadlump[j].name[0]) // occupied slot, check the name
{
if (!strcmp(lump_p->name, texwadlump[j].name)) // name match, replace old one
break;
}
else // empty slot
break;
}
if (j >= TEXWAD_MAXIMAGES)
break; // abort loading
W_CleanupName (lump_p->name, texwadlump[j].name);
texwadlump[j].file = file;
texwadlump[j].position = LittleLong(lump_p->filepos);
texwadlump[j].size = LittleLong(lump_p->disksize);
}
free(lumps);
//fclose(file);
// leaves the file open
}
byte *W_ConvertWAD3TextureHL(miptex_t *tex)
{
byte *in, *data, *out, *pal;
int d, p, image_size;
in = (byte *)((int) tex + tex->offsets[0]);
data = out = static_cast<byte*>(Q_malloc(tex->width * tex->height * 4));
if (!data)
return NULL;
image_size = tex->width * tex->height;
pal = in + (((image_size) * 85) >> 6);
pal += 2;
for (d = 0;d < image_size;d++)
{
p = *in++;
if (tex->name[0] == '{' && p == 255)
out[0] = out[1] = out[2] = out[3] = 0;
else
{
p *= 3;
out[0] = pal[p];
out[1] = pal[p+1];
out[2] = pal[p+2];
out[3] = 255;
}
out += 4;
}
return data;
}
byte *W_GetTextureHL(char *name)
{
char texname[17];
int i, j;
FILE *file;
miptex_t *tex = NULL;
byte *data;
texname[16] = 0;
W_CleanupName (name, texname);
for (i = 0;i < TEXWAD_MAXIMAGES;i++)
{
if (texwadlump[i].name[0])
{
if (!strcmp(texname, texwadlump[i].name)) // found it
{
file = texwadlump[i].file;
if (fseek(file, texwadlump[i].position, SEEK_SET))
{
Con_Printf("W_GetTexture: corrupt WAD3 file");
return NULL;
}
tex = static_cast<miptex_t*>(Q_malloc(texwadlump[i].size));
if (!tex)
return NULL;
if (fread(tex, 1, texwadlump[i].size, file) < (unsigned)texwadlump[i].size)
{
Con_Printf("W_GetTexture: corrupt WAD3 file");
return NULL;
}
tex->width = LittleLong(tex->width);
tex->height = LittleLong(tex->height);
for (j = 0;j < MIPLEVELS;j++)
tex->offsets[j] = LittleLong(tex->offsets[j]);
data = W_ConvertWAD3TextureHL(tex);
free(tex);
fclose(file);
return data;
}
}
else
break;
}
tex->width = tex->height = 0;
return NULL;
}