From d4af085a3f8bdd4f9650c34d2806c051bdb67b7d Mon Sep 17 00:00:00 2001 From: MelonSpeedruns Date: Thu, 31 Mar 2022 12:46:20 -0400 Subject: [PATCH] More TTS work --- libultraship/libultraship/Window.cpp | 27 ++- .../actors/ovl_player_actor/z_player.c | 3 + .../ovl_file_choose/z_file_choose.c | 27 ++- .../ovl_kaleido_scope/z_kaleido_collect.c | 47 +++++ .../ovl_kaleido_scope/z_kaleido_equipment.c | 96 ++++++++++ .../misc/ovl_kaleido_scope/z_kaleido_item.c | 170 ++++++++++++++++++ 6 files changed, 357 insertions(+), 13 deletions(-) diff --git a/libultraship/libultraship/Window.cpp b/libultraship/libultraship/Window.cpp index d52644c8b..00868a91d 100644 --- a/libultraship/libultraship/Window.cpp +++ b/libultraship/libultraship/Window.cpp @@ -23,7 +23,8 @@ #include "SohHooks.h" #include "SohConsole.h" #include -#include +#include +#include extern "C" { struct OSMesgQueue; @@ -251,6 +252,8 @@ namespace Ship { SPDLOG_INFO("destruct window"); } + ISpVoice* pVoice; + void Window::Init() { std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); ConfigFile& Conf = *pConf.get(); @@ -267,7 +270,7 @@ namespace Ship { //Initialize Text To Speech HRESULT hr; - HRESULT a = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + HRESULT a = CoInitializeEx(NULL, COINIT_MULTITHREADED); HRESULT CoInitializeEx(LPVOID pvReserved, DWORD dwCoInit); hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void**)&pVoice); @@ -276,14 +279,22 @@ namespace Ship { WmApi->set_keyboard_callbacks(Window::KeyDown, Window::KeyUp, Window::AllKeysUp); } + void task1(const char textToRead[]) + { + const int w = 512; + int* wp = const_cast (&w); + *wp = strlen(textToRead); + + wchar_t wtext[w]; + mbstowcs(wtext, textToRead, strlen(textToRead) + 1); + + pVoice->Speak(wtext, SPF_IS_XML | SPF_ASYNC | SPF_PURGEBEFORESPEAK, NULL); + } + void Window::ReadText(const char textToRead[]) { - wchar_t wtext[sizeof(textToRead)]; - - mbstowcs(wtext, textToRead, sizeof(textToRead)); - const LPWSTR ptr = wtext; - - pVoice->Speak(ptr, SPF_ASYNC | SPF_PURGEBEFORESPEAK, NULL); + std::thread t1(task1, textToRead); + t1.detach(); } void Window::RunCommands(Gfx* Commands) { diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index d6c18f46f..094fcdd2d 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -9649,6 +9649,9 @@ void func_808473D4(GlobalContext* globalCtx, Player* this) { if (lastAction != doAction) { Audio_PlaySoundGeneral(NA_SE_VO_NA_HELLO_1, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + + + lastAction = doAction; } } 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 77fda39b0..b3d3f7e90 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 @@ -163,7 +163,7 @@ void FileChoose_FinishFadeIn(GameState* thisx) { this->controlsAlpha = 255; this->windowAlpha = 200; this->configMode = CM_MAIN_MENU; - Audio_PlaySoundGeneral(NA_SE_VO_NA_HELLO_3, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + OTRTextToSpeechCallback("File 1"); } } @@ -283,18 +283,22 @@ void FileChoose_UpdateMainMenu(GameState* thisx) { if (lastButtonIndex != this->buttonIndex) { switch (this->buttonIndex) { case FS_BTN_MAIN_FILE_1: + OTRTextToSpeechCallback("File 1"); + break; case FS_BTN_MAIN_FILE_2: + OTRTextToSpeechCallback("File 2"); + break; case FS_BTN_MAIN_FILE_3: - Audio_PlaySoundGeneral(NA_SE_VO_NA_HELLO_3, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + OTRTextToSpeechCallback("File 3"); break; case FS_BTN_MAIN_OPTIONS: - Audio_PlaySoundGeneral(NA_SE_VO_NA_HELLO_1, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + OTRTextToSpeechCallback("Options"); break; case FS_BTN_MAIN_COPY: - Audio_PlaySoundGeneral(NA_SE_VO_NA_HELLO_2, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + OTRTextToSpeechCallback("Copy"); break; case FS_BTN_MAIN_ERASE: - Audio_PlaySoundGeneral(NA_SE_VO_NA_HELLO_0, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + OTRTextToSpeechCallback("Erase"); break; default: break; @@ -1341,6 +1345,9 @@ void FileChoose_FadeInFileInfo(GameState* thisx) { * Update the cursor and handle the option that the player picks for confirming the selected file. * Update function for `SM_CONFIRM_FILE` */ + +int16_t lastConfirmButtonIndex = NULL; + void FileChoose_ConfirmFile(GameState* thisx) { FileChooseContext* this = (FileChooseContext*)thisx; Input* input = &this->state.input[0]; @@ -1362,6 +1369,16 @@ void FileChoose_ConfirmFile(GameState* thisx) { Audio_PlaySoundGeneral(NA_SE_SY_FSEL_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); this->confirmButtonIndex ^= 1; } + + if (lastConfirmButtonIndex != this->confirmButtonIndex) { + if (this->confirmButtonIndex == FS_BTN_CONFIRM_YES) { + OTRTextToSpeechCallback("Yes"); + } else { + OTRTextToSpeechCallback("Quit"); + } + + lastConfirmButtonIndex = this->confirmButtonIndex; + } } /** diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c index 46be1154f..42fe91daa 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c @@ -171,6 +171,53 @@ void KaleidoScope_DrawQuestStatus(GlobalContext* globalCtx, GraphicsContext* gfx sp216 = pauseCtx->cursorPoint[PAUSE_QUEST]; pauseCtx->cursorItem[pauseCtx->pageIndex] = phi_s0_2; pauseCtx->cursorSlot[pauseCtx->pageIndex] = sp216; + + switch (pauseCtx->cursorItem[PAUSE_QUEST]) { + case ITEM_KOKIRI_EMERALD: + OTRTextToSpeechCallback("Kokiri Emerald"); + break; + case ITEM_GORON_RUBY: + OTRTextToSpeechCallback("Goron Ruby"); + break; + case ITEM_ZORA_SAPPHIRE: + OTRTextToSpeechCallback("Zora Sapphire"); + break; + case ITEM_MEDALLION_LIGHT: + OTRTextToSpeechCallback("Light Medallion"); + break; + case ITEM_MEDALLION_FOREST: + OTRTextToSpeechCallback("Forest Medallion"); + break; + case ITEM_MEDALLION_FIRE: + OTRTextToSpeechCallback("Fire Medallion"); + break; + case ITEM_MEDALLION_WATER: + OTRTextToSpeechCallback("Water Medallion"); + break; + case ITEM_MEDALLION_SHADOW: + OTRTextToSpeechCallback("Shadow Medallion"); + break; + case ITEM_MEDALLION_SPIRIT: + OTRTextToSpeechCallback("Spirit Medallion"); + break; + case ITEM_GERUDO_CARD: + OTRTextToSpeechCallback("Gerudo Card"); + break; + case ITEM_STONE_OF_AGONY: + OTRTextToSpeechCallback("Stone of Agony"); + break; + case ITEM_HEART_PIECE: + OTRTextToSpeechCallback("Heart Pieces"); + break; + case ITEM_SKULL_TOKEN: { + int tokens = gSaveContext.inventory.gsTokens; + OTRTextToSpeechCallback("Skulltula Tokens"); + break; + } + default: + OTRTextToSpeechCallback("Unknown Item"); + break; + } } KaleidoScope_SetCursorVtx(pauseCtx, sp216 * 4, pauseCtx->questVtx); diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c index 3c236637b..9f24fbaad 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c @@ -508,6 +508,102 @@ void KaleidoScope_DrawEquipment(GlobalContext* globalCtx) { if (oldCursorPoint != pauseCtx->cursorPoint[PAUSE_EQUIP]) { Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + + switch (pauseCtx->cursorItem[PAUSE_EQUIP]) { + case ITEM_SWORD_KOKIRI: + OTRTextToSpeechCallback("Kokiri Sword"); + break; + case ITEM_SWORD_MASTER: + OTRTextToSpeechCallback("Master Sword"); + break; + case ITEM_HEART_PIECE_2: + OTRTextToSpeechCallback("Biggoron's Sword"); + break; + case ITEM_SWORD_BGS: + OTRTextToSpeechCallback("Giant's Knife"); + break; + case ITEM_SWORD_KNIFE: + OTRTextToSpeechCallback("Broken Giant's Knife"); + break; + case ITEM_SHIELD_DEKU: + OTRTextToSpeechCallback("Deku Shield"); + break; + case ITEM_SHIELD_HYLIAN: + OTRTextToSpeechCallback("Hylian Shield"); + break; + case ITEM_SHIELD_MIRROR: + OTRTextToSpeechCallback("Mirror Shield"); + break; + case ITEM_TUNIC_KOKIRI: + OTRTextToSpeechCallback("Kokiri Tunic"); + break; + case ITEM_TUNIC_GORON: + OTRTextToSpeechCallback("Goron Tunic"); + break; + case ITEM_TUNIC_ZORA: + OTRTextToSpeechCallback("Zora Tunic"); + break; + case ITEM_BOOTS_KOKIRI: + OTRTextToSpeechCallback("Kokiri Boots"); + break; + case ITEM_BOOTS_IRON: + OTRTextToSpeechCallback("Iron Boots"); + break; + case ITEM_BOOTS_HOVER: + OTRTextToSpeechCallback("Hover Boots"); + break; + case ITEM_BULLET_BAG_30: + OTRTextToSpeechCallback("Bullet Bag"); + break; + case ITEM_BULLET_BAG_40: + OTRTextToSpeechCallback("Bigger Bullet Bag"); + break; + case ITEM_BULLET_BAG_50: + OTRTextToSpeechCallback("Biggest Bullet Bag"); + break; + case ITEM_QUIVER_30: + OTRTextToSpeechCallback("Quiver"); + break; + case ITEM_QUIVER_40: + OTRTextToSpeechCallback("Big Quiver"); + break; + case ITEM_QUIVER_50: + OTRTextToSpeechCallback("Biggest Quiver"); + break; + case ITEM_BOMB_BAG_20: + OTRTextToSpeechCallback("Bomb Bag"); + break; + case ITEM_BOMB_BAG_30: + OTRTextToSpeechCallback("Big Bomb Bag"); + break; + case ITEM_BOMB_BAG_40: + OTRTextToSpeechCallback("Biggest Bomb Bag"); + break; + case ITEM_WALLET_ADULT: + OTRTextToSpeechCallback("Adult Wallet"); + break; + case ITEM_WALLET_GIANT: + OTRTextToSpeechCallback("Giant Wallet"); + break; + case ITEM_SCALE_SILVER: + OTRTextToSpeechCallback("Silver Scale"); + break; + case ITEM_SCALE_GOLDEN: + OTRTextToSpeechCallback("Golden Scale"); + break; + case ITEM_BRACELET: + OTRTextToSpeechCallback("Goron Bracelet"); + break; + case ITEM_GAUNTLETS_SILVER: + OTRTextToSpeechCallback("Silver Gauntlets"); + break; + case ITEM_GAUNTLETS_GOLD: + OTRTextToSpeechCallback("Golden Gauntlets"); + break; + default: + OTRTextToSpeechCallback("Unknown Item"); + break; + } } } else if ((pauseCtx->unk_1E4 == 7) && (pauseCtx->pageIndex == PAUSE_EQUIP)) { KaleidoScope_SetCursorVtx(pauseCtx, pauseCtx->cursorSlot[PAUSE_EQUIP] * 4, pauseCtx->equipVtx); diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c index bb42ff711..761e6512b 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c @@ -10,6 +10,8 @@ static s16 sEquipState = 0; static s16 sEquipAnimTimer = 0; static s16 sEquipMoveTimer = 10; +int16_t lastSelectedItem; + static s16 sAmmoVtxOffset[] = { 0, 2, 4, 6, 99, 99, 8, 99, 99, 10, 99, 99, 99, 99, 99, 99, 12, }; @@ -406,6 +408,174 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) { if (oldCursorPoint != pauseCtx->cursorPoint[PAUSE_ITEM]) { Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + + switch (pauseCtx->cursorItem[PAUSE_ITEM]) { + case ITEM_STICK: + OTRTextToSpeechCallback("Deku Stick"); + break; + case ITEM_NUT: + OTRTextToSpeechCallback("Deku Nut"); + break; + case ITEM_BOMB: + OTRTextToSpeechCallback("Bomb"); + break; + case ITEM_BOW: + OTRTextToSpeechCallback("Fairy Bow"); + break; + case ITEM_ARROW_FIRE: + OTRTextToSpeechCallback("Fire Arrow"); + break; + case ITEM_DINS_FIRE: + OTRTextToSpeechCallback("Din's Fire"); + break; + case ITEM_SLINGSHOT: + OTRTextToSpeechCallback("Slingshot"); + break; + case ITEM_OCARINA_FAIRY: + OTRTextToSpeechCallback("Fairy Ocarina"); + break; + case ITEM_OCARINA_TIME: + OTRTextToSpeechCallback("Ocarina of Time"); + break; + case ITEM_BOMBCHU: + OTRTextToSpeechCallback("Bombchu"); + break; + case ITEM_HOOKSHOT: + OTRTextToSpeechCallback("Hookshot"); + break; + case ITEM_LONGSHOT: + OTRTextToSpeechCallback("Longshot"); + break; + case ITEM_ARROW_ICE: + OTRTextToSpeechCallback("Ice Arrow"); + break; + case ITEM_FARORES_WIND: + OTRTextToSpeechCallback("Farore's Wind"); + break; + case ITEM_BOOMERANG: + OTRTextToSpeechCallback("Boomerang"); + break; + case ITEM_LENS: + OTRTextToSpeechCallback("Lens of Truth"); + break; + case ITEM_BEAN: + OTRTextToSpeechCallback("Magic Bean"); + break; + case ITEM_HAMMER: + OTRTextToSpeechCallback("Megaton Hammer"); + break; + case ITEM_ARROW_LIGHT: + OTRTextToSpeechCallback("Light Arrow"); + break; + case ITEM_NAYRUS_LOVE: + OTRTextToSpeechCallback("Nayru's Love"); + break; + case ITEM_POTION_GREEN: + OTRTextToSpeechCallback("Bottled Green Potion"); + break; + case ITEM_POTION_RED: + OTRTextToSpeechCallback("Bottled Red Potion"); + break; + case ITEM_POTION_BLUE: + OTRTextToSpeechCallback("Bottled Blue Potion"); + break; + case ITEM_MILK: + OTRTextToSpeechCallback("Bottled Lon Lon Milk"); + break; + case ITEM_MILK_HALF: + OTRTextToSpeechCallback("Bottled Lon Lon Milk (Half)"); + break; + case ITEM_FAIRY: + OTRTextToSpeechCallback("Bottled Fairy"); + break; + case ITEM_BUG: + OTRTextToSpeechCallback("Bottled Bugs"); + break; + case ITEM_FISH: + OTRTextToSpeechCallback("Bottled Fish"); + break; + case ITEM_POE: + OTRTextToSpeechCallback("Bottled Poe"); + break; + case ITEM_BIG_POE: + OTRTextToSpeechCallback("Bottled Big Poe"); + break; + case ITEM_BLUE_FIRE: + OTRTextToSpeechCallback("Bottled Blue Fire"); + break; + case ITEM_LETTER_RUTO: + OTRTextToSpeechCallback("Bottled Ruto's Letter"); + break; + case ITEM_WEIRD_EGG: + OTRTextToSpeechCallback("Weird Egg"); + break; + case ITEM_CHICKEN: + OTRTextToSpeechCallback("Cucco"); + break; + case ITEM_LETTER_ZELDA: + OTRTextToSpeechCallback("Zelda's Letter"); + break; + case ITEM_MASK_KEATON: + OTRTextToSpeechCallback("Keaton Mask"); + break; + case ITEM_MASK_SKULL: + OTRTextToSpeechCallback("Skull Mask"); + break; + case ITEM_MASK_SPOOKY: + OTRTextToSpeechCallback("Spooky Mask"); + break; + case ITEM_MASK_BUNNY: + OTRTextToSpeechCallback("Bunny Hood"); + break; + case ITEM_MASK_TRUTH: + OTRTextToSpeechCallback("Mask of Truth"); + break; + case ITEM_MASK_GORON: + OTRTextToSpeechCallback("Goron Mask"); + break; + case ITEM_MASK_ZORA: + OTRTextToSpeechCallback("Zora Mask"); + break; + case ITEM_MASK_GERUDO: + OTRTextToSpeechCallback("Gerudo Mask"); + break; + case ITEM_POCKET_EGG: + OTRTextToSpeechCallback("Pocket Egg"); + break; + case ITEM_POCKET_CUCCO: + OTRTextToSpeechCallback("Pocket Cucco"); + break; + case ITEM_COJIRO: + OTRTextToSpeechCallback("Cojiro"); + break; + case ITEM_ODD_MUSHROOM: + OTRTextToSpeechCallback("Odd Mushroom"); + break; + case ITEM_ODD_POTION: + OTRTextToSpeechCallback("Odd Potion"); + break; + case ITEM_SAW: + OTRTextToSpeechCallback("Poacher's Saw"); + break; + case ITEM_PRESCRIPTION: + OTRTextToSpeechCallback("Prescription"); + break; + case ITEM_FROG: + OTRTextToSpeechCallback("Eyeball Frog"); + break; + case ITEM_EYEDROPS: + OTRTextToSpeechCallback("World's Finest Eye Drops"); + break; + case ITEM_CLAIM_CHECK: + OTRTextToSpeechCallback("Claim Check"); + break; + case ITEM_BOTTLE: + OTRTextToSpeechCallback("Empty Bottle"); + break; + default: + OTRTextToSpeechCallback("Unknown Item"); + break; + } } } else if ((pauseCtx->unk_1E4 == 3) && (pauseCtx->pageIndex == PAUSE_ITEM)) { KaleidoScope_SetCursorVtx(pauseCtx, cursorSlot * 4, pauseCtx->itemVtx);