summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/fileselect.S88
-rw-r--r--src/koopatlas/core.cpp11
-rw-r--r--src/koopatlas/core.h2
-rw-r--r--src/koopatlas/hud.cpp323
-rw-r--r--src/koopatlas/hud.h33
-rw-r--r--src/koopatlas/mapdata.cpp16
-rw-r--r--src/koopatlas/mapdata.h20
-rw-r--r--src/koopatlas/pathmanager.cpp59
-rw-r--r--src/koopatlas/pathmanager.h1
-rw-r--r--src/koopatlas/starcoin.cpp2
-rw-r--r--src/levelinfo.cpp6
-rw-r--r--src/levelinfo.h10
-rw-r--r--src/levelinfo_old.cpp4
-rw-r--r--src/levelinfo_old.h10
-rw-r--r--src/levelnames.cpp2
-rw-r--r--src/newer.cpp76
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);