More TTS work

This commit is contained in:
MelonSpeedruns 2022-03-31 12:46:20 -04:00
commit d4af085a3f
6 changed files with 357 additions and 13 deletions

View file

@ -23,7 +23,8 @@
#include "SohHooks.h" #include "SohHooks.h"
#include "SohConsole.h" #include "SohConsole.h"
#include <iostream> #include <iostream>
#include <sapi51.h> #include <sapi.h>
#include <thread>
extern "C" { extern "C" {
struct OSMesgQueue; struct OSMesgQueue;
@ -251,6 +252,8 @@ namespace Ship {
SPDLOG_INFO("destruct window"); SPDLOG_INFO("destruct window");
} }
ISpVoice* pVoice;
void Window::Init() { void Window::Init() {
std::shared_ptr<ConfigFile> pConf = GlobalCtx2::GetInstance()->GetConfig(); std::shared_ptr<ConfigFile> pConf = GlobalCtx2::GetInstance()->GetConfig();
ConfigFile& Conf = *pConf.get(); ConfigFile& Conf = *pConf.get();
@ -267,7 +270,7 @@ namespace Ship {
//Initialize Text To Speech //Initialize Text To Speech
HRESULT hr; HRESULT hr;
HRESULT a = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); HRESULT a = CoInitializeEx(NULL, COINIT_MULTITHREADED);
HRESULT CoInitializeEx(LPVOID pvReserved, DWORD dwCoInit); HRESULT CoInitializeEx(LPVOID pvReserved, DWORD dwCoInit);
hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void**)&pVoice); 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); WmApi->set_keyboard_callbacks(Window::KeyDown, Window::KeyUp, Window::AllKeysUp);
} }
void task1(const char textToRead[])
{
const int w = 512;
int* wp = const_cast <int*> (&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[]) void Window::ReadText(const char textToRead[])
{ {
wchar_t wtext[sizeof(textToRead)]; std::thread t1(task1, textToRead);
t1.detach();
mbstowcs(wtext, textToRead, sizeof(textToRead));
const LPWSTR ptr = wtext;
pVoice->Speak(ptr, SPF_ASYNC | SPF_PURGEBEFORESPEAK, NULL);
} }
void Window::RunCommands(Gfx* Commands) { void Window::RunCommands(Gfx* Commands) {

View file

@ -9649,6 +9649,9 @@ void func_808473D4(GlobalContext* globalCtx, Player* this) {
if (lastAction != doAction) { if (lastAction != doAction) {
Audio_PlaySoundGeneral(NA_SE_VO_NA_HELLO_1, &D_801333D4, 4, &D_801333E0, &D_801333E0, Audio_PlaySoundGeneral(NA_SE_VO_NA_HELLO_1, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8); &D_801333E8);
lastAction = doAction; lastAction = doAction;
} }
} }

View file

@ -163,7 +163,7 @@ void FileChoose_FinishFadeIn(GameState* thisx) {
this->controlsAlpha = 255; this->controlsAlpha = 255;
this->windowAlpha = 200; this->windowAlpha = 200;
this->configMode = CM_MAIN_MENU; 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) { if (lastButtonIndex != this->buttonIndex) {
switch (this->buttonIndex) { switch (this->buttonIndex) {
case FS_BTN_MAIN_FILE_1: case FS_BTN_MAIN_FILE_1:
OTRTextToSpeechCallback("File 1");
break;
case FS_BTN_MAIN_FILE_2: case FS_BTN_MAIN_FILE_2:
OTRTextToSpeechCallback("File 2");
break;
case FS_BTN_MAIN_FILE_3: 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; break;
case FS_BTN_MAIN_OPTIONS: 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; break;
case FS_BTN_MAIN_COPY: 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; break;
case FS_BTN_MAIN_ERASE: 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; break;
default: default:
break; 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 the cursor and handle the option that the player picks for confirming the selected file.
* Update function for `SM_CONFIRM_FILE` * Update function for `SM_CONFIRM_FILE`
*/ */
int16_t lastConfirmButtonIndex = NULL;
void FileChoose_ConfirmFile(GameState* thisx) { void FileChoose_ConfirmFile(GameState* thisx) {
FileChooseContext* this = (FileChooseContext*)thisx; FileChooseContext* this = (FileChooseContext*)thisx;
Input* input = &this->state.input[0]; 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); Audio_PlaySoundGeneral(NA_SE_SY_FSEL_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
this->confirmButtonIndex ^= 1; this->confirmButtonIndex ^= 1;
} }
if (lastConfirmButtonIndex != this->confirmButtonIndex) {
if (this->confirmButtonIndex == FS_BTN_CONFIRM_YES) {
OTRTextToSpeechCallback("Yes");
} else {
OTRTextToSpeechCallback("Quit");
}
lastConfirmButtonIndex = this->confirmButtonIndex;
}
} }
/** /**

View file

@ -171,6 +171,53 @@ void KaleidoScope_DrawQuestStatus(GlobalContext* globalCtx, GraphicsContext* gfx
sp216 = pauseCtx->cursorPoint[PAUSE_QUEST]; sp216 = pauseCtx->cursorPoint[PAUSE_QUEST];
pauseCtx->cursorItem[pauseCtx->pageIndex] = phi_s0_2; pauseCtx->cursorItem[pauseCtx->pageIndex] = phi_s0_2;
pauseCtx->cursorSlot[pauseCtx->pageIndex] = sp216; 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); KaleidoScope_SetCursorVtx(pauseCtx, sp216 * 4, pauseCtx->questVtx);

View file

@ -508,6 +508,102 @@ void KaleidoScope_DrawEquipment(GlobalContext* globalCtx) {
if (oldCursorPoint != pauseCtx->cursorPoint[PAUSE_EQUIP]) { if (oldCursorPoint != pauseCtx->cursorPoint[PAUSE_EQUIP]) {
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); 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)) { } else if ((pauseCtx->unk_1E4 == 7) && (pauseCtx->pageIndex == PAUSE_EQUIP)) {
KaleidoScope_SetCursorVtx(pauseCtx, pauseCtx->cursorSlot[PAUSE_EQUIP] * 4, pauseCtx->equipVtx); KaleidoScope_SetCursorVtx(pauseCtx, pauseCtx->cursorSlot[PAUSE_EQUIP] * 4, pauseCtx->equipVtx);

View file

@ -10,6 +10,8 @@ static s16 sEquipState = 0;
static s16 sEquipAnimTimer = 0; static s16 sEquipAnimTimer = 0;
static s16 sEquipMoveTimer = 10; static s16 sEquipMoveTimer = 10;
int16_t lastSelectedItem;
static s16 sAmmoVtxOffset[] = { static s16 sAmmoVtxOffset[] = {
0, 2, 4, 6, 99, 99, 8, 99, 99, 10, 99, 99, 99, 99, 99, 99, 12, 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]) { if (oldCursorPoint != pauseCtx->cursorPoint[PAUSE_ITEM]) {
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); 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)) { } else if ((pauseCtx->unk_1E4 == 3) && (pauseCtx->pageIndex == PAUSE_ITEM)) {
KaleidoScope_SetCursorVtx(pauseCtx, cursorSlot * 4, pauseCtx->itemVtx); KaleidoScope_SetCursorVtx(pauseCtx, cursorSlot * 4, pauseCtx->itemVtx);