diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index f8b671599..faa799c74 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -414,6 +414,17 @@ void SaveManager::InitMeta(int fileNum) { } fileMetaInfo[fileNum].healthCapacity = gSaveContext.healthCapacity; fileMetaInfo[fileNum].questItems = gSaveContext.inventory.questItems; + for (int i = 0; i < ARRAY_COUNT(fileMetaInfo[fileNum].inventoryItems); i++) { + fileMetaInfo[fileNum].inventoryItems[i] = gSaveContext.inventory.items[i]; + } + fileMetaInfo[fileNum].equipment = gSaveContext.inventory.equipment; + fileMetaInfo[fileNum].upgrades = gSaveContext.inventory.upgrades; + fileMetaInfo[fileNum].isMagicAcquired = gSaveContext.isMagicAcquired; + fileMetaInfo[fileNum].isDoubleMagicAcquired = gSaveContext.isDoubleMagicAcquired; + fileMetaInfo[fileNum].rupees = gSaveContext.rupees; + fileMetaInfo[fileNum].gsTokens = gSaveContext.inventory.gsTokens; + fileMetaInfo[fileNum].isDoubleDefenseAcquired = gSaveContext.isDoubleDefenseAcquired; + fileMetaInfo[fileNum].gregFound = Flags_GetRandomizerInf(RAND_INF_GREG_FOUND); fileMetaInfo[fileNum].defense = gSaveContext.inventory.defenseHearts; fileMetaInfo[fileNum].health = gSaveContext.health; diff --git a/soh/soh/SaveManager.h b/soh/soh/SaveManager.h index 628b694f2..f5f91c5bd 100644 --- a/soh/soh/SaveManager.h +++ b/soh/soh/SaveManager.h @@ -19,6 +19,16 @@ typedef struct { s16 buildVersionMajor; s16 buildVersionMinor; s16 buildVersionPatch; + + u8 inventoryItems[24]; + u16 equipment; + u32 upgrades; + u8 isMagicAcquired; + u8 isDoubleMagicAcquired; + s16 rupees; + s16 gsTokens; + u8 isDoubleDefenseAcquired; + u8 gregFound; } SaveFileMetaInfo; #ifdef __cplusplus diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 68f64c3a2..313bf4036 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -958,6 +958,8 @@ void DrawEnhancementsMenu() { "This might affect other decal effects\n"); UIWidgets::PaddedEnhancementSliderInt("Text Spacing: %d", "##TEXTSPACING", "gTextSpacing", 4, 6, "", 6, true, true, true); UIWidgets::Tooltip("Space between text characters (useful for HD font textures)"); + UIWidgets::PaddedEnhancementCheckbox("More info in file select", "gFileSelectMoreInfo", true, false); + UIWidgets::Tooltip("Shows what items you have collected in the file select screen, like in N64 randomizer"); ImGui::EndMenu(); } diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c index f36b5d669..d298b4715 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c @@ -5,6 +5,9 @@ #include "textures/title_static/title_static.h" #include "textures/parameter_static/parameter_static.h" #include +#include +#include +#include #include "soh/frame_interpolation.h" #include #include "objects/object_mag/object_mag.h" @@ -17,6 +20,648 @@ #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include +typedef struct { + s16 left; + s16 top; +} IconPosition; + +typedef struct { + s16 width; + s16 height; +} IconSize; + +typedef struct { + Sprite sprite; + Color_RGBA8 color; + u8 item; + IconPosition pos; + IconSize size; +} ItemData; + +#define CREATE_SPRITE_24(iconTex, spriteId) { iconTex, 24, 24, G_IM_FMT_RGBA, G_IM_SIZ_32b, spriteId }, {0xFF, 0xFF, 0xFF, 0xFF} +#define CREATE_SPRITE_32(iconTex, spriteId) { iconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b, spriteId }, {0xFF, 0xFF, 0xFF, 0xFF} +#define CREATE_SPRITE_SONG(colorR, colorG, colorB) { dgSongNoteTex, 16, 24, G_IM_FMT_IA, G_IM_SIZ_8b, 100 }, {colorR, colorG, colorB, 0xFF} +#define CREATE_SPRITE_RUPEE(colorR, colorG, colorB) { dgRupeeCounterIconTex, 16, 16, G_IM_FMT_IA, G_IM_SIZ_8b, 102 }, {colorR, colorG, colorB, 0xFF} +#define CREATE_SPRITE_SKULL { dgDungeonMapSkullTex, 16, 16, G_IM_FMT_RGBA, G_IM_SIZ_16b, 104 }, {0xFF, 0xFF, 0xFF, 0xFF} +#define CREATE_SPRITE_COUNTER_DIGIT(i) { dgAmmoDigit##i##Tex, 8, 8, G_IM_FMT_IA, G_IM_SIZ_8b, 105+i } + +#define ICON_SIZE 12 +#define COUNTER_SIZE 16 +#define SONG_WIDTH 8 +#define SONG_HEIGHT 12 + +#define LEFT_OFFSET (int)0x37 +#define TOP_OFFSET (int)0x5C + +#define COUNTER_DIGITS_LEFT_OFFSET COUNTER_SIZE / 2 - 3 +#define COUNTER_DIGITS_TOP_OFFSET COUNTER_SIZE - 3 + +#define SIZE_NORMAL {ICON_SIZE, ICON_SIZE} +#define SIZE_COUNTER {COUNTER_SIZE, COUNTER_SIZE} +#define SIZE_SONG {SONG_WIDTH, SONG_HEIGHT} + +#define INV_IC_POS(x, y) {0x4E + ICON_SIZE * x, 0x00 + ICON_SIZE * y} +#define EQP_IC_POS(x, y) {0x7E + ICON_SIZE * x, 0x2A + ICON_SIZE * y} +#define SNG_IC_POS(x, y) {0x49 + SONG_WIDTH * x, 0x45 + SONG_HEIGHT * y} +#define UPG_IC_POS(x, y) {0x5A + ICON_SIZE * x, 0x2A + ICON_SIZE * y} +#define STN_IC_POS(i) {0x29 + ICON_SIZE * i, 0x31} + +static ItemData itemData[88] = { + {CREATE_SPRITE_32(dgDekuStickIconTex, 1), ITEM_STICK, INV_IC_POS(0, 0), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgDekuNutIconTex, 0), ITEM_NUT, INV_IC_POS(1, 0), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgBombIconTex, 2), ITEM_BOMB, INV_IC_POS(2, 0), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgFairyBowIconTex, 3), ITEM_BOW, INV_IC_POS(3, 0), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgFireArrowIconTex, 4), ITEM_ARROW_FIRE, INV_IC_POS(4, 0), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgDinsFireIconTex, 5), ITEM_DINS_FIRE, INV_IC_POS(5, 0), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgEmptyBottleIconTex, 20), ITEM_BOTTLE, INV_IC_POS(6, 0), SIZE_NORMAL}, + + {CREATE_SPRITE_32(dgFairySlingshotIconTex, 6), ITEM_SLINGSHOT, INV_IC_POS(0, 1), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgFairyOcarinaIconTex, 7), ITEM_OCARINA_FAIRY, INV_IC_POS(1, 1), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgOcarinaofTimeIconTex, 7), ITEM_OCARINA_TIME, INV_IC_POS(1, 1), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgBombchuIconTex, 9), ITEM_BOMBCHU, INV_IC_POS(2, 1), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgHookshotIconTex, 10), ITEM_HOOKSHOT, INV_IC_POS(3, 1), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgLongshotIconTex, 10), ITEM_LONGSHOT, INV_IC_POS(3, 1), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgIceArrowIconTex, 12), ITEM_ARROW_ICE, INV_IC_POS(4, 1), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgFaroresWindIconTex, 13), ITEM_FARORES_WIND, INV_IC_POS(5, 1), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgWeirdEggIconTex, 37), ITEM_WEIRD_EGG, INV_IC_POS(6, 1), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgCuccoIconTex, 37), ITEM_CHICKEN, INV_IC_POS(6, 1), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgZeldasLetterIconTex, 37), ITEM_LETTER_ZELDA, INV_IC_POS(6, 1), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgKeatonMaskIconTex, 37), ITEM_MASK_KEATON, INV_IC_POS(6, 1), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgSkullMaskIconTex, 37), ITEM_MASK_SKULL, INV_IC_POS(6, 1), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgSpookyMaskIconTex, 37), ITEM_MASK_SPOOKY, INV_IC_POS(6, 1), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgBunnyHoodIconTex, 37), ITEM_MASK_BUNNY, INV_IC_POS(6, 1), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgGoronMaskIconTex, 37), ITEM_MASK_GORON, INV_IC_POS(6, 1), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgZoraMaskIconTex, 37), ITEM_MASK_ZORA, INV_IC_POS(6, 1), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgGerudoMaskIconTex, 37), ITEM_MASK_GERUDO, INV_IC_POS(6, 1), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgMaskofTruthIconTex, 37), ITEM_MASK_TRUTH, INV_IC_POS(6, 1), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgSoldOutIconTex, 37), ITEM_SOLD_OUT, INV_IC_POS(6, 1), SIZE_NORMAL}, + + {CREATE_SPRITE_32(dgBoomerangIconTex, 14), ITEM_BOOMERANG, INV_IC_POS(0, 2), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgLensofTruthIconTex, 15), ITEM_LENS, INV_IC_POS(1, 2), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgMagicBeansIconTex, 16), ITEM_BEAN, INV_IC_POS(2, 2), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgMegatonHammerIconTex, 17), ITEM_HAMMER, INV_IC_POS(3, 2), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgLightArrowIconTex, 18), ITEM_ARROW_LIGHT, INV_IC_POS(4, 2), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgNayrusLoveIconTex, 19), ITEM_NAYRUS_LOVE, INV_IC_POS(5, 2), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgPocketEggIconTex, 53), ITEM_POCKET_EGG, INV_IC_POS(6, 2), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgPocketCuccoIconTex, 53), ITEM_POCKET_CUCCO, INV_IC_POS(6, 2), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgCojiroIconTex, 53), ITEM_COJIRO, INV_IC_POS(6, 2), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgOddMushroomIconTex, 53), ITEM_ODD_MUSHROOM, INV_IC_POS(6, 2), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgOddPotionIconTex, 53), ITEM_ODD_POTION, INV_IC_POS(6, 2), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgPoachersSawIconTex, 53), ITEM_SAW, INV_IC_POS(6, 2), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgBrokenBiggoronSwordIconTex, 53), ITEM_SWORD_BROKEN, INV_IC_POS(6, 2), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgPrescriptionIconTex, 53), ITEM_PRESCRIPTION, INV_IC_POS(6, 2), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgEyeBallFrogIconTex, 53), ITEM_FROG, INV_IC_POS(6, 2), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgEyeDropsIconTex, 53), ITEM_EYEDROPS, INV_IC_POS(6, 2), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgClaimCheckIconTex, 53), ITEM_CLAIM_CHECK, INV_IC_POS(6, 2), SIZE_NORMAL}, + + {CREATE_SPRITE_32(dgKokiriSwordIconTex, 54), ITEM_SWORD_KOKIRI, EQP_IC_POS(0, 0), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgMasterSwordIconTex, 55), ITEM_SWORD_MASTER, EQP_IC_POS(1, 0), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgBiggoronSwordIconTex, 56), ITEM_SWORD_BGS, EQP_IC_POS(2, 0), SIZE_NORMAL}, + + {CREATE_SPRITE_32(dgDekuShieldIconTex, 57), ITEM_SHIELD_DEKU, EQP_IC_POS(0, 1), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgHylianShieldIconTex, 58), ITEM_SHIELD_HYLIAN, EQP_IC_POS(1, 1), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgMirrorShieldIconTex, 59), ITEM_SHIELD_MIRROR, EQP_IC_POS(2, 1), SIZE_NORMAL}, + + {CREATE_SPRITE_32(dgKokiriTunicIconTex, 60), ITEM_TUNIC_KOKIRI, EQP_IC_POS(0, 2), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgGoronTunicIconTex, 61), ITEM_TUNIC_GORON, EQP_IC_POS(1, 2), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgZoraTunicIconTex, 62), ITEM_TUNIC_ZORA, EQP_IC_POS(2, 2), SIZE_NORMAL}, + + {CREATE_SPRITE_32(dgKokiriBootsIconTex, 63), ITEM_BOOTS_KOKIRI, EQP_IC_POS(0, 3), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgIronBootsIconTex, 64), ITEM_BOOTS_IRON, EQP_IC_POS(1, 3), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgHoverBootsIconTex, 65), ITEM_BOOTS_HOVER, EQP_IC_POS(2, 3), SIZE_NORMAL}, + + {CREATE_SPRITE_24(dgKokiriEmeraldIconTex, 87), ITEM_KOKIRI_EMERALD, STN_IC_POS(-1), SIZE_NORMAL}, + {CREATE_SPRITE_24(dgGoronRubyIconTex, 88), ITEM_GORON_RUBY, STN_IC_POS(0), SIZE_NORMAL}, + {CREATE_SPRITE_24(dgZoraSapphireIconTex, 89), ITEM_ZORA_SAPPHIRE, STN_IC_POS(1), SIZE_NORMAL}, + + {CREATE_SPRITE_24(dgForestMedallionIconTex, 81), ITEM_MEDALLION_FOREST, {0x37, 0x0A}, SIZE_NORMAL}, + {CREATE_SPRITE_24(dgFireMedallionIconTex, 82), ITEM_MEDALLION_FIRE, {0x37, 0x1A}, SIZE_NORMAL}, + {CREATE_SPRITE_24(dgWaterMedallionIconTex, 83), ITEM_MEDALLION_WATER, {0x29, 0x22}, SIZE_NORMAL}, + {CREATE_SPRITE_24(dgSpiritMedallionIconTex, 84), ITEM_MEDALLION_SPIRIT, {0x1B, 0x1A}, SIZE_NORMAL}, + {CREATE_SPRITE_24(dgShadowMedallionIconTex, 85), ITEM_MEDALLION_SHADOW, {0x1B, 0x0A}, SIZE_NORMAL}, + {CREATE_SPRITE_24(dgLightMedallionIconTex, 86), ITEM_MEDALLION_LIGHT, {0x29, 0x02}, SIZE_NORMAL}, + + {CREATE_SPRITE_32(dgGoronsBraceletIconTex, 71), ITEM_BRACELET, UPG_IC_POS(0, 0), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgSilverGauntletsIconTex, 71), ITEM_GAUNTLETS_SILVER, UPG_IC_POS(0, 0), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgGoldenGauntletsIconTex, 71), ITEM_GAUNTLETS_GOLD, UPG_IC_POS(0, 0), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgSilverScaleIconTex, 74), ITEM_SCALE_SILVER, UPG_IC_POS(1, 0), SIZE_NORMAL}, + {CREATE_SPRITE_32(dgGoldenScaleIconTex, 74), ITEM_SCALE_GOLDEN, UPG_IC_POS(1, 0), SIZE_NORMAL}, + {CREATE_SPRITE_24(dgSmallMagicJarIconTex, 97), ITEM_SINGLE_MAGIC, UPG_IC_POS(2, 0), SIZE_NORMAL}, + {CREATE_SPRITE_24(dgBigMagicJarIconTex, 97), ITEM_DOUBLE_MAGIC, UPG_IC_POS(2, 0), SIZE_NORMAL}, + {CREATE_SPRITE_RUPEE(0xC8, 0xFF, 0x64), ITEM_RUPEE_GREEN, UPG_IC_POS(0, 1), SIZE_NORMAL}, + {CREATE_SPRITE_24(dgGerudosCardIconTex, 91), ITEM_GERUDO_CARD, UPG_IC_POS(1, 1), SIZE_NORMAL}, + {CREATE_SPRITE_24(dgStoneOfAgonyIconTex, 90), ITEM_STONE_OF_AGONY, UPG_IC_POS(2, 1), SIZE_NORMAL}, + + {CREATE_SPRITE_SONG(224, 107, 255), ITEM_SONG_LULLABY, SNG_IC_POS(0, 0), SIZE_SONG}, + {CREATE_SPRITE_SONG(255, 195, 60), ITEM_SONG_EPONA, SNG_IC_POS(1, 0), SIZE_SONG}, + {CREATE_SPRITE_SONG(127, 255, 137), ITEM_SONG_SARIA, SNG_IC_POS(2, 0), SIZE_SONG}, + {CREATE_SPRITE_SONG(255, 255, 60), ITEM_SONG_SUN, SNG_IC_POS(3, 0), SIZE_SONG}, + {CREATE_SPRITE_SONG(119, 236, 255), ITEM_SONG_TIME, SNG_IC_POS(4, 0), SIZE_SONG}, + {CREATE_SPRITE_SONG(165, 165, 165), ITEM_SONG_STORMS, SNG_IC_POS(5, 0), SIZE_SONG}, + {CREATE_SPRITE_SONG(150, 255, 100), ITEM_SONG_MINUET, SNG_IC_POS(0, 1), SIZE_SONG}, + {CREATE_SPRITE_SONG(255, 80, 40), ITEM_SONG_BOLERO, SNG_IC_POS(1, 1), SIZE_SONG}, + {CREATE_SPRITE_SONG(100, 150, 255), ITEM_SONG_SERENADE, SNG_IC_POS(2, 1), SIZE_SONG}, + {CREATE_SPRITE_SONG(255, 160, 0), ITEM_SONG_REQUIEM, SNG_IC_POS(3, 1), SIZE_SONG}, + {CREATE_SPRITE_SONG(255, 100, 255), ITEM_SONG_NOCTURNE, SNG_IC_POS(4, 1), SIZE_SONG}, + {CREATE_SPRITE_SONG(255, 240, 100), ITEM_SONG_PRELUDE, SNG_IC_POS(5, 1), SIZE_SONG}, + + {CREATE_SPRITE_24(dgHeartContainerIconTex, 101), ITEM_DOUBLE_DEFENSE, {0x05, -0x04}, SIZE_COUNTER}, +}; + +static u8 color_product(u8 c1, u8 c2) { + u16 prod = (u16)c1 * (u16)c2; + u16 div255 = (prod + 1 + (prod >> 8)) >> 8; + return (u8)div255; +} + +static const Color_RGBA8 DIM = {0x40, 0x40, 0x40, 0x90}; + +void SpriteLoad(FileChooseContext* this, Sprite* sprite); +void SpriteDraw(FileChooseContext* this, Sprite* sprite, int left, int top, int width, int height); + +u8 HasItem(s16 fileIndex, u8 item) { + for (int i = 0; i < ARRAY_COUNT(Save_GetSaveMetaInfo(fileIndex)->inventoryItems); i += 1) { + u8 it = Save_GetSaveMetaInfo(fileIndex)->inventoryItems[i]; + if (it == item || (item == ITEM_BOTTLE && it >= ITEM_BOTTLE && it <= ITEM_POE)) { + return 1; + } + } + + if (item >= ITEM_SONG_MINUET && item <= ITEM_SONG_STORMS) { + return (Save_GetSaveMetaInfo(fileIndex)->questItems & (1 << (item - 0x54))) != 0; + } + + if (item >= ITEM_MEDALLION_FOREST && item <= ITEM_MEDALLION_LIGHT) { + return (Save_GetSaveMetaInfo(fileIndex)->questItems & (1 << (item - 0x66))) != 0; + } + + if (item >= ITEM_KOKIRI_EMERALD && item <= ITEM_GERUDO_CARD) { + return (Save_GetSaveMetaInfo(fileIndex)->questItems & (1 << (item - 0x5A))) != 0; + } + + if (item >= ITEM_SWORD_KOKIRI && item <= ITEM_SWORD_BGS) { + return (Save_GetSaveMetaInfo(fileIndex)->equipment & (1 << (item - 0x3B))) != 0; + } + + if (item >= ITEM_SHIELD_DEKU && item <= ITEM_SHIELD_MIRROR) { + return (Save_GetSaveMetaInfo(fileIndex)->equipment & (1 << (item - 0x3E + 4))) != 0; + } + + if (item >= ITEM_TUNIC_KOKIRI && item <= ITEM_TUNIC_ZORA) { + return (Save_GetSaveMetaInfo(fileIndex)->equipment & (1 << (item - 0x41 + 8))) != 0; + } + + if (item >= ITEM_BOOTS_KOKIRI && item <= ITEM_BOOTS_HOVER) { + return (Save_GetSaveMetaInfo(fileIndex)->equipment & (1 << (item - 0x44 + 12))) != 0; + } + + if (item == ITEM_SINGLE_MAGIC) { + return Save_GetSaveMetaInfo(fileIndex)->isMagicAcquired; + } + + if (item == ITEM_DOUBLE_MAGIC) { + return Save_GetSaveMetaInfo(fileIndex)->isDoubleMagicAcquired; + } + + if (item == ITEM_BRACELET) { + return ((Save_GetSaveMetaInfo(fileIndex)->upgrades & gUpgradeMasks[UPG_STRENGTH]) >> gUpgradeShifts[UPG_STRENGTH]) == 1; + } + + if (item == ITEM_GAUNTLETS_SILVER) { + return ((Save_GetSaveMetaInfo(fileIndex)->upgrades & gUpgradeMasks[UPG_STRENGTH]) >> gUpgradeShifts[UPG_STRENGTH]) == 2; + } + + if (item == ITEM_GAUNTLETS_GOLD) { + return ((Save_GetSaveMetaInfo(fileIndex)->upgrades & gUpgradeMasks[UPG_STRENGTH]) >> gUpgradeShifts[UPG_STRENGTH]) == 3; + } + + if (item == ITEM_SCALE_SILVER) { + return ((Save_GetSaveMetaInfo(fileIndex)->upgrades & gUpgradeMasks[UPG_SCALE]) >> gUpgradeShifts[UPG_SCALE]) == 1; + } + + if (item == ITEM_SCALE_GOLDEN) { + return ((Save_GetSaveMetaInfo(fileIndex)->upgrades & gUpgradeMasks[UPG_SCALE]) >> gUpgradeShifts[UPG_SCALE]) == 2; + } + + if (item == ITEM_DOUBLE_DEFENSE) { + return Save_GetSaveMetaInfo(fileIndex)->isDoubleDefenseAcquired; + } + + //greg + if (item == ITEM_RUPEE_GREEN) { + return Save_GetSaveMetaInfo(fileIndex)->gregFound; + } + + return 0; +} + +u8 ShouldRenderItem(s16 fileIndex, u8 item) { + //strength + if (item == ITEM_BRACELET && (HasItem(fileIndex, ITEM_GAUNTLETS_SILVER) || HasItem(fileIndex, ITEM_GAUNTLETS_GOLD))) { + return 0; + } + + if (item == ITEM_GAUNTLETS_SILVER && !HasItem(fileIndex, ITEM_GAUNTLETS_SILVER)) { + return 0; + } + + if (item == ITEM_GAUNTLETS_GOLD && !HasItem(fileIndex, ITEM_GAUNTLETS_GOLD)) { + return 0; + } + + //magic + if (item == ITEM_SINGLE_MAGIC && HasItem(fileIndex, ITEM_DOUBLE_MAGIC)) { + return 0; + } + + if (item == ITEM_DOUBLE_MAGIC && !HasItem(fileIndex, ITEM_DOUBLE_MAGIC)) { + return 0; + } + + //scales + if (item == ITEM_SCALE_SILVER && HasItem(fileIndex, ITEM_SCALE_GOLDEN)) { + return 0; + } + + if (item == ITEM_SCALE_GOLDEN && !HasItem(fileIndex, ITEM_SCALE_GOLDEN)) { + return 0; + } + + //hookshot/longshot + if (item == ITEM_HOOKSHOT && HasItem(fileIndex, ITEM_LONGSHOT)) { + return 0; + } + + if (item == ITEM_LONGSHOT && !HasItem(fileIndex, ITEM_LONGSHOT)) { + return 0; + } + + //ocarinas + if (item == ITEM_OCARINA_FAIRY && HasItem(fileIndex, ITEM_OCARINA_TIME)) { + return 0; + } + + if (item == ITEM_OCARINA_TIME && !HasItem(fileIndex, ITEM_OCARINA_TIME)) { + return 0; + } + + //trade child + if (item == ITEM_WEIRD_EGG && !HasItem(fileIndex, ITEM_WEIRD_EGG)) { + return 0; + } + + if (item == ITEM_CHICKEN && !HasItem(fileIndex, ITEM_CHICKEN)) { + return 0; + } + + if (item == ITEM_LETTER_ZELDA && !HasItem(fileIndex, ITEM_LETTER_ZELDA)) { + return 0; + } + + if ( + item == ITEM_MASK_KEATON && + ( + HasItem(fileIndex, ITEM_WEIRD_EGG) || + HasItem(fileIndex, ITEM_CHICKEN) || + HasItem(fileIndex, ITEM_LETTER_ZELDA) || + HasItem(fileIndex, ITEM_MASK_SKULL) || + HasItem(fileIndex, ITEM_MASK_SPOOKY) || + HasItem(fileIndex, ITEM_MASK_BUNNY) || + HasItem(fileIndex, ITEM_MASK_GORON) || + HasItem(fileIndex, ITEM_MASK_ZORA) || + HasItem(fileIndex, ITEM_MASK_GERUDO) || + HasItem(fileIndex, ITEM_MASK_TRUTH) || + HasItem(fileIndex, ITEM_SOLD_OUT) + ) + ) { + return 0; + } + + if (item == ITEM_MASK_SKULL && !HasItem(fileIndex, ITEM_MASK_SKULL)) { + return 0; + } + + if (item == ITEM_MASK_SPOOKY && !HasItem(fileIndex, ITEM_MASK_SPOOKY)) { + return 0; + } + + if (item == ITEM_MASK_BUNNY && !HasItem(fileIndex, ITEM_MASK_BUNNY)) { + return 0; + } + + if (item == ITEM_MASK_GORON && !HasItem(fileIndex, ITEM_MASK_GORON)) { + return 0; + } + + if (item == ITEM_MASK_ZORA && !HasItem(fileIndex, ITEM_MASK_ZORA)) { + return 0; + } + + if (item == ITEM_MASK_GERUDO && !HasItem(fileIndex, ITEM_MASK_GERUDO)) { + return 0; + } + + if (item == ITEM_MASK_TRUTH && !HasItem(fileIndex, ITEM_MASK_TRUTH)) { + return 0; + } + + if (item == ITEM_SOLD_OUT && !HasItem(fileIndex, ITEM_SOLD_OUT)) { + return 0; + } + + //trade adult + if ( + item == ITEM_POCKET_EGG && + ( + HasItem(fileIndex, ITEM_POCKET_CUCCO) || + HasItem(fileIndex, ITEM_COJIRO) || + HasItem(fileIndex, ITEM_ODD_MUSHROOM) || + HasItem(fileIndex, ITEM_ODD_POTION) || + HasItem(fileIndex, ITEM_SAW) || + HasItem(fileIndex, ITEM_SWORD_BROKEN) || + HasItem(fileIndex, ITEM_PRESCRIPTION) || + HasItem(fileIndex, ITEM_FROG) || + HasItem(fileIndex, ITEM_EYEDROPS) || + HasItem(fileIndex, ITEM_CLAIM_CHECK) + ) + ) { + return 0; + } + + if (item == ITEM_POCKET_CUCCO && !HasItem(fileIndex, ITEM_POCKET_CUCCO)) { + return 0; + } + + if (item == ITEM_COJIRO && !HasItem(fileIndex, ITEM_COJIRO)) { + return 0; + } + + if (item == ITEM_ODD_MUSHROOM && !HasItem(fileIndex, ITEM_ODD_MUSHROOM)) { + return 0; + } + + if (item == ITEM_ODD_POTION && !HasItem(fileIndex, ITEM_ODD_POTION)) { + return 0; + } + + if (item == ITEM_SAW && !HasItem(fileIndex, ITEM_SAW)) { + return 0; + } + + if (item == ITEM_SWORD_BROKEN && !HasItem(fileIndex, ITEM_SWORD_BROKEN)) { + return 0; + } + + if (item == ITEM_PRESCRIPTION && !HasItem(fileIndex, ITEM_PRESCRIPTION)) { + return 0; + } + + if (item == ITEM_FROG && !HasItem(fileIndex, ITEM_FROG)) { + return 0; + } + + if (item == ITEM_EYEDROPS && !HasItem(fileIndex, ITEM_EYEDROPS)) { + return 0; + } + + if (item == ITEM_CLAIM_CHECK && !HasItem(fileIndex, ITEM_CLAIM_CHECK)) { + return 0; + } + + if (item == ITEM_DOUBLE_DEFENSE && !Save_GetSaveMetaInfo(fileIndex)->isDoubleDefenseAcquired) { + return 0; + } + + //greg + if (item == ITEM_RUPEE_GREEN) { + return Save_GetSaveMetaInfo(fileIndex)->randoSave; + } + + return 1; +} + +static void DrawItems(FileChooseContext* this, s16 fileIndex, u8 alpha) { + OPEN_DISPS(this->state.gfxCtx); + gDPPipeSync(POLY_OPA_DISP++); + gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); + + for (int i = 0; i < ARRAY_COUNT(itemData); i += 1) { + ItemData* data = &itemData[i]; + + if (ShouldRenderItem(fileIndex, data->item)) { + if (HasItem(fileIndex, data->item)) { + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, data->color.r, data->color.g, data->color.b, color_product(data->color.a, alpha)); + } else { + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, color_product(data->color.r, DIM.r), color_product(data->color.g, DIM.g), color_product(data->color.b, DIM.b), color_product(color_product(data->color.a, DIM.a), alpha)); + } + + SpriteLoad(this, &(data->sprite)); + SpriteDraw(this, &(data->sprite), LEFT_OFFSET + data->pos.left, TOP_OFFSET + data->pos.top, data->size.width, data->size.height); + } + } + + gDPPipeSync(POLY_OPA_DISP++); + CLOSE_DISPS(this->state.gfxCtx); +} + +typedef enum { + /* 0x00 */ COUNTER_HEALTH, + /* 0x01 */ COUNTER_WALLET_CHILD, + /* 0x02 */ COUNTER_WALLET_ADULT, + /* 0x03 */ COUNTER_WALLET_GIANT, + /* 0x04 */ COUNTER_WALLET_TYCOON, + /* 0x04 */ COUNTER_SKULLTULLAS, + /* 0x04 */ COUNTER_DEATHS, +} CounterID; + +typedef struct { + Sprite sprite; + Color_RGBA8 color; + u8 id; + IconPosition pos; + IconSize size; +} CounterData; + +static CounterData counterData[7] = { + {CREATE_SPRITE_24(dgHeartContainerIconTex, 101), COUNTER_HEALTH, {0x05, 0x00}, SIZE_COUNTER}, + {CREATE_SPRITE_RUPEE(0xC8, 0xFF, 0x64), COUNTER_WALLET_CHILD, {0x05, 0x15}, SIZE_COUNTER}, + {CREATE_SPRITE_RUPEE(0x82, 0x82, 0xFF), COUNTER_WALLET_ADULT, {0x05, 0x15}, SIZE_COUNTER}, + {CREATE_SPRITE_RUPEE(0xFF, 0x64, 0x64), COUNTER_WALLET_GIANT, {0x05, 0x15}, SIZE_COUNTER}, + {CREATE_SPRITE_RUPEE(0xFF, 0x5A, 0xFF), COUNTER_WALLET_TYCOON, {0x05, 0x15}, SIZE_COUNTER}, + {CREATE_SPRITE_24(dgGoldSkulltulaIconTex, 103), COUNTER_SKULLTULLAS, {0x05, 0x2A}, SIZE_COUNTER}, + {CREATE_SPRITE_SKULL, COUNTER_DEATHS, {0x48, 0x2A}, SIZE_COUNTER}, +}; + +static Sprite counterDigitSprites[10] = { + CREATE_SPRITE_COUNTER_DIGIT(0), + CREATE_SPRITE_COUNTER_DIGIT(1), + CREATE_SPRITE_COUNTER_DIGIT(2), + CREATE_SPRITE_COUNTER_DIGIT(3), + CREATE_SPRITE_COUNTER_DIGIT(4), + CREATE_SPRITE_COUNTER_DIGIT(5), + CREATE_SPRITE_COUNTER_DIGIT(6), + CREATE_SPRITE_COUNTER_DIGIT(7), + CREATE_SPRITE_COUNTER_DIGIT(8), + CREATE_SPRITE_COUNTER_DIGIT(9), +}; + +u8 ShouldRenderCounter(s16 fileIndex, u8 counterId) { + if (counterId == COUNTER_WALLET_CHILD) { + return ((Save_GetSaveMetaInfo(fileIndex)->upgrades & gUpgradeMasks[UPG_WALLET]) >> gUpgradeShifts[UPG_WALLET]) == 0; + } + + if (counterId == COUNTER_WALLET_ADULT) { + return ((Save_GetSaveMetaInfo(fileIndex)->upgrades & gUpgradeMasks[UPG_WALLET]) >> gUpgradeShifts[UPG_WALLET]) == 1; + } + + if (counterId == COUNTER_WALLET_GIANT) { + return ((Save_GetSaveMetaInfo(fileIndex)->upgrades & gUpgradeMasks[UPG_WALLET]) >> gUpgradeShifts[UPG_WALLET]) == 2; + } + + if (counterId == COUNTER_WALLET_TYCOON) { + return ((Save_GetSaveMetaInfo(fileIndex)->upgrades & gUpgradeMasks[UPG_WALLET]) >> gUpgradeShifts[UPG_WALLET]) == 3; + } + + return 1; +} + +u16 GetCurrentCounterValue(s16 fileIndex, u8 counter) { + //one heart is 16 healthCapacity + if (counter == COUNTER_HEALTH) { + return Save_GetSaveMetaInfo(fileIndex)->healthCapacity / 16; + } + + if (counter >= COUNTER_WALLET_CHILD && counter <= COUNTER_WALLET_TYCOON) { + return Save_GetSaveMetaInfo(fileIndex)->rupees; + } + + if (counter == COUNTER_SKULLTULLAS) { + return Save_GetSaveMetaInfo(fileIndex)->gsTokens; + } + + if (counter == COUNTER_DEATHS) { + return Save_GetSaveMetaInfo(fileIndex)->deaths; + } + + return 0; +} + +u16 GetMaxCounterValue(s16 fileIndex, u8 counter) { + if (counter == COUNTER_HEALTH) { + return 20; + } + + if (counter == COUNTER_WALLET_CHILD) { + return 99; + } + + if (counter == COUNTER_WALLET_ADULT) { + return 200; + } + + if (counter == COUNTER_WALLET_GIANT) { + return 500; + } + + if (counter == COUNTER_WALLET_TYCOON) { + return 999; + } + + if (counter == COUNTER_SKULLTULLAS) { + return 100; + } + + if (counter == COUNTER_DEATHS) { + return 999; + } + + return 0; +} + +void DrawCounterValue(FileChooseContext* this, s16 fileIndex, u8 alpha, CounterData* data) { + u16 currentValue; + u16 maxValue; + s16 hundreds; + s16 tens; + + currentValue = GetCurrentCounterValue(fileIndex, data->id); + maxValue = GetMaxCounterValue(fileIndex, data->id); + + //to prevent crashes if you use the save editor + if (currentValue > 999) { + currentValue = 999; + } + + OPEN_DISPS(this->state.gfxCtx); + gDPPipeSync(POLY_OPA_DISP++); + gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); + + if (currentValue == 0) { + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 130, 130, 130, alpha); + } else if (currentValue == maxValue) { + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 120, 255, 0, alpha); + } else { + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, alpha); + } + + for (hundreds = 0; currentValue >= 100; hundreds++) { + currentValue -= 100; + } + + for (tens = 0; currentValue >= 10; tens++) { + currentValue -= 10; + } + + if (hundreds != 0) { + SpriteLoad(this, &counterDigitSprites[hundreds]); + SpriteDraw(this, &counterDigitSprites[hundreds], LEFT_OFFSET + COUNTER_DIGITS_LEFT_OFFSET - 6 + data->pos.left, TOP_OFFSET + COUNTER_DIGITS_TOP_OFFSET + data->pos.top, 8, 8); + + SpriteLoad(this, &counterDigitSprites[tens]); + SpriteDraw(this, &counterDigitSprites[tens], LEFT_OFFSET + COUNTER_DIGITS_LEFT_OFFSET + data->pos.left, TOP_OFFSET + COUNTER_DIGITS_TOP_OFFSET + data->pos.top, 8, 8); + + SpriteLoad(this, &counterDigitSprites[currentValue]); + SpriteDraw(this, &counterDigitSprites[currentValue], LEFT_OFFSET + COUNTER_DIGITS_LEFT_OFFSET + 6 + data->pos.left, TOP_OFFSET + COUNTER_DIGITS_TOP_OFFSET + data->pos.top, 8, 8); + } else if (tens != 0) { + SpriteLoad(this, &counterDigitSprites[tens]); + SpriteDraw(this, &counterDigitSprites[tens], LEFT_OFFSET + COUNTER_DIGITS_LEFT_OFFSET - 3 + data->pos.left, TOP_OFFSET + COUNTER_DIGITS_TOP_OFFSET + data->pos.top, 8, 8); + + SpriteLoad(this, &counterDigitSprites[currentValue]); + SpriteDraw(this, &counterDigitSprites[currentValue], LEFT_OFFSET + COUNTER_DIGITS_LEFT_OFFSET + 3 + data->pos.left, TOP_OFFSET + COUNTER_DIGITS_TOP_OFFSET + data->pos.top, 8, 8); + } else { + SpriteLoad(this, &counterDigitSprites[currentValue]); + SpriteDraw(this, &counterDigitSprites[currentValue], LEFT_OFFSET + COUNTER_DIGITS_LEFT_OFFSET + data->pos.left, TOP_OFFSET + COUNTER_DIGITS_TOP_OFFSET + data->pos.top, 8, 8); + } + + gDPPipeSync(POLY_OPA_DISP++); + CLOSE_DISPS(this->state.gfxCtx); +} + +static void DrawCounters(FileChooseContext* this, s16 fileIndex, u8 alpha) { + OPEN_DISPS(this->state.gfxCtx); + gDPPipeSync(POLY_OPA_DISP++); + gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); + + for (int i = 0; i < ARRAY_COUNT(counterData); i += 1) { + CounterData* data = &counterData[i]; + + if (ShouldRenderCounter(fileIndex, data->id)) { + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, data->color.r, data->color.g, data->color.b, color_product(data->color.a, alpha)); + + SpriteLoad(this, &(data->sprite)); + SpriteDraw(this, &(data->sprite), LEFT_OFFSET + data->pos.left, TOP_OFFSET + data->pos.top, data->size.width, data->size.height); + + DrawCounterValue(this, fileIndex, alpha, data); + } + } + + gDPPipeSync(POLY_OPA_DISP++); + CLOSE_DISPS(this->state.gfxCtx); +} + +static void DrawMoreInfo(FileChooseContext* this, s16 fileIndex, u8 alpha) { + DrawItems(this, fileIndex, alpha); + DrawCounters(this, fileIndex, alpha); +} #define MIN_QUEST (ResourceMgr_GameHasOriginal() ? FS_QUEST_NORMAL : FS_QUEST_MASTER) #define MAX_QUEST FS_QUEST_BOSSRUSH @@ -268,14 +913,25 @@ void FileChoose_FinishFadeIn(GameState* thisx) { void SpriteLoad(FileChooseContext* this, Sprite* sprite) { OPEN_DISPS(this->state.gfxCtx); - if (sprite->im_siz == G_IM_SIZ_16b) { + /* + * Due to macro expansion and the token-pasting operator (##), we cannot pass sprite->im_siz in directly. + * Instead we must call gDPLoadTextureBlock with the raw IM_SIZ define name itself to properly expand the correct + * defines internally. + */ + + if (sprite->im_siz == G_IM_SIZ_8b) { gDPLoadTextureBlock(POLY_OPA_DISP++, sprite->tex, sprite->im_fmt, - G_IM_SIZ_16b, // @TEMP until I figure out how to use sprite->im_siz + G_IM_SIZ_8b, + sprite->width, sprite->height, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, + G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + } else if (sprite->im_siz == G_IM_SIZ_16b) { + gDPLoadTextureBlock(POLY_OPA_DISP++, sprite->tex, sprite->im_fmt, + G_IM_SIZ_16b, sprite->width, sprite->height, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); } else { gDPLoadTextureBlock(POLY_OPA_DISP++, sprite->tex, sprite->im_fmt, - G_IM_SIZ_32b, // @TEMP until I figure out how to use sprite->im_siz + G_IM_SIZ_32b, sprite->width, sprite->height, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); } @@ -317,7 +973,7 @@ void DrawSeedHashSprites(FileChooseContext* this) { if (Save_GetSaveMetaInfo(this->selectedFileIndex)->randoSave == 1) { SpriteLoad(this, GetSeedTexture(Save_GetSaveMetaInfo(this->selectedFileIndex)->seedHash[i])); SpriteDraw(this, GetSeedTexture(Save_GetSaveMetaInfo(this->selectedFileIndex)->seedHash[i]), - xStart + (18 * i), 136, 16, 16); + xStart + (40 * i), 10, 24, 24); } } } @@ -331,7 +987,7 @@ void DrawSeedHashSprites(FileChooseContext* this) { gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 0xFF, 0xFF, 0xFF, alpha); // Draw Seed Icons for spoiler log - if (strnlen(CVarGetString("gSpoilerLog", ""), 1) != 0 && fileSelectSpoilerFileLoaded) { + if (this->configMode == CM_QUEST_MENU && this->questType[this->buttonIndex] == FS_QUEST_RANDOMIZER && strnlen(CVarGetString("gSpoilerLog", ""), 1) != 0 && fileSelectSpoilerFileLoaded) { u16 xStart = 64; for (unsigned int i = 0; i < 5; i++) { SpriteLoad(this, GetSeedTexture(gSaveContext.seedIcons[i])); @@ -1346,9 +2002,11 @@ void FileChoose_DrawFileInfo(GameState* thisx, s16 fileIndex, s16 isActive) { &deathCountSplit[2]); // draw death count - for (i = 0, vtxOffset = 0; i < 3; i++, vtxOffset += 4) { - FileChoose_DrawCharacter(this->state.gfxCtx, sp54->fontBuf + deathCountSplit[i] * FONT_CHAR_TEX_SIZE, - vtxOffset); + if (CVarGetInteger("gFileSelectMoreInfo", 0) == 0 || this->menuMode != FS_MENU_MODE_SELECT) { + for (i = 0, vtxOffset = 0; i < 3; i++, vtxOffset += 4) { + FileChoose_DrawCharacter(this->state.gfxCtx, sp54->fontBuf + deathCountSplit[i] * FONT_CHAR_TEX_SIZE, + vtxOffset); + } } gDPPipeSync(POLY_OPA_DISP++); @@ -1368,42 +2026,48 @@ void FileChoose_DrawFileInfo(GameState* thisx, s16 fileIndex, s16 isActive) { i = Save_GetSaveMetaInfo(fileIndex)->healthCapacity / 0x10; - // draw hearts - for (vtxOffset = 0, j = 0; j < i; j++, vtxOffset += 4) { - gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_8081284C[fileIndex] + vtxOffset] + 0x30, 4, 0); + if (CVarGetInteger("gFileSelectMoreInfo", 0) == 0 || this->menuMode != FS_MENU_MODE_SELECT) { + // draw hearts + for (vtxOffset = 0, j = 0; j < i; j++, vtxOffset += 4) { + gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_8081284C[fileIndex] + vtxOffset] + 0x30, 4, 0); - POLY_OPA_DISP = FileChoose_QuadTextureIA8(POLY_OPA_DISP, sHeartTextures[heartType], 0x10, 0x10, 0); + POLY_OPA_DISP = FileChoose_QuadTextureIA8(POLY_OPA_DISP, sHeartTextures[heartType], 0x10, 0x10, 0); + } } gDPPipeSync(POLY_OPA_DISP++); - // draw quest items - for (vtxOffset = 0, j = 0; j < 9; j++, vtxOffset += 4) { - if (Save_GetSaveMetaInfo(fileIndex)->questItems & gBitFlags[sQuestItemFlags[j]]) { - gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_8081284C[fileIndex] + vtxOffset] + 0x80, 4, 0); - gDPPipeSync(POLY_OPA_DISP++); - gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, sQuestItemRed[j], sQuestItemGreen[j], sQuestItemBlue[j], - this->fileInfoAlpha[fileIndex]); - gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 0); - - if (j < 3) { - gDPLoadTextureBlock(POLY_OPA_DISP++, sQuestItemTextures[j], G_IM_FMT_RGBA, G_IM_SIZ_32b, 16, 16, 0, - G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP, - G_TX_NOMASK, G_TX_NOLOD); - gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0); - - } else { - POLY_OPA_DISP = FileChoose_QuadTextureIA8(POLY_OPA_DISP, sQuestItemTextures[j], 0x10, 0x10, 0); - } - } - } - // Use file info alpha to match fading u8 textAlpha = this->fileInfoAlpha[fileIndex]; if (textAlpha >= 200) { textAlpha = 255; } + if (CVarGetInteger("gFileSelectMoreInfo", 0) != 0 && this->menuMode == FS_MENU_MODE_SELECT) { + DrawMoreInfo(this, fileIndex, textAlpha); + } else { + // draw quest items + for (vtxOffset = 0, j = 0; j < 9; j++, vtxOffset += 4) { + if (Save_GetSaveMetaInfo(fileIndex)->questItems & gBitFlags[sQuestItemFlags[j]]) { + gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_8081284C[fileIndex] + vtxOffset] + 0x80, 4, 0); + gDPPipeSync(POLY_OPA_DISP++); + gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, sQuestItemRed[j], sQuestItemGreen[j], sQuestItemBlue[j], + this->fileInfoAlpha[fileIndex]); + gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 0); + + if (j < 3) { + gDPLoadTextureBlock(POLY_OPA_DISP++, sQuestItemTextures[j], G_IM_FMT_RGBA, G_IM_SIZ_32b, 16, 16, 0, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP, + G_TX_NOMASK, G_TX_NOLOD); + gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0); + + } else { + POLY_OPA_DISP = FileChoose_QuadTextureIA8(POLY_OPA_DISP, sQuestItemTextures[j], 0x10, 0x10, 0); + } + } + } + } + // Draw rando seed warning when build version doesn't match for Major or Minor number if (Save_GetSaveMetaInfo(fileIndex)->randoSave == 1 && this->menuMode == FS_MENU_MODE_SELECT && @@ -1698,13 +2362,25 @@ void FileChoose_DrawWindowContents(GameState* thisx) { gDPPipeSync(POLY_OPA_DISP++); gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2], this->fileInfoAlpha[fileIndex]); - gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[temp], 20, 0); - for (quadVtxIndex = 0, i = 0; i < 5; i++, quadVtxIndex += 4) { - gDPLoadTextureBlock(POLY_OPA_DISP++, sFileInfoBoxTextures[i], G_IM_FMT_IA, G_IM_SIZ_16b, - sFileInfoBoxPartWidths[i], 56, 0, G_TX_NOMIRROR | G_TX_WRAP, - G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - gSP1Quadrangle(POLY_OPA_DISP++, quadVtxIndex, quadVtxIndex + 2, quadVtxIndex + 3, quadVtxIndex + 1, 0); + // Draw the small file name box instead when more meta info is enabled + if (CVarGetInteger("gFileSelectMoreInfo", 0) != 0 && this->menuMode == FS_MENU_MODE_SELECT) { + // Location of file 1 small name box vertices + gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[68], 4, 0); + + gDPLoadTextureBlock(POLY_OPA_DISP++, gFileSelNameBoxTex, G_IM_FMT_IA, G_IM_SIZ_16b, 108, 16, 0, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, + G_TX_NOLOD, G_TX_NOLOD); + gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0); + } else { + gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[temp], 20, 0); + + for (quadVtxIndex = 0, i = 0; i < 5; i++, quadVtxIndex += 4) { + gDPLoadTextureBlock(POLY_OPA_DISP++, sFileInfoBoxTextures[i], G_IM_FMT_IA, G_IM_SIZ_16b, + sFileInfoBoxPartWidths[i], 56, 0, G_TX_NOMIRROR | G_TX_WRAP, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + gSP1Quadrangle(POLY_OPA_DISP++, quadVtxIndex, quadVtxIndex + 2, quadVtxIndex + 3, quadVtxIndex + 1, 0); + } } }