diff options
| author | Colin Noga <Tempus@chronometry.ca> | 2012-09-27 22:59:41 -0500 | 
|---|---|---|
| committer | Colin Noga <Tempus@chronometry.ca> | 2012-09-27 22:59:41 -0500 | 
| commit | 64f38f642113ac4bd5b1d96e76c9ae97965bc416 (patch) | |
| tree | 99d9bbf4d577ae2d8a79fcb5f7101df1b57398fe /src | |
| parent | f9afbf1109b30bbc6011e81109b7e11961a4361a (diff) | |
| parent | b3c37e5a9ef81250d6554fcbb8089154b4940c9f (diff) | |
| download | kamek-64f38f642113ac4bd5b1d96e76c9ae97965bc416.tar.gz kamek-64f38f642113ac4bd5b1d96e76c9ae97965bc416.zip | |
Merge branch 'level-select' of ssh://treeki.rustedlogic.net:30000/Kamek into level-select
Diffstat (limited to 'src')
| -rw-r--r-- | src/fileselect.S | 88 | ||||
| -rw-r--r-- | src/koopatlas/core.cpp | 11 | ||||
| -rw-r--r-- | src/koopatlas/core.h | 2 | ||||
| -rw-r--r-- | src/koopatlas/hud.cpp | 323 | ||||
| -rw-r--r-- | src/koopatlas/hud.h | 33 | ||||
| -rw-r--r-- | src/koopatlas/mapdata.cpp | 16 | ||||
| -rw-r--r-- | src/koopatlas/mapdata.h | 20 | ||||
| -rw-r--r-- | src/koopatlas/pathmanager.cpp | 59 | ||||
| -rw-r--r-- | src/koopatlas/pathmanager.h | 1 | ||||
| -rw-r--r-- | src/koopatlas/starcoin.cpp | 2 | ||||
| -rw-r--r-- | src/levelinfo.cpp | 6 | ||||
| -rw-r--r-- | src/levelinfo.h | 10 | ||||
| -rw-r--r-- | src/levelinfo_old.cpp | 4 | ||||
| -rw-r--r-- | src/levelinfo_old.h | 10 | ||||
| -rw-r--r-- | src/levelnames.cpp | 2 | ||||
| -rw-r--r-- | src/newer.cpp | 76 | 
16 files changed, 501 insertions, 162 deletions
| diff --git a/src/fileselect.S b/src/fileselect.S index 9f7f396..6ee1c39 100644 --- a/src/fileselect.S +++ b/src/fileselect.S @@ -54,8 +54,7 @@ DFNiceTitle:  	bctr  .extern findTextBoxByName__Q23m2d17EmbedLayoutBase_cCFPCc -.extern NewerWorldNames -.extern NewerWorldCount +.extern findPictureByName__Q23m2d17EmbedLayoutBase_cCFPCc  .extern InsertIntIntoTextBox1  .global DFNiceWorldName  DFNiceWorldName: @@ -71,22 +70,21 @@ DFNiceWorldName:  	stw r25, 0x14(r1)  	mr r20, r4 -	# get Newer map number -	lbz r6, 0x6FC(r31) -	lis r8, NewerWorldCount@h -	ori r8, r8, NewerWorldCount@l -	lwz r8, 0(r8) -	cmpw r6, r8 -	bge invalidThing -	slwi r6, r6, 2 -	lis r7, NewerWorldNames@h -	ori r7, r7, NewerWorldNames@l -	lwzx r4, r7, r6 -	b gotName -invalidThing: -	lis r4, InvalidWorld@h -	ori r4, r4, InvalidWorld@l -gotName: +	# Savefile is in r31 +	# World Name field is in r20 + +	lis r4, ConvertedWorldName@h +	ori r4, r4, ConvertedWorldName@l +	mr r3, r4 +	mr r5, r31 +	li r6, 36 +	mtctr r6 +convWNameLoop: +	lbz r6, 0x6FC(r5) +	sth r6, 0(r3) +	addi r3, r3, 2 +	addi r5, r5, 1 +	bdnz convWNameLoop  	mr r3, r20  	li r5, 0 @@ -95,6 +93,24 @@ gotName:  	mtctr r12  	bctrl +	# now set the colours +	# Text colours: 0x720, hint colours: 0x728 +	lwz r3, 0x720(r31) +	stw r3, 0xDC(r20) +	lwz r3, 0x724(r31) +	stw r3, 0xE0(r20) + +	addi r3, r30, 0x74 +	lis r4, Picture_00@h +	ori r4, r4, Picture_00@l +	bl findPictureByName__Q23m2d17EmbedLayoutBase_cCFPCc +	lwz r4, 0x728(r31) +	stw r4, 0xD8(r3) +	stw r4, 0xDC(r3) +	lwz r4, 0x72C(r31) +	stw r4, 0xE0(r3) +	stw r4, 0xE4(r3) +  	# While we're at it, take care of some other things  	# r21 shall hold our star coin count; r22 shall hold our exit count  	# r23 shall hold the level pointer @@ -231,6 +247,22 @@ FSDebugStates:  	addi r1, r1, 0x10  	blr +.global DefaultSavefileInfo +DefaultSavefileInfo: +	addi r4, r3, 0x6FC +	lis r5, DefaultSavefileInfoData@h +	ori r5, r5, DefaultSavefileInfoData@l +	lis r6, DefaultSavefileInfoDataEnd@h +	ori r6, r6, DefaultSavefileInfoDataEnd@l +DSFICopyLoop: +	lwz r7, 0(r5) +	stw r7, 0(r4) +	addi r4, r4, 4 +	addi r5, r5, 4 +	cmpw r5, r6 +	blt DSFICopyLoop +	blr +  .align 4  .data @@ -255,10 +287,26 @@ NormalExitStr: .string "<Normal> %d-%d\n"  SecretExitStr: .string "<Secret> %d-%d\n"  StarCoinCount: .string "StarCoinCount"  ExitCount: .string "ExitCount" +Picture_00: .string "Picture_00"  .align 4  DFTitle:  .short 'F','i','l','e',' ','X',0 -InvalidWorld: -.short '<','I','n','v','a','l','i','d',' ','W','o','r','l','d','>',0 +ConvertedWorldName: +.short 0,0,0,0,0,0,0,0,0,0,0,0 # 12 +.short 0,0,0,0,0,0,0,0,0,0,0,0 # 12 +.short 0,0,0,0,0,0,0,0,0,0,0,0 # 12 +.align 4 +DefaultSavefileInfoData: +.string "Yoshi's Island" #15 +.byte 0,0,0,0,0,0,0,0,0,0,0 # 11 +.byte 0,0,0,0,0,0,0,0,0,0 # 10 +.long 0xFFFF99FF,0x1FB423FF +.long 0x173714FF,0x3C9135FF +.long 0xFFFF99FF,0x1FB423FF +.short 0x75,0x2E,0xB +.byte 0,0 + +DefaultSavefileInfoDataEnd: +.long 0 diff --git a/src/koopatlas/core.cpp b/src/koopatlas/core.cpp index c20d715..a48a565 100644 --- a/src/koopatlas/core.cpp +++ b/src/koopatlas/core.cpp @@ -970,13 +970,10 @@ void dScKoopatlas_c::startLevel(dLevelInfo_c::entry_s *entry) {  	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); +	sl.world1 = entry->worldSlot; +	sl.world2 = entry->worldSlot; +	sl.level1 = entry->levelSlot; +	sl.level2 = entry->levelSlot;  	ActivateWipe(WIPE_MARIO); diff --git a/src/koopatlas/core.h b/src/koopatlas/core.h index 41fba45..cfac014 100644 --- a/src/koopatlas/core.h +++ b/src/koopatlas/core.h @@ -18,7 +18,7 @@  #include "koopatlas/pathmanager.h"  #define WM_DEBUGGING -#define WM_SPAMMY_DEBUGGING +//#define WM_SPAMMY_DEBUGGING  #ifdef WM_DEBUGGING  #define MapReport OSReport diff --git a/src/koopatlas/hud.cpp b/src/koopatlas/hud.cpp index c9124d2..2401a04 100644 --- a/src/koopatlas/hud.cpp +++ b/src/koopatlas/hud.cpp @@ -1,5 +1,146 @@  #include "koopatlas/hud.h" + +dTexMapColouriser_c::dTexMapColouriser_c() { +	texmap = 0; +	original = 0; +	mine = 0; +} + +void *EGG__Heap__alloc(unsigned long size, int unk, void *heap); +void EGG__Heap__free(void *ptr, void *heap); + +dTexMapColouriser_c::~dTexMapColouriser_c() { +	resetAndClear(); +} + +void dTexMapColouriser_c::resetAndClear() { +	texmap = 0; +	if (mine) { +		EGG__Heap__free(mine, 0); +		mine = 0; +	} +} + +void dTexMapColouriser_c::setTexMap(nw4r::lyt::TexMap *tm) { +	OSReport("Colourising TexMap: %p (w:%d h:%d)\n", tm, tm->width, tm->height); +	if (texmap) +		resetAndClear(); + +	if (tm->mBits.textureFormat != GX_TF_IA8) { +		OSReport("Warning: Trying to colourise image whose format is %d not GX_TF_IA8\n", tm->mBits.textureFormat); +	} + +	texmap = tm; +	original = (u16*)tm->image; +	mine = (u16*)EGG__Heap__alloc(tm->width * tm->height * 4, 0x20, mHeap::gameHeaps[2]); +	tm->image = mine; +	tm->mBits.textureFormat = GX_TF_RGBA8; +} + +void dTexMapColouriser_c::applyAlso(nw4r::lyt::TexMap *tm) { +	if (!texmap) { +		setTexMap(tm); +	} else { +		tm->image = mine; +		tm->mBits.textureFormat = GX_TF_RGBA8; +	} +} + +inline static float hslValue(float n1, float n2, float hue) { +	if (hue > 6.0f) +		hue -= 6.0f; +	else if (hue < 0.0f) +		hue += 6.0f; + +	if (hue < 1.0f) +		return n1 + (n1 - n1) * hue; +	else if (hue < 3.0f) +		return n2; +	else if (hue < 4.0f) +		return n1 + (n2 - n1) * (4.0f - hue); +	else +		return n1; +} + +void dTexMapColouriser_c::colourise(int h, int s, int l) { +	if (!mine) +		return; + +	int width = texmap->width, height = texmap->height; +	int texelW = width / 4, texelH = height / 4; + +	u16 *source = original, *dest = mine; + +	float hueParam = h / 360.0f; +	float satParam = s / 100.0f; +	float lumParam = l / 100.0f; + +	for (int texelY = 0; texelY < texelH; texelY++) { +		for (int texelX = 0; texelX < texelW; texelX++) { +			for (int y = 0; y < 4; y++) { +				for (int x = 0; x < 4; x++) { +					u8 intensity = *source & 0xFF; +					u8 alpha = *source >> 8; + +					u8 r, g, b; + +					// This is a hack +					if (alpha < 250) { +						r = g = b = intensity; +					} else { +						// converting from GIMP's colourise code... +						// h and s are always the same +						// l is the only thing we need to touch: +						// we get the luminance from the source pixel +						// (which, conveniently, is the intensity) +						// manipulate it using the passed l and then +						// convert the whole thing to RGB + +						float lum = intensity / 255.0f; + +						// manipulate it +						if (l > 0) { +							lum = lum * (1.0f - lumParam); +							lum += (1.0f - (1.0f - lumParam)); +						} else if (l < 0) { +							lum = lum * (lumParam + 1.0f); +						} + +						// make it RGB + +						if (s == 0) { +							r = g = b = lum*255.0f; +						} else { +							float m1, m2; +							if (lum <= 0.5f) +								m2 = lum * (1.0f + satParam); +							else +								m2 = lum + satParam - lum * satParam; + +							m1 = 2.0f * lum - m2; + +							r = hslValue(m1, m2, hueParam * 6.0f + 2.0) * 255.0f; +							g = hslValue(m1, m2, hueParam * 6.0f) * 255.0f; +							b = hslValue(m1, m2, hueParam * 6.0f - 2.0) * 255.0f; +						} +					} + +					// now write it +					dest[0] = (alpha<<8)|r; +					dest[16] = (g<<8)|b; + +					source++; +					dest++; +				} +			} + +			dest += 16; +		} +	} +} + +  dWMHud_c *dWMHud_c::instance = 0;  dWMHud_c *dWMHud_c::build() { @@ -15,6 +156,7 @@ dWMHud_c *dWMHud_c::build() {  dWMHud_c::dWMHud_c() {  	layoutLoaded = false;  	displayedControllerType = -1; +	isFooterVisible = false;  }  enum WMHudAnimation { @@ -50,7 +192,7 @@ int dWMHud_c::onCreate() {  		layout.disableAllAnimations();  		layout.enableNonLoopAnim(SHOW_LIVES); -		layout.enableNonLoopAnim(SHOW_FOOTER); +		layout.resetAnim(SHOW_FOOTER);  		layout.resetAnim(SHOW_HEADER);  		static const char *tbNames[2] = {"MenuButtonInfo", "ItemsButtonInfo"}; @@ -63,13 +205,14 @@ int dWMHud_c::onCreate() {  		layout.getPanes(paneNames, &N_IconPosXP_00[0], 4);  		static const char *pictureNames[] = { -			"Header_Centre", "Header_Right", +			"Header_Centre", "Header_Right", "Footer",  			"NormalExitFlag", "SecretExitFlag", +			"StarCoinOff0", "StarCoinOff1", "StarCoinOff2",  			"StarCoinOn0", "StarCoinOn1", "StarCoinOn2",  			"P_marioFace_00", "P_luigiFace_00",  			"P_BkinoFace_00", "P_YkinoFace_00"  		}; -		layout.getPictures(pictureNames, &Header_Centre, 11); +		layout.getPictures(pictureNames, &Header_Centre, 15);  		static const char *textBoxNames[] = {  			"LevelName", "LevelNameS", @@ -81,9 +224,20 @@ int dWMHud_c::onCreate() {  		};  		layout.getTextBoxes(textBoxNames, &LevelName, 11); +		headerCol.setTexMap(Header_Right->material->texMaps); +		headerCol.applyAlso(Header_Centre->material->texMaps); +		footerCol.setTexMap(Footer->material->texMaps); +  		layoutLoaded = true; +		layout.drawOrder = 0; +  		willShowHeader = false; +		willShowFooter = false; + +		loadFooterInfo(); +		SaveBlock *save = GetSaveFile()->GetBlock(-1); +		willShowFooter = (save->newerWorldName[0] != 0);  		if (!dScKoopatlas_c::instance->pathManager.isMoving)  			enteredNode(); @@ -96,6 +250,8 @@ int dWMHud_c::onCreate() {  int dWMHud_c::onDelete() { +	dWMHud_c::instance = 0; +  	if (!layoutLoaded)  		return true; @@ -110,11 +266,22 @@ int dWMHud_c::onExecute() {  	if (willShowHeader && (!(layout.isAnimOn(SHOW_HEADER)))) {  		willShowHeader = false;  		loadHeaderInfo(); -		playShowHeaderAnim(); +		playShowAnim(SHOW_HEADER); +	} + +	if (willShowFooter && (!(layout.isAnimOn(SHOW_FOOTER)))) { +		willShowFooter = false; +		isFooterVisible = true; +		loadFooterInfo(); +		playShowAnim(SHOW_FOOTER);  	} +	setupLives(); // FUCK IT  	updatePressableButtonThingies(); +	int scCount = getStarCoinCount(); +	WriteNumberToTextBox(&scCount, StarCoinCounter, false); +  	layout.execAnimations();  	layout.update(); @@ -134,26 +301,28 @@ int dWMHud_c::onDraw() { -void dWMHud_c::playShowHeaderAnim() { +void dWMHud_c::playShowAnim(int id) {  	if (!this || !this->layoutLoaded) return; -	layout.enableNonLoopAnim(SHOW_HEADER); +	layout.enableNonLoopAnim(id);  } -void dWMHud_c::playHideHeaderAnim() { +void dWMHud_c::playHideAnim(int id) {  	if (!this || !this->layoutLoaded) return; -	if (!layout.isAnimOn(SHOW_HEADER)) { -		layout.enableNonLoopAnim(SHOW_HEADER, true); +	if (!layout.isAnimOn(id)) { +		layout.enableNonLoopAnim(id, true);  	} -	layout.grpHandlers[SHOW_HEADER].frameCtrl.flags = 3; // NO_LOOP | REVERSE +	layout.grpHandlers[id].frameCtrl.flags = 3; // NO_LOOP | REVERSE +	if (id == SHOW_FOOTER) +		isFooterVisible = false;  }  void dWMHud_c::loadHeaderInfo() {  	dLevelInfo_c *levelInfo = &dScKoopatlas_c::instance->levelInfo; -	dLevelInfo_c::entry_s *infEntry = levelInfo->search( +	dLevelInfo_c::entry_s *infEntry = levelInfo->searchBySlot(  			nodeForHeader->levelNumber[0]-1, nodeForHeader->levelNumber[1]-1);  	if (infEntry == 0) { @@ -177,32 +346,102 @@ void dWMHud_c::loadHeaderInfo() {  	LevelName->SetString(convertedLevelName);  	LevelNameS->SetString(convertedLevelName); +	// a hack because I don't feel like editing the rlyt +	LevelName->size.x = LevelNameS->size.x = 400.0f; +  	// LEVEL NUMBER -	wchar_t levelNumber[6]; -	levelNumber[0] = '0' + nodeForHeader->levelNumber[0]; +	static const wchar_t *numberKinds[] = { +		// 0-19 are handled by code +		// To insert a picturefont character: +		// \x0B\x01YY\xZZZZ +		// YY is the character code, ZZZZ is ignored +		L"A", // 20, alternate +		L"\x0B\x012F\xBEEF", // 21, tower +		L"\x0B\x012F\xBEEF" L"2", // 22, tower 2 +		L"\x0B\x012E\xBEEF", // 23, castle +		L"\x0B\x012F\xBEEF", // 24, fortress +		L"\x0B\x013D\xBEEF", // 25, final castle +		L"Train", // 26, train +		L"\x0B\x0132\xBEEF", // 27, airship +		L"Palace", // 28, switch palace +		L"House", // 29, yoshi's house +		L"Key1", // 30, key 1 +		L"Key2", // 31, key 2 +		L"Key3", // 32, key 3 +		L"Key4", // 33, key 4 +		L"Key5", // 34, key 5 +		L"Key6", // 35, key 6 +	}; + +	int origWN = infEntry->displayWorld; +	int origWL = infEntry->displayLevel; + +	wchar_t levelNumber[16]; +	levelNumber[0] = (origWN >= 10) ? (origWN-10+'A') : (origWN+'0');  	levelNumber[1] = '-'; -	if (nodeForHeader->levelNumber[1] >= 10) { -		levelNumber[2] = '0' + (nodeForHeader->levelNumber[1] / 10); -		levelNumber[3] = '0' + (nodeForHeader->levelNumber[1] % 10); +	if (origWL > 20) { +		wcscpy(&levelNumber[2], numberKinds[origWL-20]); +	} else if (origWL >= 10) { +		levelNumber[2] = '1'; +		levelNumber[3] = ('0' - 10) + origWL;  		levelNumber[4] = 0;  	} else { -		levelNumber[2] = '0' + nodeForHeader->levelNumber[1]; +		levelNumber[2] = '0' + origWL;  		levelNumber[3] = 0;  	}  	LevelNumber->SetString(levelNumber); + +	// make the picture shadowy +	int sidx = 0; +	while (levelNumber[sidx]) { +		if (levelNumber[sidx] == 11) { +			levelNumber[sidx+1] = 0x200 | (levelNumber[sidx+1]&0xFF); +			sidx += 2; +		} +		sidx++; +	}  	LevelNumberS->SetString(levelNumber); +	nw4r::ut::TextWriter tw2; +	tw2.font = LevelNumber->font; +	tw2.SetFontSize(LevelNumber->fontSizeX, LevelNumber->fontSizeY); +	tw2.lineSpace = LevelNumber->lineSpace; +	tw2.charSpace = LevelNumber->charSpace; +	if (LevelNumber->tagProc != 0) +		tw2.tagProcessor = LevelNumber->tagProc; + +	float currentPos = tw2.CalcStringWidth(levelNumber, wcslen(levelNumber)); +	currentPos += LevelNumber->trans.x + 12.0f; +  	// INFO  	int w = nodeForHeader->levelNumber[0] - 1;  	int l = nodeForHeader->levelNumber[1] - 1;  	u32 conds = GetSaveFile()->GetBlock(-1)->GetLevelCondition(w, l); + +	NormalExitFlag->trans.x = currentPos;  	NormalExitFlag->SetVisible(conds & COND_NORMAL); +	if (conds & COND_NORMAL) +		currentPos += NormalExitFlag->size.x; + +	SecretExitFlag->trans.x = currentPos;  	SecretExitFlag->SetVisible(conds & COND_SECRET); -	StarCoinOn[0]->SetVisible(conds & COND_COIN1); -	StarCoinOn[1]->SetVisible(conds & COND_COIN2); -	StarCoinOn[2]->SetVisible(conds & COND_COIN3); +	if (conds & COND_SECRET) +		currentPos += SecretExitFlag->size.x; + +	// are star coins enabled or not? +	bool haveSC = (infEntry->flags & 2); + +	for (int i = 0; i < 3; i++) { +		bool flag = (conds & (COND_COIN1 << i)); +		StarCoinOn[i]->SetVisible(flag); +		StarCoinOff[i]->SetVisible(haveSC); +		if (haveSC) { +			StarCoinOff[i]->trans.x = currentPos; +			currentPos += StarCoinOff[i]->size.x + 4.0f; +		} +	}  	// SIZE THING  	nw4r::ut::TextWriter tw; @@ -215,10 +454,35 @@ void dWMHud_c::loadHeaderInfo() {  	float width = tw.CalcStringWidth(convertedLevelName, charCount);  	float totalWidth = width + LevelName->trans.x - 20.0f; -	if (totalWidth < 270.0f) -		totalWidth = 270.0f; +	if (totalWidth < currentPos) +		totalWidth = currentPos;  	Header_Centre->size.x = totalWidth;  	Header_Right->trans.x = totalWidth; + +	SaveBlock *save = GetSaveFile()->GetBlock(-1); +	headerCol.colourise(save->hudHintH, save->hudHintS, save->hudHintL); +} + + +void dWMHud_c::loadFooterInfo() { +	SaveBlock *save = GetSaveFile()->GetBlock(-1); + +	wchar_t convertedWorldName[36]; +	int i; +	for (i = 0; i < 36; i++) { +		convertedWorldName[i] = save->newerWorldName[i]; +		if (convertedWorldName[i] == 0) +			break; +	} +	convertedWorldName[35] = 0; + +	WorldName->SetString(convertedWorldName); +	WorldNameS->SetString(convertedWorldName); + +	WorldName->colour1 = save->hudTextColours[0]; +	WorldName->colour2 = save->hudTextColours[1]; + +	footerCol.colourise(save->hudHintH, save->hudHintS, save->hudHintL);  } @@ -237,15 +501,26 @@ void dWMHud_c::leftNode() {  	if (layout.grpHandlers[SHOW_HEADER].frameCtrl.currentFrame > 0.1f) {  		// not hidden -		if ((layout.isAnimOn(SHOW_HEADER) && (layout.grpHandlers[SHOW_HEADER].frameCtrl.flags & 2)) +		if ((layout.isAnimOn(SHOW_HEADER) && !(layout.grpHandlers[SHOW_HEADER].frameCtrl.flags & 2))  				|| (!layout.isAnimOn(SHOW_HEADER))) {  			// currently being shown, OR fully shown already -			playHideHeaderAnim(); +			playHideAnim(SHOW_HEADER);  		}  	}  } +void dWMHud_c::hideFooter() { +	if (isFooterVisible) +		playHideAnim(SHOW_FOOTER); +} + +void dWMHud_c::showFooter() { +	willShowFooter = true; +	if (isFooterVisible) +		playHideAnim(SHOW_FOOTER); +} +  void dWMHud_c::setupLives() {  	static const int LogicalPlayerIDs[] = {0,1,3,2}; diff --git a/src/koopatlas/hud.h b/src/koopatlas/hud.h index e507aea..5996b88 100644 --- a/src/koopatlas/hud.h +++ b/src/koopatlas/hud.h @@ -3,6 +3,23 @@  #include "koopatlas/core.h" +// Colourises an IA8 texture +class dTexMapColouriser_c { +	public: +		dTexMapColouriser_c(); +		~dTexMapColouriser_c(); + +		void resetAndClear(); +		void setTexMap(nw4r::lyt::TexMap *tm); +		void applyAlso(nw4r::lyt::TexMap *tm); +		void colourise(int h, int s, int l); + +	private: +		nw4r::lyt::TexMap *texmap; +		u16 *original; +		u16 *mine; +}; +  class dWMHud_c : public dBase_c {  	public:  		dWMHud_c(); @@ -21,11 +38,14 @@ class dWMHud_c : public dBase_c {  		void enteredNode(dKPNode_s *node = 0);  		void leftNode(); +		void hideFooter(); +		void showFooter(); +  		void setupLives();  	private: -		void playShowHeaderAnim(); -		void playHideHeaderAnim(); +		void playShowAnim(int id); +		void playHideAnim(int id);  		void loadHeaderInfo();  		bool willShowHeader; @@ -34,13 +54,20 @@ class dWMHud_c : public dBase_c {  		int displayedControllerType;  		void updatePressableButtonThingies(); +		void loadFooterInfo(); +		bool willShowFooter; +		bool isFooterVisible; + +		dTexMapColouriser_c headerCol, footerCol; +  		nw4r::lyt::Pane  			*N_IconPosXP_00[4];  		nw4r::lyt::Picture -			*Header_Centre, *Header_Right, +			*Header_Centre, *Header_Right, *Footer,  			*NormalExitFlag, *SecretExitFlag, +			*StarCoinOff[3],  			*StarCoinOn[3],  			*P_marioFace_00, *P_luigiFace_00,  			*P_BkinoFace_00, *P_YkinoFace_00; diff --git a/src/koopatlas/mapdata.cpp b/src/koopatlas/mapdata.cpp index cbd0c69..d766bed 100644 --- a/src/koopatlas/mapdata.cpp +++ b/src/koopatlas/mapdata.cpp @@ -205,6 +205,12 @@ void dKPMapData_c::fixup() {  	fixRef(data->unlockData);  	fixRef(data->sectors);  	fixRef(data->backgroundName); +	if (data->version >= 2) { +		fixRef(data->worlds); +		for (int i = 0; i < data->worldCount; i++) { +			fixRef(data->worlds[i].name); +		} +	}  	for (int iLayer = 0; iLayer < data->layerCount; iLayer++) {  		dKPLayer_s *layer = fixRef(data->layers[iLayer]); @@ -280,6 +286,16 @@ void dKPMapData_c::fixup() {  } +const dKPWorldDef_s *dKPMapData_c::findWorldDef(int id) const { +	for (int i = 0; i < data->worldCount; i++) { +		if (data->worlds[i].key == id) +			return &data->worlds[i]; +	} + +	return 0; +} + +  /******************************************************************************   * Generic Layer   ******************************************************************************/ diff --git a/src/koopatlas/mapdata.h b/src/koopatlas/mapdata.h index bc0c599..a0beb4d 100644 --- a/src/koopatlas/mapdata.h +++ b/src/koopatlas/mapdata.h @@ -53,7 +53,7 @@ struct dKPPath_s;  struct dKPNode_s {  	enum NodeTypes { -		PASS_THROUGH, STOP, LEVEL, CHANGE +		PASS_THROUGH, STOP, LEVEL, CHANGE, WORLD_CHANGE  	};  	short x, y; @@ -79,6 +79,7 @@ struct dKPNode_s {  	union {  		struct { u8 levelNumber[2]; bool hasSecret; };  		struct { const char *destMap; u8 thisID, foreignID, transition, _; }; +		struct { u8 worldID, __[3]; };  	};  	dKPPath_s *getAnyExit() { @@ -187,6 +188,18 @@ struct dKPLayer_s {  	int findNodeID(dKPNode_s *node);  }; +struct dKPWorldDef_s { +	const char *name; +	GXColor fsTextColours[2]; +	GXColor fsHintColours[2]; +	GXColor hudTextColours[2]; +	u8 hudHintH; +	s8 hudHintS, hudHintL; +	u8 key, trackID; +	u8 worldID; +	u8 padding1, padding2; +}; +  struct dKPMapFile_s {  	u32 magic;  	int version; @@ -202,6 +215,9 @@ struct dKPMapFile_s {  	dKPLayer_s::sector_s *sectors;  	const char *backgroundName; + +	dKPWorldDef_s *worlds; +	int worldCount;  };  class dKPMapData_c { @@ -253,6 +269,8 @@ class dKPMapData_c {  		dKPNodeExtra_c *levelNodeExtraArray; +		const dKPWorldDef_s *findWorldDef(int id) const; +  		dKPMapData_c();  		bool load(const char *filename);  		~dKPMapData_c(); diff --git a/src/koopatlas/pathmanager.cpp b/src/koopatlas/pathmanager.cpp index 536b43a..c691a89 100644 --- a/src/koopatlas/pathmanager.cpp +++ b/src/koopatlas/pathmanager.cpp @@ -374,7 +374,7 @@ void dWMPathManager_c::startMovementTo(dKPPath_s *path) {  	SpammyReport("moving to path %p [%d,%d to %d,%d]\n", path, path->start->x, path->start->y, path->end->x, path->end->y);  	if (!path->isAvailable) { return; } -	if (currentNode) +	if (currentNode && dWMHud_c::instance)  		dWMHud_c::instance->leftNode();  	calledEnteredNode = false; @@ -557,7 +557,7 @@ void dWMPathManager_c::moveThroughPath() {  		float distToEnd = VECMag(&toEndVec);  		//OSReport("Distance: %f; To:%d,%d; Player:%f,%f; Diff:%f,%f\n", distToEnd, to->x, to->y, player->pos.x, player->pos.y, toEndVec.x, toEndVec.y); -		if (distToEnd < 64.0f) { +		if (distToEnd < 64.0f && dWMHud_c::instance) {  			calledEnteredNode = true;  			dWMHud_c::instance->enteredNode(to);  		} @@ -578,15 +578,15 @@ void dWMPathManager_c::moveThroughPath() {     		isJumping = false;     		timer = 0.0; -   		SpammyReport("reached path end (%p)\n", to); +   		SpammyReport("reached path end (%p) with type %d\n", to, to->type);     		bool reallyStop = false;     		if (to->type == dKPNode_s::LEVEL) {     			// Always stop on levels     			reallyStop = true; -   		} else if (to->type == dKPNode_s::CHANGE) { -			// Never stop on entrances +   		} else if (to->type == dKPNode_s::CHANGE || to->type == dKPNode_s::WORLD_CHANGE) { +			// Never stop on entrances or on world changes  			reallyStop = false;     		} else if (to->type == dKPNode_s::PASS_THROUGH) {  			// If there's only one exit here, then stop even though @@ -602,6 +602,44 @@ void dWMPathManager_c::moveThroughPath() {  				reallyStop = true;  		} +		if (to->type == dKPNode_s::WORLD_CHANGE) { +			// Set the current world info +			SaveBlock *save = GetSaveFile()->GetBlock(-1); + +			OSReport("Activating world change %d\n", to->worldID); +			const dKPWorldDef_s *world = dScKoopatlas_c::instance->mapData.findWorldDef(to->worldID); +			if (world) { +				if (strncmp(save->newerWorldName, world->name, 36) == 0) { +					OSReport("Already here\n"); +				} else { +					OSReport("Found!\n"); +					strncpy(save->newerWorldName, world->name, 36); +					save->newerWorldName[35] = 0; +					save->currentMapMusic = world->trackID; + +					for (int i = 0; i < 2; i++) { +						save->fsTextColours[i] = world->fsTextColours[i]; +						save->fsHintColours[i] = world->fsHintColours[i]; +						save->hudTextColours[i] = world->hudTextColours[i]; +					} + +					save->hudHintH = world->hudHintH; +					save->hudHintS = world->hudHintS; +					save->hudHintL = world->hudHintL; + +					if (dWMHud_c::instance) +						dWMHud_c::instance->showFooter(); +				} +			} else if (to->worldID == 0) { +				OSReport("No world\n"); +				save->newerWorldName[0] = 0; +				if (dWMHud_c::instance) +					dWMHud_c::instance->hideFooter(); +			} else { +				OSReport("Not found!\n"); +			} +		} +  		if (to->type == dKPNode_s::CHANGE) {  			// Go to another map @@ -635,15 +673,8 @@ void dWMPathManager_c::moveThroughPath() {  			SaveBlock *save = GetSaveFile()->GetBlock(-1);  			save->current_path_node = pathLayer->findNodeID(to); -			if (!calledEnteredNode) +			if (!calledEnteredNode && dWMHud_c::instance)  				dWMHud_c::instance->enteredNode(); - -			if (to->type == dKPNode_s::LEVEL) { -				NWRWorld nWorld = NewerWorldForLevelID(to->levelNumber[0], to->levelNumber[1]); -				if (nWorld != UNKNOWN_WORLD) { -					save->currentNewerWorld = (u8)nWorld; -				} -			}  		} else {  			startMovementTo(to->getOppositeAvailableExitTo(currentPath));  			SpammyReport("passthrough node, continuing to next path\n"); @@ -684,7 +715,7 @@ void dWMPathManager_c::activatePoint() {  		isEnteringLevel = true;  		levelStartWait = 40; -		enteredLevel = dScKoopatlas_c::instance->levelInfo.search(w, l); +		enteredLevel = dScKoopatlas_c::instance->levelInfo.searchBySlot(w, l);  	}  } diff --git a/src/koopatlas/pathmanager.h b/src/koopatlas/pathmanager.h index 5579f66..a1d916d 100644 --- a/src/koopatlas/pathmanager.h +++ b/src/koopatlas/pathmanager.h @@ -9,6 +9,7 @@  #endif  #include "koopatlas/mapdata.h" +#include "levelinfo.h"  extern "C" void *SoundRelatedClass;  extern "C" void *MapSoundPlayer(void *SoundClass, int soundID, int unk); diff --git a/src/koopatlas/starcoin.cpp b/src/koopatlas/starcoin.cpp index 3842f87..4366895 100644 --- a/src/koopatlas/starcoin.cpp +++ b/src/koopatlas/starcoin.cpp @@ -238,7 +238,7 @@ void dWMStarCoin::LoadCoinsForWorld(int world) {  			if (levelArray[world][l][i]) {  				levelNum--;  				dLevelInfo_c *li = &dScKoopatlas_c::instance->levelInfo; -				dLevelInfo_c::entry_s *entry = li->search(world, levelNum); +				dLevelInfo_c::entry_s *entry = li->searchBySlot(world, levelNum);  				setText(li->getNameForLevel(entry), levelPane);  				totalCoins += 3; diff --git a/src/levelinfo.cpp b/src/levelinfo.cpp index 3a0ef6f..8ce2845 100644 --- a/src/levelinfo.cpp +++ b/src/levelinfo.cpp @@ -12,6 +12,8 @@ void dLevelInfo_c::load(void *buffer) {  		for (int lev = 0; lev < thisSect->levelCount; lev++) {
  			entry_s *level = &levels[lev];
 +			SetSomeConditionShit(level->worldSlot, level->levelSlot, level->flags);
 +
  			char *name = (char*)getNameForLevel(level);
  			for (int i = 0; i < level->nameLength+1; i++) {
 @@ -21,13 +23,13 @@ void dLevelInfo_c::load(void *buffer) {  	}
  }
 -dLevelInfo_c::entry_s *dLevelInfo_c::search(int world, int level) {
 +dLevelInfo_c::entry_s *dLevelInfo_c::searchBySlot(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)
 +			if (entry->worldSlot == world && entry->levelSlot == level)
  				return entry;
  		}
  	}
 diff --git a/src/levelinfo.h b/src/levelinfo.h index 470992b..20628d9 100644 --- a/src/levelinfo.h +++ b/src/levelinfo.h @@ -16,10 +16,10 @@ public:  	};
  	struct entry_s {
 -		u8 world;
 -		u8 level;
 -		u8 reserved1;
 -		u8 reserved2;
 +		u8 worldSlot;
 +		u8 levelSlot;
 +		u8 displayWorld;
 +		u8 displayLevel;
  		u8 nameLength;
  		u8 reserved3;
  		u16 flags;
 @@ -32,7 +32,7 @@ private:  public:
  	void load(void *buffer);
 -	entry_s *search(int world, int level);
 +	entry_s *searchBySlot(int world, int level);
  	u32 sectionCount() {
  		return data->sectionCount;
 diff --git a/src/levelinfo_old.cpp b/src/levelinfo_old.cpp index 01dda85..bd5a2eb 100644 --- a/src/levelinfo_old.cpp +++ b/src/levelinfo_old.cpp @@ -21,13 +21,13 @@ void LevelInfo_Prepare(FileHandle *fh) {  	}  } -LevelInfo_Entry *LevelInfo_Search(void *file, int world, int level) { +LevelInfo_Entry *LevelInfo_SearchSlot(void *file, int world, int level) {  	for (int i = 0; i < LevelInfo_GetSectionCount(file); i++) {  		LevelInfo_Section *sect = LevelInfo_GetSection(file, i);  		for (int j = 0; j < sect->levelCount; j++) {  			LevelInfo_Entry *entry = &LevelInfo_GetLevels(file, sect)[j]; -			if (entry->world == world && entry->level == level) +			if (entry->worldSlot == world && entry->levelSlot == level)  				return entry;  		}  	} diff --git a/src/levelinfo_old.h b/src/levelinfo_old.h index d8cb888..ed43757 100644 --- a/src/levelinfo_old.h +++ b/src/levelinfo_old.h @@ -14,10 +14,10 @@ struct LevelInfo_Section {  };  struct LevelInfo_Entry { -	u8 world; -	u8 level; -	u8 reserved1; -	u8 reserved2; +	u8 worldSlot; +	u8 levelSlot; +	u8 displayWorld; +	u8 displayLevel;  	u8 nameLength;  	u8 reserved3;  	u16 flags; @@ -50,7 +50,7 @@ inline char *LevelInfo_GetName(void *file, LevelInfo_Entry *entry) {  }  void LevelInfo_Prepare(FileHandle *fh); -LevelInfo_Entry *LevelInfo_Search(void *file, int world, int level); +LevelInfo_Entry *LevelInfo_SearchSlot(void *file, int world, int level);  #endif diff --git a/src/levelnames.cpp b/src/levelnames.cpp index 1f05386..7c64c0b 100644 --- a/src/levelnames.cpp +++ b/src/levelnames.cpp @@ -38,7 +38,7 @@ int DoNames(int state) {  			void *info = LoadFile(&fh, "/NewerRes/LevelInfo.bin");  			LevelInfo_Prepare(&fh); -			LevelInfo_Entry *entry = LevelInfo_Search(info, wnum, lnum); +			LevelInfo_Entry *entry = LevelInfo_SearchSlot(info, wnum, lnum);  			char *worldname = LevelInfo_GetName(info, entry);  			char *levelname = ""; diff --git a/src/newer.cpp b/src/newer.cpp index 2bad8a0..0b53fa6 100644 --- a/src/newer.cpp +++ b/src/newer.cpp @@ -1,82 +1,6 @@  #include <newer.h>  #include <game.h> -NWRWorld NewerWorldForLevelID(int w, int l) { -	switch (w) { -		case 1: return YOSHI_ISLAND; -		case 2: -				if (((l>1) && (l<5)) || (l==15) || (l==33) || (l==34)) -					return SOGGY_SEWERS; -				else -					return RUBBLE_RUINS; -		case 3: return MUSHROOM_PEAKS; -		case 4: return SAKURA_VILLAGE; -		case 5: -				if (l<7 || l==15 || l==33 || l==34) -					return FREEZEFLAME_GLACIER; -				else -					return FREEZEFLAME_VOLCANO; -		case 6: return PUMPKIN_BONEYARD; -		case 7: -				if (l<4) -					return SKY_MOUNTAIN; -				else -					return STARRY_SKIES; -		case 8: -				if (l<6 || l==15 || l==25 || l==33 || l==34) -					return KOOPA_PLANET; -				else -					return KOOPA_CORE; -		case 9: return BONUS_LAND; -		case 10: -				if (l<6 || l==30 || l==41) -					return GOLDWOOD_FOREST; -				else if (l<11 || l==32) -					return MINIMEGA_ISLAND; -				else if (l<16 || l==33 || l==34 || l==31) -					return CRYSTAL_CAVES; -				else if (l<19) -					return BOMBARD_CLIFFS; -				else -					return SKY_CITY; -	} - -	return UNKNOWN_WORLD; -} - - -const wchar_t *NewerWorldNames[] = { -	L"Yoshi's Island", -	L"Rubble Ruins", -	L"Soggy Sewers", -	L"Mushroom Peaks", -	L"Sakura Village", -	L"Freezeflame Glacier", -	L"Freezeflame Volcano", -	L"Pumpkin Boneyard", -	L"Sky Mountain", -	L"Starry Skies", -	L"Koopa Planet", -	L"Koopa Core", -	L"Bonus Land", -	L"Goldwood Forest", -	L"Mini-Mega Island", -	L"Crystal Caves", -	L"Bombard Cliffs", -	L"Sky City" -}; - -// This is an array so it can be accessed from fileselect.S -int NewerWorldCount[] = { -	18 -}; - -const wchar_t *NewerWorldName(NWRWorld world) { -	if (world < 0 || world >= WORLD_COUNT) -		return L"Unknown World"; -	return NewerWorldNames[world]; -} -  int getStarCoinCount() {  	SaveBlock *save = GetSaveFile()->GetBlock(-1); | 
