diff --git a/doomsday/plugins/wadmapconverter/include/map.h b/doomsday/plugins/wadmapconverter/include/map.h index 0c70ba6214..5224d82564 100644 --- a/doomsday/plugins/wadmapconverter/include/map.h +++ b/doomsday/plugins/wadmapconverter/include/map.h @@ -57,6 +57,12 @@ typedef enum lumptype_e { NUM_LUMP_TYPES } lumptype_t; +typedef struct maplumpinfo_s { + lumpnum_t lumpNum; + lumptype_t lumpType; + size_t length; +} maplumpinfo_t; + typedef struct materialref_s { char name[9]; materialid_t id; // Doomsday's unique identifier for this. @@ -151,7 +157,8 @@ typedef struct mlight_s { } surfacetint_t; typedef enum { - MF_DOOM = 0, + MF_UNKNOWN = -1, + MF_DOOM = 0, MF_HEXEN, MF_DOOM64 } mapformatid_t; @@ -186,9 +193,9 @@ typedef struct map_s { extern map_t* DENG_PLUGIN_GLOBAL(map); -int IsSupportedFormat(const lumpnum_t* lumpList, int numLumps); +int IsSupportedFormat(maplumpinfo_t* lumpInfos[NUM_LUMP_TYPES]); -int LoadMap(const lumpnum_t* lumpList, int numLumps); +int LoadMap(maplumpinfo_t* lumpInfos[NUM_LUMP_TYPES]); void AnalyzeMap(void); int TransferMap(void); diff --git a/doomsday/plugins/wadmapconverter/include/maplumpinfo.h b/doomsday/plugins/wadmapconverter/include/maplumpinfo.h new file mode 100644 index 0000000000..f86a8985f9 --- /dev/null +++ b/doomsday/plugins/wadmapconverter/include/maplumpinfo.h @@ -0,0 +1,60 @@ +/** + * @file maplumpinfo.h @ingroup wadmapconverter + * + * @authors Copyright © 2007-2012 Daniel Swanson + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef __WADMAPCONVERTER_MAPLUMPINFO_H__ +#define __WADMAPCONVERTER_MAPLUMPINFO_H__ + +#include "doomsday.h" +#include "dd_types.h" + +typedef enum lumptype_e { + ML_INVALID = -1, + FIRST_LUMP_TYPE, + ML_LABEL = FIRST_LUMP_TYPE, // A separator, name, ExMx or MAPxx + ML_THINGS, // Monsters, items.. + ML_LINEDEFS, // LineDefs, from editing + ML_SIDEDEFS, // SideDefs, from editing + ML_VERTEXES, // Vertices, edited and BSP splits generated + ML_SEGS, // LineSegs, from LineDefs split by BSP + ML_SSECTORS, // Subsectors, list of LineSegs + ML_NODES, // BSP nodes + ML_SECTORS, // Sectors, from editing + ML_REJECT, // LUT, sector-sector visibility + ML_BLOCKMAP, // LUT, motion clipping, walls/grid element + ML_BEHAVIOR, // ACS Scripts (compiled). + ML_SCRIPTS, // ACS Scripts (source). + ML_LIGHTS, // Surface color tints. + ML_MACROS, // DOOM64 format, macro scripts. + ML_LEAFS, // DOOM64 format, segs (close subsectors). + ML_GLVERT, // GL vertexes + ML_GLSEGS, // GL segs + ML_GLSSECT, // GL subsectors + ML_GLNODES, // GL nodes + ML_GLPVS, // GL PVS dataset + NUM_LUMP_TYPES +} lumptype_t; + +typedef struct maplumpinfo_s { + lumpnum_t lumpNum; + lumptype_t lumpType; + size_t length; +} maplumpinfo_t; + +#endif /* __WADMAPCONVERTER_MAPLUMPINFO_H__ */ diff --git a/doomsday/plugins/wadmapconverter/src/load.cpp b/doomsday/plugins/wadmapconverter/src/load.cpp index 2cf7cf5021..29ac211ccd 100644 --- a/doomsday/plugins/wadmapconverter/src/load.cpp +++ b/doomsday/plugins/wadmapconverter/src/load.cpp @@ -515,49 +515,6 @@ static void buildReject(gamemap_t *map) } #endif -lumptype_t DataTypeForLumpName(const char* name) -{ - static const struct lumptype_s { - lumptype_t type; - const char* name; - } knownLumps[] = - { - {ML_LABEL, "*"}, - {ML_THINGS, "THINGS"}, - {ML_LINEDEFS, "LINEDEFS"}, - {ML_SIDEDEFS, "SIDEDEFS"}, - {ML_VERTEXES, "VERTEXES"}, - {ML_SEGS, "SEGS"}, - {ML_SSECTORS, "SSECTORS"}, - {ML_NODES, "NODES"}, - {ML_SECTORS, "SECTORS"}, - {ML_REJECT, "REJECT"}, - {ML_BLOCKMAP, "BLOCKMAP"}, - {ML_BEHAVIOR, "BEHAVIOR"}, - {ML_SCRIPTS, "SCRIPTS"}, - {ML_LIGHTS, "LIGHTS"}, - {ML_MACROS, "MACROS"}, - {ML_LEAFS, "LEAFS"}, - {ML_GLVERT, "GL_VERT"}, - {ML_GLSEGS, "GL_SEGS"}, - {ML_GLSSECT, "GL_SSECT"}, - {ML_GLNODES, "GL_NODES"}, - {ML_GLPVS, "GL_PVS"}, - {ML_INVALID, NULL}, - }; - - if(name && name[0]) - { - for(uint i = (uint)FIRST_LUMP_TYPE; knownLumps[i].type != ML_INVALID; ++i) - { - if(!strnicmp(knownLumps[i].name, name, strlen(knownLumps[i].name))) - return knownLumps[i].type; - } - } - - return ML_INVALID; -} - /** * Create a temporary polyobj (read from the original map data). */ @@ -838,92 +795,92 @@ void AnalyzeMap(void) } } -int IsSupportedFormat(const lumpnum_t* lumpList, int numLumps) +int IsSupportedFormat(maplumpinfo_t* lumpInfos[NUM_LUMP_TYPES]) { - boolean supported = false; + DENG_ASSERT(lumpInfos); - // Lets first check for format specific lumps, as their prescense - // determines the format of the map data. Assume DOOM format by default. + bool recognised = false; + // Assume DOOM format by default. map->format = MF_DOOM; - for(int i = 0; i < numLumps; ++i) - { - const char* lumpName = W_LumpName(lumpList[i]); - if(!lumpName || !lumpName[0]) - continue; + // Check for format specific lumps. + for(uint i = 0; i < (uint)NUM_LUMP_TYPES; ++i) + { + const maplumpinfo_t* info = lumpInfos[i]; + if(!info) continue; - if(!strncmp(lumpName, "BEHAVIOR", 8)) + switch(info->lumpType) { - map->format = MF_HEXEN; - break; - } + case ML_BEHAVIOR: map->format = MF_HEXEN; break; - if(!strncmp(lumpName, "MACROS", 6) || - !strncmp(lumpName, "LIGHTS", 6) || - !strncmp(lumpName, "LEAFS", 5)) - { - map->format = MF_DOOM64; - break; + case ML_MACROS: + case ML_LIGHTS: + case ML_LEAFS: map->format = MF_DOOM64; break; + + default: break; } } - for(int i = 0; i < numLumps; ++i) + for(uint i = 0; i < (uint)NUM_LUMP_TYPES; ++i) { - const char* lumpName = W_LumpName(lumpList[i]); - size_t elmSize = 0; // Num of bytes. + const maplumpinfo_t* info = lumpInfos[i]; + if(!info) continue; // Determine the number of map data objects of each data type. - uint* ptr = NULL; - switch(DataTypeForLumpName(lumpName)) + uint* elmCountAddr = NULL; + size_t elmSize = 0; // Num of bytes. + switch(info->lumpType) { case ML_VERTEXES: - ptr = &map->numVertexes; + elmCountAddr = &map->numVertexes; elmSize = (map->format == MF_DOOM64? SIZEOF_64VERTEX : SIZEOF_VERTEX); break; case ML_THINGS: - ptr = &map->numThings; + elmCountAddr = &map->numThings; elmSize = (map->format == MF_DOOM64? SIZEOF_64THING : map->format == MF_HEXEN? SIZEOF_XTHING : SIZEOF_THING); break; case ML_LINEDEFS: - ptr = &map->numLines; + elmCountAddr = &map->numLines; elmSize = (map->format == MF_DOOM64? SIZEOF_64LINEDEF : map->format == MF_HEXEN? SIZEOF_XLINEDEF : SIZEOF_LINEDEF); break; case ML_SIDEDEFS: - ptr = &map->numSides; + elmCountAddr = &map->numSides; elmSize = (map->format == MF_DOOM64? SIZEOF_64SIDEDEF : SIZEOF_SIDEDEF); break; case ML_SECTORS: - ptr = &map->numSectors; + elmCountAddr = &map->numSectors; elmSize = (map->format == MF_DOOM64? SIZEOF_64SECTOR : SIZEOF_SECTOR); break; case ML_LIGHTS: - ptr = &map->numLights; + elmCountAddr = &map->numLights; elmSize = SIZEOF_LIGHT; break; default: break; } - if(ptr) + if(elmCountAddr) { - size_t lumpLength = W_LumpLength(lumpList[i]); - if(0 != lumpLength % elmSize) + if(0 != info->length % elmSize) + { return false; // What is this?? - *ptr += lumpLength / elmSize; + } + + *elmCountAddr += info->length / elmSize; } } if(map->numVertexes > 0 && map->numLines > 0 && map->numSides > 0 && map->numSectors > 0) { - supported = true; + recognised = true; } - return supported; + return (int)recognised; } static void freeMapData(void) @@ -1638,8 +1595,10 @@ static void bufferLump(lumpnum_t lumpNum, uint8_t** buf, size_t* len, size_t* ol W_ReadLump(lumpNum, *buf); } -int LoadMap(const lumpnum_t* lumpList, int numLumps) +int LoadMap(maplumpinfo_t* lumpInfos[NUM_LUMP_TYPES]) { + DENG_ASSERT(lumpInfos); + VERBOSE( Con_Message("WadMapConverter: Recognised a %s format map.\n", (map->format == MF_DOOM64? "DOOM64" : map->format == MF_HEXEN? "Hexen" : "DOOM")) ); @@ -1656,38 +1615,40 @@ int LoadMap(const lumpnum_t* lumpList, int numLumps) uint8_t* buf = NULL; size_t oldLen = 0; - for(int i = 0; i < numLumps; ++i) + for(uint i = 0; i < (uint)NUM_LUMP_TYPES; ++i) { - lumptype_t lumpType = DataTypeForLumpName(W_LumpName(lumpList[i])); + const maplumpinfo_t* info = lumpInfos[i]; size_t len; + if(!info) continue; + // Process it, transforming it into our local representation. - switch(lumpType) + switch(info->lumpType) { case ML_VERTEXES: - bufferLump(lumpList[i], &buf, &len, &oldLen); + bufferLump(info->lumpNum, &buf, &len, &oldLen); loadVertexes(buf, len); break; case ML_LINEDEFS: - bufferLump(lumpList[i], &buf, &len, &oldLen); + bufferLump(info->lumpNum, &buf, &len, &oldLen); loadLinedefs(buf, len); break; case ML_SIDEDEFS: - bufferLump(lumpList[i], &buf, &len, &oldLen); + bufferLump(info->lumpNum, &buf, &len, &oldLen); loadSidedefs(buf, len); break; case ML_SECTORS: - bufferLump(lumpList[i], &buf, &len, &oldLen); + bufferLump(info->lumpNum, &buf, &len, &oldLen); loadSectors(buf, len); break; case ML_THINGS: if(map->numThings) { - bufferLump(lumpList[i], &buf, &len, &oldLen); + bufferLump(info->lumpNum, &buf, &len, &oldLen); loadThings(buf, len); } break; @@ -1695,13 +1656,13 @@ int LoadMap(const lumpnum_t* lumpList, int numLumps) case ML_LIGHTS: if(map->numLights) { - bufferLump(lumpList[i], &buf, &len, &oldLen); + bufferLump(info->lumpNum, &buf, &len, &oldLen); loadLights(buf, len); } break; case ML_MACROS: - //// \todo Write me! + /// @todo Write me! break; default: break; diff --git a/doomsday/plugins/wadmapconverter/src/wadmapconverter.cpp b/doomsday/plugins/wadmapconverter/src/wadmapconverter.cpp index bb25a5204a..ff29f747cb 100644 --- a/doomsday/plugins/wadmapconverter/src/wadmapconverter.cpp +++ b/doomsday/plugins/wadmapconverter/src/wadmapconverter.cpp @@ -27,145 +27,78 @@ #include #include "map.h" -typedef struct maplumpformat_s { - int hversion; - char* formatName; - int lumpClass; -} maplumpformat_t; - -typedef struct maplumpinfo_s { - lumpnum_t lumpNum; - maplumpformat_t* format; - int lumpClass; - size_t startOffset; - uint elements; - size_t length; -} maplumpinfo_t; - -typedef struct listnode_s { - void* data; - struct listnode_s* next; -} listnode_t; - map_t DENG_PLUGIN_GLOBAL(theMap); map_t* DENG_PLUGIN_GLOBAL(map) = &DENG_PLUGIN_GLOBAL(theMap); int DENG_PLUGIN_GLOBAL(verbose); -static int mapLumpTypeForName(const char* name) +static void configure(void) +{ + DENG_PLUGIN_GLOBAL(verbose) = CommandLine_Exists("-verbose"); +} + +static lumptype_t mapLumpTypeForName(const char* name) { static const struct maplumpinfo_s { - int type; const char* name; - } mapLumpInfos[] = + lumptype_t type; + } lumptypeForNameDict[] = { - { ML_THINGS, "THINGS" }, - { ML_LINEDEFS, "LINEDEFS" }, - { ML_SIDEDEFS, "SIDEDEFS" }, - { ML_VERTEXES, "VERTEXES" }, - { ML_SEGS, "SEGS" }, - { ML_SSECTORS, "SSECTORS" }, - { ML_NODES, "NODES" }, - { ML_SECTORS, "SECTORS" }, - { ML_REJECT, "REJECT" }, - { ML_BLOCKMAP, "BLOCKMAP" }, - { ML_BEHAVIOR, "BEHAVIOR" }, - { ML_SCRIPTS, "SCRIPTS" }, - { ML_LIGHTS, "LIGHTS" }, - { ML_MACROS, "MACROS" }, - { ML_LEAFS, "LEAFS" }, - { ML_INVALID, NULL } + { "THINGS", ML_THINGS }, + { "LINEDEFS", ML_LINEDEFS }, + { "SIDEDEFS", ML_SIDEDEFS }, + { "VERTEXES", ML_VERTEXES }, + { "SEGS", ML_SEGS }, + { "SSECTORS", ML_SSECTORS }, + { "NODES", ML_NODES }, + { "SECTORS", ML_SECTORS }, + { "REJECT", ML_REJECT }, + { "BLOCKMAP", ML_BLOCKMAP }, + { "BEHAVIOR", ML_BEHAVIOR }, + { "SCRIPTS", ML_SCRIPTS }, + { "LIGHTS", ML_LIGHTS }, + { "MACROS", ML_MACROS }, + { "LEAFS", ML_LEAFS }, + { "GL_VERT", ML_GLVERT }, + { "GL_SEGS", ML_GLSEGS }, + { "GL_SSECT", ML_GLSSECT }, + { "GL_NODES", ML_GLNODES }, + { "GL_PVS", ML_GLPVS}, + { NULL } }; - if(!name) return ML_INVALID; + DENG_ASSERT(name); - for(int i = 0; mapLumpInfos[i].type > ML_INVALID; ++i) + if(name[0]) + for(int i = 0; lumptypeForNameDict[i].name; ++i) { - if(!strnicmp(mapLumpInfos[i].name, name, strlen(mapLumpInfos[i].name))) - return mapLumpInfos[i].type; + if(!strnicmp(lumptypeForNameDict[i].name, name, strlen(lumptypeForNameDict[i].name))) + return lumptypeForNameDict[i].type; } return ML_INVALID; } -/** - * Allocate a new list node. - */ -static listnode_t* allocListNode(void) -{ - listnode_t* node = static_cast(Z_Calloc(sizeof(listnode_t), PU_APPSTATIC, 0)); - return node; -} - -/** - * Free all memory acquired for the given list node. - */ -static void freeListNode(listnode_t* node) -{ - if(!node) return; - Z_Free(node); -} - -/** - * Allocate memory for a new map lump info record. - */ -static maplumpinfo_t* allocMapLumpInfo(void) -{ - maplumpinfo_t* info = static_cast(Z_Calloc(sizeof(maplumpinfo_t), PU_APPSTATIC, 0)); - return info; -} - -/** - * Free all memory acquired for the given map lump info record. - */ -static void freeMapLumpInfo(maplumpinfo_t* info) -{ - if(!info) return; - Z_Free(info); -} - -/** - * Free a list of maplumpinfo records. - */ -static void freeMapLumpInfoList(listnode_t* headPtr) -{ - listnode_t* node = headPtr; - while(node) - { - listnode_t* np = node->next; - - if(node->data) - freeMapLumpInfo(reinterpret_cast(node->data)); - freeListNode(node); - - node = np; - } -} - /** * Create a new map lump info record. */ -static maplumpinfo_t* createMapLumpInfo(lumpnum_t lumpNum, int lumpClass) +static maplumpinfo_t* createMapLumpInfo(lumpnum_t lumpNum, lumptype_t lumpType) { - maplumpinfo_t* info = allocMapLumpInfo(); + maplumpinfo_t* info = static_cast(calloc(1, sizeof(*info))); info->lumpNum = lumpNum; - info->lumpClass = lumpClass; + info->lumpType = lumpType; info->length = W_LumpLength(lumpNum); - info->format = NULL; - info->startOffset = 0; return info; } /** - * Link a maplumpinfo record to an archivedmap record. + * Free all memory acquired for the given map lump info record. */ -static void addLumpInfoToList(listnode_t** headPtr, maplumpinfo_t* info) +static void freeMapLumpInfo(maplumpinfo_t* info) { - listnode_t* node = allocListNode(); - node->data = info; - node->next = *headPtr; - *headPtr = node; + if(!info) return; + free(info); } /** @@ -177,41 +110,43 @@ static void addLumpInfoToList(listnode_t** headPtr, maplumpinfo_t* info) * * @param headPtr The list to link the created maplump records to. * @param startLump The lump number to begin our search with. - * - * @return The number of collected lumps. */ -static uint collectMapLumps(listnode_t** headPtr, lumpnum_t startLump) +static void collectMapLumps(maplumpinfo_t* lumpInfos[NUM_LUMP_TYPES], lumpnum_t startLump) { - WADMAPCONVERTER_TRACE("collectMapLumps: Locating lumps..."); + DENG_ASSERT(lumpInfos); + + WADMAPCONVERTER_TRACE("Locating data lumps..."); const int numLumps = *reinterpret_cast(DD_GetVariable(DD_NUMLUMPS)); - uint numCollectedLumps = 0; + if(startLump < 0 || startLump >= numLumps) return; - if(startLump > 0 && startLump < numLumps) + // Keep checking lumps to see if its a map data lump. + for(lumpnum_t i = startLump; i < numLumps; ++i) { - // Keep checking lumps to see if its a map data lump. - for(lumpnum_t i = startLump; i < numLumps; ++i) - { - // Lookup the lump name in our list of known map lump names. - const char* lumpName = W_LumpName(i); - int lumpType = mapLumpTypeForName(lumpName); - - if(lumpType != ML_INVALID) - { - // Its a known map lump. - maplumpinfo_t* info = createMapLumpInfo(i, lumpType); - - addLumpInfoToList(headPtr, info); - numCollectedLumps += 1; - continue; - } + // Lookup the lump name in our list of known map lump names. + const char* lumpName = W_LumpName(i); + lumptype_t lumpType = mapLumpTypeForName(lumpName); + if(lumpType == ML_INVALID) + { // Stop looking, we *should* have found them all. break; } + + // A recognised map data lump; record it in the collection. + if(lumpInfos[lumpType]) + { + freeMapLumpInfo(lumpInfos[lumpType]); + } + lumpInfos[lumpType] = createMapLumpInfo(i, lumpType); } +} - return numCollectedLumps; +static lumpnum_t locateMapDataMarkerLumpForUri(const Uri* uri) +{ + DENG_ASSERT(uri); + const char* mapId = Str_Text(Uri_Path(uri)); + return W_CheckLumpNumForName2(mapId, true /*quiet please*/); } /** @@ -223,57 +158,31 @@ static uint collectMapLumps(listnode_t** headPtr, lumpnum_t startLump) */ int ConvertMapHook(int hookType, int parm, void* context) { - int ret_val = true; // Assume success. - DENG_UNUSED(hookType); DENG_UNUSED(parm); - DENG_PLUGIN_GLOBAL(verbose) = CommandLine_Exists("-verbose"); + // Setup the processing parameters. + configure(); - const Uri* uri = reinterpret_cast(context); - const char* mapId = Str_Text(Uri_Path(uri)); - lumpnum_t markerLump; + // Begin the conversion attempt. + int ret_val = true; // Assume success. - markerLump = W_CheckLumpNumForName2(mapId, true /*quiet please*/); + // Attempt to locate the identified map data marker lump. + const Uri* uri = reinterpret_cast(context); + lumpnum_t markerLump = locateMapDataMarkerLumpForUri(uri); if(0 > markerLump) { ret_val = false; goto FAIL_LOCATE_MAP; } - // Add the marker lump to the list of lumps for this map. - listnode_t* sourceLumpListHead = NULL; - addLumpInfoToList(&sourceLumpListHead, createMapLumpInfo(markerLump, ML_LABEL)); - - // Find the rest of the map data lumps associated with this map. - collectMapLumps(&sourceLumpListHead, markerLump + 1); - - // Count the number of source data lumps. - uint lumpListSize = 0; - listnode_t* node = sourceLumpListHead; - while(node) - { - ++lumpListSize; - node = node->next; - } - - // Allocate and populate the source data lump list. - lumpnum_t* lumpList = static_cast(Z_Malloc(sizeof(*lumpList) * lumpListSize, PU_APPSTATIC, 0)); - if(!lumpList) - Con_Error("WadMapConverter: Failed on allocation of %lu bytes for lump list.", - (unsigned long) (sizeof(*lumpList) * lumpListSize)); - - node = sourceLumpListHead; - uint idx = 0; - while(node) - { - maplumpinfo_t* info = reinterpret_cast(node->data); - lumpList[idx++] = info->lumpNum; - node = node->next; - } + // Collect all of the map data lumps associated with this map. + maplumpinfo_t* lumpInfos[NUM_LUMP_TYPES]; + memset(lumpInfos, 0, sizeof(lumpInfos)); + collectMapLumps(lumpInfos, markerLump + 1 /*begin after the marker*/); memset(DENG_PLUGIN_GLOBAL(map), 0, sizeof(*DENG_PLUGIN_GLOBAL(map))); - if(!IsSupportedFormat(lumpList, lumpListSize)) + if(!IsSupportedFormat(lumpInfos)) { Con_Message("WadMapConverter: Unknown map format, aborting.\n"); ret_val = false; @@ -281,7 +190,7 @@ int ConvertMapHook(int hookType, int parm, void* context) } // Read the archived map. - int loadError = !LoadMap(lumpList, lumpListSize); + int loadError = !LoadMap(lumpInfos); if(loadError) { Con_Message("WadMapConverter: Internal error, load failed.\n"); @@ -298,9 +207,12 @@ int ConvertMapHook(int hookType, int parm, void* context) // Cleanup. FAIL_LOAD_ERROR: FAIL_UNKNOWN_FORMAT: - sourceLumpListHead; - freeMapLumpInfoList(sourceLumpListHead); - Z_Free(lumpList); + for(uint i = 0; i < (uint)NUM_LUMP_TYPES; ++i) + { + maplumpinfo_t* info = lumpInfos[i]; + if(!info) continue; + freeMapLumpInfo(info); + } FAIL_LOCATE_MAP: