From 411c5a8e210b5cbca330a5438e2406dbe1ffecab Mon Sep 17 00:00:00 2001 From: Treeki Date: Thu, 27 Sep 2012 04:40:34 +0200 Subject: made world changes work, and HUD colourising and other fun things --- src/fileselect.S | 59 ++++++++++------ src/koopatlas/hud.cpp | 158 ++++++++++++++++++++++++++++++++++++++++-- src/koopatlas/hud.h | 21 +++++- src/koopatlas/mapdata.cpp | 2 +- src/koopatlas/pathmanager.cpp | 11 +-- src/newer.cpp | 76 -------------------- 6 files changed, 216 insertions(+), 111 deletions(-) (limited to 'src') diff --git a/src/fileselect.S b/src/fileselect.S index 9f7f396..16a1047 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 @@ -255,10 +271,13 @@ NormalExitStr: .string " %d-%d\n" SecretExitStr: .string " %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 diff --git a/src/koopatlas/hud.cpp b/src/koopatlas/hud.cpp index 4f4ce2f..84329bf 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() { @@ -63,13 +204,13 @@ 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", "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, 12); static const char *textBoxNames[] = { "LevelName", "LevelNameS", @@ -81,6 +222,10 @@ 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; willShowHeader = false; @@ -228,6 +373,9 @@ void dWMHud_c::loadHeaderInfo() { totalWidth = 270.0f; Header_Centre->size.x = totalWidth; Header_Right->trans.x = totalWidth; + + SaveBlock *save = GetSaveFile()->GetBlock(-1); + headerCol.colourise(save->hudHintH, save->hudHintS, save->hudHintL); } @@ -246,8 +394,10 @@ void dWMHud_c::loadFooterInfo() { WorldName->SetString(convertedWorldName); WorldNameS->SetString(convertedWorldName); - WorldName->colour1 = save->hudTextColour[0]; - WorldName->colour2 = save->hudTextColour[1]; + WorldName->colour1 = save->hudTextColours[0]; + WorldName->colour2 = save->hudTextColours[1]; + + footerCol.colourise(save->hudHintH, save->hudHintS, save->hudHintL); } diff --git a/src/koopatlas/hud.h b/src/koopatlas/hud.h index deac84f..c0079af 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(); @@ -39,12 +56,14 @@ class dWMHud_c : public dBase_c { void loadFooterInfo(); bool willShowFooter; + 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, *StarCoinOn[3], *P_marioFace_00, *P_luigiFace_00, diff --git a/src/koopatlas/mapdata.cpp b/src/koopatlas/mapdata.cpp index 29c6a23..d4f9d0c 100644 --- a/src/koopatlas/mapdata.cpp +++ b/src/koopatlas/mapdata.cpp @@ -286,7 +286,7 @@ void dKPMapData_c::fixup() { } -const dKPWorldDef_s *dKPMapData_c::findWorldDef(int id) { +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]; diff --git a/src/koopatlas/pathmanager.cpp b/src/koopatlas/pathmanager.cpp index 2401e04..896707a 100644 --- a/src/koopatlas/pathmanager.cpp +++ b/src/koopatlas/pathmanager.cpp @@ -566,7 +566,7 @@ 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; @@ -595,7 +595,7 @@ void dWMPathManager_c::moveThroughPath() { SaveBlock *save = GetSaveFile()->GetBlock(-1); OSReport("Activating world change %d\n", to->worldID); - dKPWorldDef_s *world = dScKoopatlas_c::instance->mapData.findWorldDef(to->worldID); + const dKPWorldDef_s *world = dScKoopatlas_c::instance->mapData.findWorldDef(to->worldID); if (world) { OSReport("Found!\n"); strncpy(save->newerWorldName, world->name, 36); @@ -653,13 +653,6 @@ void dWMPathManager_c::moveThroughPath() { save->current_path_node = pathLayer->findNodeID(to); if (!calledEnteredNode) 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"); 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 #include -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); -- cgit v1.2.3