21 #include "shared/shared.h"
22 #include "shared/list.h"
23 #include "common/common.h"
24 #include "common/files.h"
25 #include "system/hunk.h"
26 #include "format/md2.h"
28 #include "format/md3.h"
30 #include "format/sp2.h"
31 #include "refresh/images.h"
32 #include "refresh/models.h"
37 #define MAX_RMODELS (MAX_MODELS * 2)
74 if (!FS_pathcmp(model->name, name)) {
84 static const char types[4] =
"FASE";
89 Com_Printf(
"------------------\n");
96 Com_Printf(
"%c %8"PRIz
" : %s\n", types[model->type],
97 model->hunk.mapped, model->name);
98 bytes += model->hunk.mapped;
101 Com_Printf(
"Total models: %d (out of %d slots)\n", count,
r_numModels);
102 Com_Printf(
"Total resident: %"PRIz
"\n", bytes);
120 memset(model, 0,
sizeof(*model));
136 memset(model, 0,
sizeof(*model));
147 if (header->ident != MD2_IDENT)
148 return Q_ERR_UNKNOWN_FORMAT;
149 if (header->version != MD2_VERSION)
150 return Q_ERR_UNKNOWN_FORMAT;
153 if (header->num_tris < 1)
154 return Q_ERR_TOO_FEW;
155 if (header->num_tris > MD2_MAX_TRIANGLES)
156 return Q_ERR_TOO_MANY;
158 end = header->ofs_tris +
sizeof(dmd2triangle_t) * header->num_tris;
159 if (header->ofs_tris <
sizeof(header) || end < header->ofs_tris || end > length)
160 return Q_ERR_BAD_EXTENT;
163 if (header->num_st < 3)
164 return Q_ERR_TOO_FEW;
165 if (header->num_st > MAX_ALIAS_VERTS)
166 return Q_ERR_TOO_MANY;
168 end = header->ofs_st +
sizeof(dmd2stvert_t) * header->num_st;
169 if (header->ofs_st <
sizeof(header) || end < header->ofs_st || end > length)
170 return Q_ERR_BAD_EXTENT;
173 if (header->num_xyz < 3)
174 return Q_ERR_TOO_FEW;
175 if (header->num_xyz > MAX_ALIAS_VERTS)
176 return Q_ERR_TOO_MANY;
177 if (header->num_frames < 1)
178 return Q_ERR_TOO_FEW;
179 if (header->num_frames > MD2_MAX_FRAMES)
180 return Q_ERR_TOO_MANY;
182 end =
sizeof(dmd2frame_t) + (header->num_xyz - 1) *
sizeof(dmd2trivertx_t);
183 if (header->framesize < end || header->framesize > MD2_MAX_FRAMESIZE)
184 return Q_ERR_BAD_EXTENT;
186 end = header->ofs_frames + (size_t)header->framesize * header->num_frames;
187 if (header->ofs_frames <
sizeof(header) || end < header->ofs_frames || end > length)
188 return Q_ERR_BAD_EXTENT;
191 if (header->num_skins) {
192 if (header->num_skins > MAX_ALIAS_SKINS)
193 return Q_ERR_TOO_MANY;
195 end = header->ofs_skins + (size_t)MD2_MAX_SKINNAME * header->num_skins;
196 if (header->ofs_skins <
sizeof(header) || end < header->ofs_skins || end > length)
197 return Q_ERR_BAD_EXTENT;
200 if (header->skinwidth < 1 || header->skinwidth > MD2_MAX_SKINWIDTH)
201 return Q_ERR_INVALID_FORMAT;
202 if (header->skinheight < 1 || header->skinheight > MD2_MAX_SKINHEIGHT)
203 return Q_ERR_INVALID_FORMAT;
205 return Q_ERR_SUCCESS;
211 if (!strcmp(name,
"models/objects/explode/tris.md2"))
212 return MCLASS_EXPLOSION;
213 else if (!strcmp(name,
"models/objects/r_explode/tris.md2"))
214 return MCLASS_EXPLOSION;
215 else if (!strcmp(name,
"models/objects/flash/tris.md2"))
217 else if (!strcmp(name,
"models/objects/smoke/tris.md2"))
219 else if (!strcmp(name,
"models/objects/minelite/light2/tris.md2"))
220 return MCLASS_STATIC_LIGHT;
221 else if (!strcmp(name,
"models/objects/flare/tris.md2"))
224 return MCLASS_REGULAR;
227 static qerror_t
MOD_LoadSP2(model_t *model,
const void *rawdata,
size_t length)
230 dsp2frame_t *src_frame;
231 mspriteframe_t *dst_frame;
233 char buffer[SP2_MAX_FRAMENAME];
236 if (length <
sizeof(header))
237 return Q_ERR_FILE_TOO_SMALL;
240 header = *(dsp2header_t *)rawdata;
241 for (i = 0; i <
sizeof(header) / 4; i++) {
242 ((uint32_t *)&header)[i] = LittleLong(((uint32_t *)&header)[i]);
245 if (header.ident != SP2_IDENT)
246 return Q_ERR_UNKNOWN_FORMAT;
247 if (header.version != SP2_VERSION)
248 return Q_ERR_UNKNOWN_FORMAT;
249 if (header.numframes < 1) {
251 model->type = MOD_EMPTY;
252 return Q_ERR_SUCCESS;
254 if (header.numframes > SP2_MAX_FRAMES)
255 return Q_ERR_TOO_MANY;
256 if (
sizeof(dsp2header_t) +
sizeof(dsp2frame_t) * header.numframes > length)
257 return Q_ERR_BAD_EXTENT;
260 model->type = MOD_SPRITE;
262 model->spriteframes = MOD_Malloc(
sizeof(mspriteframe_t) * header.numframes);
263 model->numframes = header.numframes;
265 src_frame = (dsp2frame_t *)((
byte *)rawdata +
sizeof(dsp2header_t));
266 dst_frame = model->spriteframes;
267 for (i = 0; i < header.numframes; i++) {
268 w = LittleLong(src_frame->width);
269 h = LittleLong(src_frame->height);
270 if (w < 1 || h < 1 || w > MAX_TEXTURE_SIZE || h > MAX_TEXTURE_SIZE) {
271 Com_WPrintf(
"%s has bad frame dimensions\n", model->name);
275 dst_frame->width = w;
276 dst_frame->height = h;
279 x = LittleLong(src_frame->origin_x);
280 y = LittleLong(src_frame->origin_y);
281 if (x > 8192 || y > 8192) {
282 Com_WPrintf(
"%s has bad frame origin\n", model->name);
285 dst_frame->origin_x = x;
286 dst_frame->origin_y = y;
288 if (!
Q_memccpy(buffer, src_frame->name, 0,
sizeof(buffer))) {
289 Com_WPrintf(
"%s has bad frame name\n", model->name);
290 dst_frame->image = R_NOTEXTURE;
293 dst_frame->image =
IMG_Find(buffer, IT_SPRITE, IF_SRGB);
302 return Q_ERR_SUCCESS;
307 char normalized[MAX_QPATH];
312 byte *rawdata = NULL;
323 index = atoi(name + 1);
331 if (namelen >= MAX_QPATH)
332 Com_Error(ERR_DROP,
"%s: oversize name", __func__);
336 Com_DPrintf(
"%s: empty name\n", __func__);
347 char* extension = normalized + namelen - 4;
348 if (namelen > 4 && (strcmp(extension,
".md2") == 0) &&
vid_rtx->integer)
350 memcpy(extension,
".md3", 4);
352 filelen = FS_LoadFile(normalized, (
void **)&rawdata);
354 memcpy(extension,
".md2", 4);
359 filelen = FS_LoadFile(normalized, (
void **)&rawdata);
362 if (filelen == Q_ERR_NOENT) {
372 ret = Q_ERR_FILE_TOO_SMALL;
377 ident = LittleLong(*(uint32_t *)rawdata);
391 ret = Q_ERR_UNKNOWN_FORMAT;
397 ret = Q_ERR_OUT_OF_SLOTS;
401 memcpy(model->name, normalized, namelen + 1);
404 ret =
load(model, rawdata, filelen);
406 FS_FreeFile(rawdata);
409 memset(model, 0,
sizeof(*model));
417 #if USE_REF == REF_VKPT
424 FS_FreeFile(rawdata);
426 Com_EPrintf(
"Couldn't load %s: %s\n", normalized,
Q_ErrorString(ret));
439 Com_Error(ERR_DROP,
"%s: %d out of range", __func__, h);