diff options
-rw-r--r-- | koopatlas.yaml | 2 | ||||
-rw-r--r-- | src/koopatlas/camera.cpp | 63 | ||||
-rw-r--r-- | src/koopatlas/camera.h | 4 | ||||
-rw-r--r-- | src/koopatlas/core.cpp | 55 | ||||
-rw-r--r-- | src/koopatlas/core.h | 8 | ||||
-rw-r--r-- | src/koopatlas/hud.cpp | 23 | ||||
-rw-r--r-- | src/koopatlas/hud.h | 5 | ||||
-rw-r--r-- | src/koopatlas/map.cpp | 2 | ||||
-rw-r--r-- | src/koopatlas/map.h | 5 | ||||
-rw-r--r-- | src/koopatlas/mapdata.cpp | 35 | ||||
-rw-r--r-- | src/koopatlas/mapdata.h | 34 | ||||
-rw-r--r-- | src/koopatlas/pathmanager.cpp | 130 | ||||
-rw-r--r-- | src/koopatlas/pathmanager.h | 29 | ||||
-rw-r--r-- | src/koopatlas/player.h | 4 | ||||
-rw-r--r-- | src/levelinfo.cpp | 37 | ||||
-rw-r--r-- | src/levelinfo.h | 56 |
16 files changed, 414 insertions, 78 deletions
diff --git a/koopatlas.yaml b/koopatlas.yaml index 9c4af7b..37c4a3d 100644 --- a/koopatlas.yaml +++ b/koopatlas.yaml @@ -3,6 +3,7 @@ source_files: - ../src/fileload.cpp - ../src/scene.S - ../src/levelinfo.cpp + - ../src/levelinfo_old.cpp # backwards compatibility for LevelNames - ../src/player.cpp - ../src/effects.cpp - ../src/koopatlas/core.cpp @@ -11,6 +12,7 @@ source_files: - ../src/koopatlas/camera.cpp - ../src/koopatlas/map.cpp - ../src/koopatlas/mapdata.cpp + - ../src/koopatlas/pathmanager.cpp hooks: - name: BuildWorldMap diff --git a/src/koopatlas/camera.cpp b/src/koopatlas/camera.cpp index bfcc674..9efbcd6 100644 --- a/src/koopatlas/camera.cpp +++ b/src/koopatlas/camera.cpp @@ -31,8 +31,8 @@ dWorldCamera_c::dWorldCamera_c() { projection2d.near = 1.0; projection2d.far = 20000.0; - currentX = 0; - currentY = 0; + currentX = 416; + currentY = -224; zoomLevel = 2.0f; } @@ -68,34 +68,37 @@ int dWorldCamera_c::onDelete() { int dWorldCamera_c::onExecute() { - int nowPressed = Remocon_GetPressed(GetActiveRemocon()); - bool change = false; - if (nowPressed & WPAD_LEFT) { - currentX -= 16; - change = true; - } - if (nowPressed & WPAD_RIGHT) { - currentX += 16; - change = true; - } - if (nowPressed & WPAD_UP) { - currentY += 16; - change = true; - } - if (nowPressed & WPAD_DOWN) { - currentY -= 16; - change = true; - } - if (nowPressed & WPAD_B) { - zoomLevel -= 0.02; - change = true; - } - if (nowPressed & WPAD_A) { - zoomLevel += 0.02; - change = true; - } - if (change) { - OSReport("%f, %f (%f)\n", currentX, currentY, zoomLevel); + int heldButtons = Remocon_GetButtons(GetActiveRemocon()); + if (heldButtons & WPAD_MINUS) { + int nowPressed = Remocon_GetPressed(GetActiveRemocon()); + bool change = false; + if (nowPressed & WPAD_LEFT) { + currentX -= 16; + change = true; + } + if (nowPressed & WPAD_RIGHT) { + currentX += 16; + change = true; + } + if (nowPressed & WPAD_UP) { + currentY += 16; + change = true; + } + if (nowPressed & WPAD_DOWN) { + currentY -= 16; + change = true; + } + if (nowPressed & WPAD_B) { + zoomLevel -= 0.02; + change = true; + } + if (nowPressed & WPAD_A) { + zoomLevel += 0.02; + change = true; + } + if (change) { + OSReport("%f, %f (%f)\n", currentX, currentY, zoomLevel); + } } calculateScreenGeometry(); doStuff(10000.0); diff --git a/src/koopatlas/camera.h b/src/koopatlas/camera.h index f057374..39e34d0 100644 --- a/src/koopatlas/camera.h +++ b/src/koopatlas/camera.h @@ -1,3 +1,6 @@ +#ifndef __KOOPATLAS_CAMERA_H +#define __KOOPATLAS_CAMERA_H + #include "koopatlas/core.h" class dWorldCamera_c : public dBase_c { @@ -34,4 +37,5 @@ class dWorldCamera_c : public dBase_c { static dWorldCamera_c *instance; }; +#endif diff --git a/src/koopatlas/core.cpp b/src/koopatlas/core.cpp index fb1e865..03b64dc 100644 --- a/src/koopatlas/core.cpp +++ b/src/koopatlas/core.cpp @@ -158,10 +158,9 @@ bool WMInit_LoadResources(void *ptr) { SpammyReport("WMInit_LoadResources returning true\n"); dScKoopatlas_c *wm = (dScKoopatlas_c*)ptr; - return wm->mapData.load("/Maps/yat.kpbin"); - //TODO - //return wm->resMng.loadSet("MMFullWorld"); - //return true; + return + wm->mapData.load("/Maps/yat.kpbin") && + wm->levelInfoLoader.load("/NewerRes/LevelInfo.bin"); } bool WMInit_SetupWait(void *ptr) { @@ -203,21 +202,24 @@ bool WMInit_SetupExtra(void *ptr) { } // since we've got all the resources, set up the path data too - //wm->pathManager->setup(); - //wm->pathManager->computeEvents(); + SpammyReport("preparing level info\n"); + wm->levelInfo.load(wm->levelInfoLoader.buffer); + wm->pathManager.setup(); // and now Player setup wm->player = (daWMPlayer_c*)CreateParentedObject(WM_PLAYER, wm, 0, 2); wm->player->modelHandler->mdlClass->setPowerup(2); wm->player->modelHandler->mdlClass->startAnimation(0, 1.2f, 10.0f, 0.0f); - //wm->player->pos = wm->pathManager->currentPoint->position; + + dKPNode_s *cNode = wm->pathManager.currentNode; + wm->player->pos = (Vec){cNode->x, -cNode->y, wm->player->pos.y}; // is last param correct? must check :/ wm->map = (dWMMap_c*)CreateParentedObject(WM_MAP, wm, 0, 0); wm->hud = (dWMHud_c*)CreateParentedObject(WM_HUD, wm, 0, 0); - // note: world_camera and wm_path_manager are not created here - // because we require them earlier - // they are created in dScKoopatlas_c::onCreate + // note: world_camera is not created here + // because we require it earlier + // it is created in dScKoopatlas_c::onCreate return true; } @@ -334,8 +336,6 @@ int dScKoopatlas_c::onCreate() { SpammyReport("world camera\n"); CreateParentedObject(WORLD_CAMERA, this, 0, 0); - /*pathManager = (dWMPathManager_c*)CreateParentedObject(WM_PATH_MANAGER, this, 0, 0);*/ - SpammyReport("setting NewerMapDrawFunc\n"); *CurrentDrawFunc = NewerMapDrawFunc; @@ -411,6 +411,8 @@ void dScKoopatlas_c::executeState_Normal() { CSMENU_ACTIVE(this->csMenu) = true; state.setState(&StateID_CSMenu); } + + pathManager.execute(); } void dScKoopatlas_c::executeState_CSMenu() { @@ -798,6 +800,35 @@ void dScKoopatlas_c::executeState_QuickSaveEndCloseWait() { void dScKoopatlas_c::executeState_SaveError() { } +void dScKoopatlas_c::startLevel(dLevelInfo_c::entry_s *entry) { + for (int i = 0; i < 4; i++) { + bool isThere = QueryPlayerAvailability(i); + int id = Player_ID[i]; + Player_Active[i] = isThere ? 1 : 0; + if (!isThere) Player_Flags[i] = 0; + } + + StartLevelInfo sl; + sl.unk1 = 0; + sl.unk2 = 0xFF; + sl.unk3 = 0; + sl.unk4 = 0; + sl.purpose = 0; + + sl.world1 = entry->world; + sl.world2 = entry->world; + sl.level1 = entry->level; + sl.level2 = entry->level; + + // hopefully this will fix the Star Coin issues + SetSomeConditionShit(entry->world, entry->level, 2); + + ActivateWipe(WIPE_MARIO); + + DoStartLevel(GetGameMgr(), &sl); +} + + void NewerMapDrawFunc() { Reset3DState(); SetCurrentCameraID(0); diff --git a/src/koopatlas/core.h b/src/koopatlas/core.h index cfe5bde..9ca1935 100644 --- a/src/koopatlas/core.h +++ b/src/koopatlas/core.h @@ -9,7 +9,9 @@ #include <game.h> #include <g3dhax.h> +#include "levelinfo.h" #include "koopatlas/mapdata.h" +#include "koopatlas/pathmanager.h" #define WM_DEBUGGING //#define WM_SPAMMY_DEBUGGING @@ -89,8 +91,14 @@ class dScKoopatlas_c : public dScene_c { daWMPlayer_c *player; dWMHud_c *hud; dWMMap_c *map; + dKPMapData_c mapData; + dWMPathManager_c pathManager; + + dDvdLoader_c levelInfoLoader; + dLevelInfo_c levelInfo; + void startLevel(dLevelInfo_c::entry_s *level); bool canDoStuff(); }; diff --git a/src/koopatlas/hud.cpp b/src/koopatlas/hud.cpp index c5b2c6e..183e85f 100644 --- a/src/koopatlas/hud.cpp +++ b/src/koopatlas/hud.cpp @@ -95,13 +95,14 @@ void dWMHud_c::setPointName() { int length; // figure this out... - /*WMPathPoint *point = dWMPathManager_c::instance->currentPoint; + dKPNode_s *node = dScKoopatlas_c::instance->pathManager.currentNode; - if (point->type == WMPathPoint::LEVEL_TYPE) { - LevelInfo *li = &dScNewerWorldMap_c::instance->levelInfo; - LevelInfo::Entry *entry = li->search(point->params[0] - 1, point->params[1] - 1); + if (node->type == dKPNode_s::LEVEL) { + OSReport("Trying level %d-%d\n", node->levelNumber[0], node->levelNumber[1]); + dLevelInfo_c *li = &dScKoopatlas_c::instance->levelInfo; + dLevelInfo_c::entry_s *entry = li->search(node->levelNumber[0] - 1, node->levelNumber[1] - 1); - char *levelName = li->getNameForLevel(entry); + const char *levelName = li->getNameForLevel(entry); // copy it // I need to make this into a function. @@ -114,13 +115,7 @@ void dWMHud_c::setPointName() { } else { newPointName[0] = 0; length = 0; - }*/ - - const char *str = "This needs to be done\0"; - length = 21; - for (int i = 0; i < length; i++) - newPointName[i] = str[i]; - newPointName[length] = 0; + } nw4r::lyt::TextBox *box = layout.findTextBoxByName("T_levelname_01"); @@ -144,9 +139,9 @@ void dWMHud_c::setPointName() { void dWMHud_c::showPointBar() { - //WMPathPoint *point = dWMPathManager_c::instance->currentPoint; + dKPNode_s *node = dScKoopatlas_c::instance->pathManager.currentNode; - if (true) {//point->type == WMPathPoint::LEVEL_TYPE) { + if (node->type == dKPNode_s::LEVEL) { isPointBarShown = true; updateText(); diff --git a/src/koopatlas/hud.h b/src/koopatlas/hud.h index 71dacdd..1ef94ce 100644 --- a/src/koopatlas/hud.h +++ b/src/koopatlas/hud.h @@ -1,3 +1,6 @@ +#ifndef __KOOPATLAS_HUD_H +#define __KOOPATLAS_HUD_H + #include "koopatlas/core.h" class dWMHud_c : public dBase_c { @@ -26,3 +29,5 @@ class dWMHud_c : public dBase_c { bool isPointBarShown; }; +#endif + diff --git a/src/koopatlas/map.cpp b/src/koopatlas/map.cpp index 35aadab..ac7cc51 100644 --- a/src/koopatlas/map.cpp +++ b/src/koopatlas/map.cpp @@ -81,7 +81,7 @@ void dWMMap_c::renderer_c::drawLayers() { dKPMapData_c *dataCls = &dScKoopatlas_c::instance->mapData; dKPMapFile_s *data = dataCls->data; - baseZ = -(2 * data->layerCount); + baseZ = -100 - (2 * data->layerCount); beginRendering(); diff --git a/src/koopatlas/map.h b/src/koopatlas/map.h index 2e7b7b6..c74384f 100644 --- a/src/koopatlas/map.h +++ b/src/koopatlas/map.h @@ -1,3 +1,6 @@ +#ifndef __KOOPATLAS_MAP_H +#define __KOOPATLAS_MAP_H + #include "koopatlas/core.h" // Can't remember why I had this. Who cares @@ -60,3 +63,5 @@ class dWMMap_c : public dBase_c { static dWMMap_c *instance; }; +#endif + diff --git a/src/koopatlas/mapdata.cpp b/src/koopatlas/mapdata.cpp index 37565ea..a6031b1 100644 --- a/src/koopatlas/mapdata.cpp +++ b/src/koopatlas/mapdata.cpp @@ -1,6 +1,31 @@ #include "koopatlas/mapdata.h" +// HELPER FUNCTIONS +dKPPath_s *dKPNode_s::getOppositeExitTo(dKPPath_s *path) { + for (int i = 0; i < 4; i++) { + dKPPath_s *check = exits[i]; + + if (check != 0 && check != path) + return check; + } + + return 0; +} + + +int dKPLayer_s::findNodeID(dKPNode_s *node) { + for (int i = 0; i < nodeCount; i++) + if (nodes[i] == node) + return i; + + return -1; +} + + + + + dKPMapData_c::dKPMapData_c() { data = 0; fixedUp = false; @@ -83,6 +108,8 @@ void dKPMapData_c::fixup() { break; case dKPLayer_s::PATHS: + pathLayer = layer; + fixRef(layer->paths); fixRef(layer->nodes); @@ -112,14 +139,6 @@ void dKPMapData_c::fixup() { } } - fixRef(data->unlocks); - - for (int iUnlock = 0; iUnlock < data->unlockCount; iUnlock++) { - dKPUnlock_s *unlock = &data->unlocks[iUnlock]; - - fixRef(unlock->targetPath); - } - fixRef(data->tilesets); } diff --git a/src/koopatlas/mapdata.h b/src/koopatlas/mapdata.h index b6d1838..f9aa545 100644 --- a/src/koopatlas/mapdata.h +++ b/src/koopatlas/mapdata.h @@ -1,3 +1,6 @@ +#ifndef __KOOPATLAS_MAPDATA_H +#define __KOOPATLAS_MAPDATA_H + #include <game.h> // forward declarations @@ -50,22 +53,34 @@ struct dKPNode_s { }; short x, y; - dKPPath_s *exits[4]; + union { + dKPPath_s *exits[4]; + struct { + dKPPath_s *leftExit; + dKPPath_s *rightExit; + dKPPath_s *upExit; + dKPPath_s *downExit; + }; + }; dKPLayer_s *tileLayer, *doodadLayer; - int type; + NodeTypes type; union { struct { u8 levelNumber[2]; }; struct { char *destMap; u8 thisID, foreignID, transition; }; }; + + + dKPPath_s *getOppositeExitTo(dKPPath_s *path); }; struct dKPPath_s { dKPNode_s *start, *end; dKPLayer_s *tileLayer, *doodadLayer; - u8 unlockType; // 0 = always, 1 = start, 2 = end - u8 unlockIsSecret; + u8 unlockType; // 0 = always, 1 = normal, 2 = secret + u8 unlockLevelNumber[2]; + bool isAvailable; // computed on-the-fly - default from Koopatlas is true float speed; int animation; }; @@ -118,23 +133,15 @@ struct dKPLayer_s { dKPPath_s **paths; }; }; -}; -struct dKPUnlock_s { - u8 isSecret; - u8 level[2]; - u8 _; - dKPPath_s *targetPath; + int findNodeID(dKPNode_s *node); }; struct dKPMapFile_s { int layerCount; dKPLayer_s **layers; - int unlockCount; - dKPUnlock_s *unlocks; - int tilesetCount; GXTexObj *tilesets; @@ -191,4 +198,5 @@ class dKPMapData_c { ~dKPMapData_c(); }; +#endif diff --git a/src/koopatlas/pathmanager.cpp b/src/koopatlas/pathmanager.cpp new file mode 100644 index 0000000..30f4920 --- /dev/null +++ b/src/koopatlas/pathmanager.cpp @@ -0,0 +1,130 @@ +#include "koopatlas/pathmanager.h" +#include "koopatlas/core.h" +#include "koopatlas/hud.h" +#include "koopatlas/player.h" + +void dWMPathManager_c::setup() { + isMoving = false; + currentPath = 0; + reverseThroughPath = false; + + pathLayer = dScKoopatlas_c::instance->mapData.pathLayer; + + SaveBlock *save = GetSaveFile()->GetBlock(-1); + if (save->current_path_node >= pathLayer->nodeCount) { + currentNode = pathLayer->nodes[0]; + } else { + currentNode = pathLayer->nodes[save->current_path_node]; + } + + // unlock all needed paths + for (int i = 0; i < pathLayer->pathCount; i++) { + dKPPath_s *path = pathLayer->paths[i]; + + if (path->unlockType > 0) { + u32 conds = save->GetLevelCondition(path->unlockLevelNumber[0] - 1, path->unlockLevelNumber[1] - 1); + + if (path->unlockType == 1 && (conds & COND_NORMAL)) + path->isAvailable = true; + else if (path->unlockType == 2 && (conds & COND_SECRET)) + path->isAvailable = true; + } + } +} + + +void dWMPathManager_c::execute() { + int nowPressed = Remocon_GetPressed(GetActiveRemocon()); + + if (isMoving) { + moveThroughPath(); + } else { + if (nowPressed & WPAD_LEFT && canUseExit(currentNode->leftExit)) + startMovementTo(currentNode->leftExit); + else if (nowPressed & WPAD_RIGHT && canUseExit(currentNode->rightExit)) + startMovementTo(currentNode->rightExit); + else if (nowPressed & WPAD_UP && canUseExit(currentNode->upExit)) + startMovementTo(currentNode->upExit); + else if (nowPressed & WPAD_DOWN && canUseExit(currentNode->downExit)) + startMovementTo(currentNode->downExit); + else if (nowPressed & WPAD_TWO) + activatePoint(); + } +} + + +void dWMPathManager_c::startMovementTo(dKPPath_s *path) { + dWMHud_c::instance->hidePointBar(); + + isMoving = true; + reverseThroughPath = (path->end == currentNode); + + currentPath = path; + + // calculate direction of the path + short deltaX = path->end->x - path->start->x; + short deltaY = path->end->y - path->start->y; + u16 direction = (u16)(atan2(deltaX, deltaY) / ((M_PI * 2) / 65536.0)); + + if (reverseThroughPath) { + direction += 0x8000; + } + + daWMPlayer_c *player = daWMPlayer_c::instance; + player->startAnimation(2, 2.0, 10.0, 0.0); + player->rot.y = direction; +} + +void dWMPathManager_c::moveThroughPath() { + dKPNode_s *from, *to; + + from = reverseThroughPath ? currentPath->end : currentPath->start; + to = reverseThroughPath ? currentPath->start : currentPath->end; + + Vec move = (Vec){to->x - from->x, to->y - from->y, 0}; + VECNormalize(&move, &move); + VECScale(&move, &move, 1.5); + + daWMPlayer_c *player = daWMPlayer_c::instance; + + player->pos.x += move.x; + player->pos.y -= move.y; + + // Check if we've reached the end yet + if ( + ((move.x > 0) ? (player->pos.x >= to->x) : (player->pos.x <= to->x)) && + ((move.y > 0) ? (-player->pos.y >= to->y) : (-player->pos.y <= to->y)) + ) { + + currentNode = to; + player->pos.x = to->x; + player->pos.y = -to->y; + + if (to->type != dKPNode_s::PASS_THROUGH) { + // Stop here + player->startAnimation(0, 1.2, 10.0, 0.0); + + isMoving = false; + + SaveBlock *save = GetSaveFile()->GetBlock(-1); + save->current_path_node = pathLayer->findNodeID(to); + + dWMHud_c::instance->showPointBar(); + } else { + startMovementTo(to->getOppositeExitTo(currentPath)); + } + } +} + +void dWMPathManager_c::activatePoint() { + if (currentNode->type == dKPNode_s::LEVEL) { + daWMPlayer_c::instance->startAnimation(170, 1.2, 10.0, 0.0); + + int w = currentNode->levelNumber[0] - 1; + int l = currentNode->levelNumber[1] - 1; + dLevelInfo_c::entry_s *level = dScKoopatlas_c::instance->levelInfo.search(w, l); + dScKoopatlas_c::instance->startLevel(level); + } +} + + diff --git a/src/koopatlas/pathmanager.h b/src/koopatlas/pathmanager.h new file mode 100644 index 0000000..3ddcf58 --- /dev/null +++ b/src/koopatlas/pathmanager.h @@ -0,0 +1,29 @@ +#ifndef __KOOPATLAS_PATH_MANAGER_H +#define __KOOPATLAS_PATH_MANAGER_H + +#include "koopatlas/mapdata.h" + +class dWMPathManager_c { + public: + void setup(); + void execute(); + + bool canUseExit(dKPPath_s *path) { + return (path != 0) && (path->isAvailable); + } + + void startMovementTo(dKPPath_s *path); + void moveThroughPath(); + void activatePoint(); + + dKPLayer_s *pathLayer; + + bool isMoving; + dKPNode_s *currentNode; + + dKPPath_s *currentPath; + bool reverseThroughPath; // direction we are going through the path +}; + +#endif + diff --git a/src/koopatlas/player.h b/src/koopatlas/player.h index d5fcc33..2b53119 100644 --- a/src/koopatlas/player.h +++ b/src/koopatlas/player.h @@ -1,3 +1,6 @@ +#ifndef __KOOPATLAS_PLAYER_H +#define __KOOPATLAS_PLAYER_H + #include "koopatlas/core.h" class daWMPlayer_c : public dActor_c { @@ -22,4 +25,5 @@ class daWMPlayer_c : public dActor_c { static daWMPlayer_c *instance; }; +#endif diff --git a/src/levelinfo.cpp b/src/levelinfo.cpp new file mode 100644 index 0000000..3a0ef6f --- /dev/null +++ b/src/levelinfo.cpp @@ -0,0 +1,37 @@ +#include "levelinfo.h"
+
+void dLevelInfo_c::load(void *buffer) {
+ data = (header_s*)buffer;
+
+ // decode all the level names
+ for (int sect = 0; sect < sectionCount(); sect++) {
+ // parse this section
+ section_s *thisSect = getSectionByIndex(sect);
+ entry_s *levels = getLevelsForSection(thisSect);
+
+ for (int lev = 0; lev < thisSect->levelCount; lev++) {
+ entry_s *level = &levels[lev];
+
+ char *name = (char*)getNameForLevel(level);
+
+ for (int i = 0; i < level->nameLength+1; i++) {
+ name[i] -= 0xD0;
+ }
+ }
+ }
+}
+
+dLevelInfo_c::entry_s *dLevelInfo_c::search(int world, int level) {
+ for (int i = 0; i < sectionCount(); i++) {
+ section_s *sect = getSectionByIndex(i);
+
+ for (int j = 0; j < sect->levelCount; j++) {
+ entry_s *entry = &getLevelsForSection(sect)[j];
+ if (entry->world == world && entry->level == level)
+ return entry;
+ }
+ }
+
+ return 0;
+}
+
diff --git a/src/levelinfo.h b/src/levelinfo.h new file mode 100644 index 0000000..470992b --- /dev/null +++ b/src/levelinfo.h @@ -0,0 +1,56 @@ +#ifndef __NEWER_LEVELINFO_H
+#define __NEWER_LEVELINFO_H
+
+#include <common.h>
+
+class dLevelInfo_c {
+public:
+ struct header_s {
+ u32 magic;
+ u32 sectionCount;
+ u32 sectionOffsets[1];
+ };
+
+ struct section_s {
+ u32 levelCount;
+ };
+
+ struct entry_s {
+ u8 world;
+ u8 level;
+ u8 reserved1;
+ u8 reserved2;
+ u8 nameLength;
+ u8 reserved3;
+ u16 flags;
+ u32 nameOffset;
+ };
+
+private:
+ header_s *data;
+
+public:
+ void load(void *buffer);
+
+ entry_s *search(int world, int level);
+
+ u32 sectionCount() {
+ return data->sectionCount;
+ }
+
+ section_s *getSectionByIndex(u32 index) {
+ return (section_s*)(((char*)data) + data->sectionOffsets[index]);
+ }
+
+ entry_s *getLevelsForSection(section_s *section) {
+ return (entry_s*)(section + 1);
+ }
+
+ const char *getNameForLevel(entry_s *entry) {
+ return (const char*)data + entry->nameOffset;
+ }
+};
+
+
+#endif
+
|