*/
static void Mod_Print(void);
static void Mod_Precache (void);
+static void Mod_Decompile_f(void);
static void Mod_BuildVBOs(void);
void Mod_Init (void)
{
Cvar_RegisterVariable(&r_mipskins);
Cmd_AddCommand ("modellist", Mod_Print, "prints a list of loaded models");
Cmd_AddCommand ("modelprecache", Mod_Precache, "load a model");
+ Cmd_AddCommand ("modeldecompile", Mod_Decompile_f, "exports a model in several formats for editing purposes");
}
void Mod_RenderInit(void)
num = LittleLong(*((int *)buf));
// call the apropriate loader
loadmodel = mod;
- if (!memcmp(buf, "IDPO", 4)) Mod_IDP0_Load(mod, buf, bufend);
+ if (!strcasecmp(FS_FileExtension(mod->name), "obj")) Mod_OBJ_Load(mod, buf, bufend);
+ else if (!memcmp(buf, "IDPO", 4)) Mod_IDP0_Load(mod, buf, bufend);
else if (!memcmp(buf, "IDP2", 4)) Mod_IDP2_Load(mod, buf, bufend);
else if (!memcmp(buf, "IDP3", 4)) Mod_IDP3_Load(mod, buf, bufend);
else if (!memcmp(buf, "IDSP", 4)) Mod_IDSP_Load(mod, buf, bufend);
dp_model_t *Mod_FindName(const char *name)
{
int i;
- int nummodels = Mem_ExpandableArray_IndexRange(&models);
+ int nummodels;
dp_model_t *mod;
+ // if we're not dedicatd, the renderer calls will crash without video
+ Host_StartVideo();
+
+ nummodels = Mem_ExpandableArray_IndexRange(&models);
+
if (!name[0])
Host_Error ("Mod_ForName: NULL name");
match = -1;
n[p] = match;
}
+
+ // also send a keepalive here (this can take a while too!)
+ CL_KeepaliveMessage(false);
}
// free the allocated buffer
if (edgehashentries != edgehashentriesbuffer)
}
Mod_ShadowMesh_AddTriangle(mempool, mesh, map_diffuse, map_specular, map_normal, vbuf);
}
+
+ // the triangle calculation can take a while, so let's do a keepalive here
+ CL_KeepaliveMessage(false);
}
shadowmesh_t *Mod_ShadowMesh_Begin(mempool_t *mempool, int maxverts, int maxtriangles, rtexture_t *map_diffuse, rtexture_t *map_specular, rtexture_t *map_normal, int light, int neighbors, int expandable)
{
+ // the preparation before shadow mesh initialization can take a while, so let's do a keepalive here
+ CL_KeepaliveMessage(false);
+
return Mod_ShadowMesh_Alloc(mempool, maxverts, maxtriangles, map_diffuse, map_specular, map_normal, light, neighbors, expandable);
}
}
Mem_Free(mesh);
}
+
+ // this can take a while, so let's do a keepalive here
+ CL_KeepaliveMessage(false);
+
return firstmesh;
}
if(!(defaulttexflags & TEXF_COMPRESS))
texture->textureflags &= ~TEXF_COMPRESS;
- texture->basematerialflags = 0;
if (shader->surfaceparms & Q3SURFACEPARM_SKY)
{
texture->basematerialflags = MATERIALFLAG_SKY | MATERIALFLAG_NOSHADOW;
texture->basematerialflags = MATERIALFLAG_NODRAW | MATERIALFLAG_NOSHADOW;
else
texture->basematerialflags = MATERIALFLAG_WALL;
+
if (shader->layers[0].alphatest)
texture->basematerialflags |= MATERIALFLAG_ALPHATEST | MATERIALFLAG_NOSHADOW;
if (shader->textureflags & Q3TEXTUREFLAG_TWOSIDED)
*lastvertexpointer = lastvertex;
}
+void Mod_MakeSortedSurfaces(dp_model_t *mod)
+{
+ // make an optimal set of texture-sorted batches to draw...
+ int j, t;
+ int *firstsurfacefortexture;
+ int *numsurfacesfortexture;
+ if (!mod->sortedmodelsurfaces)
+ mod->sortedmodelsurfaces = Mem_Alloc(loadmodel->mempool, mod->nummodelsurfaces * sizeof(*mod->sortedmodelsurfaces));
+ firstsurfacefortexture = Mem_Alloc(tempmempool, mod->num_textures * sizeof(*firstsurfacefortexture));
+ numsurfacesfortexture = Mem_Alloc(tempmempool, mod->num_textures * sizeof(*numsurfacesfortexture));
+ memset(numsurfacesfortexture, 0, mod->num_textures * sizeof(*numsurfacesfortexture));
+ for (j = 0;j < mod->nummodelsurfaces;j++)
+ {
+ const msurface_t *surface = mod->data_surfaces + j + mod->firstmodelsurface;
+ int t = (int)(surface->texture - mod->data_textures);
+ numsurfacesfortexture[t]++;
+ }
+ j = 0;
+ for (t = 0;t < mod->num_textures;t++)
+ {
+ firstsurfacefortexture[t] = j;
+ j += numsurfacesfortexture[t];
+ }
+ for (j = 0;j < mod->nummodelsurfaces;j++)
+ {
+ const msurface_t *surface = mod->data_surfaces + j + mod->firstmodelsurface;
+ int t = (int)(surface->texture - mod->data_textures);
+ mod->sortedmodelsurfaces[firstsurfacefortexture[t]++] = j + mod->firstmodelsurface;
+ }
+ Mem_Free(firstsurfacefortexture);
+ Mem_Free(numsurfacesfortexture);
+}
+
static void Mod_BuildVBOs(void)
{
if (!gl_support_arb_vertex_buffer_object)
Mem_Free(mem);
}
}
+
+static void Mod_Decompile_OBJ(dp_model_t *model, const char *filename, const char *mtlfilename, const char *originalfilename)
+{
+ int vertexindex, surfaceindex, triangleindex, textureindex, countvertices = 0, countsurfaces = 0, countfaces = 0, counttextures = 0;
+ int a, b, c;
+ const char *texname;
+ const int *e;
+ const float *v, *vn, *vt;
+ size_t l;
+ size_t outbufferpos = 0;
+ size_t outbuffermax = 0x100000;
+ char *outbuffer = (char *) Z_Malloc(outbuffermax), *oldbuffer;
+ const msurface_t *surface;
+ const int maxtextures = 256;
+ char *texturenames = (char *) Z_Malloc(maxtextures * MAX_QPATH);
+
+ // construct the mtllib file
+ l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "# mtllib for %s exported by darkplaces engine\n", originalfilename);
+ if (l > 0)
+ outbufferpos += l;
+ for (surfaceindex = 0, surface = model->data_surfaces;surfaceindex < model->num_surfaces;surfaceindex++, surface++)
+ {
+ countsurfaces++;
+ countvertices += surface->num_vertices;
+ countfaces += surface->num_triangles;
+ texname = (surface->texture && surface->texture->name[0]) ? surface->texture->name : "default";
+ for (textureindex = 0;textureindex < maxtextures && texturenames[textureindex*MAX_QPATH];textureindex++)
+ if (!strcmp(texturenames + textureindex * MAX_QPATH, texname))
+ break;
+ if (textureindex >= maxtextures)
+ continue; // just a precaution
+ if (counttextures < textureindex + 1)
+ counttextures = textureindex + 1;
+ strlcpy(texturenames + textureindex * MAX_QPATH, texname, MAX_QPATH);
+ if (outbufferpos >= outbuffermax >> 1)
+ {
+ outbuffermax *= 2;
+ oldbuffer = outbuffer;
+ outbuffer = (char *) Z_Malloc(outbuffermax);
+ memcpy(outbuffer, oldbuffer, outbufferpos);
+ Z_Free(oldbuffer);
+ }
+ l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "newmtl %s\nNs 96.078431\nKa 0 0 0\nKd 0.64 0.64 0.64\nKs 0.5 0.5 0.5\nNi 1\nd 1\nillum 2\nmap_Kd %s%s\n\n", texname, texname, strstr(texname, ".tga") ? "" : ".tga");
+ if (l > 0)
+ outbufferpos += l;
+ }
+
+ // write the mtllib file
+ FS_WriteFile(mtlfilename, outbuffer, outbufferpos);
+ outbufferpos = 0;
+
+ // construct the obj file
+ l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "# model exported from %s by darkplaces engine\n# %i vertices, %i faces, %i surfaces\nmtllib %s\n", originalfilename, countvertices, countfaces, countsurfaces, mtlfilename);
+ if (l > 0)
+ outbufferpos += l;
+ for (vertexindex = 0, v = model->surfmesh.data_vertex3f, vn = model->surfmesh.data_normal3f, vt = model->surfmesh.data_texcoordtexture2f;vertexindex < model->surfmesh.num_vertices;vertexindex++, v += 3, vn += 3, vt += 2)
+ {
+ if (outbufferpos >= outbuffermax >> 1)
+ {
+ outbuffermax *= 2;
+ oldbuffer = outbuffer;
+ outbuffer = (char *) Z_Malloc(outbuffermax);
+ memcpy(outbuffer, oldbuffer, outbufferpos);
+ Z_Free(oldbuffer);
+ }
+ l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "v %f %f %f\nvn %f %f %f\nvt %f %f\n", v[0], v[2], -v[1], vn[0], vn[2], -vn[1], vt[0], 1-vt[1]);
+ if (l > 0)
+ outbufferpos += l;
+ }
+ for (surfaceindex = 0, surface = model->data_surfaces;surfaceindex < model->num_surfaces;surfaceindex++, surface++)
+ {
+ l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "usemtl %s\n", (surface->texture && surface->texture->name[0]) ? surface->texture->name : "default");
+ if (l > 0)
+ outbufferpos += l;
+ for (triangleindex = 0, e = model->surfmesh.data_element3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
+ {
+ if (outbufferpos >= outbuffermax >> 1)
+ {
+ outbuffermax *= 2;
+ oldbuffer = outbuffer;
+ outbuffer = (char *) Z_Malloc(outbuffermax);
+ memcpy(outbuffer, oldbuffer, outbufferpos);
+ Z_Free(oldbuffer);
+ }
+ a = e[0]+1;
+ b = e[2]+1;
+ c = e[1]+1;
+ l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "f %i/%i/%i %i/%i/%i %i/%i/%i\n", a,a,a,b,b,b,c,c,c);
+ if (l > 0)
+ outbufferpos += l;
+ }
+ }
+
+ // write the obj file
+ FS_WriteFile(filename, outbuffer, outbufferpos);
+
+ // clean up
+ Z_Free(outbuffer);
+ Z_Free(texturenames);
+
+ // print some stats
+ Con_Printf("Wrote %s (%i bytes, %i vertices, %i faces, %i surfaces with %i distinct textures)\n", filename, (int)outbufferpos, countvertices, countfaces, countsurfaces, counttextures);
+}
+
+static void Mod_Decompile_SMD(dp_model_t *model, const char *filename, int firstpose, int numposes, qboolean writetriangles)
+{
+ int countnodes = 0, counttriangles = 0, countframes = 0;
+ int surfaceindex;
+ int triangleindex;
+ int transformindex;
+ int poseindex;
+ int cornerindex;
+ float modelscale;
+ const int *e;
+ const float *pose;
+ size_t l;
+ size_t outbufferpos = 0;
+ size_t outbuffermax = 0x100000;
+ char *outbuffer = (char *) Z_Malloc(outbuffermax), *oldbuffer;
+ const msurface_t *surface;
+ l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "version 1\nnodes\n");
+ if (l > 0)
+ outbufferpos += l;
+ modelscale = 1;
+ if(model->num_poses >= 0)
+ modelscale = sqrt(model->data_poses[0] * model->data_poses[0] + model->data_poses[1] * model->data_poses[1] + model->data_poses[2] * model->data_poses[2]);
+ if(fabs(modelscale - 1) > 1e-4)
+ {
+ if(firstpose == 0) // only print the when writing the reference pose
+ Con_Printf("The model has an old-style model scale of %f\n", modelscale);
+ }
+ else
+ modelscale = 1;
+ for (transformindex = 0;transformindex < model->num_bones;transformindex++)
+ {
+ if (outbufferpos >= outbuffermax >> 1)
+ {
+ outbuffermax *= 2;
+ oldbuffer = outbuffer;
+ outbuffer = (char *) Z_Malloc(outbuffermax);
+ memcpy(outbuffer, oldbuffer, outbufferpos);
+ Z_Free(oldbuffer);
+ }
+ countnodes++;
+ l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i \"%s\" %3i\n", transformindex, model->data_bones[transformindex].name, model->data_bones[transformindex].parent);
+ if (l > 0)
+ outbufferpos += l;
+ }
+ l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "end\nskeleton\n");
+ if (l > 0)
+ outbufferpos += l;
+ for (poseindex = 0, pose = model->data_poses + model->num_bones * 12 * firstpose;poseindex < numposes;poseindex++)
+ {
+ countframes++;
+ l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "time %i\n", poseindex);
+ if (l > 0)
+ outbufferpos += l;
+ for (transformindex = 0;transformindex < model->num_bones;transformindex++, pose += 12)
+ {
+ float a, b, c;
+ float angles[3];
+ float mtest[3][4];
+ if (outbufferpos >= outbuffermax >> 1)
+ {
+ outbuffermax *= 2;
+ oldbuffer = outbuffer;
+ outbuffer = (char *) Z_Malloc(outbuffermax);
+ memcpy(outbuffer, oldbuffer, outbufferpos);
+ Z_Free(oldbuffer);
+ }
+
+ // strangely the smd angles are for a transposed matrix, so we
+ // have to generate a transposed matrix, then convert that...
+ mtest[0][0] = pose[ 0];
+ mtest[0][1] = pose[ 4];
+ mtest[0][2] = pose[ 8];
+ mtest[0][3] = pose[ 3];
+ mtest[1][0] = pose[ 1];
+ mtest[1][1] = pose[ 5];
+ mtest[1][2] = pose[ 9];
+ mtest[1][3] = pose[ 7];
+ mtest[2][0] = pose[ 2];
+ mtest[2][1] = pose[ 6];
+ mtest[2][2] = pose[10];
+ mtest[2][3] = pose[11];
+ AnglesFromVectors(angles, mtest[0], mtest[2], false);
+ if (angles[0] >= 180) angles[0] -= 360;
+ if (angles[1] >= 180) angles[1] -= 360;
+ if (angles[2] >= 180) angles[2] -= 360;
+
+ a = DEG2RAD(angles[ROLL]);
+ b = DEG2RAD(angles[PITCH]);
+ c = DEG2RAD(angles[YAW]);
+
+#if 0
+{
+ float cy, sy, cp, sp, cr, sr;
+ float test[3][4];
+ // smd matrix construction, for comparing to non-transposed m
+ sy = sin(c);
+ cy = cos(c);
+ sp = sin(b);
+ cp = cos(b);
+ sr = sin(a);
+ cr = cos(a);
+
+ test[0][0] = cp*cy;
+ test[1][0] = cp*sy;
+ test[2][0] = -sp;
+ test[0][1] = sr*sp*cy+cr*-sy;
+ test[1][1] = sr*sp*sy+cr*cy;
+ test[2][1] = sr*cp;
+ test[0][2] = (cr*sp*cy+-sr*-sy);
+ test[1][2] = (cr*sp*sy+-sr*cy);
+ test[2][2] = cr*cp;
+ test[0][3] = pose[3];
+ test[1][3] = pose[7];
+ test[2][3] = pose[11];
+}
+#endif
+ l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f\n", transformindex, pose[3] * modelscale, pose[7] * modelscale, pose[11] * modelscale, DEG2RAD(angles[ROLL]), DEG2RAD(angles[PITCH]), DEG2RAD(angles[YAW]));
+ if (l > 0)
+ outbufferpos += l;
+ }
+ }
+ l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "end\n");
+ if (l > 0)
+ outbufferpos += l;
+ if (writetriangles)
+ {
+ l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "triangles\n");
+ if (l > 0)
+ outbufferpos += l;
+ for (surfaceindex = 0, surface = model->data_surfaces;surfaceindex < model->num_surfaces;surfaceindex++, surface++)
+ {
+ for (triangleindex = 0, e = model->surfmesh.data_element3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
+ {
+ counttriangles++;
+ if (outbufferpos >= outbuffermax >> 1)
+ {
+ outbuffermax *= 2;
+ oldbuffer = outbuffer;
+ outbuffer = (char *) Z_Malloc(outbuffermax);
+ memcpy(outbuffer, oldbuffer, outbufferpos);
+ Z_Free(oldbuffer);
+ }
+ l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%s\n", surface->texture && surface->texture->name[0] ? surface->texture->name : "default.bmp");
+ if (l > 0)
+ outbufferpos += l;
+ for (cornerindex = 0;cornerindex < 3;cornerindex++)
+ {
+ const int index = e[2-cornerindex];
+ const float *v = model->surfmesh.data_vertex3f + index * 3;
+ const float *vn = model->surfmesh.data_normal3f + index * 3;
+ const float *vt = model->surfmesh.data_texcoordtexture2f + index * 2;
+ const int *wi = model->surfmesh.data_vertexweightindex4i + index * 4;
+ const float *wf = model->surfmesh.data_vertexweightinfluence4f + index * 4;
+ if (wf[3]) l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f %f %f 4 %i %f %i %f %i %f %i %f\n", wi[0], v[0], v[1], v[2], vn[0], vn[1], vn[2], vt[0], 1 - vt[1], wi[0], wf[0], wi[1], wf[1], wi[2], wf[2], wi[3], wf[3]);
+ else if (wf[2]) l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f %f %f 3 %i %f %i %f %i %f\n" , wi[0], v[0], v[1], v[2], vn[0], vn[1], vn[2], vt[0], 1 - vt[1], wi[0], wf[0], wi[1], wf[1], wi[2], wf[2]);
+ else if (wf[1]) l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f %f %f 2 %i %f %i %f\n" , wi[0], v[0], v[1], v[2], vn[0], vn[1], vn[2], vt[0], 1 - vt[1], wi[0], wf[0], wi[1], wf[1]);
+ else l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f %f %f\n" , wi[0], v[0], v[1], v[2], vn[0], vn[1], vn[2], vt[0], 1 - vt[1]);
+ if (l > 0)
+ outbufferpos += l;
+ }
+ }
+ }
+ l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "end\n");
+ if (l > 0)
+ outbufferpos += l;
+ }
+
+ FS_WriteFile(filename, outbuffer, outbufferpos);
+ Z_Free(outbuffer);
+
+ Con_Printf("Wrote %s (%i bytes, %i nodes, %i frames, %i triangles)\n", filename, (int)outbufferpos, countnodes, countframes, counttriangles);
+}
+
+/*
+================
+Mod_Decompile_f
+
+decompiles a model to editable files
+================
+*/
+static void Mod_Decompile_f(void)
+{
+ int i, j, k, l, first, count;
+ dp_model_t *mod;
+ char inname[MAX_QPATH];
+ char outname[MAX_QPATH];
+ char mtlname[MAX_QPATH];
+ char basename[MAX_QPATH];
+ char animname[MAX_QPATH];
+ char animname2[MAX_QPATH];
+ char zymtextbuffer[16384];
+ char dpmtextbuffer[16384];
+ int zymtextsize = 0;
+ int dpmtextsize = 0;
+
+ if (Cmd_Argc() != 2)
+ {
+ Con_Print("usage: modeldecompile <filename>\n");
+ return;
+ }
+
+ strlcpy(inname, Cmd_Argv(1), sizeof(inname));
+ FS_StripExtension(inname, basename, sizeof(basename));
+
+ mod = Mod_ForName(inname, false, true, cl.worldmodel && !strcasecmp(inname, cl.worldmodel->name));
+ if (!mod)
+ {
+ Con_Print("No such model\n");
+ return;
+ }
+ if (!mod->surfmesh.num_triangles)
+ {
+ Con_Print("Empty model (or sprite)\n");
+ return;
+ }
+
+ // export OBJ if possible (not on sprites)
+ if (mod->surfmesh.num_triangles)
+ {
+ dpsnprintf(outname, sizeof(outname), "%s_decompiled.obj", basename);
+ dpsnprintf(mtlname, sizeof(mtlname), "%s_decompiled.mtl", basename);
+ Mod_Decompile_OBJ(mod, outname, mtlname, inname);
+ }
+
+ // export SMD if possible (only for skeletal models)
+ if (mod->surfmesh.num_triangles && mod->num_bones)
+ {
+ dpsnprintf(outname, sizeof(outname), "%s_decompiled/ref1.smd", basename);
+ Mod_Decompile_SMD(mod, outname, 0, 1, true);
+ l = dpsnprintf(zymtextbuffer + zymtextsize, sizeof(zymtextbuffer) - zymtextsize, "output out.zym\nscale 1\norigin 0 0 0\nmesh ref1.smd\n");
+ if (l > 0) zymtextsize += l;
+ l = dpsnprintf(dpmtextbuffer + dpmtextsize, sizeof(dpmtextbuffer) - dpmtextsize, "outputdir .\nmodel out\nscale 1\norigin 0 0 0\nscene ref1.smd\n");
+ if (l > 0) dpmtextsize += l;
+ for (i = 0;i < mod->numframes;i = j)
+ {
+ strlcpy(animname, mod->animscenes[i].name, sizeof(animname));
+ first = mod->animscenes[i].firstframe;
+ if (mod->animscenes[i].framecount > 1)
+ {
+ // framegroup anim
+ count = mod->animscenes[i].framecount;
+ j = i + 1;
+ }
+ else
+ {
+ // individual frame
+ // check for additional frames with same name
+ for (l = 0, k = strlen(animname);animname[l];l++)
+ if ((animname[l] < '0' || animname[l] > '9') && animname[l] != '_')
+ k = l + 1;
+ animname[k] = 0;
+ count = (mod->num_poses / mod->num_bones) - first;
+ for (j = i + 1;j < mod->numframes;j++)
+ {
+ strlcpy(animname2, mod->animscenes[j].name, sizeof(animname2));
+ for (l = 0, k = strlen(animname2);animname2[l];l++)
+ if ((animname2[l] < '0' || animname2[l] > '9') && animname2[l] != '_')
+ k = l + 1;
+ animname2[k] = 0;
+ if (strcmp(animname2, animname) || mod->animscenes[j].framecount > 1)
+ {
+ count = mod->animscenes[j].firstframe - first;
+ break;
+ }
+ }
+ // if it's only one frame, use the original frame name
+ if (j == i + 1)
+ strlcpy(animname, mod->animscenes[i].name, sizeof(animname));
+
+ }
+ dpsnprintf(outname, sizeof(outname), "%s_decompiled/%s.smd", basename, animname);
+ Mod_Decompile_SMD(mod, outname, first, count, false);
+ if (zymtextsize < (int)sizeof(zymtextbuffer) - 100)
+ {
+ l = dpsnprintf(zymtextbuffer + zymtextsize, sizeof(zymtextbuffer) - zymtextsize, "scene %s.smd fps %g\n", animname, mod->animscenes[i].framerate);
+ if (l > 0) zymtextsize += l;
+ }
+ if (dpmtextsize < (int)sizeof(dpmtextbuffer) - 100)
+ {
+ l = dpsnprintf(dpmtextbuffer + dpmtextsize, sizeof(dpmtextbuffer) - dpmtextsize, "scene %s.smd\n", animname);
+ if (l > 0) dpmtextsize += l;
+ }
+ }
+ if (zymtextsize)
+ FS_WriteFile(va("%s_decompiled/out_zym.txt", basename), zymtextbuffer, (fs_offset_t)zymtextsize);
+ if (dpmtextsize)
+ FS_WriteFile(va("%s_decompiled/out_dpm.txt", basename), dpmtextbuffer, (fs_offset_t)dpmtextsize);
+ }
+}
+