diff --git a/Makefile b/Makefile index b082cefc..93b9bff7 100644 --- a/Makefile +++ b/Makefile @@ -1008,6 +1008,7 @@ CLIENT_OBJS_ := \ src/common/filesystem.o \ src/common/glob.o \ src/common/md4.o \ + src/common/models.o \ src/common/movemsg.o \ src/common/frame.o \ src/common/netchan.o \ @@ -1296,6 +1297,7 @@ SERVER_OBJS_ := \ src/common/glob.o \ src/common/md4.o \ src/common/frame.o \ + src/common/models.o \ src/common/movemsg.o \ src/common/netchan.o \ src/common/pmove.o \ diff --git a/src/client/refresh/files/models.c b/src/client/refresh/files/models.c index d69fa216..9c5c2990 100644 --- a/src/client/refresh/files/models.c +++ b/src/client/refresh/files/models.c @@ -1495,7 +1495,7 @@ Mod_LoadModel_MD3(const char *mod_name, const void *buffer, int modfilelen, { const md3_shader_t *md3_shader = (md3_shader_t*)((byte*)buffer + meshofs + LittleLong(md3_mesh->ofs_shaders)) + j; - strncpy(skin, md3_shader->name, MAX_SKINNAME - 1); + strncpy(skin, md3_shader->name, Q_min(sizeof(md3_shader->name), MAX_SKINNAME) - 1); skin += MAX_SKINNAME; } @@ -1943,50 +1943,6 @@ Mod_LoadModel_MD2(const char *mod_name, const void *buffer, int modfilelen, return extradata; } -static void -Mod_LoadSkinList_MD2(const char *mod_name, const void *buffer, int modfilelen, - char **skins, int *numskins) -{ - dmdl_t pinmodel; - int i; - - if (modfilelen < sizeof(pinmodel)) - { - R_Printf(PRINT_ALL, "%s: %s has incorrect header size (%i should be " YQ2_COM_PRIdS ")\n", - __func__, mod_name, modfilelen, sizeof(pinmodel)); - return; - } - - for (i = 0; i < sizeof(pinmodel) / sizeof(int); i++) - { - ((int *)&pinmodel)[i] = LittleLong(((int *)buffer)[i]); - } - - if (pinmodel.version != ALIAS_VERSION) - { - R_Printf(PRINT_ALL, "%s: %s has wrong version number (%i should be %i)\n", - __func__, mod_name, pinmodel.version, ALIAS_VERSION); - } - - if (pinmodel.ofs_end < 0 || pinmodel.ofs_end > modfilelen) - { - R_Printf(PRINT_ALL, "%s: model %s file size(%d) too small, should be %d\n", - __func__, mod_name, modfilelen, pinmodel.ofs_end); - } - - if (pinmodel.num_skins < 0) - { - R_Printf(PRINT_ALL, "%s: model %s file has incorrect skins count %d\n", - __func__, mod_name, pinmodel.num_skins); - } - - *numskins = pinmodel.num_skins; - *skins = malloc(pinmodel.num_skins * MAX_SKINNAME); - - memcpy(*skins, (char *)buffer + pinmodel.ofs_skins, - pinmodel.num_skins * MAX_SKINNAME); -} - /* ============= Mod_LoadModel_Flex @@ -2685,19 +2641,6 @@ Mod_LoadMinMaxUpdate(const char *mod_name, vec3_t mins, vec3_t maxs, void *extra } } -static void -Mod_LoadSkinList(const char *mod_name, const void *buffer, int modfilelen, - char **skins, int *numskins) -{ - switch (LittleLong(*(unsigned *)buffer)) - { - case IDALIASHEADER: - Mod_LoadSkinList_MD2(mod_name, buffer, modfilelen, - skins, numskins); - break; - } -} - /* ================= Mod_LoadModel @@ -2783,294 +2726,6 @@ Mod_LoadModel(const char *mod_name, const void *buffer, int modfilelen, return extradata; } -/* Add md5 to full file name */ -static void -Mod_LoadFileInsertMD5(char *newname, const char *oldname, int size) -{ - const char *filename; - - filename = COM_SkipPath(oldname); - memset(newname, 0, size); - memcpy(newname, oldname, strlen(oldname) - strlen(filename)); - Q_strlcat(newname, "md5/", size); - Q_strlcat(newname, filename, size); -} - -static int -Mod_LoadFileMD5Merge(const char *namewe, void **buffer) -{ - int fullsize, filesize_anim, filesize, filesize_skins; - char *final_buffer = NULL, *skins_list = NULL; - void *anim_buffer = NULL, *skins_buffer = NULL; - qboolean md5path = false; - char newname[256]; - - /* search mesh file */ - Q_strlcpy(newname, namewe, sizeof(newname)); - Q_strlcat(newname, ".md5mesh", sizeof(newname)); - filesize = ri.FS_LoadFile(newname, buffer); - - /* check overwrite file */ - if (filesize <= 0) - { - char md5modelname[256]; - - Mod_LoadFileInsertMD5(md5modelname, newname, sizeof(md5modelname)); - - filesize = ri.FS_LoadFile(md5modelname, buffer); - /* no replace file */ - if (filesize <= 0) - { - return filesize; - } - - md5path = true; - strcpy(newname, md5modelname); - } - - /* search animation file */ - memcpy(newname + strlen(newname) - strlen("mesh"), "anim", strlen("anim")); - filesize_anim = ri.FS_LoadFile(newname, &anim_buffer); - if (filesize_anim <= 0) - { - ri.FS_FreeFile(*buffer); - return filesize; - } - - /* search skins list */ - Q_strlcpy(newname, namewe, sizeof(newname)); - Q_strlcat(newname, ".md2", sizeof(newname)); - filesize_skins = ri.FS_LoadFile(newname, &skins_buffer); - if (filesize_skins > 0) - { - char *skins = NULL; - int numskins = 0, i; - - Mod_LoadSkinList(newname, skins_buffer, filesize_skins, - &skins, &numskins); - ri.FS_FreeFile(skins_buffer); - - /* - * 20 -> numSkins | skin "MAX_SKINNAME" + md5 - */ - skins_list = malloc((numskins + 1) * (MAX_SKINNAME + 20)); - sprintf(skins_list, "\nnumSkins %d\n", numskins); - for(i = 0; i < numskins; i++) - { - const char *skinname = skins + MAX_SKINNAME * i; - - if (!md5path) - { - sprintf(skins_list + strlen(skins_list), "skin %d \"%s\"\n", - i, skinname); - } - else - { - char md5skinname[256]; - - Mod_LoadFileInsertMD5(md5skinname, skinname, sizeof(md5skinname)); - - sprintf(skins_list + strlen(skins_list), "skin %d \"%s\"\n", - i, md5skinname); - } - } - } - - /* prepare final file */ - fullsize = filesize + filesize_anim + 1; - if (skins_list) - { - fullsize += strlen(skins_list); - } - - /* allocate new buffer, ERR_FATAL on alloc fail */ - final_buffer = ri.FS_AllocFile(fullsize); - - /* copy combined information */ - memcpy(final_buffer, *buffer, filesize); - if (skins_list) - { - memcpy(final_buffer + filesize, skins_list, strlen(skins_list)); - filesize += strlen(skins_list); - free(skins_list); - } - final_buffer[filesize] = 0; - memcpy(final_buffer + filesize + 1, anim_buffer, filesize_anim); - - /* Remove old buffers */ - ri.FS_FreeFile(anim_buffer); - ri.FS_FreeFile(*buffer); - - *buffer = final_buffer; - return fullsize; -} - -static int -Mod_LoadFileWithoutExt(const char *namewe, void **buffer, const char* ext) -{ - char newname[256]; - size_t tlen; - - *buffer = NULL; - - tlen = strlen(namewe); - - if (!strcmp(ext, "fm") || - !strcmp(ext, "dkm") || - !strcmp(ext, "md2") || - !strcmp(ext, "md3") || - !strcmp(ext, "md5mesh") || - !strcmp(ext, "mdx") || - !strcmp(ext, "mdl")) - { - int filesize; - - /* Check ReRelease / Doom 3 / Quake 4 model */ - filesize = Mod_LoadFileMD5Merge(namewe, buffer); - if (filesize > 0) - { - R_Printf(PRINT_DEVELOPER, "%s: %s loaded as md5 (Doom 3)\n", - __func__, namewe); - return filesize; - } - - /* Check Quake 3 model */ - Q_strlcpy(newname, namewe, sizeof(newname)); - Q_strlcpy(newname + tlen, ".md3", sizeof(newname)); - filesize = ri.FS_LoadFile(newname, buffer); - if (filesize > 0) - { - R_Printf(PRINT_DEVELOPER, "%s: %s loaded as md3 (Quake 3)\n", - __func__, namewe); - return filesize; - } - - /* Check Heretic2 model */ - Q_strlcpy(newname, namewe, sizeof(newname)); - Q_strlcat(newname, ".fm", sizeof(newname)); - filesize = ri.FS_LoadFile(newname, buffer); - if (filesize > 0) - { - R_Printf(PRINT_DEVELOPER, "%s: %s loaded as fm (Heretic 2)\n", - __func__, namewe); - return filesize; - } - - /* Check Quake 2 model */ - Q_strlcpy(newname + tlen, ".md2", sizeof(newname)); - filesize = ri.FS_LoadFile(newname, buffer); - if (filesize > 0) - { - R_Printf(PRINT_DEVELOPER, "%s: %s loaded as md2 (Quake 2/Anachronox)\n", - __func__, namewe); - return filesize; - } - - /* Check Kingpin model */ - Q_strlcpy(newname + tlen, ".mdx", sizeof(newname)); - filesize = ri.FS_LoadFile(newname, buffer); - if (filesize > 0) - { - R_Printf(PRINT_DEVELOPER, "%s: %s loaded as mdx (Kingpin)\n", - __func__, namewe); - return filesize; - } - - /* Check Daikatana model */ - Q_strlcpy(newname + tlen, ".dkm", sizeof(newname)); - filesize = ri.FS_LoadFile(newname, buffer); - if (filesize > 0) - { - R_Printf(PRINT_DEVELOPER, "%s: %s loaded as dkm (Daikatana)\n", - __func__, namewe); - return filesize; - } - - /* Check Quake model */ - Q_strlcpy(newname + tlen, ".mdl", sizeof(newname)); - filesize = ri.FS_LoadFile(newname, buffer); - if (filesize > 0) - { - R_Printf(PRINT_DEVELOPER, "%s: %s loaded as mdl (Quake 1)\n", - __func__, namewe); - return filesize; - } - } - - Q_strlcpy(newname, namewe, sizeof(newname)); - Q_strlcat(newname, ".", sizeof(newname)); - Q_strlcat(newname, ext, sizeof(newname)); - - return ri.FS_LoadFile(newname, buffer); -} - -/* -================= -Mod_LoadFile -================= -*/ -int -Mod_LoadFile(const char *name, void **buffer) -{ - char namewe[256]; - const char* ext; - int filesize, len; - size_t tlen; - - if (!name) - { - return -1; - } - - ext = COM_FileExtension(name); - if(!ext[0]) - { - /* file has no extension */ - return -1; - } - - len = strlen(name); - if (len < 5) - { - return -1; - } - - /* Remove the extension */ - tlen = len - (strlen(ext) + 1); - memset(namewe, 0, 256); - memcpy(namewe, name, tlen); - - filesize = Mod_LoadFileWithoutExt(namewe, buffer, ext); - if (filesize > 0) - { - return filesize; - } - - /* Replacement of ReRelease models */ - if (!strcmp(namewe, "models/monsters/soldierh/tris")) - { - filesize = Mod_LoadFileWithoutExt("models/monsters/soldier/tris", - buffer, ext); - } - else if (!strcmp(namewe, "models/monsters/gladb/tris")) - { - filesize = Mod_LoadFileWithoutExt("models/monsters/gladiatr/tris", - buffer, ext); - } - else if (!strcmp(namewe, "models/monsters/boss5/tris")) - { - filesize = Mod_LoadFileWithoutExt("models/monsters/boss1/tris", - buffer, ext); - } - else if (!strcmp(namewe, "models/monsters/bitch2/tris")) - { - filesize = Mod_LoadFileWithoutExt("models/monsters/bitch/tris", - buffer, ext); - } - - return filesize; -} - /* ================= Mod_ReLoad diff --git a/src/client/refresh/gl1/gl1_model.c b/src/client/refresh/gl1/gl1_model.c index 8ca412a3..eba8b9cf 100644 --- a/src/client/refresh/gl1/gl1_model.c +++ b/src/client/refresh/gl1/gl1_model.c @@ -443,7 +443,7 @@ Mod_ForName(const char *name, model_t *parent_model, qboolean crash) strcpy(mod->name, name); /* load the file */ - modfilelen = Mod_LoadFile(mod->name, &buf); + modfilelen = ri.Mod_LoadFile(mod->name, &buf); if (!buf) { diff --git a/src/client/refresh/gl3/gl3_model.c b/src/client/refresh/gl3/gl3_model.c index bdb4a169..4942db78 100644 --- a/src/client/refresh/gl3/gl3_model.c +++ b/src/client/refresh/gl3/gl3_model.c @@ -444,7 +444,7 @@ Mod_ForName(const char *name, gl3model_t *parent_model, qboolean crash) strcpy(mod->name, name); /* load the file */ - modfilelen = Mod_LoadFile(mod->name, &buf); + modfilelen = ri.Mod_LoadFile(mod->name, &buf); if (!buf) { diff --git a/src/client/refresh/gl4/gl4_model.c b/src/client/refresh/gl4/gl4_model.c index 2275fcdc..b03e13c9 100644 --- a/src/client/refresh/gl4/gl4_model.c +++ b/src/client/refresh/gl4/gl4_model.c @@ -444,7 +444,7 @@ Mod_ForName(const char *name, gl4model_t *parent_model, qboolean crash) strcpy(mod->name, name); /* load the file */ - modfilelen = Mod_LoadFile(mod->name, &buf); + modfilelen = ri.Mod_LoadFile(mod->name, &buf); if (!buf) { diff --git a/src/client/refresh/ref_shared.h b/src/client/refresh/ref_shared.h index 1a897d1a..0d516444 100644 --- a/src/client/refresh/ref_shared.h +++ b/src/client/refresh/ref_shared.h @@ -368,7 +368,6 @@ extern const void *Mod_LoadBSPXFindLump(const bspx_header_t *bspx_header, extern const bspx_header_t *Mod_LoadBSPX(int filesize, const byte *mod_base, maptype_t maptype); extern int Mod_LoadBSPXDecoupledLM(const dlminfo_t* lminfos, int surfnum, msurface_t *out); -extern int Mod_LoadFile(const char *name, void **buffer); extern int Mod_CalcNonModelLumpHunkSize(const byte *mod_base, const dheader_t *header, maptype_t maptype); diff --git a/src/client/refresh/soft/sw_model.c b/src/client/refresh/soft/sw_model.c index cca9a335..44cddc6b 100644 --- a/src/client/refresh/soft/sw_model.c +++ b/src/client/refresh/soft/sw_model.c @@ -451,7 +451,7 @@ Mod_ForName(const char *name, model_t *parent_model, qboolean crash) strcpy(mod->name, name); /* load the file */ - modfilelen = Mod_LoadFile(mod->name, &buf); + modfilelen = ri.Mod_LoadFile(mod->name, &buf); if (!buf) { diff --git a/src/client/refresh/vk/vk_model.c b/src/client/refresh/vk/vk_model.c index 8edd70ab..2eeb6614 100644 --- a/src/client/refresh/vk/vk_model.c +++ b/src/client/refresh/vk/vk_model.c @@ -418,7 +418,7 @@ Mod_ForName(const char *name, model_t *parent_model, qboolean crash) strcpy(mod->name, name); /* load the file */ - modfilelen = Mod_LoadFile(mod->name, &buf); + modfilelen = ri.Mod_LoadFile(mod->name, &buf); if (!buf) { diff --git a/src/client/vid/header/ref.h b/src/client/vid/header/ref.h index b0a667e3..2096a56c 100644 --- a/src/client/vid/header/ref.h +++ b/src/client/vid/header/ref.h @@ -258,6 +258,9 @@ typedef struct qboolean (IMPORT *GLimp_GetDesktopMode)(int *pwidth, int *pheight); void (IMPORT *Vid_RequestRestart)(ref_restart_t rs); + + /* Rerelease: Get file from cache/converted */ + int (IMPORT *Mod_LoadFile)(const char *path, void **buffer); } refimport_t; // this is the only function actually exported at the linker level diff --git a/src/client/vid/vid.c b/src/client/vid/vid.c index 878b0d00..55faff8d 100644 --- a/src/client/vid/vid.c +++ b/src/client/vid/vid.c @@ -439,6 +439,7 @@ VID_LoadRenderer(void) ri.FS_Gamedir = FS_Gamedir; ri.FS_LoadFile = FS_LoadFile; ri.FS_AllocFile = Z_Malloc; + ri.Mod_LoadFile = Mod_LoadFile; ri.GLimp_InitGraphics = GLimp_InitGraphics; ri.GLimp_GetDesktopMode = GLimp_GetDesktopMode; ri.Sys_Error = Com_Error; diff --git a/src/common/collision.c b/src/common/collision.c index 4c703fa3..316d6afa 100644 --- a/src/common/collision.c +++ b/src/common/collision.c @@ -2114,3 +2114,11 @@ CM_ClusterPHS(int cluster) return phsrow; } +/* + * Return file content for most case but could cache converted file in future + */ +int +CM_LoadFile(const char *path, void **buffer) +{ + return -1; +} diff --git a/src/common/header/common.h b/src/common/header/common.h index 4b4264c3..2a934161 100644 --- a/src/common/header/common.h +++ b/src/common/header/common.h @@ -680,6 +680,10 @@ int CM_WriteAreaBits(byte *buffer, int area); qboolean CM_HeadnodeVisible(int headnode, byte *visbits); void CM_WritePortalState(FILE *f); +int CM_LoadFile(const char *path, void **buffer); + +/* Shared Model load code */ +int Mod_LoadFile(const char *path, void **buffer); /* PLAYER MOVEMENT CODE */ diff --git a/src/common/models.c b/src/common/models.c new file mode 100644 index 00000000..61008d8a --- /dev/null +++ b/src/common/models.c @@ -0,0 +1,388 @@ +/* + * Copyright (C) 1997-2001 Id Software, Inc. + * + * 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. + * + * ======================================================================= + * + * The collision model. Slaps "boxes" through the world and checks if + * they collide with the world model, entities or other boxes. + * + * ======================================================================= + */ + +#include "header/common.h" + +static void +Mod_LoadSkinList_MD2(const char *mod_name, const void *buffer, int modfilelen, + char **skins, int *numskins) +{ + dmdl_t pinmodel; + int i; + + if (modfilelen < sizeof(pinmodel)) + { + Com_Printf("%s: %s has incorrect header size (%i should be " YQ2_COM_PRIdS ")\n", + __func__, mod_name, modfilelen, sizeof(pinmodel)); + return; + } + + for (i = 0; i < sizeof(pinmodel) / sizeof(int); i++) + { + ((int *)&pinmodel)[i] = LittleLong(((int *)buffer)[i]); + } + + if (pinmodel.version != ALIAS_VERSION) + { + Com_Printf("%s: %s has wrong version number (%i should be %i)\n", + __func__, mod_name, pinmodel.version, ALIAS_VERSION); + } + + if (pinmodel.ofs_end < 0 || pinmodel.ofs_end > modfilelen) + { + Com_Printf("%s: model %s file size(%d) too small, should be %d\n", + __func__, mod_name, modfilelen, pinmodel.ofs_end); + } + + if (pinmodel.num_skins < 0) + { + Com_Printf("%s: model %s file has incorrect skins count %d\n", + __func__, mod_name, pinmodel.num_skins); + } + + *numskins = pinmodel.num_skins; + *skins = malloc(pinmodel.num_skins * MAX_SKINNAME); + + memcpy(*skins, (char *)buffer + pinmodel.ofs_skins, + pinmodel.num_skins * MAX_SKINNAME); +} + +static void +Mod_LoadSkinList(const char *mod_name, const void *buffer, int modfilelen, + char **skins, int *numskins) +{ + switch (LittleLong(*(unsigned *)buffer)) + { + case IDALIASHEADER: + Mod_LoadSkinList_MD2(mod_name, buffer, modfilelen, + skins, numskins); + break; + } +} + +/* Add md5 to full file name */ +static void +Mod_LoadFileInsertMD5(char *newname, const char *oldname, int size) +{ + const char *filename; + + filename = COM_SkipPath(oldname); + memset(newname, 0, size); + memcpy(newname, oldname, strlen(oldname) - strlen(filename)); + Q_strlcat(newname, "md5/", size); + Q_strlcat(newname, filename, size); +} + +static int +Mod_LoadFileMD5Merge(const char *namewe, void **buffer) +{ + int fullsize, filesize_anim, filesize, filesize_skins; + char *final_buffer = NULL, *skins_list = NULL; + void *anim_buffer = NULL, *skins_buffer = NULL; + qboolean md5path = false; + char newname[256]; + + /* search mesh file */ + Q_strlcpy(newname, namewe, sizeof(newname)); + Q_strlcat(newname, ".md5mesh", sizeof(newname)); + filesize = FS_LoadFile(newname, buffer); + + /* check overwrite file */ + if (filesize <= 0) + { + char md5modelname[256]; + + Mod_LoadFileInsertMD5(md5modelname, newname, sizeof(md5modelname)); + + filesize = FS_LoadFile(md5modelname, buffer); + /* no replace file */ + if (filesize <= 0) + { + return filesize; + } + + md5path = true; + strcpy(newname, md5modelname); + } + + /* search animation file */ + memcpy(newname + strlen(newname) - strlen("mesh"), "anim", strlen("anim")); + filesize_anim = FS_LoadFile(newname, &anim_buffer); + if (filesize_anim <= 0) + { + FS_FreeFile(*buffer); + return filesize; + } + + /* search skins list */ + Q_strlcpy(newname, namewe, sizeof(newname)); + Q_strlcat(newname, ".md2", sizeof(newname)); + filesize_skins = FS_LoadFile(newname, &skins_buffer); + if (filesize_skins > 0) + { + char *skins = NULL; + int numskins = 0, i; + + Mod_LoadSkinList(newname, skins_buffer, filesize_skins, + &skins, &numskins); + FS_FreeFile(skins_buffer); + + /* + * 20 -> numSkins | skin "MAX_SKINNAME" + md5 + */ + skins_list = malloc((numskins + 1) * (MAX_SKINNAME + 20)); + sprintf(skins_list, "\nnumSkins %d\n", numskins); + for(i = 0; i < numskins; i++) + { + const char *skinname = skins + MAX_SKINNAME * i; + + if (!md5path) + { + sprintf(skins_list + strlen(skins_list), "skin %d \"%s\"\n", + i, skinname); + } + else + { + char md5skinname[256]; + + Mod_LoadFileInsertMD5(md5skinname, skinname, sizeof(md5skinname)); + + sprintf(skins_list + strlen(skins_list), "skin %d \"%s\"\n", + i, md5skinname); + } + } + } + + /* prepare final file */ + fullsize = filesize + filesize_anim + 1; + if (skins_list) + { + fullsize += strlen(skins_list); + } + + /* allocate new buffer, ERR_FATAL on alloc fail */ + final_buffer = Z_Malloc(fullsize); + + /* copy combined information */ + memcpy(final_buffer, *buffer, filesize); + if (skins_list) + { + memcpy(final_buffer + filesize, skins_list, strlen(skins_list)); + filesize += strlen(skins_list); + free(skins_list); + } + final_buffer[filesize] = 0; + memcpy(final_buffer + filesize + 1, anim_buffer, filesize_anim); + + /* Remove old buffers */ + FS_FreeFile(anim_buffer); + FS_FreeFile(*buffer); + + *buffer = final_buffer; + return fullsize; +} + +static int +Mod_LoadFileWithoutExt(const char *namewe, void **buffer, const char* ext) +{ + char newname[256]; + size_t tlen; + + *buffer = NULL; + + tlen = strlen(namewe); + + if (!strcmp(ext, "fm") || + !strcmp(ext, "dkm") || + !strcmp(ext, "md2") || + !strcmp(ext, "md3") || + !strcmp(ext, "md5mesh") || + !strcmp(ext, "mdx") || + !strcmp(ext, "mdl")) + { + int filesize; + + /* Check ReRelease / Doom 3 / Quake 4 model */ + filesize = Mod_LoadFileMD5Merge(namewe, buffer); + if (filesize > 0) + { + Com_DPrintf("%s: %s loaded as md5 (Doom 3)\n", + __func__, namewe); + return filesize; + } + + /* Check Quake 3 model */ + Q_strlcpy(newname, namewe, sizeof(newname)); + Q_strlcpy(newname + tlen, ".md3", sizeof(newname)); + filesize = FS_LoadFile(newname, buffer); + if (filesize > 0) + { + Com_DPrintf("%s: %s loaded as md3 (Quake 3)\n", + __func__, namewe); + return filesize; + } + + /* Check Heretic2 model */ + Q_strlcpy(newname, namewe, sizeof(newname)); + Q_strlcat(newname, ".fm", sizeof(newname)); + filesize = FS_LoadFile(newname, buffer); + if (filesize > 0) + { + Com_DPrintf("%s: %s loaded as fm (Heretic 2)\n", + __func__, namewe); + return filesize; + } + + /* Check Quake 2 model */ + Q_strlcpy(newname + tlen, ".md2", sizeof(newname)); + filesize = FS_LoadFile(newname, buffer); + if (filesize > 0) + { + Com_DPrintf("%s: %s loaded as md2 (Quake 2/Anachronox)\n", + __func__, namewe); + return filesize; + } + + /* Check Kingpin model */ + Q_strlcpy(newname + tlen, ".mdx", sizeof(newname)); + filesize = FS_LoadFile(newname, buffer); + if (filesize > 0) + { + Com_DPrintf("%s: %s loaded as mdx (Kingpin)\n", + __func__, namewe); + return filesize; + } + + /* Check Daikatana model */ + Q_strlcpy(newname + tlen, ".dkm", sizeof(newname)); + filesize = FS_LoadFile(newname, buffer); + if (filesize > 0) + { + Com_DPrintf("%s: %s loaded as dkm (Daikatana)\n", + __func__, namewe); + return filesize; + } + + /* Check Quake model */ + Q_strlcpy(newname + tlen, ".mdl", sizeof(newname)); + filesize = FS_LoadFile(newname, buffer); + if (filesize > 0) + { + Com_DPrintf("%s: %s loaded as mdl (Quake 1)\n", + __func__, namewe); + return filesize; + } + } + + if (!strcmp(ext, "bsp")) + { + int filesize; + + Q_strlcpy(newname, namewe, sizeof(newname)); + Q_strlcat(newname, ".", sizeof(newname)); + Q_strlcat(newname, ext, sizeof(newname)); + + filesize = CM_LoadFile(newname, buffer); + if (filesize > 0) + { + return filesize; + } + } + + Q_strlcpy(newname, namewe, sizeof(newname)); + Q_strlcat(newname, ".", sizeof(newname)); + Q_strlcat(newname, ext, sizeof(newname)); + + return FS_LoadFile(newname, buffer); +} + +/* +================= +Mod_LoadFile +================= +*/ +int +Mod_LoadFile(const char *name, void **buffer) +{ + char namewe[256]; + const char* ext; + int filesize, len; + size_t tlen; + + if (!name) + { + return -1; + } + + ext = COM_FileExtension(name); + if(!ext[0]) + { + /* file has no extension */ + return -1; + } + + len = strlen(name); + if (len < 5) + { + return -1; + } + + /* Remove the extension */ + tlen = len - (strlen(ext) + 1); + memset(namewe, 0, 256); + memcpy(namewe, name, tlen); + + filesize = Mod_LoadFileWithoutExt(namewe, buffer, ext); + if (filesize > 0) + { + return filesize; + } + + /* Replacement of ReRelease models */ + if (!strcmp(namewe, "models/monsters/soldierh/tris")) + { + filesize = Mod_LoadFileWithoutExt("models/monsters/soldier/tris", + buffer, ext); + } + else if (!strcmp(namewe, "models/monsters/gladb/tris")) + { + filesize = Mod_LoadFileWithoutExt("models/monsters/gladiatr/tris", + buffer, ext); + } + else if (!strcmp(namewe, "models/monsters/boss5/tris")) + { + filesize = Mod_LoadFileWithoutExt("models/monsters/boss1/tris", + buffer, ext); + } + else if (!strcmp(namewe, "models/monsters/bitch2/tris")) + { + filesize = Mod_LoadFileWithoutExt("models/monsters/bitch/tris", + buffer, ext); + } + + return filesize; +}