UFO: Alien Invasion
Loading...
Searching...
No Matches
md2.cpp
Go to the documentation of this file.
1#include "md2.h"
3#include "../../common/mem.h"
7#include "../../common/mem.h"
9#include "../../shared/byte.h"
10
11void MD2HeaderCheck (const dMD2Model_t* md2, const char* fileName, int bufSize)
12{
13 /* sanity checks */
14 const uint32_t version = LittleLong(md2->version);
15 const uint32_t numSkins = LittleLong(md2->num_skins);
16 const uint32_t numTris = LittleLong(md2->num_tris);
17 const uint32_t numVerts = LittleLong(md2->num_verts);
18 const uint32_t ident = LittleLong(md2->ident);
19
20 if (ident != IDALIASHEADER)
21 Com_Error(ERR_DROP, "%s is no valid md2 file", fileName);
22
23 if (version != MD2_ALIAS_VERSION)
24 Com_Error(ERR_DROP, "%s has wrong version number (%i should be %i)", fileName, version, MD2_ALIAS_VERSION);
25
26 if (bufSize != LittleLong(md2->ofs_end))
27 Com_Error(ERR_DROP, "model %s broken offset values (%i, %i)", fileName, bufSize, LittleLong(md2->ofs_end));
28
29 if (numSkins == 0 || numSkins >= MD2_MAX_SKINS)
30 Com_Error(ERR_DROP, "model '%s' has invalid skin number: %i", fileName, numSkins);
31
32 if (numVerts == 0 || numVerts >= MD2_MAX_VERTS)
33 Com_Error(ERR_DROP, "model %s has too many (or no) vertices (%i/%i)", fileName, numVerts, MD2_MAX_VERTS);
34
35 if (numTris == 0 || numTris >= MD2_MAX_TRIANGLES)
36 Com_Error(ERR_DROP, "model %s has too many (or no) triangles (%i/%i)", fileName, numTris, MD2_MAX_TRIANGLES);
37}
38
39void MD2SkinEdit (const byte* buf, const char* fileName, int bufSize, void* userData)
40{
41 uint32_t numSkins;
42 byte* const copy = Mem_Dup(byte, buf, bufSize);
43 dMD2Model_t* md2 = (dMD2Model_t*)copy;
44 char* md2Path;
45
46 MD2HeaderCheck(md2, fileName, bufSize);
47
48 md2Path = (char*) copy + LittleLong(md2->ofs_skins);
49 numSkins = LittleLong(md2->num_skins);
50
51 Com_Printf(" \\ - skins %i\n", numSkins);
52 for (int i = 0; i < numSkins; i++) {
53 char* name = md2Path + i * MD2_MAX_SKINNAME;
54 Com_Printf(" \\ - skin %i: %s\n", i + 1, name);
55 printf(" \\ - new skin: ");
56 fflush(stdout);
57 scanf(va("%%%is", MD2_MAX_SKINNAME), name);
58 }
59
60 ScopedFile md2ModelFile;
61 FS_OpenFile(fileName, &md2ModelFile, FILE_WRITE);
62 if (!md2ModelFile) {
63 Com_Printf("Error writing md2 file %s\n", fileName);
64 Mem_Free(copy);
65 return;
66 }
67 FS_Write(copy, bufSize, &md2ModelFile);
68 Mem_Free(copy);
69}
70
71void MD2Info (const byte* buf, const char* fileName, int bufSize, void* userData)
72{
73 const dMD2Model_t* md2 = (const dMD2Model_t*)buf;
74
75 MD2HeaderCheck(md2, fileName, bufSize);
76
77 const uint32_t numSkins = LittleLong(md2->num_skins);
78 const uint32_t numVerts = LittleLong(md2->num_verts);
79 const uint32_t numST = LittleLong(md2->num_st);
80 const uint32_t numTris = LittleLong(md2->num_tris);
81 const uint32_t numGLCmds = LittleLong(md2->num_glcmds);
82 const uint32_t numFrames = LittleLong(md2->num_frames);
83 const uint32_t frameSize = LittleLong(md2->framesize);
84 const uint32_t skinHeight = LittleLong(md2->skinheight);
85 const uint32_t skinWidth = LittleLong(md2->skinwidth);
86 const uint32_t version = LittleLong(md2->version);
87
88 const uint32_t ofsST = LittleLong(md2->ofs_st);
89 const uint32_t ofsTris = LittleLong(md2->ofs_tris);
90 const uint32_t ofsFrames = LittleLong(md2->ofs_frames);
91 const uint32_t ofsGLCmds = LittleLong(md2->ofs_glcmds);
92 const uint32_t ofsEnd = LittleLong(md2->ofs_end);
93 const uint32_t ofsSkins = LittleLong(md2->ofs_skins);
94
95 const char* md2Path = (const char*) md2 + LittleLong(md2->ofs_skins);
96
97 Com_Printf(" \\ - skins %i\n", numSkins);
98 for (int i = 0; i < numSkins; i++) {
99 const char* name = md2Path + i * MD2_MAX_SKINNAME;
100 Com_Printf(" \\ -> skin %i: %s\n", i + 1, name);
101 }
102 Com_Printf(" \\ - vertices %i\n", numVerts);
103 Com_Printf(" \\ - texcoords %i\n", numST);
104 Com_Printf(" \\ - tris %i\n", numTris);
105 Com_Printf(" \\ - glcmds %i\n", numGLCmds);
106 Com_Printf(" \\ - frames %i\n", numFrames);
107 Com_Printf(" \\ - frameSize %i\n", frameSize);
108 Com_Printf(" \\ - skinHeight %i\n", skinHeight);
109 Com_Printf(" \\ - skinWidth %i\n", skinWidth);
110 Com_Printf(" \\ - version %i\n", version);
111 Com_Printf(" \\ - offsets\n");
112 Com_Printf(" \\ - ofsST %i\n", ofsST);
113 Com_Printf(" \\ - ofsTris %i\n", ofsTris);
114 Com_Printf(" \\ - ofsFrames %i\n", ofsFrames);
115 Com_Printf(" \\ - ofsGLCmds %i\n", ofsGLCmds);
116 Com_Printf(" \\ - ofsSkins %i\n", ofsSkins);
117 Com_Printf(" \\ - ofsEnd %i\n", ofsEnd);
118}
119
120void MD2SkinNum (const byte* buf, const char* fileName, int bufSize, void* userData)
121{
122 byte* copy = Mem_Dup(byte, buf, bufSize);
123 dMD2Model_t* md2 = (dMD2Model_t*)copy;
124
125 MD2HeaderCheck(md2, fileName, bufSize);
126
127 const uint32_t numSkins = LittleLong(md2->num_skins);
128
129 const uint32_t ofsST = LittleLong(md2->ofs_st);
130 const uint32_t ofsTris = LittleLong(md2->ofs_tris);
131 const uint32_t ofsFrames = LittleLong(md2->ofs_frames);
132 const uint32_t ofsGLCmds = LittleLong(md2->ofs_glcmds);
133 const uint32_t ofsEnd = LittleLong(md2->ofs_end);
134 const uint32_t ofsSkins = LittleLong(md2->ofs_skins);
135
136 uint32_t moveOffset = ofsEnd;
137#define CHECKMAX(val) if ((val) > ofsSkins && (val) < moveOffset) moveOffset = (val);
138 CHECKMAX(ofsST);
139 CHECKMAX(ofsTris);
140 CHECKMAX(ofsFrames);
141 CHECKMAX(ofsGLCmds);
142 CHECKMAX(ofsSkins);
143#undef CHECKMAX
144
145 Com_Printf(" \\ - skins %i\n", numSkins);
146 int newSkins = 0;
147 printf(" \\ - new skin number: ");
148 fflush(stdout);
149 scanf("%i", &newSkins);
150 if (newSkins <= 0) {
151 Com_Printf("A model must have a skin\n");
152 Mem_Free(copy);
153 return;
154 }
155 if (newSkins > MD2_MAX_SKINS) {
156 Com_Printf("Only %i skins are allowed\n", MD2_MAX_SKINS);
157 Mem_Free(copy);
158 return;
159 }
160
161 if (newSkins == numSkins) {
162 Mem_Free(copy);
163 return;
164 }
165
166 const int32_t deltaSkins = newSkins - numSkins;
167 const int32_t offsetDelta = deltaSkins * MD2_MAX_SKINNAME;
168 if (ofsST > ofsSkins)
169 md2->ofs_st = LittleLong(ofsST + offsetDelta);
170 if (ofsTris > ofsSkins)
171 md2->ofs_tris = LittleLong(ofsTris + offsetDelta);
172 if (ofsFrames > ofsSkins)
173 md2->ofs_frames = LittleLong(ofsFrames + offsetDelta);
174 if (ofsGLCmds > ofsSkins)
175 md2->ofs_glcmds = LittleLong(ofsGLCmds + offsetDelta);
176 md2->ofs_end = LittleLong(ofsEnd + offsetDelta);
177 md2->num_skins = LittleLong(newSkins);
178
179 Com_Printf("change to %i skins\n", newSkins);
180 if (deltaSkins > 0) {
181 copy = (byte*)Mem_ReAlloc(copy, md2->ofs_end);
182 md2 = (dMD2Model_t*)copy;
183 }
184
185 const int n = ofsEnd - moveOffset;
186 byte* from = copy + moveOffset;
187 byte* to = from + offsetDelta;
188 memmove(to, from, n);
189
190 if (deltaSkins > 0) {
191 char* md2Path = (char*) copy + LittleLong(md2->ofs_skins);
192 for (int i = numSkins; i < numSkins + deltaSkins; i++) {
193 char* name = md2Path + i * MD2_MAX_SKINNAME;
194 memset(name, 0, MD2_MAX_SKINNAME);
195 strcpy(name, ".none");
196 Com_Printf(" \\ - skin %i: %s\n", i + 1, name);
197 printf(" \\ - new skin: ");
198 fflush(stdout);
199 scanf(va("%%%is", MD2_MAX_SKINNAME), name);
200 }
201 }
202 ScopedFile md2ModelFile;
203 FS_OpenFile(fileName, &md2ModelFile, FILE_WRITE);
204 if (!md2ModelFile) {
205 Com_Printf("Error writing md2 file %s\n", fileName);
206 Mem_Free(copy);
207 return;
208 }
209 FS_Write(copy, md2->ofs_end, &md2ModelFile);
210 Mem_Free(copy);
211}
212
213void MD2GLCmdsRemove (const byte* buf, const char* fileName, int bufSize, void* userData)
214{
215 uint32_t numGLCmds;
216 const dMD2Model_t* md2 = (const dMD2Model_t*)buf;
217
218 MD2HeaderCheck(md2, fileName, bufSize);
219
220 numGLCmds = LittleLong(md2->num_glcmds);
221
222 if (numGLCmds > 0) {
223 byte *const copy = Mem_Dup(byte, buf, bufSize);
224 dMD2Model_t* const fixedMD2 = (dMD2Model_t*)copy;
225 const size_t delta = numGLCmds * sizeof(uint32_t);
226 const uint32_t offset = LittleLong(fixedMD2->ofs_glcmds);
227
228 if (LittleLong(fixedMD2->ofs_skins) > offset || LittleLong(fixedMD2->ofs_frames) > offset
229 || LittleLong(fixedMD2->ofs_st) > offset || LittleLong(fixedMD2->ofs_tris) > offset) {
230 Com_Error(ERR_DROP, "Unexpected order of the different data lumps");
231 }
232
233 fixedMD2->ofs_end = LittleLong(fixedMD2->ofs_end - delta);
234 fixedMD2->ofs_glcmds = 0;
235 fixedMD2->num_glcmds = 0;
236
237 bufSize -= delta;
238
239 FS_WriteFile(fixedMD2, bufSize, fileName);
240
241 Mem_Free(copy);
242
243 *(size_t*)userData += delta;
244 Com_Printf(" \\ - removed %i glcmds from '%s' (save " UFO_SIZE_T " bytes)\n",
245 numGLCmds, fileName, delta);
246 }
247}
Byte order functions header.
#define LittleLong(X)
Definition byte.h:37
void Com_Error(int code, const char *fmt,...)
Definition common.cpp:459
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
definitions common between client and server, but not game lib
#define ERR_DROP
Definition common.h:211
int FS_Write(const void *buffer, int len, qFILE *f)
Properly handles partial writes.
Definition files.cpp:1513
int FS_WriteFile(const void *buffer, size_t len, const char *filename)
Definition files.cpp:1546
int FS_OpenFile(const char *filename, qFILE *file, filemode_t mode)
Finds and opens the file in the search path.
Definition files.cpp:162
Filesystem header file.
@ FILE_WRITE
Definition filesys.h:111
voidpf void * buf
Definition ioapi.h:42
voidpf uLong offset
Definition ioapi.h:45
void MD2SkinEdit(const byte *buf, const char *fileName, int bufSize, void *userData)
Definition md2.cpp:39
#define CHECKMAX(val)
void MD2GLCmdsRemove(const byte *buf, const char *fileName, int bufSize, void *userData)
Definition md2.cpp:213
void MD2Info(const byte *buf, const char *fileName, int bufSize, void *userData)
Definition md2.cpp:71
void MD2SkinNum(const byte *buf, const char *fileName, int bufSize, void *userData)
Definition md2.cpp:120
void MD2HeaderCheck(const dMD2Model_t *md2, const char *fileName, int bufSize)
Definition md2.cpp:11
Memory handling with sentinel checking and pools with tags for grouped free'ing.
#define Mem_Dup(type, in, n)
Definition mem.h:47
#define Mem_Free(ptr)
Definition mem.h:35
#define Mem_ReAlloc(ptr, size)
Definition mem.h:44
#define MD2_MAX_TRIANGLES
Definition qfiles.h:45
#define MD2_MAX_SKINNAME
Definition qfiles.h:49
#define MD2_MAX_VERTS
Definition qfiles.h:46
#define IDALIASHEADER
Definition qfiles.h:40
#define MD2_ALIAS_VERSION
Definition qfiles.h:42
#define MD2_MAX_SKINS
Definition qfiles.h:48
QGL_EXTERN GLint i
Definition r_gl.h:113
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition r_gl.h:110
QGL_EXTERN GLuint GLsizei bufSize
Definition r_gl.h:110
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functi...
Definition shared.cpp:410
the glcmd format: a positive integer starts a tristrip command, followed by that many vertex structur...
Definition qfiles.h:109
uint32_t version
Definition qfiles.h:115
uint32_t ofs_tris
Definition qfiles.h:130
uint32_t skinwidth
Definition qfiles.h:117
uint32_t ofs_st
Definition qfiles.h:129
uint32_t ident
Definition qfiles.h:110
uint32_t ofs_frames
Definition qfiles.h:131
uint32_t num_glcmds
Definition qfiles.h:125
uint32_t ofs_end
Definition qfiles.h:133
uint32_t num_frames
Definition qfiles.h:126
uint32_t ofs_skins
Definition qfiles.h:128
uint32_t ofs_glcmds
Definition qfiles.h:132
uint32_t num_tris
Definition qfiles.h:124
uint32_t skinheight
Definition qfiles.h:118
uint32_t num_verts
Definition qfiles.h:122
uint32_t num_st
Definition qfiles.h:123
uint32_t num_skins
Definition qfiles.h:121
uint32_t framesize
Definition qfiles.h:119
Cross-platform type definitions.
#define UFO_SIZE_T
Definition ufotypes.h:89