RBA and BA

This commit is contained in:
rozlette 2024-12-08 00:22:33 -06:00
parent bccd96966f
commit 4ffdc0b2f9
2 changed files with 281 additions and 15 deletions

View File

@ -1551,8 +1551,6 @@ void DrawEnhancementsMenu() {
UIWidgets::Tooltip("Restore pre-release behavior where defeating a Gold Skulltula will play a cutscene showing it die.");
UIWidgets::PaddedEnhancementCheckbox("Quick Bongo Kill", CVAR_ENHANCEMENT("QuickBongoKill"), true, false);
UIWidgets::Tooltip("Restore a bug from NTSC 1.0 that allows bypassing Bongo Bongo's intro cutscene to quickly kill him");
UIWidgets::PaddedEnhancementCheckbox("Original RBA Values", CVAR_ENHANCEMENT("RestoreRBAValues"), true, false);
UIWidgets::Tooltip("Restores the original outcomes when performing Reverse Bottle Adventure.");
UIWidgets::PaddedEnhancementCheckbox("Early Eyeball Frog", CVAR_ENHANCEMENT("EarlyEyeballFrog"), true, false);
UIWidgets::Tooltip("Restores a bug from NTSC 1.0/1.1 that allows you to obtain the eyeball frog from King Zora instead of the Zora Tunic by holding shield.");

View File

@ -1439,6 +1439,140 @@ Gfx* Gfx_TextureI8(Gfx* displayListHead, void* texture, s16 textureWidth, s16 te
return displayListHead;
}
void Inventory_DoBA(u8 cRight) {
if (cRight >= ITEM_STICK && cRight <= ITEM_POTION_BLUE) {
gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.items[cRight];
} else if (cRight >= ITEM_FAIRY && cRight <= ITEM_MASK_BUNNY) {
gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.ammo[cRight - ITEM_FAIRY];
} else if (cRight == ITEM_MASK_GORON) {
gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.equipment >> 8) & 0xFF;
} else if (cRight == ITEM_MASK_ZORA) {
gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.equipment & 0xFF;
} else if (cRight == ITEM_MASK_GERUDO || cRight == ITEM_MASK_TRUTH) {
// ITEM_MASK_GERUDO and ITEM_MASK_TRUTH land in padding bytes
gSaveContext.equips.buttonItems[0] = 0;
} else if (cRight == ITEM_SOLD_OUT) {
gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.upgrades >> 24) & 0xFF;
} else if (cRight == ITEM_POCKET_EGG) {
gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.upgrades >> 16) & 0xFF;
} else if (cRight == ITEM_POCKET_CUCCO) {
gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.upgrades >> 8) & 0xFF;
} else if (cRight == ITEM_COJIRO) {
gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.upgrades & 0xFF;
} else if (cRight == ITEM_ODD_MUSHROOM) {
gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.questItems >> 24) & 0xFF;
} else if (cRight == ITEM_ODD_POTION) {
gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.questItems >> 16) & 0xFF;
} else if (cRight == ITEM_SAW) {
gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.questItems >> 8) & 0xFF;
} else if (cRight == ITEM_SWORD_BROKEN) {
gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.questItems & 0xFF;
} else if (cRight >= ITEM_PRESCRIPTION && cRight <= ITEM_BULLET_BAG_30) {
gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.dungeonItems[cRight - ITEM_PRESCRIPTION];
} else if (cRight >= ITEM_BULLET_BAG_40 && cRight <= ITEM_SWORD_KNIFE) {
gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.dungeonKeys[cRight - ITEM_BULLET_BAG_40];
} else if (cRight == ITEM_SONG_BOLERO) {
gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.defenseHearts;
} else if (cRight == ITEM_SONG_SERENADE) {
gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.gsTokens >> 8) & 0xFF;
} else if (cRight == ITEM_SONG_REQUIEM) {
gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.gsTokens & 0xFF;
} else if (cRight == ITEM_SONG_NOCTURNE || cRight == ITEM_SONG_PRELUDE) {
// ITEM_SONG_NOCTURNE and ITEM_SONG_PRELUDE land in padding bytes
gSaveContext.equips.buttonItems[0] = 0;
} else if (cRight >= ITEM_SONG_LULLABY) {
// The rest of the items fall into the saved scene flags. Let's calculate the scene and which field it pulls from
u32 offset = cRight - ITEM_SONG_LULLABY;
u32 scene = offset / sizeof(SavedSceneFlags);
switch (offset % sizeof(SavedSceneFlags)) {
case 0:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].chest >> 24) & 0xFF;
break;
case 1:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].chest >> 16) & 0xFF;
break;
case 2:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].chest >> 8) & 0xFF;
break;
case 3:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].chest & 0xFF;
break;
case 4:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].swch >> 24) & 0xFF;
break;
case 5:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].swch >> 16) & 0xFF;
break;
case 6:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].swch >> 8) & 0xFF;
break;
case 7:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].swch & 0xFF;
break;
case 8:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].clear >> 24) & 0xFF;
break;
case 9:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].clear >> 16) & 0xFF;
break;
case 10:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].clear >> 8) & 0xFF;
break;
case 11:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].clear & 0xFF;
break;
case 12:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].collect >> 24) & 0xFF;
break;
case 13:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].collect >> 16) & 0xFF;
break;
case 14:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].collect >> 8) & 0xFF;
break;
case 15:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].collect & 0xFF;
break;
case 16:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].unk >> 24) & 0xFF;
break;
case 17:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].unk >> 16) & 0xFF;
break;
case 18:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].unk >> 8) & 0xFF;
break;
case 19:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].unk & 0xFF;
break;
case 20:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].rooms >> 24) & 0xFF;
break;
case 21:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].rooms >> 16) & 0xFF;
break;
case 22:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].rooms >> 8) & 0xFF;
break;
case 23:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].rooms & 0xFF;
break;
case 24:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].floors >> 24) & 0xFF;
break;
case 25:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].floors >> 16) & 0xFF;
break;
case 26:
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].floors >> 8) & 0xFF;
break;
case 27:
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].floors & 0xFF;
break;
}
}
}
void Rando_Inventory_SwapAgeEquipment(void) {
s16 i;
u16 shieldEquipValue;
@ -1518,8 +1652,13 @@ void Rando_Inventory_SwapAgeEquipment(void) {
(gSaveContext.equips.buttonItems[i] <= ITEM_POE)) ||
((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) &&
(gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) {
gSaveContext.equips.buttonItems[i] =
gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]];
if (i == 0) {
// If bottle is on B, it triggers BA, which we need to recreate
Inventory_DoBA(gSaveContext.equips.buttonItems[3]);
} else {
gSaveContext.equips.buttonItems[i] =
gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]];
}
}
}
@ -1675,8 +1814,13 @@ void Inventory_SwapAgeEquipment(void) {
((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) &&
(gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) {
osSyncPrintf("Register_Item_Pt(%d)=%d\n", i, gSaveContext.equips.cButtonSlots[i - 1]);
gSaveContext.equips.buttonItems[i] =
gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]];
if (i == 0) {
// If bottle is on B, it triggers BA, which we need to recreate
Inventory_DoBA(gSaveContext.equips.buttonItems[3]);
} else {
gSaveContext.equips.buttonItems[i] =
gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]];
}
}
}
@ -2699,11 +2843,136 @@ s32 Inventory_HasSpecificBottle(u8 bottleItem) {
}
}
void byteSwapInventory() {
gSaveContext.inventory.equipment = BE16SWAP(gSaveContext.inventory.equipment);
gSaveContext.inventory.upgrades = BE32SWAP(gSaveContext.inventory.upgrades);
gSaveContext.inventory.questItems = BE32SWAP(gSaveContext.inventory.questItems);
gSaveContext.inventory.gsTokens = BE16SWAP(gSaveContext.inventory.gsTokens);
void Inventory_DoRBA(u8 cRight, u8 item) {
if (cRight >= ITEM_STICK && cRight <= ITEM_POTION_BLUE) {
gSaveContext.inventory.items[cRight] = item;
} else if (cRight >= ITEM_FAIRY && cRight <= ITEM_MASK_BUNNY) {
gSaveContext.inventory.ammo[cRight - ITEM_FAIRY] = item;
} else if (cRight == ITEM_MASK_GORON) {
gSaveContext.inventory.equipment = (item << 8) | (gSaveContext.inventory.equipment & 0x00FF);
} else if (cRight == ITEM_MASK_ZORA) {
gSaveContext.inventory.equipment = item | (gSaveContext.inventory.equipment & 0xFF00);
}
// ITEM_MASK_GERUDO and ITEM_MASK_TRUTH land in padding bytes
else if (cRight == ITEM_SOLD_OUT) {
gSaveContext.inventory.upgrades = (item << 24) | (gSaveContext.inventory.upgrades & 0x00FFFFFF);
} else if (cRight == ITEM_POCKET_EGG) {
gSaveContext.inventory.upgrades = (item << 16) | (gSaveContext.inventory.upgrades & 0xFF00FFFF);
} else if (cRight == ITEM_POCKET_CUCCO) {
gSaveContext.inventory.upgrades = (item << 8) | (gSaveContext.inventory.upgrades & 0xFFFF00FF);
} else if (cRight == ITEM_COJIRO) {
gSaveContext.inventory.upgrades = item | (gSaveContext.inventory.upgrades & 0xFFFFFF00);
} else if (cRight == ITEM_ODD_MUSHROOM) {
gSaveContext.inventory.questItems = (item << 24) | (gSaveContext.inventory.questItems & 0x00FFFFFF);
} else if (cRight == ITEM_ODD_POTION) {
gSaveContext.inventory.questItems = (item << 16) | (gSaveContext.inventory.questItems & 0xFF00FFFF);
} else if (cRight == ITEM_SAW) {
gSaveContext.inventory.questItems = (item << 8) | (gSaveContext.inventory.questItems & 0xFFFF00FF);
} else if (cRight == ITEM_SWORD_BROKEN) {
gSaveContext.inventory.questItems = item | (gSaveContext.inventory.questItems & 0xFFFFFF00);
} else if (cRight >= ITEM_PRESCRIPTION && cRight <= ITEM_BULLET_BAG_30) {
gSaveContext.inventory.dungeonItems[cRight - ITEM_PRESCRIPTION] = item;
} else if (cRight >= ITEM_BULLET_BAG_40 && cRight <= ITEM_SWORD_KNIFE) {
gSaveContext.inventory.dungeonKeys[cRight - ITEM_BULLET_BAG_40] = item;
} else if (cRight == ITEM_SONG_BOLERO) {
gSaveContext.inventory.defenseHearts = item;
} else if (cRight == ITEM_SONG_SERENADE) {
gSaveContext.inventory.gsTokens = (item << 8) | (gSaveContext.inventory.gsTokens & 0x00FF);
} else if (cRight == ITEM_SONG_REQUIEM) {
gSaveContext.inventory.gsTokens = item | (gSaveContext.inventory.gsTokens & 0xFF00);
}
// ITEM_SONG_NOCTURNE and ITEM_SONG_PRELUDE land in padding bytes
else if (cRight >= ITEM_SONG_LULLABY) {
// The rest of the items fall into the saved scene flags. Let's calculate the scene and which field it sets
u32 offset = cRight - ITEM_SONG_LULLABY;
u32 scene = offset / sizeof(SavedSceneFlags);
switch (offset % sizeof(SavedSceneFlags)) {
case 0:
gSaveContext.sceneFlags[scene].chest = (item << 24) | (gSaveContext.sceneFlags[scene].chest & 0x00FFFFFF);
break;
case 1:
gSaveContext.sceneFlags[scene].chest = (item << 16) | (gSaveContext.sceneFlags[scene].chest & 0xFF00FFFF);
break;
case 2:
gSaveContext.sceneFlags[scene].chest = (item << 8) | (gSaveContext.sceneFlags[scene].chest & 0xFFFF00FF);
break;
case 3:
gSaveContext.sceneFlags[scene].chest = item | (gSaveContext.sceneFlags[scene].chest & 0xFFFFFF00);
break;
case 4:
gSaveContext.sceneFlags[scene].swch = (item << 24) | (gSaveContext.sceneFlags[scene].swch & 0x00FFFFFF);
break;
case 5:
gSaveContext.sceneFlags[scene].swch = (item << 16) | (gSaveContext.sceneFlags[scene].swch & 0xFF00FFFF);
break;
case 6:
gSaveContext.sceneFlags[scene].swch = (item << 8) | (gSaveContext.sceneFlags[scene].swch & 0xFFFF00FF);
break;
case 7:
gSaveContext.sceneFlags[scene].swch = item | (gSaveContext.sceneFlags[scene].swch & 0xFFFFFF00);
break;
case 8:
gSaveContext.sceneFlags[scene].clear = (item << 24) | (gSaveContext.sceneFlags[scene].clear & 0x00FFFFFF);
break;
case 9:
gSaveContext.sceneFlags[scene].clear = (item << 16) | (gSaveContext.sceneFlags[scene].clear & 0xFF00FFFF);
break;
case 10:
gSaveContext.sceneFlags[scene].clear = (item << 8) | (gSaveContext.sceneFlags[scene].clear & 0xFFFF00FF);
break;
case 11:
gSaveContext.sceneFlags[scene].clear = item | (gSaveContext.sceneFlags[scene].clear & 0xFFFFFF00);
break;
case 12:
gSaveContext.sceneFlags[scene].collect = (item << 24) | (gSaveContext.sceneFlags[scene].collect & 0x00FFFFFF);
break;
case 13:
gSaveContext.sceneFlags[scene].collect = (item << 16) | (gSaveContext.sceneFlags[scene].collect & 0xFF00FFFF);
break;
case 14:
gSaveContext.sceneFlags[scene].collect = (item << 8) | (gSaveContext.sceneFlags[scene].collect & 0xFFFF00FF);
break;
case 15:
gSaveContext.sceneFlags[scene].collect = item | (gSaveContext.sceneFlags[scene].collect & 0xFFFFFF00);
break;
case 16:
gSaveContext.sceneFlags[scene].unk = (item << 24) | (gSaveContext.sceneFlags[scene].unk & 0x00FFFFFF);
break;
case 17:
gSaveContext.sceneFlags[scene].unk = (item << 16) | (gSaveContext.sceneFlags[scene].unk & 0xFF00FFFF);
break;
case 18:
gSaveContext.sceneFlags[scene].unk = (item << 8) | (gSaveContext.sceneFlags[scene].unk & 0xFFFF00FF);
break;
case 19:
gSaveContext.sceneFlags[scene].unk = item | (gSaveContext.sceneFlags[scene].unk & 0xFFFFFF00);
break;
case 20:
gSaveContext.sceneFlags[scene].rooms = (item << 24) | (gSaveContext.sceneFlags[scene].rooms & 0x00FFFFFF);
break;
case 21:
gSaveContext.sceneFlags[scene].rooms = (item << 16) | (gSaveContext.sceneFlags[scene].rooms & 0xFF00FFFF);
break;
case 22:
gSaveContext.sceneFlags[scene].rooms = (item << 8) | (gSaveContext.sceneFlags[scene].rooms & 0xFFFF00FF);
break;
case 23:
gSaveContext.sceneFlags[scene].rooms = item | (gSaveContext.sceneFlags[scene].rooms & 0xFFFFFF00);
break;
case 24:
gSaveContext.sceneFlags[scene].floors = (item << 24) | (gSaveContext.sceneFlags[scene].floors & 0x00FFFFFF);
break;
case 25:
gSaveContext.sceneFlags[scene].floors = (item << 16) | (gSaveContext.sceneFlags[scene].floors & 0xFF00FFFF);
break;
case 26:
gSaveContext.sceneFlags[scene].floors = (item << 8) | (gSaveContext.sceneFlags[scene].floors & 0xFFFF00FF);
break;
case 27:
gSaveContext.sceneFlags[scene].floors = item | (gSaveContext.sceneFlags[scene].floors & 0xFFFFFF00);
break;
}
}
}
void Inventory_UpdateBottleItem(PlayState* play, u8 item, u8 button) {
@ -2717,10 +2986,9 @@ void Inventory_UpdateBottleItem(PlayState* play, u8 item, u8 button) {
item = ITEM_MILK_HALF;
}
if (CVarGetInteger(CVAR_ENHANCEMENT("RestoreRBAValues"),0)) {
byteSwapInventory();
gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[button - 1]] = item;
byteSwapInventory();
if (button == 0) {
// If bottle is on B, it triggers RBA, which we need to recreate
Inventory_DoRBA(gSaveContext.equips.buttonItems[3], item);
} else {
gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[button - 1]] = item;
}