UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
md2.cpp
Go to the documentation of this file.
1 #include "md2.h"
2 #include "../../shared/ufotypes.h"
3 #include "../../common/mem.h"
4 #include "../../shared/shared.h"
5 #include "../../common/filesys.h"
6 #include "../../shared/typedefs.h"
7 #include "../../common/mem.h"
8 #include "../../common/common.h"
9 #include "../../shared/byte.h"
10 
11 void 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 
39 void 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 
71 void 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 
120 void 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 
213 void 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 }
uint32_t skinheight
Definition: qfiles.h:118
#define IDALIASHEADER
Definition: qfiles.h:40
uint32_t num_skins
Definition: qfiles.h:121
#define Mem_ReAlloc(ptr, size)
Definition: mem.h:44
#define MD2_MAX_SKINS
Definition: qfiles.h:48
void MD2SkinEdit(const byte *buf, const char *fileName, int bufSize, void *userData)
Definition: md2.cpp:39
uint32_t num_tris
Definition: qfiles.h:124
int FS_OpenFile(const char *filename, qFILE *file, filemode_t mode)
Finds and opens the file in the search path.
Definition: files.cpp:162
#define MD2_ALIAS_VERSION
Definition: qfiles.h:42
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
uint32_t num_st
Definition: qfiles.h:123
#define MD2_MAX_SKINNAME
Definition: qfiles.h:49
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
void MD2SkinNum(const byte *buf, const char *fileName, int bufSize, void *userData)
Definition: md2.cpp:120
uint32_t ofs_end
Definition: qfiles.h:133
voidpf void * buf
Definition: ioapi.h:42
uint32_t num_glcmds
Definition: qfiles.h:125
void MD2Info(const byte *buf, const char *fileName, int bufSize, void *userData)
Definition: md2.cpp:71
void Com_Error(int code, const char *fmt,...)
Definition: common.cpp:417
uint32_t framesize
Definition: qfiles.h:119
#define ERR_DROP
Definition: common.h:211
uint32_t ofs_glcmds
Definition: qfiles.h:132
uint32_t ofs_skins
Definition: qfiles.h:128
#define MD2_MAX_VERTS
Definition: qfiles.h:46
int FS_WriteFile(const void *buffer, size_t len, const char *filename)
Definition: files.cpp:1544
void MD2GLCmdsRemove(const byte *buf, const char *fileName, int bufSize, void *userData)
Definition: md2.cpp:213
uint32_t num_frames
Definition: qfiles.h:126
uint32_t ofs_frames
Definition: qfiles.h:131
uint32_t ofs_tris
Definition: qfiles.h:130
the glcmd format: a positive integer starts a tristrip command, followed by that many vertex structur...
Definition: qfiles.h:109
uint32_t ofs_st
Definition: qfiles.h:129
QGL_EXTERN GLint i
Definition: r_gl.h:113
void MD2HeaderCheck(const dMD2Model_t *md2, const char *fileName, int bufSize)
Definition: md2.cpp:11
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
#define MD2_MAX_TRIANGLES
Definition: qfiles.h:45
#define Mem_Free(ptr)
Definition: mem.h:35
#define UFO_SIZE_T
Definition: ufotypes.h:89
uint32_t version
Definition: qfiles.h:115
voidpf uLong offset
Definition: ioapi.h:45
uint32_t num_verts
Definition: qfiles.h:122
uint8_t byte
Definition: ufotypes.h:34
QGL_EXTERN GLuint GLsizei bufSize
Definition: r_gl.h:110
#define Mem_Dup(type, in, n)
Definition: mem.h:47
uint32_t skinwidth
Definition: qfiles.h:117
#define CHECKMAX(val)
uint32_t ident
Definition: qfiles.h:110
#define LittleLong(X)
Definition: byte.h:37
int FS_Write(const void *buffer, int len, qFILE *f)
Properly handles partial writes.
Definition: files.cpp:1511