#include // forward declarations struct dKPLayer_s; /****************************************************************************** * Doodads ******************************************************************************/ struct dKPDoodad_s { struct animation_s { enum LoopTypes { CONTIGUOUS, LOOP, REVERSE_LOOP }; enum CurveTypes { LINEAR, SIN, COS }; enum AnimTypes { X_POS, Y_POS, ANGLE, X_SCALE, Y_SCALE, OPACITY }; LoopTypes loop; CurveTypes curve; float frameCount; AnimTypes type; float start, end; }; float x, y; float width, height; float angle; GXTexObj *texObj; int animationCount; animation_s animations[1]; // variable size }; /****************************************************************************** * Paths ******************************************************************************/ struct dKPPath_s; struct dKPNode_s { enum NodeTypes { PASS_THROUGH, STOP, LEVEL, CHANGE }; short x, y; dKPPath_s *exits[4]; dKPLayer_s *tileLayer, *doodadLayer; int type; union { struct { u8 levelNumber[2]; }; struct { char *destMap; u8 thisID, foreignID, transition; }; }; }; struct dKPPath_s { dKPNode_s *start, *end; dKPLayer_s *tileLayer, *doodadLayer; u8 unlockType; // 0 = always, 1 = start, 2 = end u8 unlockIsSecret; float speed; int animation; }; /****************************************************************************** * Tying It All Together ******************************************************************************/ struct dKPLayer_s { enum LayerTypes { OBJECTS, DOODADS, PATHS }; LayerTypes type; typedef u16 sector_s[16][16]; union { struct { GXTexObj *tileset; union { int sectorBounds[4]; struct { int sectorLeft; int sectorTop; int sectorRight; int sectorBottom; }; }; union { int bounds[4]; struct { int left; int top; int right; int bottom; }; }; u16 indices[1]; // variable size }; struct { int doodadCount; dKPDoodad_s *doodads[1]; // variable size }; struct { int nodeCount; dKPNode_s **nodes; int pathCount; dKPPath_s **paths; }; }; }; struct dKPUnlock_s { u8 isSecret; u8 level[2]; u8 _; dKPPath_s *targetPath; }; struct dKPMapFile_s { int layerCount; dKPLayer_s **layers; int unlockCount; dKPUnlock_s *unlocks; int tilesetCount; GXTexObj *tilesets; dKPLayer_s::sector_s sectors[1]; // variable size }; class dKPMapData_c { private: dDvdLoader_c m_fileLoader; template inline T* fixRef(T*& indexAsPtr) { unsigned int index = (unsigned int)indexAsPtr; if (index == 0xFFFFFFFF) indexAsPtr = 0; else indexAsPtr = (T*)(((char*)data) + index); return indexAsPtr; } template inline T* fixRefSafe(T*& indexAsPtr) { unsigned int index = (unsigned int)indexAsPtr; if (index == 0xFFFFFFFF) indexAsPtr = 0; else if (index < 0x80000000) indexAsPtr = (T*)(((char*)data) + index); return indexAsPtr; } inline void fixTexObjSafe(GXTexObj *obj) { if (obj->dummy[3] >= 0x10000000) { obj->dummy[3] = (((u32)data) & 0x7FFFFFFF) + (obj->dummy[3] - 0x10000000); obj->dummy[3] >>= 5; } } bool fixedUp; bool tilesetsLoaded; void fixup(); bool loadTilesets(); void unloadTilesets(); public: dDvdLoader_c *tilesetLoaders; dKPMapFile_s *data; dKPLayer_s *pathLayer; dKPMapData_c(); bool load(const char *filename); ~dKPMapData_c(); };