mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-04-19 16:51:53 +00:00
Merge branch 'animated-textures-with-model-features' into 'next'
Animated model textures See merge request STJr/SRB2!2489
This commit is contained in:
commit
8820304cc5
15 changed files with 2077 additions and 921 deletions
|
@ -47,7 +47,7 @@ EXPORT void HWRAPI(ClearMipMapCache) (void);
|
|||
EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value);
|
||||
|
||||
//Hurdler: added for new development
|
||||
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface);
|
||||
EXPORT void HWRAPI(DrawModel) (model_t *model, float frameIndex, float duration, float tics, float nextFrameIndex, float frameIndexStep, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface);
|
||||
EXPORT void HWRAPI(CreateModelVBOs) (model_t *model);
|
||||
EXPORT void HWRAPI(SetTransform) (FTransform *ptransform);
|
||||
EXPORT INT32 HWRAPI(GetTextureUsed) (void);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -23,13 +23,12 @@
|
|||
|
||||
typedef struct
|
||||
{
|
||||
size_t index;
|
||||
char filename[32];
|
||||
float scale;
|
||||
float offset;
|
||||
model_t *model;
|
||||
void *grpatch;
|
||||
boolean notexturefile; // true if texture file was not found
|
||||
void *blendgrpatch;
|
||||
boolean noblendfile; // true if blend texture file was not found
|
||||
boolean found;
|
||||
boolean error;
|
||||
|
|
|
@ -231,20 +231,12 @@ typedef struct
|
|||
} md2frame_t;
|
||||
|
||||
// Load the model
|
||||
model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat)
|
||||
model_t *MD2_LoadModel(char *buffer, int ztag, boolean useFloat)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
model_t *retModel = NULL;
|
||||
md2header_t *header;
|
||||
|
||||
size_t fileLen;
|
||||
int i, j;
|
||||
size_t namelen;
|
||||
char *texturefilename;
|
||||
const char *texPos;
|
||||
|
||||
char *buffer;
|
||||
|
||||
const float WUNITS = 1.0f;
|
||||
float dataScale = WUNITS;
|
||||
|
@ -271,49 +263,8 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat)
|
|||
|
||||
useFloat = true;
|
||||
|
||||
f = fopen(fileName, "rb");
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
retModel = (model_t*)Z_Calloc(sizeof(model_t), ztag, 0);
|
||||
|
||||
//size_t fileLen;
|
||||
|
||||
//int i, j;
|
||||
|
||||
//size_t namelen;
|
||||
//char *texturefilename;
|
||||
texPos = strchr(fileName, '/');
|
||||
|
||||
if (texPos)
|
||||
{
|
||||
texPos++;
|
||||
namelen = strlen(texPos) + 1;
|
||||
texturefilename = (char*)Z_Malloc(namelen, PU_CACHE, 0);
|
||||
strcpy(texturefilename, texPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
namelen = strlen(fileName) + 1;
|
||||
texturefilename = (char*)Z_Malloc(namelen, PU_CACHE, 0);
|
||||
strcpy(texturefilename, fileName);
|
||||
}
|
||||
|
||||
texturefilename[namelen - 2] = 'z';
|
||||
texturefilename[namelen - 3] = 'u';
|
||||
texturefilename[namelen - 4] = 'b';
|
||||
|
||||
// find length of file
|
||||
fseek(f, 0, SEEK_END);
|
||||
fileLen = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
// read in file
|
||||
buffer = malloc(fileLen);
|
||||
if (fread(buffer, fileLen, 1, f)) { } // squash ignored fread error
|
||||
fclose(f);
|
||||
|
||||
|
||||
// get pointer to file header
|
||||
header = (md2header_t*)buffer;
|
||||
|
||||
|
@ -571,6 +522,5 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat)
|
|||
}
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
return retModel;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,6 @@
|
|||
#include "../doomtype.h"
|
||||
|
||||
// Load the Model
|
||||
model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat);
|
||||
model_t *MD2_LoadModel(char *buffer, int ztag, boolean useFloat);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -144,20 +144,17 @@ static void LatLngInit(void)
|
|||
|
||||
static boolean latlnginit = false;
|
||||
|
||||
model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat)
|
||||
model_t *MD3_LoadModel(char *buffer, int ztag, boolean useFloat)
|
||||
{
|
||||
const float WUNITS = 1.0f;
|
||||
model_t *retModel = NULL;
|
||||
md3Frame *frames = NULL;
|
||||
char *fname = NULL;
|
||||
md3modelHeader *mdh;
|
||||
long fileLen;
|
||||
long fileReadLen;
|
||||
char *buffer;
|
||||
int surfEnd;
|
||||
int i, t;
|
||||
int matCount;
|
||||
FILE *f;
|
||||
|
||||
|
||||
if (!latlnginit)
|
||||
{
|
||||
|
@ -165,25 +162,8 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat)
|
|||
latlnginit = true;
|
||||
}
|
||||
|
||||
f = fopen(fileName, "rb");
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
retModel = (model_t*)Z_Calloc(sizeof(model_t), ztag, 0);
|
||||
|
||||
// find length of file
|
||||
fseek(f, 0, SEEK_END);
|
||||
fileLen = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
// read in file
|
||||
buffer = malloc(fileLen);
|
||||
fileReadLen = fread(buffer, fileLen, 1, f);
|
||||
fclose(f);
|
||||
|
||||
(void)fileReadLen; // intentionally ignore return value, per buildbot
|
||||
|
||||
// get pointer to file header
|
||||
mdh = (md3modelHeader*)buffer;
|
||||
|
||||
|
@ -516,7 +496,5 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat)
|
|||
}*/
|
||||
|
||||
|
||||
free(buffer);
|
||||
|
||||
return retModel;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,6 @@
|
|||
#include "../doomtype.h"
|
||||
|
||||
// Load the Model
|
||||
model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat);
|
||||
model_t *MD3_LoadModel(char *buffer, int ztag, boolean useFloat);
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -10,7 +10,9 @@
|
|||
#ifndef _HW_MODEL_H_
|
||||
#define _HW_MODEL_H_
|
||||
|
||||
#include "hw_glob.h"
|
||||
#include "../doomtype.h"
|
||||
#include "../w_wad.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -78,13 +80,44 @@ typedef struct tag_s
|
|||
// matrix_t transform;
|
||||
} tag_t;
|
||||
|
||||
#define MODEL_INTERPOLATION_FLAG "+i"
|
||||
#define MODEL_INTERPOLATION_FLAG 'i'
|
||||
#define MODEL_EXTEND_FLAG 'e'
|
||||
#define MODEL_0ANGLE_FLAG 'o'
|
||||
#define MODEL_NO_0ANGLE_FLAG 'n'
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MODEL_TYPE_NONE,
|
||||
MODEL_TYPE_ZIP,
|
||||
MODEL_TYPE_MD3,
|
||||
MODEL_TYPE_MD3S,
|
||||
MODEL_TYPE_MD2,
|
||||
MODEL_TYPE_MD2S
|
||||
} modeltype_t;
|
||||
|
||||
typedef enum //results from the LoadModelTextures function
|
||||
{
|
||||
TEXLOAD_NONE,
|
||||
TEXLOAD_TEXTURE,
|
||||
TEXLOAD_BLEND,
|
||||
} modeltexload_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
patch_t **patches;
|
||||
UINT8 *frames;
|
||||
UINT8 numtextures;
|
||||
} textureframe_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
INT32 frames[256];
|
||||
UINT8 numframes;
|
||||
boolean interpolate;
|
||||
boolean extend;
|
||||
signed char zeroangle;
|
||||
textureframe_t textures;
|
||||
textureframe_t blends;
|
||||
} modelspr2frames_t;
|
||||
|
||||
typedef struct model_s
|
||||
|
@ -98,11 +131,20 @@ typedef struct model_s
|
|||
int numTags;
|
||||
tag_t *tags;
|
||||
|
||||
int startFrame; //starting frame for non-spr2 models, can be used in order to allow multiple sprites to be contained in one md3
|
||||
char *frameNames;
|
||||
boolean interpolate[256];
|
||||
signed char zeroangle[256];
|
||||
|
||||
playersprite_t numspr2;
|
||||
modelspr2frames_t *spr2frames;
|
||||
modelspr2frames_t *superspr2frames;
|
||||
|
||||
textureframe_t *textures;
|
||||
textureframe_t *blends;
|
||||
UINT8 numtextures;
|
||||
UINT8 numblends;
|
||||
|
||||
// the max_s and max_t values that the uvs are currently adjusted to
|
||||
// (if a sprite is used as a texture)
|
||||
float max_s;
|
||||
|
@ -119,15 +161,17 @@ extern model_t *modelHead;
|
|||
void HWR_ReloadModels(void);
|
||||
|
||||
tag_t *GetTagByName(model_t *model, char *name, int frame);
|
||||
model_t *LoadModel(const char *filename, int ztag);
|
||||
model_t *LoadModel(const char *filename, int ztag, size_t spriteModelIndex);
|
||||
void UnloadModel(model_t *model);
|
||||
modeltype_t GetModelType(const char *name, boolean printfail);
|
||||
void Optimize(model_t *model);
|
||||
void LoadModelInterpolationSettings(model_t *model);
|
||||
void LoadModelSettings(model_t *model, size_t spriteModelIndex);
|
||||
void LoadModelSprite2(model_t *model);
|
||||
void GenerateVertexNormals(model_t *model);
|
||||
void GeneratePolygonNormals(model_t *model, int ztag);
|
||||
void CreateVBOTiny(mesh_t *mesh, tinyframe_t *frame);
|
||||
void CreateVBO(mesh_t *mesh, mdlframe_t *frame);
|
||||
void DeleteVBOs(model_t *model);
|
||||
modeltexload_t LoadModelTextures(const char *filename, model_t *model, wadfile_t *zip, size_t spriteModelIndex);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2462,7 +2462,7 @@ EXPORT void HWRAPI(CreateModelVBOs) (model_t *model)
|
|||
|
||||
#define BUFFER_OFFSET(i) ((void*)(i))
|
||||
|
||||
static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface)
|
||||
static void DrawModelEx(model_t *model, float frameIndex, float duration, float tics, float nextFrameIndex, float frameIndexStep, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface)
|
||||
{
|
||||
static GLRGBAFloat poly = {0,0,0,0};
|
||||
static GLRGBAFloat tint = {0,0,0,0};
|
||||
|
@ -2630,11 +2630,40 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float
|
|||
|
||||
if (useTinyFrames)
|
||||
{
|
||||
tinyframe_t *frame = &mesh->tinyframes[frameIndex % mesh->numFrames];
|
||||
UINT32 idx = frameIndex;
|
||||
UINT32 nidx;
|
||||
float offset = frameIndex - idx;
|
||||
float step = fabsf(frameIndexStep) * pol;
|
||||
tinyframe_t *frame = &mesh->tinyframes[idx];
|
||||
tinyframe_t *nextframe = NULL;
|
||||
|
||||
if (nextFrameIndex != -1)
|
||||
nextframe = &mesh->tinyframes[nextFrameIndex % mesh->numFrames];
|
||||
if (nextFrameIndex > -1.0f)
|
||||
{
|
||||
nidx = nextFrameIndex;
|
||||
if (nextFrameIndex >= mesh->numFrames)
|
||||
{
|
||||
if (model->startFrame)
|
||||
nidx = model->startFrame;
|
||||
else
|
||||
nidx = 0;
|
||||
}
|
||||
if (frameIndexStep > 1.0f) //extend the animation beyond the normal allotted amount within the same amount of time, and interpolate
|
||||
{
|
||||
idx = ((frameIndex + step >= frameIndex + frameIndexStep) ? nidx : frameIndex + step);
|
||||
frame = &mesh->tinyframes[idx];
|
||||
if (nextFrameIndex <= frameIndex && (frameIndex + step >= frameIndex + frameIndexStep - 1))
|
||||
nextframe = &mesh->tinyframes[nidx];
|
||||
else
|
||||
nextframe = &mesh->tinyframes[idx + 1];
|
||||
}
|
||||
else if (frameIndexStep < -1.0f) //dont interpolate, still extend
|
||||
{
|
||||
idx = ((frameIndex + step >= frameIndex + (-1 * frameIndexStep)) ? nidx : frameIndex + step);
|
||||
frame = &mesh->tinyframes[idx];
|
||||
}
|
||||
else
|
||||
nextframe = &mesh->tinyframes[nidx];
|
||||
}
|
||||
|
||||
if (!nextframe || fpclassify(pol) == FP_ZERO)
|
||||
{
|
||||
|
@ -2661,17 +2690,21 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float
|
|||
short *vertPtr;
|
||||
char *normPtr;
|
||||
int j = 0;
|
||||
float inter = pol;
|
||||
|
||||
// Dangit, I soooo want to do this in a GLSL shader...
|
||||
AllocLerpTinyBuffer(mesh->numVertices * sizeof(short) * 3);
|
||||
vertPtr = vertTinyBuffer;
|
||||
normPtr = normTinyBuffer;
|
||||
|
||||
inter = fmodf(offset + step, 1.0f);
|
||||
inter = (inter <= 0) ? 1.0f : inter;
|
||||
|
||||
for (j = 0; j < mesh->numVertices * 3; j++)
|
||||
{
|
||||
// Interpolate
|
||||
*vertPtr++ = (short)(frame->vertices[j] + (pol * (nextframe->vertices[j] - frame->vertices[j])));
|
||||
*normPtr++ = (char)(frame->normals[j] + (pol * (nextframe->normals[j] - frame->normals[j])));
|
||||
*vertPtr++ = (short)(frame->vertices[j] + (inter * (nextframe->vertices[j] - frame->vertices[j])));
|
||||
*normPtr++ = (char)(frame->normals[j] + (inter * (nextframe->normals[j] - frame->normals[j])));
|
||||
}
|
||||
|
||||
pglVertexPointer(3, GL_SHORT, 0, vertTinyBuffer);
|
||||
|
@ -2682,11 +2715,40 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float
|
|||
}
|
||||
else
|
||||
{
|
||||
mdlframe_t *frame = &mesh->frames[frameIndex % mesh->numFrames];
|
||||
UINT32 idx = frameIndex;
|
||||
UINT32 nidx;
|
||||
float offset = frameIndex - idx;
|
||||
float step = fabsf(frameIndexStep) * pol;
|
||||
mdlframe_t *frame = &mesh->frames[idx];
|
||||
mdlframe_t *nextframe = NULL;
|
||||
|
||||
if (nextFrameIndex != -1)
|
||||
nextframe = &mesh->frames[nextFrameIndex % mesh->numFrames];
|
||||
if (nextFrameIndex > -1.0f)
|
||||
{
|
||||
nidx = nextFrameIndex;
|
||||
if (nextFrameIndex >= mesh->numFrames)
|
||||
{
|
||||
if (model->startFrame)
|
||||
nidx = model->startFrame;
|
||||
else
|
||||
nidx = 0;
|
||||
}
|
||||
if (frameIndexStep > 1.0f) //extend the animation beyond the normal allotted amount within the same amount of time, and interpolate
|
||||
{
|
||||
idx = ((frameIndex + step >= frameIndex + frameIndexStep) ? nidx : frameIndex + step);
|
||||
frame = &mesh->frames[idx];
|
||||
if (nextFrameIndex <= frameIndex && (frameIndex + step >= frameIndex + frameIndexStep - 1))
|
||||
nextframe = &mesh->frames[nidx];
|
||||
else
|
||||
nextframe = &mesh->frames[idx + 1];
|
||||
}
|
||||
else if (frameIndexStep < -1.0f) //dont interpolate, still extend
|
||||
{
|
||||
idx = ((frameIndex + step >= frameIndex + (-1 * frameIndexStep)) ? nidx : frameIndex + step);
|
||||
frame = &mesh->frames[idx];
|
||||
}
|
||||
else
|
||||
nextframe = &mesh->frames[nidx];
|
||||
}
|
||||
|
||||
if (!nextframe || fpclassify(pol) == FP_ZERO)
|
||||
{
|
||||
|
@ -2715,6 +2777,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float
|
|||
float *vertPtr;
|
||||
float *normPtr;
|
||||
int j = 0;
|
||||
float inter = pol;
|
||||
|
||||
// Dangit, I soooo want to do this in a GLSL shader...
|
||||
AllocLerpBuffer(mesh->numVertices * sizeof(float) * 3);
|
||||
|
@ -2722,11 +2785,14 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float
|
|||
normPtr = normBuffer;
|
||||
//int j = 0;
|
||||
|
||||
inter = fmodf(offset + step, 1.0f);
|
||||
inter = (inter <= 0) ? 1.0f : inter;
|
||||
|
||||
for (j = 0; j < mesh->numVertices * 3; j++)
|
||||
{
|
||||
// Interpolate
|
||||
*vertPtr++ = frame->vertices[j] + (pol * (nextframe->vertices[j] - frame->vertices[j]));
|
||||
*normPtr++ = frame->normals[j] + (pol * (nextframe->normals[j] - frame->normals[j]));
|
||||
*vertPtr++ = frame->vertices[j] + (inter * (nextframe->vertices[j] - frame->vertices[j]));
|
||||
*normPtr++ = frame->normals[j] + (inter * (nextframe->normals[j] - frame->normals[j]));
|
||||
}
|
||||
|
||||
pglVertexPointer(3, GL_FLOAT, 0, vertBuffer);
|
||||
|
@ -2756,9 +2822,9 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float
|
|||
// -----------------+
|
||||
// HWRAPI DrawModel : Draw a model
|
||||
// -----------------+
|
||||
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface)
|
||||
EXPORT void HWRAPI(DrawModel) (model_t *model, float frameIndex, float duration, float tics, float nextFrameIndex, float frameIndexStep, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface)
|
||||
{
|
||||
DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, hscale, vscale, flipped, hflipped, Surface);
|
||||
DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, frameIndexStep, pos, hscale, vscale, flipped, hflipped, Surface);
|
||||
}
|
||||
|
||||
// -----------------+
|
||||
|
|
20
src/info.c
20
src/info.c
|
@ -828,18 +828,18 @@ state_t states[NUMSTATES] =
|
|||
|
||||
// c:
|
||||
{SPR_PLAY, SPR2_TAL0|FF_SPR2MIDSTART, 5, {NULL}, 0, 0, S_TAILSOVERLAY_STAND, 0}, // S_TAILSOVERLAY_STAND
|
||||
{SPR_PLAY, SPR2_TAL1|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_0DEGREES, 0}, // S_TAILSOVERLAY_0DEGREES
|
||||
{SPR_PLAY, SPR2_TAL2|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_PLUS30DEGREES, 0}, // S_TAILSOVERLAY_PLUS30DEGREES
|
||||
{SPR_PLAY, SPR2_TAL3|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_PLUS60DEGREES, 0}, // S_TAILSOVERLAY_PLUS60DEGREES
|
||||
{SPR_PLAY, SPR2_TAL4|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_MINUS30DEGREES, 0}, // S_TAILSOVERLAY_MINUS30DEGREES
|
||||
{SPR_PLAY, SPR2_TAL5|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_MINUS60DEGREES, 0}, // S_TAILSOVERLAY_MINUS60DEGREES
|
||||
{SPR_PLAY, SPR2_TAL6|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_RUN, 0}, // S_TAILSOVERLAY_RUN
|
||||
{SPR_PLAY, SPR2_TAL1|FF_SPR2MIDSTART, 4, {NULL}, 0, 0, S_TAILSOVERLAY_0DEGREES, 0}, // S_TAILSOVERLAY_0DEGREES
|
||||
{SPR_PLAY, SPR2_TAL2|FF_SPR2MIDSTART, 4, {NULL}, 0, 0, S_TAILSOVERLAY_PLUS30DEGREES, 0}, // S_TAILSOVERLAY_PLUS30DEGREES
|
||||
{SPR_PLAY, SPR2_TAL3|FF_SPR2MIDSTART, 4, {NULL}, 0, 0, S_TAILSOVERLAY_PLUS60DEGREES, 0}, // S_TAILSOVERLAY_PLUS60DEGREES
|
||||
{SPR_PLAY, SPR2_TAL4|FF_SPR2MIDSTART, 4, {NULL}, 0, 0, S_TAILSOVERLAY_MINUS30DEGREES, 0}, // S_TAILSOVERLAY_MINUS30DEGREES
|
||||
{SPR_PLAY, SPR2_TAL5|FF_SPR2MIDSTART, 4, {NULL}, 0, 0, S_TAILSOVERLAY_MINUS60DEGREES, 0}, // S_TAILSOVERLAY_MINUS60DEGREES
|
||||
{SPR_PLAY, SPR2_TAL6|FF_SPR2MIDSTART, 2, {NULL}, 0, 0, S_TAILSOVERLAY_RUN, 0}, // S_TAILSOVERLAY_RUN
|
||||
{SPR_PLAY, SPR2_TAL7|FF_SPR2MIDSTART, 4, {NULL}, 0, 0, S_TAILSOVERLAY_FLY, 0}, // S_TAILSOVERLAY_FLY
|
||||
{SPR_PLAY, SPR2_TAL8|FF_SPR2MIDSTART, 4, {NULL}, 0, 0, S_TAILSOVERLAY_TIRE, 0}, // S_TAILSOVERLAY_TIRE
|
||||
{SPR_PLAY, SPR2_TAL9|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_PAIN, 0}, // S_TAILSOVERLAY_PAIN
|
||||
{SPR_PLAY, SPR2_TALA|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_GASP, 0}, // S_TAILSOVERLAY_GASP
|
||||
{SPR_PLAY, SPR2_TALB , 35, {NULL}, 0, 0, S_TAILSOVERLAY_EDGE, 0}, // S_TAILSOVERLAY_EDGE
|
||||
{SPR_PLAY, SPR2_TALC|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_DASH, 0}, // S_TAILSOVERLAY_DASH
|
||||
{SPR_PLAY, SPR2_TAL9|FF_SPR2MIDSTART, 4, {NULL}, 0, 0, S_TAILSOVERLAY_PAIN, 0}, // S_TAILSOVERLAY_PAIN
|
||||
{SPR_PLAY, SPR2_TALA|FF_SPR2MIDSTART, 4, {NULL}, 0, 0, S_TAILSOVERLAY_GASP, 0}, // S_TAILSOVERLAY_GASP
|
||||
{SPR_PLAY, SPR2_TALB , 12, {NULL}, 0, 0, S_TAILSOVERLAY_EDGE, 0}, // S_TAILSOVERLAY_EDGE
|
||||
{SPR_PLAY, SPR2_TALC|FF_SPR2MIDSTART, 2, {NULL}, 0, 0, S_TAILSOVERLAY_DASH, 0}, // S_TAILSOVERLAY_DASH
|
||||
|
||||
// [:
|
||||
{SPR_JETF, 3|FF_ANIMATE|FF_FULLBRIGHT, 2, {NULL}, 1, 1, S_JETFUME1, 0}, // S_JETFUMEFLASH
|
||||
|
|
|
@ -915,14 +915,8 @@ boolean Picture_IsLumpPNG(const UINT8 *d, size_t s)
|
|||
/*#if PNG_LIBPNG_VER_DLLNUM < 14
|
||||
typedef PNG_CONST png_byte *png_const_bytep;
|
||||
#endif*/
|
||||
typedef struct
|
||||
{
|
||||
const UINT8 *buffer;
|
||||
UINT32 size;
|
||||
UINT32 position;
|
||||
} png_io_t;
|
||||
|
||||
static void PNG_IOReader(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
void PNG_IOReader(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
png_io_t *f = png_get_io_ptr(png_ptr);
|
||||
if (length > (f->size - f->position))
|
||||
|
|
|
@ -17,6 +17,28 @@
|
|||
#include "r_defs.h"
|
||||
#include "doomdef.h"
|
||||
|
||||
#ifdef HAVE_PNG
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#ifndef _LARGEFILE64_SOURCE
|
||||
#define _LARGEFILE64_SOURCE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _LFS64_LARGEFILE
|
||||
#define _LFS64_LARGEFILE
|
||||
#endif
|
||||
|
||||
#ifndef _FILE_OFFSET_BITS
|
||||
#define _FILE_OFFSET_BITS 0
|
||||
#endif
|
||||
|
||||
#include "png.h"
|
||||
#ifndef PNG_READ_SUPPORTED
|
||||
#undef HAVE_PNG
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PICFMT_NONE = 0,
|
||||
|
@ -78,6 +100,8 @@ void *Picture_GetPatchPixel(
|
|||
|
||||
void *Picture_TextureToFlat(size_t texnum);
|
||||
|
||||
void PNG_IOReader(png_structp png_ptr, png_bytep data, png_size_t length);
|
||||
|
||||
INT32 Picture_FormatBPP(pictureformat_t format);
|
||||
boolean Picture_IsPatchFormat(pictureformat_t format);
|
||||
boolean Picture_IsInternalPatchFormat(pictureformat_t format);
|
||||
|
@ -118,6 +142,13 @@ void *Picture_PNGConvert(
|
|||
pictureflags_t flags);
|
||||
boolean Picture_PNGDimensions(UINT8 *png, INT32 *width, INT32 *height, INT16 *topoffset, INT16 *leftoffset, size_t size);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const UINT8 *buffer;
|
||||
UINT32 size;
|
||||
UINT32 position;
|
||||
} png_io_t;
|
||||
|
||||
#define PICTURE_PNG_USELOOKUP
|
||||
#endif
|
||||
|
||||
|
|
683
src/w_wad.c
683
src/w_wad.c
|
@ -121,22 +121,7 @@ void W_Shutdown(void)
|
|||
while (numwadfiles--)
|
||||
{
|
||||
wadfile_t *wad = wadfiles[numwadfiles];
|
||||
|
||||
if (wad->handle)
|
||||
fclose(wad->handle);
|
||||
Z_Free(wad->filename);
|
||||
if (wad->path)
|
||||
Z_Free(wad->path);
|
||||
while (wad->numlumps--)
|
||||
{
|
||||
if (wad->lumpinfo[wad->numlumps].diskpath)
|
||||
Z_Free(wad->lumpinfo[wad->numlumps].diskpath);
|
||||
Z_Free(wad->lumpinfo[wad->numlumps].longname);
|
||||
Z_Free(wad->lumpinfo[wad->numlumps].fullname);
|
||||
}
|
||||
|
||||
Z_Free(wad->lumpinfo);
|
||||
Z_Free(wad);
|
||||
W_DeleteResourceFile(wad);
|
||||
}
|
||||
|
||||
Z_Free(wadfiles);
|
||||
|
@ -338,11 +323,36 @@ static void W_InvalidateLumpnumCache(void)
|
|||
memset(lumpnumcache, 0, sizeof (lumpnumcache));
|
||||
}
|
||||
|
||||
/** Detect a file type.
|
||||
* \todo Actually detect the wad/pkzip headers and whatnot, instead of just checking the extensions.
|
||||
*/
|
||||
static restype_t ResourceFileDetect (const char* filename)
|
||||
static boolean MagicIsWAD(char id[4])
|
||||
{
|
||||
// Very likely a wad
|
||||
if (!memcmp(id, "IWAD", 4) || !memcmp(id, "PWAD", 4) || !memcmp(id, "ZWAD", 4) || !memcmp(id, "SDLL", 4))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Detect a file type.
|
||||
*/
|
||||
static restype_t ResourceFileDetect (FILE* handle, const char* filename)
|
||||
{
|
||||
char id[4];
|
||||
size_t read;
|
||||
|
||||
// Read the first four bytes, then seek back
|
||||
read = fread(&id, 1, sizeof id, handle);
|
||||
|
||||
fseek(handle, 0, SEEK_SET);
|
||||
|
||||
if (read >= sizeof id)
|
||||
{
|
||||
if (MagicIsWAD(id))
|
||||
return RET_WAD;
|
||||
// Seems to be a zip (so, a pk3)
|
||||
else if (!memcmp(id, "PK\x03\x04", 4))
|
||||
return RET_PK3;
|
||||
}
|
||||
|
||||
if (!stricmp(&filename[strlen(filename) - 4], ".pk3"))
|
||||
return RET_PK3;
|
||||
if (!stricmp(&filename[strlen(filename) - 4], ".soc"))
|
||||
|
@ -402,9 +412,7 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen
|
|||
|
||||
if (memcmp(header.identification, "ZWAD", 4) == 0)
|
||||
compressed = 1;
|
||||
else if (memcmp(header.identification, "IWAD", 4) != 0
|
||||
&& memcmp(header.identification, "PWAD", 4) != 0
|
||||
&& memcmp(header.identification, "SDLL", 4) != 0)
|
||||
else if (!MagicIsWAD(header.identification))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Invalid WAD header\n"));
|
||||
return NULL;
|
||||
|
@ -921,7 +929,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
|
|||
}
|
||||
#endif
|
||||
|
||||
switch(type = ResourceFileDetect(filename))
|
||||
switch(type = ResourceFileDetect(handle, filename))
|
||||
{
|
||||
case RET_SOC:
|
||||
lumpinfo = ResGetLumpsStandalone(handle, &numlumps, "OBJCTCFG");
|
||||
|
@ -1018,6 +1026,391 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
|
|||
return wadfile->numlumps;
|
||||
}
|
||||
|
||||
wadfile_t *W_LoadResourceFile(const char *filename)
|
||||
{
|
||||
FILE *handle;
|
||||
lumpinfo_t *lumpinfo = NULL;
|
||||
restype_t type;
|
||||
UINT16 numlumps = 0;
|
||||
|
||||
// open wad file
|
||||
if ((handle = fopen(filename, "rb")) == NULL)
|
||||
{
|
||||
CONS_Printf(M_GetText("Errors occurred while loading %s.\n"), filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (type = ResourceFileDetect(handle, filename))
|
||||
{
|
||||
case RET_PK3:
|
||||
lumpinfo = ResGetLumpsZip(handle, &numlumps);
|
||||
break;
|
||||
case RET_WAD:
|
||||
lumpinfo = ResGetLumpsWad(handle, &numlumps, filename);
|
||||
break;
|
||||
default:
|
||||
CONS_Alert(CONS_ERROR, "Unsupported file format\n");
|
||||
}
|
||||
|
||||
if (lumpinfo == NULL)
|
||||
{
|
||||
fclose(handle);
|
||||
CONS_Printf(M_GetText("Errors occurred while loading %s.\n"), filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wadfile_t *wadfile = Z_Malloc(sizeof (*wadfile), PU_STATIC, NULL);
|
||||
wadfile->filename = Z_StrDup(filename);
|
||||
wadfile->path = NULL;
|
||||
wadfile->type = type;
|
||||
wadfile->handle = handle;
|
||||
wadfile->numlumps = numlumps;
|
||||
wadfile->foldercount = 0;
|
||||
wadfile->lumpinfo = lumpinfo;
|
||||
wadfile->important = false;
|
||||
fseek(handle, 0, SEEK_END);
|
||||
wadfile->filesize = (unsigned)ftell(handle);
|
||||
|
||||
// Irrelevant.
|
||||
memset(wadfile->md5sum, 0x00, 16);
|
||||
|
||||
Z_Calloc(numlumps * sizeof (*wadfile->lumpcache), PU_STATIC, &wadfile->lumpcache);
|
||||
Z_Calloc(numlumps * sizeof (*wadfile->patchcache), PU_STATIC, &wadfile->patchcache);
|
||||
|
||||
return wadfile;
|
||||
}
|
||||
|
||||
void W_DeleteResourceFile(wadfile_t *wad)
|
||||
{
|
||||
if (!wad)
|
||||
return;
|
||||
|
||||
if (wad->handle)
|
||||
fclose(wad->handle);
|
||||
Z_Free(wad->filename);
|
||||
if (wad->path)
|
||||
Z_Free(wad->path);
|
||||
|
||||
while (wad->numlumps--)
|
||||
{
|
||||
Z_Free(wad->lumpcache[wad->numlumps]);
|
||||
if (wad->patchcache[wad->numlumps])
|
||||
Patch_Free(wad->patchcache[wad->numlumps]);
|
||||
if (wad->lumpinfo[wad->numlumps].diskpath)
|
||||
Z_Free(wad->lumpinfo[wad->numlumps].diskpath);
|
||||
Z_Free(wad->lumpinfo[wad->numlumps].longname);
|
||||
Z_Free(wad->lumpinfo[wad->numlumps].fullname);
|
||||
}
|
||||
|
||||
Z_Free(wad->lumpcache);
|
||||
Z_Free(wad->patchcache);
|
||||
Z_Free(wad->lumpinfo);
|
||||
Z_Free(wad);
|
||||
}
|
||||
|
||||
UINT16 Resource_CheckNumForName(wadfile_t *wad, const char *name)
|
||||
{
|
||||
lumpinfo_t *lump_p = wad->lumpinfo;
|
||||
for (UINT16 i = 0; i < wad->numlumps; i++, lump_p++)
|
||||
if (!strcmp(lump_p->fullname, name))
|
||||
return i;
|
||||
|
||||
// not found.
|
||||
return INT16_MAX;
|
||||
}
|
||||
|
||||
void *Resource_CacheLumpNum(wadfile_t *wad, UINT16 lump, INT32 tag)
|
||||
{
|
||||
if (lump >= wad->numlumps)
|
||||
return NULL;
|
||||
|
||||
lumpcache_t *lumpcache = wad->lumpcache;
|
||||
if (!lumpcache[lump])
|
||||
{
|
||||
void *ptr = Z_Malloc(Resource_LumpLength(wad, lump), tag, &lumpcache[lump]);
|
||||
Resource_ReadLumpHeader(wad, lump, ptr, 0, 0); // read the lump in full
|
||||
}
|
||||
else
|
||||
Z_ChangeTag(lumpcache[lump], tag);
|
||||
|
||||
return lumpcache[lump];
|
||||
}
|
||||
|
||||
void *Resource_CacheLumpName(wadfile_t *wad, const char *name, INT32 tag)
|
||||
{
|
||||
UINT16 lumpnum = Resource_CheckNumForName(wad, name);
|
||||
if (lumpnum == INT16_MAX)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Resource file %s does not contain any lump named %s\n", wad->filename, name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return Resource_CacheLumpNum(wad, lumpnum, tag);
|
||||
}
|
||||
|
||||
boolean Resource_LumpExists(wadfile_t *wad, const char *name)
|
||||
{
|
||||
return Resource_CheckNumForName(wad, name) != INT16_MAX;
|
||||
}
|
||||
|
||||
size_t Resource_LumpLength(wadfile_t *wad, UINT16 lump)
|
||||
{
|
||||
lumpinfo_t *l;
|
||||
|
||||
if (lump >= wad->numlumps)
|
||||
return 0;
|
||||
|
||||
l = wad->lumpinfo + lump;
|
||||
|
||||
// Open the external file for this lump, if the WAD is a folder.
|
||||
if (wad->type == RET_FOLDER)
|
||||
{
|
||||
// pathisdirectory calls stat, so if anything wrong has happened,
|
||||
// this is the time to be aware of it.
|
||||
INT32 stat = pathisdirectory(l->diskpath);
|
||||
|
||||
if (stat < 0)
|
||||
{
|
||||
#ifndef AVOID_ERRNO
|
||||
if (direrror == ENOENT)
|
||||
I_Error("W_LumpLengthPwad: file %s doesn't exist", l->diskpath);
|
||||
else
|
||||
I_Error("W_LumpLengthPwad: could not stat %s: %s", l->diskpath, strerror(direrror));
|
||||
#else
|
||||
I_Error("W_LumpLengthPwad: could not access %s", l->diskpath);
|
||||
#endif
|
||||
}
|
||||
else if (stat == 1) // Path is a folder.
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
FILE *handle = fopen(l->diskpath, "rb");
|
||||
if (handle == NULL)
|
||||
I_Error("W_LumpLengthPwad: could not open file %s", l->diskpath);
|
||||
|
||||
fseek(handle, 0, SEEK_END);
|
||||
l->size = l->disksize = ftell(handle);
|
||||
fclose(handle);
|
||||
}
|
||||
}
|
||||
|
||||
return l->size;
|
||||
}
|
||||
|
||||
size_t Resource_ReadLumpHeader(wadfile_t *wad, UINT16 lump, void *dest, size_t size, size_t offset)
|
||||
{
|
||||
size_t lumpsize, bytesread;
|
||||
lumpinfo_t *l;
|
||||
FILE *handle = NULL;
|
||||
|
||||
if (lump >= wad->numlumps)
|
||||
return 0;
|
||||
|
||||
l = wad->lumpinfo + lump;
|
||||
|
||||
// Open the external file for this lump, if the WAD is a folder.
|
||||
if (wad->type == RET_FOLDER)
|
||||
{
|
||||
// pathisdirectory calls stat, so if anything wrong has happened,
|
||||
// this is the time to be aware of it.
|
||||
INT32 stat = pathisdirectory(l->diskpath);
|
||||
|
||||
if (stat < 0)
|
||||
{
|
||||
#ifndef AVOID_ERRNO
|
||||
if (direrror == ENOENT)
|
||||
I_Error("Resource_ReadLumpHeader: file %s doesn't exist", l->diskpath);
|
||||
else
|
||||
I_Error("Resource_ReadLumpHeader: could not stat %s: %s", l->diskpath, strerror(direrror));
|
||||
#else
|
||||
I_Error("Resource_ReadLumpHeader: could not access %s", l->diskpath);
|
||||
#endif
|
||||
}
|
||||
else if (stat == 1) // Path is a folder.
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
handle = fopen(l->diskpath, "rb");
|
||||
if (handle == NULL)
|
||||
I_Error("Resource_ReadLumpHeader: could not open file %s", l->diskpath);
|
||||
|
||||
// Find length of file
|
||||
fseek(handle, 0, SEEK_END);
|
||||
l->size = l->disksize = ftell(handle);
|
||||
}
|
||||
}
|
||||
|
||||
lumpsize = wad->lumpinfo[lump].size;
|
||||
|
||||
// empty resource (usually markers like S_START, F_END ..)
|
||||
if (!lumpsize || lumpsize < offset)
|
||||
{
|
||||
if (wad->type == RET_FOLDER)
|
||||
fclose(handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// zero size means read all the lump
|
||||
if (!size || size + offset > lumpsize)
|
||||
size = lumpsize - offset;
|
||||
|
||||
// Let's get the raw lump data.
|
||||
// We setup the desired file handle to read the lump data.
|
||||
if (wad->type != RET_FOLDER)
|
||||
handle = wad->handle;
|
||||
fseek(handle, (long)(l->position + offset), SEEK_SET);
|
||||
|
||||
// But let's not copy it yet. We support different compression formats on lumps, so we need to take that into account.
|
||||
switch (wad->lumpinfo[lump].compression)
|
||||
{
|
||||
case CM_NOCOMPRESSION: // If it's uncompressed, we directly write the data into our destination, and return the bytes read.
|
||||
bytesread = fread(dest, 1, size, handle);
|
||||
if (wad->type == RET_FOLDER)
|
||||
fclose(handle);
|
||||
#ifdef NO_PNG_LUMPS
|
||||
if (Picture_IsLumpPNG((UINT8 *)dest, bytesread))
|
||||
Picture_ThrowPNGError(l->fullname, wad->filename);
|
||||
#endif
|
||||
return bytesread;
|
||||
case CM_LZF: // Is it LZF compressed? Used by ZWADs.
|
||||
{
|
||||
#ifdef ZWAD
|
||||
char *rawData; // The lump's raw data.
|
||||
char *decData; // Lump's decompressed real data.
|
||||
size_t retval; // Helper var, lzf_decompress returns 0 when an error occurs.
|
||||
|
||||
rawData = Z_Malloc(l->disksize, PU_STATIC, NULL);
|
||||
decData = Z_Malloc(l->size, PU_STATIC, NULL);
|
||||
|
||||
if (fread(rawData, 1, l->disksize, handle) < l->disksize)
|
||||
I_Error("wad %s, lump %d: cannot read compressed data", wad->filename, lump);
|
||||
retval = lzf_decompress(rawData, l->disksize, decData, l->size);
|
||||
#ifndef AVOID_ERRNO
|
||||
if (retval == 0) // If this was returned, check if errno was set
|
||||
{
|
||||
// errno is a global var set by the lzf functions when something goes wrong.
|
||||
if (errno == E2BIG)
|
||||
I_Error("wad %s, lump %d: compressed data too big (bigger than %s)", wad->filename, lump, sizeu1(l->size));
|
||||
else if (errno == EINVAL)
|
||||
I_Error("wad %s, lump %d: invalid compressed data", wad->filename, lump);
|
||||
}
|
||||
// Otherwise, fall back on below error (if zero was actually the correct size then ???)
|
||||
#endif
|
||||
if (retval != l->size)
|
||||
{
|
||||
I_Error("wad %s, lump %d: decompressed to wrong number of bytes (expected %s, got %s)", wad->filename, lump, sizeu1(l->size), sizeu2(retval));
|
||||
}
|
||||
|
||||
if (!decData) // Did we get no data at all?
|
||||
return 0;
|
||||
M_Memcpy(dest, decData + offset, size);
|
||||
Z_Free(rawData);
|
||||
Z_Free(decData);
|
||||
#ifdef NO_PNG_LUMPS
|
||||
if (Picture_IsLumpPNG((UINT8 *)dest, size))
|
||||
Picture_ThrowPNGError(l->fullname, wad->filename);
|
||||
#endif
|
||||
return size;
|
||||
#else
|
||||
//I_Error("ZWAD files not supported on this platform.");
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
}
|
||||
#ifdef HAVE_ZLIB
|
||||
case CM_DEFLATE: // Is it compressed via DEFLATE? Very common in ZIPs/PK3s, also what most doom-related editors support.
|
||||
{
|
||||
UINT8 *rawData; // The lump's raw data.
|
||||
UINT8 *decData; // Lump's decompressed real data.
|
||||
|
||||
int zErr; // Helper var.
|
||||
z_stream strm;
|
||||
unsigned long rawSize = l->disksize;
|
||||
unsigned long decSize = l->size;
|
||||
|
||||
rawData = Z_Malloc(rawSize, PU_STATIC, NULL);
|
||||
decData = Z_Malloc(decSize, PU_STATIC, NULL);
|
||||
|
||||
if (fread(rawData, 1, rawSize, handle) < rawSize)
|
||||
I_Error("wad %s, lump %d: cannot read compressed data", wad->filename, lump);
|
||||
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
|
||||
strm.total_in = strm.avail_in = rawSize;
|
||||
strm.total_out = strm.avail_out = decSize;
|
||||
|
||||
strm.next_in = rawData;
|
||||
strm.next_out = decData;
|
||||
|
||||
zErr = inflateInit2(&strm, -15);
|
||||
if (zErr == Z_OK)
|
||||
{
|
||||
zErr = inflate(&strm, Z_FINISH);
|
||||
if (zErr == Z_STREAM_END)
|
||||
{
|
||||
M_Memcpy(dest, decData, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
size = 0;
|
||||
zerr(zErr);
|
||||
}
|
||||
|
||||
(void)inflateEnd(&strm);
|
||||
}
|
||||
else
|
||||
{
|
||||
size = 0;
|
||||
zerr(zErr);
|
||||
}
|
||||
|
||||
Z_Free(rawData);
|
||||
Z_Free(decData);
|
||||
|
||||
#ifdef NO_PNG_LUMPS
|
||||
if (Picture_IsLumpPNG((UINT8 *)dest, size))
|
||||
Picture_ThrowPNGError(l->fullname, wad->filename);
|
||||
#endif
|
||||
return size;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
I_Error("wad %s, lump %d: unsupported compression type!", wad->filename, lump);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT16 Resource_CheckNumForFolderStartPK3(wadfile_t *wad, const char *name, UINT16 startlump){
|
||||
size_t name_length;
|
||||
INT32 i;
|
||||
lumpinfo_t *lump_p = wad->lumpinfo + startlump;
|
||||
name_length = strlen(name);
|
||||
for (i = startlump; i < wad->numlumps; i++, lump_p++)
|
||||
{
|
||||
if (strnicmp(name, lump_p->fullname, name_length) == 0)
|
||||
{
|
||||
/* SLADE is special and puts a single directory entry. Skip that. */
|
||||
if (strlen(lump_p->fullname) == name_length)
|
||||
i++;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return INT16_MAX;
|
||||
}
|
||||
|
||||
UINT16 Resource_CheckNumForFolderEndPK3(wadfile_t *wad, const char *name, UINT16 startlump){
|
||||
INT32 i;
|
||||
lumpinfo_t *lump_p = wad->lumpinfo + startlump;
|
||||
for (i = startlump; i < wad->numlumps; i++, lump_p++)
|
||||
{
|
||||
if (strnicmp(name, lump_p->fullname, strlen(name)))
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
//
|
||||
// Loads a folder as a WAD.
|
||||
//
|
||||
|
@ -1326,21 +1719,7 @@ W_CheckNumForMarkerStartPwad (const char *name, UINT16 wad, UINT16 startlump)
|
|||
// Look for the first lump from a folder.
|
||||
UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlump)
|
||||
{
|
||||
size_t name_length;
|
||||
INT32 i;
|
||||
lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
|
||||
name_length = strlen(name);
|
||||
for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
|
||||
{
|
||||
if (strnicmp(name, lump_p->fullname, name_length) == 0)
|
||||
{
|
||||
/* SLADE is special and puts a single directory entry. Skip that. */
|
||||
if (strlen(lump_p->fullname) == name_length)
|
||||
i++;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return INT16_MAX;
|
||||
return Resource_CheckNumForFolderStartPK3(wadfiles[wad], name, startlump);
|
||||
}
|
||||
|
||||
// In a PK3 type of resource file, it looks for the next lumpinfo entry that doesn't share the specified pathfile.
|
||||
|
@ -1348,14 +1727,7 @@ UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlum
|
|||
// Returns the position of the lumpinfo entry.
|
||||
UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump)
|
||||
{
|
||||
INT32 i;
|
||||
lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
|
||||
for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
|
||||
{
|
||||
if (strnicmp(name, lump_p->fullname, strlen(name)))
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
return Resource_CheckNumForFolderEndPK3(wadfiles[wad], name, startlump);
|
||||
}
|
||||
|
||||
char *W_GetLumpFolderPathPK3(UINT16 wad, UINT16 lump)
|
||||
|
@ -1902,46 +2274,10 @@ UINT8 W_LumpExists(const char *name)
|
|||
|
||||
size_t W_LumpLengthPwad(UINT16 wad, UINT16 lump)
|
||||
{
|
||||
lumpinfo_t *l;
|
||||
|
||||
if (!TestValidLump(wad, lump))
|
||||
return 0;
|
||||
|
||||
l = wadfiles[wad]->lumpinfo + lump;
|
||||
|
||||
// Open the external file for this lump, if the WAD is a folder.
|
||||
if (wadfiles[wad]->type == RET_FOLDER)
|
||||
{
|
||||
// pathisdirectory calls stat, so if anything wrong has happened,
|
||||
// this is the time to be aware of it.
|
||||
INT32 stat = pathisdirectory(l->diskpath);
|
||||
|
||||
if (stat < 0)
|
||||
{
|
||||
#ifndef AVOID_ERRNO
|
||||
if (direrror == ENOENT)
|
||||
I_Error("W_LumpLengthPwad: file %s doesn't exist", l->diskpath);
|
||||
else
|
||||
I_Error("W_LumpLengthPwad: could not stat %s: %s", l->diskpath, strerror(direrror));
|
||||
#else
|
||||
I_Error("W_LumpLengthPwad: could not access %s", l->diskpath);
|
||||
#endif
|
||||
}
|
||||
else if (stat == 1) // Path is a folder.
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
FILE *handle = fopen(l->diskpath, "rb");
|
||||
if (handle == NULL)
|
||||
I_Error("W_LumpLengthPwad: could not open file %s", l->diskpath);
|
||||
|
||||
fseek(handle, 0, SEEK_END);
|
||||
l->size = l->disksize = ftell(handle);
|
||||
fclose(handle);
|
||||
}
|
||||
}
|
||||
|
||||
return l->size;
|
||||
return Resource_LumpLength(wadfiles[wad], lump);
|
||||
}
|
||||
|
||||
/** Returns the buffer size needed to load the given lump.
|
||||
|
@ -2032,174 +2368,10 @@ void zerr(int ret)
|
|||
*/
|
||||
size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, size_t offset)
|
||||
{
|
||||
size_t lumpsize, bytesread;
|
||||
lumpinfo_t *l;
|
||||
FILE *handle = NULL;
|
||||
|
||||
if (!TestValidLump(wad, lump))
|
||||
return 0;
|
||||
|
||||
l = wadfiles[wad]->lumpinfo + lump;
|
||||
|
||||
// Open the external file for this lump, if the WAD is a folder.
|
||||
if (wadfiles[wad]->type == RET_FOLDER)
|
||||
{
|
||||
// pathisdirectory calls stat, so if anything wrong has happened,
|
||||
// this is the time to be aware of it.
|
||||
INT32 stat = pathisdirectory(l->diskpath);
|
||||
|
||||
if (stat < 0)
|
||||
{
|
||||
#ifndef AVOID_ERRNO
|
||||
if (direrror == ENOENT)
|
||||
I_Error("W_ReadLumpHeaderPwad: file %s doesn't exist", l->diskpath);
|
||||
else
|
||||
I_Error("W_ReadLumpHeaderPwad: could not stat %s: %s", l->diskpath, strerror(direrror));
|
||||
#else
|
||||
I_Error("W_ReadLumpHeaderPwad: could not access %s", l->diskpath);
|
||||
#endif
|
||||
}
|
||||
else if (stat == 1) // Path is a folder.
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
handle = fopen(l->diskpath, "rb");
|
||||
if (handle == NULL)
|
||||
I_Error("W_ReadLumpHeaderPwad: could not open file %s", l->diskpath);
|
||||
|
||||
// Find length of file
|
||||
fseek(handle, 0, SEEK_END);
|
||||
l->size = l->disksize = ftell(handle);
|
||||
}
|
||||
}
|
||||
|
||||
lumpsize = wadfiles[wad]->lumpinfo[lump].size;
|
||||
// empty resource (usually markers like S_START, F_END ..)
|
||||
if (!lumpsize || lumpsize<offset)
|
||||
{
|
||||
if (wadfiles[wad]->type == RET_FOLDER)
|
||||
fclose(handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// zero size means read all the lump
|
||||
if (!size || size+offset > lumpsize)
|
||||
size = lumpsize - offset;
|
||||
|
||||
// Let's get the raw lump data.
|
||||
// We setup the desired file handle to read the lump data.
|
||||
if (wadfiles[wad]->type != RET_FOLDER)
|
||||
handle = wadfiles[wad]->handle;
|
||||
fseek(handle, (long)(l->position + offset), SEEK_SET);
|
||||
|
||||
// But let's not copy it yet. We support different compression formats on lumps, so we need to take that into account.
|
||||
switch(wadfiles[wad]->lumpinfo[lump].compression)
|
||||
{
|
||||
case CM_NOCOMPRESSION: // If it's uncompressed, we directly write the data into our destination, and return the bytes read.
|
||||
bytesread = fread(dest, 1, size, handle);
|
||||
if (wadfiles[wad]->type == RET_FOLDER)
|
||||
fclose(handle);
|
||||
return bytesread;
|
||||
case CM_LZF: // Is it LZF compressed? Used by ZWADs.
|
||||
{
|
||||
#ifdef ZWAD
|
||||
char *rawData; // The lump's raw data.
|
||||
char *decData; // Lump's decompressed real data.
|
||||
size_t retval; // Helper var, lzf_decompress returns 0 when an error occurs.
|
||||
|
||||
rawData = Z_Malloc(l->disksize, PU_STATIC, NULL);
|
||||
decData = Z_Malloc(l->size, PU_STATIC, NULL);
|
||||
|
||||
if (fread(rawData, 1, l->disksize, handle) < l->disksize)
|
||||
I_Error("wad %d, lump %d: cannot read compressed data", wad, lump);
|
||||
retval = lzf_decompress(rawData, l->disksize, decData, l->size);
|
||||
#ifndef AVOID_ERRNO
|
||||
if (retval == 0) // If this was returned, check if errno was set
|
||||
{
|
||||
// errno is a global var set by the lzf functions when something goes wrong.
|
||||
if (errno == E2BIG)
|
||||
I_Error("wad %d, lump %d: compressed data too big (bigger than %s)", wad, lump, sizeu1(l->size));
|
||||
else if (errno == EINVAL)
|
||||
I_Error("wad %d, lump %d: invalid compressed data", wad, lump);
|
||||
}
|
||||
// Otherwise, fall back on below error (if zero was actually the correct size then ???)
|
||||
#endif
|
||||
if (retval != l->size)
|
||||
{
|
||||
I_Error("wad %d, lump %d: decompressed to wrong number of bytes (expected %s, got %s)", wad, lump, sizeu1(l->size), sizeu2(retval));
|
||||
}
|
||||
|
||||
if (!decData) // Did we get no data at all?
|
||||
return 0;
|
||||
M_Memcpy(dest, decData + offset, size);
|
||||
Z_Free(rawData);
|
||||
Z_Free(decData);
|
||||
return size;
|
||||
#else
|
||||
//I_Error("ZWAD files not supported on this platform.");
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
}
|
||||
#ifdef HAVE_ZLIB
|
||||
case CM_DEFLATE: // Is it compressed via DEFLATE? Very common in ZIPs/PK3s, also what most doom-related editors support.
|
||||
{
|
||||
UINT8 *rawData; // The lump's raw data.
|
||||
UINT8 *decData; // Lump's decompressed real data.
|
||||
|
||||
int zErr; // Helper var.
|
||||
z_stream strm;
|
||||
unsigned long rawSize = l->disksize;
|
||||
unsigned long decSize = l->size;
|
||||
|
||||
rawData = Z_Malloc(rawSize, PU_STATIC, NULL);
|
||||
decData = Z_Malloc(decSize, PU_STATIC, NULL);
|
||||
|
||||
if (fread(rawData, 1, rawSize, handle) < rawSize)
|
||||
I_Error("wad %d, lump %d: cannot read compressed data", wad, lump);
|
||||
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
|
||||
strm.total_in = strm.avail_in = rawSize;
|
||||
strm.total_out = strm.avail_out = decSize;
|
||||
|
||||
strm.next_in = rawData;
|
||||
strm.next_out = decData;
|
||||
|
||||
zErr = inflateInit2(&strm, -15);
|
||||
if (zErr == Z_OK)
|
||||
{
|
||||
zErr = inflate(&strm, Z_FINISH);
|
||||
if (zErr == Z_STREAM_END)
|
||||
{
|
||||
M_Memcpy(dest, decData, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
size = 0;
|
||||
zerr(zErr);
|
||||
}
|
||||
|
||||
(void)inflateEnd(&strm);
|
||||
}
|
||||
else
|
||||
{
|
||||
size = 0;
|
||||
zerr(zErr);
|
||||
}
|
||||
|
||||
Z_Free(rawData);
|
||||
Z_Free(decData);
|
||||
|
||||
return size;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
I_Error("wad %d, lump %d: unsupported compression type!", wad, lump);
|
||||
}
|
||||
return 0;
|
||||
return Resource_ReadLumpHeader(wadfiles[wad], lump, dest, size, offset);
|
||||
}
|
||||
|
||||
size_t W_ReadLumpHeader(lumpnum_t lumpnum, void *dest, size_t size, size_t offset)
|
||||
|
@ -2229,21 +2401,10 @@ void W_ReadLumpPwad(UINT16 wad, UINT16 lump, void *dest)
|
|||
// ==========================================================================
|
||||
void *W_CacheLumpNumPwad(UINT16 wad, UINT16 lump, INT32 tag)
|
||||
{
|
||||
lumpcache_t *lumpcache;
|
||||
|
||||
if (!TestValidLump(wad,lump))
|
||||
return NULL;
|
||||
|
||||
lumpcache = wadfiles[wad]->lumpcache;
|
||||
if (!lumpcache[lump])
|
||||
{
|
||||
void *ptr = Z_Malloc(W_LumpLengthPwad(wad, lump), tag, &lumpcache[lump]);
|
||||
W_ReadLumpHeaderPwad(wad, lump, ptr, 0, 0); // read the lump in full
|
||||
}
|
||||
else
|
||||
Z_ChangeTag(lumpcache[lump], tag);
|
||||
|
||||
return lumpcache[lump];
|
||||
return Resource_CacheLumpNum(wadfiles[wad], lump, tag);
|
||||
}
|
||||
|
||||
void *W_CacheLumpNum(lumpnum_t lumpnum, INT32 tag)
|
||||
|
|
15
src/w_wad.h
15
src/w_wad.h
|
@ -160,6 +160,12 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup);
|
|||
// Adds a folder as a file
|
||||
UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup);
|
||||
|
||||
// Loads a wadfile, but doesn't add it to the active wad files.
|
||||
wadfile_t *W_LoadResourceFile(const char *filename);
|
||||
|
||||
// Deletes a wadfile.
|
||||
void W_DeleteResourceFile(wadfile_t *wad);
|
||||
|
||||
// W_InitMultipleFiles exits if a file was not found, but not if all is okay.
|
||||
void W_InitMultipleFiles(addfilelist_t *list);
|
||||
|
||||
|
@ -168,6 +174,15 @@ void W_InitMultipleFiles(addfilelist_t *list);
|
|||
INT32 W_IsPathToFolderValid(const char *path);
|
||||
char *W_GetFullFolderPath(const char *path);
|
||||
|
||||
UINT16 Resource_CheckNumForName(wadfile_t *wad, const char *name);
|
||||
void *Resource_CacheLumpNum(wadfile_t *wad, UINT16 lump, INT32 tag);
|
||||
void *Resource_CacheLumpName(wadfile_t *wad, const char *name, INT32 tag);
|
||||
boolean Resource_LumpExists(wadfile_t *wad, const char *name);
|
||||
size_t Resource_LumpLength(wadfile_t *wad, UINT16 lump);
|
||||
size_t Resource_ReadLumpHeader(wadfile_t *wad, UINT16 lump, void *dest, size_t size, size_t offset);
|
||||
UINT16 Resource_CheckNumForFolderStartPK3(wadfile_t *wad, const char *name, UINT16 startlump);
|
||||
UINT16 Resource_CheckNumForFolderEndPK3(wadfile_t *wad, const char *name, UINT16 startlump);
|
||||
|
||||
const char *W_CheckNameForNumPwad(UINT16 wad, UINT16 lump);
|
||||
const char *W_CheckNameForNum(lumpnum_t lumpnum);
|
||||
|
||||
|
|
Loading…
Reference in a new issue