diff options
| author | Treeki <treeki@gmail.com> | 2012-01-17 00:40:00 +0100 | 
|---|---|---|
| committer | Treeki <treeki@gmail.com> | 2012-01-17 00:40:00 +0100 | 
| commit | bb5d7f7e737e318d095d23939b7d288eaf5f9e63 (patch) | |
| tree | ec41984cd10376e7fec2b24e22b1b695c3692b36 | |
| parent | 28efd888af3ffe227565683e2cd2960ea5b52f61 (diff) | |
| download | kamek-bb5d7f7e737e318d095d23939b7d288eaf5f9e63.tar.gz kamek-bb5d7f7e737e318d095d23939b7d288eaf5f9e63.zip | |
added path support and the new API LevelInfo
Diffstat (limited to '')
| -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
 +
 | 
