//* // ======================================================================================================================= // ======================================================================================================================= // TRACK *sound_LoadTrackFromFile(const char *fileName) { TRACK *pTrack; PHYSFS_file *fileHandle; size_t filename_size; char *track_name; // Use PhysicsFS to open the file fileHandle = PHYSFS_openRead(fileName); debug(LOG_NEVER, "Reading...[directory: %s] %s", PHYSFS_getRealDir(fileName), fileName); if (fileHandle == NULL) { debug(LOG_ERROR, "sound_LoadTrackFromFile: PHYSFS_openRead(\"%s\") failed with error: %s\n", fileName, PHYSFS_getLastError()); return NULL; } if (GetLastResourceFilename() == NULL) { // This is a non fatal error. We just can't find filename for some reason. debug(LOG_WARNING, "sound_LoadTrackFromFile: missing resource filename?"); filename_size = 0; } else { filename_size = strlen(GetLastResourceFilename()) + 1; } // allocate track, plus the memory required to contain the filename // one malloc call ensures only one free call is required pTrack = (TRACK *)malloc(sizeof(TRACK) + filename_size); if (pTrack == NULL) { debug(LOG_FATAL, "sound_ConstructTrack: couldn't allocate memory\n"); abort(); return NULL; } // Initialize everyting (except for the filename) to zero memset(pTrack, 0, sizeof(TRACK)); // Set filename pointer; if the filename (as returned by // GetLastResourceFilename()) is a NULL pointer, then this will be a // NULL pointer as well. track_name = filename_size ? (char *)(pTrack + 1) : NULL; // Copy the filename into the struct, if we don't have a NULL pointer if (filename_size != 0) { strcpy(track_name, GetLastResourceFilename()); } pTrack->fileName = track_name; // Now use sound_ReadTrackFromBuffer to decode the file's contents pTrack = sound_DecodeOggVorbisTrack(pTrack, fileHandle); PHYSFS_close(fileHandle); return pTrack; }
// All scripts, binary or otherwise are now passed through this routine static bool dataScriptLoad(const char* fileName, void **ppData) { static const bool printHack = false; SCRIPT_CODE** psProg = (SCRIPT_CODE**)ppData; PHYSFS_file* fileHandle; uint8_t *pBuffer; PHYSFS_sint64 fileSize = 0; debug(LOG_WZ, "COMPILING SCRIPT ...%s", GetLastResourceFilename()); fileHandle = PHYSFS_openRead(fileName); debug(LOG_WZ, "Reading...[directory: %s] %s", PHYSFS_getRealDir(fileName), fileName); if (fileHandle == NULL) { return false; } // due to the changes in r2531 we must do this routine a bit different. fileSize = PHYSFS_fileLength(fileHandle); pBuffer = malloc(fileSize * sizeof(char)); if (pBuffer == NULL) { debug(LOG_FATAL, "Fatal memory allocation, couldn't allocate %lld buffer", fileSize); abort(); } PHYSFS_read(fileHandle, pBuffer, 1, fileSize); calcDataHash(pBuffer, fileSize, DATA_SCRIPT); free(pBuffer); PHYSFS_seek(fileHandle, 0); //reset position *psProg = scriptCompile(fileHandle, SCRIPTTYPE); PHYSFS_close(fileHandle); if (!*psProg) // see script.h { debug(LOG_ERROR, "Script %s did not compile", GetLastResourceFilename()); return false; } if (printHack) { cpPrintProgram(*psProg); } return true; }
// Load a script variable values file static bool dataScriptLoadVals(const char* fileName, void **ppData) { bool success; PHYSFS_file* fileHandle; uint8_t *pBuffer; PHYSFS_sint64 fileSize = 0; *ppData = NULL; // don't load anything if a saved game is being loaded if (saveFlag) { return true; } debug(LOG_WZ, "Loading script data %s", GetLastResourceFilename()); fileHandle = PHYSFS_openRead(fileName); debug(LOG_WZ, "Reading...[directory: %s] %s", PHYSFS_getRealDir(fileName), fileName); if (fileHandle == NULL) { return false; } // due to the changes in r2532 we must do this routine a bit different. fileSize = PHYSFS_fileLength(fileHandle); pBuffer = malloc(fileSize * sizeof(char)); if (pBuffer == NULL) { debug(LOG_FATAL, "Fatal memory allocation, couldn't allocate %lld buffer", fileSize); abort(); } PHYSFS_read(fileHandle, pBuffer, 1, fileSize); calcDataHash(pBuffer, fileSize, DATA_SCRIPTVAL); free(pBuffer); PHYSFS_seek(fileHandle, 0); //reset position success = scrvLoad(fileHandle); if (!success) debug(LOG_FATAL, "Script %s did not compile", GetLastResourceFilename()); PHYSFS_close(fileHandle); return success; }
// Load a script variable values file static bool dataScriptLoadVals(const char *fileName, void **ppData) { bool success; PHYSFS_file *fileHandle; uint8_t *pBuffer; PHYSFS_sint64 fileSize = 0; *ppData = nullptr; // don't load anything if a saved game is being loaded if (saveFlag) { return true; } debug(LOG_WZ, "Loading script data %s", GetLastResourceFilename()); fileHandle = PHYSFS_openRead(fileName); debug(LOG_WZ, "Reading...[directory: %s] %s", PHYSFS_getRealDir(fileName), fileName); if (fileHandle == nullptr) { return false; } // due to the changes in r2532 we must do this routine a bit different. fileSize = PHYSFS_fileLength(fileHandle); pBuffer = (uint8_t *)malloc(fileSize * sizeof(uint8_t)); ASSERT_OR_RETURN(false, pBuffer, "Out of memory"); WZ_PHYSFS_readBytes(fileHandle, pBuffer, fileSize); calcDataHash(pBuffer, fileSize, DATA_SCRIPTVAL); free(pBuffer); PHYSFS_seek(fileHandle, 0); //reset position success = scrvLoad(fileHandle); if (!success) { debug(LOG_FATAL, "Script %s did not compile", GetLastResourceFilename()); } PHYSFS_close(fileHandle); return success; }
/* Load a team colour mask texturepage into memory */ static bool dataTexPageTCMaskLoad(const char *fileName, void **ppData) { char texpage[PATH_MAX] = {'\0'}; // This hackery is needed, because fileName will include the directory name, whilst the LastResourceFilename will not, and we need a short name to identify the texpage sstrcpy(texpage, GetLastResourceFilename()); // Check if a corresponding texpage exists, exit if no pie_MakeTexPageName(texpage); ASSERT_OR_RETURN(false, resPresent(DT_TEXPAGE, texpage), "Corresponding texpage %s doesn't exists!", texpage); pie_MakeTexPageTCMaskName(texpage); if (!dataImageLoad(fileName, ppData)) { return false; } // see if this texture page has already been loaded if (resPresent(DT_TCMASK, texpage)) { // replace the old texture page with the new one debug(LOG_TEXTURE, "replacing %s with new tcmask %s", texpage, fileName); pie_ReplaceTexPage((iV_Image *)*ppData, texpage, getTextureSize(), false); } else { debug(LOG_TEXTURE, "adding page %s with tcmask %s", texpage, fileName); SetLastResourceFilename(texpage); pie_AddTexPage((iV_Image *)*ppData, texpage, 0, getTextureSize(), false); } return true; }
/* Load a texturepage into memory */ static bool dataTexPageLoad(const char *fileName, void **ppData) { char texpage[PATH_MAX] = {'\0'}; // This hackery is needed, because fileName will include the directory name, whilst the LastResourceFilename will not, and we need a short name to identify the texpage sstrcpy(texpage, GetLastResourceFilename()); pie_MakeTexPageName(texpage); if (!dataImageLoad(fileName, ppData)) { return false; } // see if this texture page has already been loaded if (resPresent(DT_TEXPAGE, texpage)) { // replace the old texture page with the new one debug(LOG_TEXTURE, "replacing %s with new texture %s", texpage, fileName); (void) pie_ReplaceTexPage(*ppData, texpage, getTextureSize(), true); } else { debug(LOG_TEXTURE, "adding page %s with texture %s", texpage, fileName); SetLastResourceFilename(texpage); (void) pie_AddTexPage(*ppData, texpage, 0, getTextureSize(), true); } return true; }
/* Load an imd */ static bool dataIMDBufferLoad(const char *pBuffer, UDWORD size, void **ppData) { iIMDShape *psIMD; const char *pBufferPosition = pBuffer; psIMD = iV_ProcessIMD( &pBufferPosition, pBufferPosition + size ); if (psIMD == NULL) { debug( LOG_ERROR, "IMD load failed - %s", GetLastResourceFilename() ); return false; } *ppData = psIMD; return true; }
// ppFileData is incremented to the end of the file on exit! static iIMDShape *iV_ProcessIMD(const char **ppFileData, const char *FileDataEnd) { const char *pFileName = GetLastResourceFilename(); // Last loaded filename const char *pFileData = *ppFileData; char buffer[PATH_MAX], texfile[PATH_MAX], normalfile[PATH_MAX], specfile[PATH_MAX]; int cnt, nlevels; iIMDShape *shape; UDWORD level; int32_t imd_version; uint32_t imd_flags; bool bTextured = false; GLuint shader = 0; memset(normalfile, 0, sizeof(normalfile)); memset(specfile, 0, sizeof(specfile)); if (sscanf(pFileData, "%255s %d%n", buffer, &imd_version, &cnt) != 2) { debug(LOG_ERROR, "iV_ProcessIMD %s bad version: (%s)", pFileName, buffer); assert(false); return NULL; } pFileData += cnt; if (strcmp(PIE_NAME, buffer) != 0) { debug(LOG_ERROR, "iV_ProcessIMD %s not an IMD file (%s %d)", pFileName, buffer, imd_version); return NULL; } //Now supporting version PIE_VER and PIE_FLOAT_VER files if (imd_version != PIE_VER && imd_version != PIE_FLOAT_VER) { debug(LOG_ERROR, "iV_ProcessIMD %s version %d not supported", pFileName, imd_version); return NULL; } // Read flag if (sscanf(pFileData, "%255s %x%n", buffer, &imd_flags, &cnt) != 2) { debug(LOG_ERROR, "iV_ProcessIMD %s bad flags: %s", pFileName, buffer); return NULL; } pFileData += cnt; /* This can be either texture or levels */ if (sscanf(pFileData, "%255s %d%n", buffer, &nlevels, &cnt) != 2) { debug(LOG_ERROR, "iV_ProcessIMD %s expecting TEXTURE or LEVELS: %s", pFileName, buffer); return NULL; } pFileData += cnt; // get texture page if specified if (strncmp(buffer, "TEXTURE", 7) == 0) { int i, pwidth, pheight; char ch, texType[PATH_MAX]; /* the first parameter for textures is always ignored; which is why we ignore * nlevels read in above */ ch = *pFileData++; // Run up to the dot or till the buffer is filled. Leave room for the extension. for (i = 0; i < PATH_MAX - 5 && (ch = *pFileData++) != '\0' && ch != '.'; ++i) { texfile[i] = ch; } texfile[i] = '\0'; if (sscanf(pFileData, "%255s%n", texType, &cnt) != 1) { debug(LOG_ERROR, "iV_ProcessIMD %s texture info corrupt: %s", pFileName, buffer); return NULL; } pFileData += cnt; if (strcmp(texType, "png") != 0) { debug(LOG_ERROR, "iV_ProcessIMD %s: only png textures supported", pFileName); return NULL; } sstrcat(texfile, ".png"); if (sscanf(pFileData, "%d %d%n", &pwidth, &pheight, &cnt) != 2) { debug(LOG_ERROR, "iV_ProcessIMD %s bad texture size: %s", pFileName, buffer); return NULL; } pFileData += cnt; /* Now read in LEVELS directive */ if (sscanf(pFileData, "%255s %d%n", buffer, &nlevels, &cnt) != 2) { debug(LOG_ERROR, "iV_ProcessIMD %s bad levels info: %s", pFileName, buffer); return NULL; } pFileData += cnt; bTextured = true; } if (strncmp(buffer, "NORMALMAP", 9) == 0) { char ch, texType[PATH_MAX]; int i; /* the first parameter for textures is always ignored; which is why we ignore * nlevels read in above */ ch = *pFileData++; // Run up to the dot or till the buffer is filled. Leave room for the extension. for (i = 0; i < PATH_MAX - 5 && (ch = *pFileData++) != '\0' && ch != '.'; ++i) { normalfile[i] = ch; } normalfile[i] = '\0'; if (sscanf(pFileData, "%255s%n", texType, &cnt) != 1) { debug(LOG_ERROR, "iV_ProcessIMD %s normal map info corrupt: %s", pFileName, buffer); return NULL; } pFileData += cnt; if (strcmp(texType, "png") != 0) { debug(LOG_ERROR, "iV_ProcessIMD %s: only png normal maps supported", pFileName); return NULL; } sstrcat(normalfile, ".png"); /* Now read in LEVELS directive */ if (sscanf(pFileData, "%255s %d%n", buffer, &nlevels, &cnt) != 2) { debug(LOG_ERROR, "iV_ProcessIMD %s bad levels info: %s", pFileName, buffer); return NULL; } pFileData += cnt; } if (strncmp(buffer, "SPECULARMAP", 11) == 0) { char ch, texType[PATH_MAX]; int i; /* the first parameter for textures is always ignored; which is why we ignore nlevels read in above */ ch = *pFileData++; // Run up to the dot or till the buffer is filled. Leave room for the extension. for (i = 0; i < PATH_MAX - 5 && (ch = *pFileData++) != '\0' && ch != '.'; ++i) { specfile[i] = ch; } specfile[i] = '\0'; if (sscanf(pFileData, "%255s%n", texType, &cnt) != 1) { debug(LOG_ERROR, "%s specular map info corrupt: %s", pFileName, buffer); return NULL; } pFileData += cnt; if (strcmp(texType, "png") != 0) { debug(LOG_ERROR, "%s: only png specular maps supported", pFileName); return NULL; } sstrcat(specfile, ".png"); /* Try -again- to read in LEVELS directive */ if (sscanf(pFileData, "%255s %d%n", buffer, &nlevels, &cnt) != 2) { debug(LOG_ERROR, "iV_ProcessIMD %s bad levels info: %s", pFileName, buffer); return NULL; } pFileData += cnt; } // DEPRECATED SHADERS DIRECTIVE! Has been moved into levels block now. Remove me later. if (strncmp(buffer, "SHADERS", 7) == 0) { char vertex[PATH_MAX], fragment[PATH_MAX]; /* the first parameter for "textures" is always ignored; which is why we ignore nlevels read in above */ pFileData++; if (sscanf(pFileData, "%255s %255s%n", vertex, fragment, &cnt) != 2) { debug(LOG_ERROR, "%s shader corrupt: %s", pFileName, buffer); return NULL; } pFileData += cnt; shader = pie_LoadShader(pFileName, vertex, fragment); /* Try -yet again- to read in LEVELS directive */ if (sscanf(pFileData, "%255s %d%n", buffer, &nlevels, &cnt) != 2) { debug(LOG_ERROR, "iV_ProcessIMD %s bad levels info: %s", pFileName, buffer); return NULL; } pFileData += cnt; } if (strncmp(buffer, "LEVELS", 6) != 0) { debug(LOG_ERROR, "iV_ProcessIMD: expecting 'LEVELS' directive (%s)", buffer); return NULL; } /* Read first LEVEL directive */ if (sscanf(pFileData, "%255s %d%n", buffer, &level, &cnt) != 2) { debug(LOG_ERROR, "(_load_level) file corrupt -J"); return NULL; } pFileData += cnt; if (strncmp(buffer, "LEVEL", 5) != 0) { debug(LOG_ERROR, "iV_ProcessIMD(2): expecting 'LEVEL' directive (%s)", buffer); return NULL; } shape = _imd_load_level(&pFileData, FileDataEnd, nlevels, imd_version); if (shape == NULL) { debug(LOG_ERROR, "iV_ProcessIMD %s unsuccessful", pFileName); return NULL; } // assign shader to all levels, if old deprecated SHADERS directive used. FIXME remove this later. for (iIMDShape *psShape = shape; shader && psShape != NULL; psShape = psShape->next) { shape->shaderProgram = shader; } // load texture page if specified if (bTextured) { int texpage = iV_GetTexture(texfile); int normalpage = iV_TEX_INVALID; int specpage = iV_TEX_INVALID; ASSERT_OR_RETURN(NULL, texpage >= 0, "%s could not load tex page %s", pFileName, texfile); if (normalfile[0] != '\0') { debug(LOG_TEXTURE, "Loading normal map %s for %s", normalfile, pFileName); normalpage = iV_GetTexture(normalfile); ASSERT_OR_RETURN(NULL, normalpage >= 0, "%s could not load tex page %s", pFileName, normalfile); } if (specfile[0] != '\0') { debug(LOG_TEXTURE, "Loading specular map %s for %s", specfile, pFileName); specpage = iV_GetTexture(specfile); ASSERT_OR_RETURN(NULL, specpage >= 0, "%s could not load tex page %s", pFileName, specfile); } // assign tex pages and flags to all levels for (iIMDShape *psShape = shape; psShape != NULL; psShape = psShape->next) { psShape->texpage = texpage; psShape->normalpage = normalpage; psShape->specularpage = specpage; psShape->flags = imd_flags; } // check if model should use team colour mask if (imd_flags & iV_IMD_TCMASK) { int texpage_mask; pie_MakeTexPageTCMaskName(texfile); sstrcat(texfile, ".png"); texpage_mask = iV_GetTexture(texfile); ASSERT_OR_RETURN(shape, texpage_mask >= 0, "%s could not load tcmask %s", pFileName, texfile); // Propagate settings through levels for (iIMDShape *psShape = shape; psShape != NULL; psShape = psShape->next) { psShape->tcmaskpage = texpage_mask; } } } *ppFileData = pFileData; return shape; }
/*! * Load shape levels recursively * \param ppFileData Pointer to the data (usualy read from a file) * \param FileDataEnd ??? * \param nlevels Number of levels to load * \return pointer to iFSDShape structure (or NULL on error) * \pre ppFileData loaded * \post s allocated */ static iIMDShape *_imd_load_level(const char **ppFileData, const char *FileDataEnd, int nlevels, int pieVersion) { const char *pFileName = GetLastResourceFilename(); // Last loaded filename const char *pFileData = *ppFileData; char buffer[PATH_MAX] = {'\0'}; int cnt = 0, n = 0, i; iIMDShape *s = NULL; float dummy; if (nlevels == 0) { return NULL; } i = sscanf(pFileData, "%255s %n", buffer, &cnt); ASSERT_OR_RETURN(NULL, i == 1, "Bad directive following LEVEL"); s = new iIMDShape; // Optionally load and ignore deprecated MATERIALS directive if (strcmp(buffer, "MATERIALS") == 0) { i = sscanf(pFileData, "%255s %f %f %f %f %f %f %f %f %f %f%n", buffer, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &cnt); ASSERT_OR_RETURN(NULL, i == 11, "Bad MATERIALS directive"); debug(LOG_WARNING, "MATERIALS directive no longer supported!"); pFileData += cnt; } else if (strcmp(buffer, "SHADERS") == 0) { char vertex[PATH_MAX], fragment[PATH_MAX]; if (sscanf(pFileData, "%255s %255s %255s%n", buffer, vertex, fragment, &cnt) != 3) { debug(LOG_ERROR, "%s shader corrupt: %s", pFileName, buffer); return NULL; } s->shaderProgram = pie_LoadShader(pFileName, vertex, fragment); pFileData += cnt; } if (sscanf(pFileData, "%255s %d%n", buffer, &s->npoints, &cnt) != 2) { debug(LOG_ERROR, "_imd_load_level(2): file corrupt"); return NULL; } pFileData += cnt; // load points ASSERT_OR_RETURN(NULL, strcmp(buffer, "POINTS") == 0, "Expecting 'POINTS' directive, got: %s", buffer); _imd_load_points(&pFileData, s); if (sscanf(pFileData, "%255s %d%n", buffer, &s->npolys, &cnt) != 2) { debug(LOG_ERROR, "_imd_load_level(3): file corrupt"); return NULL; } pFileData += cnt; ASSERT_OR_RETURN(NULL, strcmp(buffer, "POLYGONS") == 0, "Expecting 'POLYGONS' directive, got: %s", buffer); _imd_load_polys(&pFileData, s, pieVersion); // NOW load optional stuff while (!AtEndOfFile(pFileData, FileDataEnd)) // check for end of file (give or take white space) { // Scans in the line ... if we don't get 2 parameters then quit if (sscanf(pFileData, "%255s %d%n", buffer, &n, &cnt) != 2) { break; } pFileData += cnt; if (strcmp(buffer, "LEVEL") == 0) // check for next level { debug(LOG_3D, "imd[_load_level] = npoints %d, npolys %d", s->npoints, s->npolys); s->next = _imd_load_level(&pFileData, FileDataEnd, nlevels - 1, pieVersion); } else if (strcmp(buffer, "CONNECTORS") == 0) { //load connector stuff s->nconnectors = n; _imd_load_connectors(&pFileData, s); } else { debug(LOG_ERROR, "(_load_level) unexpected directive %s %d", buffer, n); break; } } // FINALLY, massage the data into what can stream directly to OpenGL glGenBuffers(VBO_COUNT, s->buffers); vertexCount = 0; for (int k = 0; k < MAX(1, s->numFrames); k++) { // Go through all polygons for each frame for (int i = 0; i < s->npolys; i++) { const iIMDPoly *pPolys = &s->polys[i]; // Do we already have the vertex data for this polygon? indices.append(addVertex(s, 0, pPolys, k)); indices.append(addVertex(s, 1, pPolys, k)); indices.append(addVertex(s, 2, pPolys, k)); } } glBindBuffer(GL_ARRAY_BUFFER, s->buffers[VBO_VERTEX]); glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), vertices.constData(), GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, s->buffers[VBO_NORMAL]); glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(GLfloat), normals.constData(), GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->buffers[VBO_INDEX]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(uint16_t), indices.constData(), GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, s->buffers[VBO_TEXCOORD]); glBufferData(GL_ARRAY_BUFFER, texcoords.size() * sizeof(GLfloat), texcoords.constData(), GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); // unbind indices.resize(0); vertices.resize(0); texcoords.resize(0); normals.resize(0); *ppFileData = pFileData; return s; }
/*! * Load shape level polygons * \param ppFileData Pointer to the data (usualy read from a file) * \param s Pointer to shape level * \return false on error (memory allocation failure/bad file format), true otherwise * \pre ppFileData loaded * \pre s allocated * \pre s->npolys set * \post s->polys allocated (iFSDPoly * s->npolys) * \post s->pindex allocated for each poly */ static bool _imd_load_polys(const char **ppFileData, iIMDShape *s, int pieVersion) { const char *pFileData = *ppFileData; unsigned int i, j; iIMDPoly *poly; s->numFrames = 0; s->animInterval = 0; s->polys = (iIMDPoly *)malloc(sizeof(iIMDPoly) * s->npolys); if (s->polys == NULL) { debug(LOG_ERROR, "(_load_polys) Out of memory (polys)"); return false; } for (i = 0, poly = s->polys; i < s->npolys; i++, poly++) { unsigned int flags, npnts; int cnt; if (sscanf(pFileData, "%x %u%n", &flags, &npnts, &cnt) != 2) { debug(LOG_ERROR, "(_load_polys) [poly %u] error loading flags and npoints", i); } pFileData += cnt; poly->flags = flags; ASSERT_OR_RETURN(false, npnts == 3, "Invalid polygon size (%d)", npnts); if (sscanf(pFileData, "%d %d %d%n", &poly->pindex[0], &poly->pindex[1], &poly->pindex[2], &cnt) != 3) { debug(LOG_ERROR, "failed reading triangle, point %d", i); return false; } pFileData += cnt; // calc poly normal { Vector3f p0, p1, p2; //assumes points already set p0.x = s->points[poly->pindex[0]].x; p0.y = s->points[poly->pindex[0]].y; p0.z = s->points[poly->pindex[0]].z; p1.x = s->points[poly->pindex[1]].x; p1.y = s->points[poly->pindex[1]].y; p1.z = s->points[poly->pindex[1]].z; p2.x = s->points[poly->pindex[2]].x; p2.y = s->points[poly->pindex[2]].y; p2.z = s->points[poly->pindex[2]].z; poly->normal = pie_SurfaceNormal3fv(p0, p1, p2); } // texture coord routine if (poly->flags & iV_IMD_TEX) { int nFrames, framesPerLine, frame, pbRate; float tWidth, tHeight; if (poly->flags & iV_IMD_TEXANIM) { if (sscanf(pFileData, "%d %d %f %f%n", &nFrames, &pbRate, &tWidth, &tHeight, &cnt) != 4) { debug(LOG_ERROR, "(_load_polys) [poly %u] error reading texanim data", i); return false; } pFileData += cnt; ASSERT(tWidth > 0.0001f, "%s: texture width = %f", GetLastResourceFilename(), tWidth); ASSERT(tHeight > 0.f, "%s: texture height = %f (width=%f)", GetLastResourceFilename(), tHeight, tWidth); ASSERT(nFrames > 1, "%s: animation frames = %d", GetLastResourceFilename(), nFrames); ASSERT(pbRate > 0, "%s: animation interval = %d ms", GetLastResourceFilename(), pbRate); /* Must have same number of frames and same playback rate for all polygons */ if (s->numFrames == 0) { s->numFrames = nFrames; s->animInterval = pbRate; } else { ASSERT(s->numFrames == nFrames, "%s: varying number of frames within one PIE level: %d != %d", GetLastResourceFilename(), nFrames, s->numFrames); ASSERT(s->animInterval == pbRate, "%s: varying animation intervals within one PIE level: %d != %d", GetLastResourceFilename(), pbRate, s->animInterval); } poly->texAnim.x = tWidth; poly->texAnim.y = tHeight; if (pieVersion != PIE_FLOAT_VER) { poly->texAnim.x /= OLD_TEXTURE_SIZE_FIX; poly->texAnim.y /= OLD_TEXTURE_SIZE_FIX; } framesPerLine = 1 / poly->texAnim.x; } else { nFrames = 1; framesPerLine = 1; pbRate = 1; tWidth = 0.f; tHeight = 0.f; poly->texAnim.x = 0; poly->texAnim.y = 0; } poly->texCoord = (Vector2f *)malloc(sizeof(*poly->texCoord) * nFrames * 3); ASSERT_OR_RETURN(false, poly->texCoord, "Out of memory allocating texture coordinates"); for (j = 0; j < 3; j++) { float VertexU, VertexV; if (sscanf(pFileData, "%f %f%n", &VertexU, &VertexV, &cnt) != 2) { debug(LOG_ERROR, "(_load_polys) [poly %u] error reading tex outline", i); return false; } pFileData += cnt; if (pieVersion != PIE_FLOAT_VER) { VertexU /= OLD_TEXTURE_SIZE_FIX; VertexV /= OLD_TEXTURE_SIZE_FIX; } for (frame = 0; frame < nFrames; frame++) { const float uFrame = (frame % framesPerLine) * poly->texAnim.x; const float vFrame = (frame / framesPerLine) * poly->texAnim.y; Vector2f *c = &poly->texCoord[frame * 3 + j]; c->x = VertexU + uFrame; c->y = VertexV + vFrame; } } } else { ASSERT_OR_RETURN(false, !(poly->flags & iV_IMD_TEXANIM), "Polygons with texture animation must have textures!"); poly->texCoord = NULL; } } *ppFileData = pFileData; return true; }
/*! * Call the load function (registered in data.c) * for this filetype */ bool resLoadFile(const char *pType, const char *pFile) { RES_TYPE *psT; void *pData; RES_DATA *psRes; char aFileName[PATH_MAX]; UDWORD HashedName, HashedType = HashString(pType); // Find the resource-type for(psT = psResTypes; psT != NULL; psT = psT->psNext ) { if (psT->HashedType == HashedType) { ASSERT(strcmp(psT->aType, pType) == 0, "Hash collision \"%s\" vs \"%s\"", psT->aType, pType); break; } } if (psT == NULL) { debug(LOG_WZ, "resLoadFile: Unknown type: %s", pType); return false; } // Check for duplicates HashedName = HashStringIgnoreCase(pFile); for (psRes = psT->psRes; psRes; psRes = psRes->psNext) { if(psRes->HashedID == HashedName) { ASSERT(strcasecmp(psRes->aID, pFile) == 0, "Hash collision \"%s\" vs \"%s\"", psRes->aID, pFile); debug(LOG_WZ, "Duplicate file name: %s (hash %x) for type %s", pFile, HashedName, psT->aType); // assume that they are actually both the same and silently fail // lovely little hack to allow some files to be loaded from disk (believe it or not!). return true; } } // Create the file name if (strlen(aCurrResDir) + strlen(pFile) + 1 >= PATH_MAX) { debug(LOG_ERROR, "resLoadFile: Filename too long!! %s%s", aCurrResDir, pFile); return false; } sstrcpy(aFileName, aCurrResDir); sstrcat(aFileName, pFile); makeLocaleFile(aFileName, sizeof(aFileName)); // check for translated file SetLastResourceFilename(pFile); // Save the filename in case any routines need it // load the resource if (psT->buffLoad) { RESOURCEFILE *Resource; // Load the file in a buffer if (!RetreiveResourceFile(aFileName, &Resource)) { debug(LOG_ERROR, "resLoadFile: Unable to retreive resource - %s", aFileName); return false; } // Now process the buffer data if (!psT->buffLoad(Resource->pBuffer, Resource->size, &pData)) { ASSERT(false, "The load function for resource type \"%s\" failed for file \"%s\"", pType, pFile); FreeResourceFile(Resource); if (psT->release != NULL) { psT->release(pData); } return false; } FreeResourceFile(Resource); } else if(psT->fileLoad) { // Process data directly from file if (!psT->fileLoad(aFileName, &pData)) { ASSERT(false, "The load function for resource type \"%s\" failed for file \"%s\"", pType, pFile); if (psT->release != NULL) { psT->release(pData); } return false; } } else { ASSERT(false, "No load functions for this type (%s)", pType); return false; } resDoResLoadCallback(); // do callback. // Set up the resource structure if there is something to store if (pData != NULL) { // LastResourceFilename may have been changed (e.g. by TEXPAGE loading) psRes = resDataInit( GetLastResourceFilename(), HashStringIgnoreCase(GetLastResourceFilename()), pData, resBlockID ); if (!psRes) { if (psT->release != NULL) { psT->release(pData); } return false; } // Add the resource to the list psRes->psNext = psT->psRes; psT->psRes = psRes; } return true; }