diff --git a/OTRExporter/assets/accessibility/texts/filechoose_eng.json b/OTRExporter/assets/accessibility/texts/filechoose_eng.json index b61aa5ae0..b43719926 100644 --- a/OTRExporter/assets/accessibility/texts/filechoose_eng.json +++ b/OTRExporter/assets/accessibility/texts/filechoose_eng.json @@ -19,6 +19,9 @@ "audio_surround": "Sound - Surround", "target_switch": "Targeting Mode - Switch", "target_hold": "Targeting Mode - Hold", + "language_english": "Language - English", + "language_german": "Language - German", + "language_french": "Language - French", "quest_sel_vanilla": "Quest - Original", "quest_sel_mq": "Quest - Master Quest", "quest_sel_randomizer": "Quest - Randomizer", diff --git a/OTRExporter/assets/accessibility/texts/filechoose_fra.json b/OTRExporter/assets/accessibility/texts/filechoose_fra.json index 23be1ee3d..f76861f21 100644 --- a/OTRExporter/assets/accessibility/texts/filechoose_fra.json +++ b/OTRExporter/assets/accessibility/texts/filechoose_fra.json @@ -19,6 +19,9 @@ "audio_surround": "Son - Surround", "target_switch": "Visée - Fixe", "target_hold": "Visée - Maintenue", + "language_english": "Langue - Anglaise", + "language_german": "Langue - Allemande", + "language_french": "Langue - Français", "quest_sel_vanilla": "Quête - Originale", "quest_sel_mq": "Quête - Master Quest", "quest_sel_randomizer": "Quête - Randomizer", diff --git a/OTRExporter/assets/accessibility/texts/filechoose_ger.json b/OTRExporter/assets/accessibility/texts/filechoose_ger.json index 6c88f9d44..2ad1322fd 100644 --- a/OTRExporter/assets/accessibility/texts/filechoose_ger.json +++ b/OTRExporter/assets/accessibility/texts/filechoose_ger.json @@ -19,6 +19,9 @@ "audio_surround": "Sound - Surround", "target_switch": "Zielerfassung - Einmal drücken", "target_hold": "Zielerfassung - Trigger halten", + "language_english": "Sprache - Englisch", + "language_german": "Sprache - Deutsch", + "language_french": "Sprache - Französisch", "quest_sel_vanilla": "Quest - Original", "quest_sel_mq": "Quest - Master Quest", "quest_sel_randomizer": "Quest - Randomizer", diff --git a/soh/assets/soh_assets.h b/soh/assets/soh_assets.h index 667a9ff1a..b1feac469 100644 --- a/soh/assets/soh_assets.h +++ b/soh/assets/soh_assets.h @@ -44,6 +44,10 @@ static const ALIGN_ASSET(2) char gTitleRandomizerSubtitleTex[] = dgTitleRandomiz #define dgTitleBossRushSubtitleTex "__OTR__objects/object_mag/gTitleBossRushSubtitleTex" static const ALIGN_ASSET(2) char gTitleBossRushSubtitleTex[] = dgTitleBossRushSubtitleTex; +// overlays +#define dgOptionsDividerChangeLangVtx "__OTR__overlays/ovl_file_choose/gOptionsDividerChangeLangVtx" +static const ALIGN_ASSET(2) char gOptionsDividerChangeLangVtx[] = dgOptionsDividerChangeLangVtx; + // textures #define dgDPad "__OTR__textures/parameter_static/gDPad" static const ALIGN_ASSET(2) char gDPadTex[] = dgDPad; @@ -78,5 +82,23 @@ static const ALIGN_ASSET(2) char gFileSelBossRushSettingsGERText[] = dgFileSelBo #define dgFileSelRANDButtonTex "__OTR__textures/title_static/gFileSelRANDButtonTex" static const ALIGN_ASSET(2) char gFileSelRANDButtonTex[] = dgFileSelRANDButtonTex; +#define dgFileSelLangEnglishENGTex "__OTR__textures/title_static/gFileSelLangEnglishENGTex" +static const ALIGN_ASSET(2) char gFileSelLangEnglishENGTex[] = dgFileSelLangEnglishENGTex; + +#define dgFileSelLangDeutschGERTex "__OTR__textures/title_static/gFileSelLangDeutschGERTex" +static const ALIGN_ASSET(2) char gFileSelLangDeutschGERTex[] = dgFileSelLangDeutschGERTex; + +#define dgFileSelLangFrancaisFRATex "__OTR__textures/title_static/gFileSelLangFrancaisFRATex" +static const ALIGN_ASSET(2) char gFileSelLangFrancaisFRATex[] = dgFileSelLangFrancaisFRATex; + +#define dgFileSelLanguageENGTex "__OTR__textures/title_static/gFileSelLanguageENGTex" +static const ALIGN_ASSET(2) char gFileSelLanguageENGTex[] = dgFileSelLanguageENGTex; + +#define dgFileSelLanguageFRATex "__OTR__textures/title_static/gFileSelLanguageFRATex" +static const ALIGN_ASSET(2) char gFileSelLanguageFRATex[] = dgFileSelLanguageFRATex; + +#define dgFileSelLanguageGERTex "__OTR__textures/title_static/gFileSelLanguageGERTex" +static const ALIGN_ASSET(2) char gFileSelLanguageGERTex[] = dgFileSelLanguageGERTex; + #define dgEmptyTexture "__OTR__textures/virtual/gEmptyTexture" static const ALIGN_ASSET(2) char gEmptyTexture[] = dgEmptyTexture; diff --git a/soh/assets/xml/N64_PAL_11/overlays/ovl_File_Choose.xml b/soh/assets/xml/N64_PAL_11/overlays/ovl_File_Choose.xml index de41882eb..b97861d62 100644 --- a/soh/assets/xml/N64_PAL_11/overlays/ovl_File_Choose.xml +++ b/soh/assets/xml/N64_PAL_11/overlays/ovl_File_Choose.xml @@ -3,18 +3,16 @@ - + - - - + + - + @@ -26,6 +24,9 @@ - + + + + diff --git a/soh/assets/xml/N64_PAL_11/textures/title_static.xml b/soh/assets/xml/N64_PAL_11/textures/title_static.xml index 7367190a9..eb8d3288f 100644 --- a/soh/assets/xml/N64_PAL_11/textures/title_static.xml +++ b/soh/assets/xml/N64_PAL_11/textures/title_static.xml @@ -185,6 +185,28 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 79a2cb465..546a70635 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -175,6 +175,7 @@ public: DEFINE_HOOK(OnUpdateFileEraseConfirmationSelection, void(uint16_t optionIndex)); DEFINE_HOOK(OnUpdateFileAudioSelection, void(uint8_t optionIndex)); DEFINE_HOOK(OnUpdateFileTargetSelection, void(uint8_t optionIndex)); + DEFINE_HOOK(OnUpdateFileLanguageSelection, void(uint8_t optionIndex)); DEFINE_HOOK(OnUpdateFileQuestSelection, void(uint8_t questIndex)); DEFINE_HOOK(OnUpdateFileBossRushOptionSelection, void(uint8_t optionIndex, uint8_t optionValue)); DEFINE_HOOK(OnUpdateFileNameSelection, void(int16_t charCode)); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp index e96474996..75879e3e6 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp @@ -132,6 +132,10 @@ void GameInteractor_ExecuteOnUpdateFileTargetSelection(uint8_t optionIndex) { GameInteractor::Instance->ExecuteHooks(optionIndex); } +void GameInteractor_ExecuteOnUpdateFileLanguageSelection(uint8_t optionIndex) { + GameInteractor::Instance->ExecuteHooks(optionIndex); +} + void GameInteractor_ExecuteOnUpdateFileQuestSelection(uint8_t questIndex) { GameInteractor::Instance->ExecuteHooks(questIndex); } diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h index c69a8ec24..ca21b9a6b 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h @@ -42,6 +42,7 @@ void GameInteractor_ExecuteOnUpdateFileEraseSelection(uint16_t optionIndex); void GameInteractor_ExecuteOnUpdateFileEraseConfirmationSelection(uint16_t optionIndex); void GameInteractor_ExecuteOnUpdateFileAudioSelection(uint8_t optionIndex); void GameInteractor_ExecuteOnUpdateFileTargetSelection(uint8_t optionIndex); +void GameInteractor_ExecuteOnUpdateFileLanguageSelection(uint8_t optionIndex); void GameInteractor_ExecuteOnUpdateFileQuestSelection(uint8_t questIndex); void GameInteractor_ExecuteOnUpdateFileBossRushOptionSelection(uint8_t optionIndex, uint8_t optionValue); void GameInteractor_ExecuteOnUpdateFileNameSelection(int16_t charCode); diff --git a/soh/soh/Enhancements/tts/tts.cpp b/soh/soh/Enhancements/tts/tts.cpp index 128ab4b1e..3387bfd21 100644 --- a/soh/soh/Enhancements/tts/tts.cpp +++ b/soh/soh/Enhancements/tts/tts.cpp @@ -674,7 +674,7 @@ void RegisterOnUpdateMainMenuSelection() { break; } }); - + GameInteractor::Instance->RegisterGameHook([](uint8_t optionIndex) { if (!CVarGetInteger("gA11yTTS", 0)) return; @@ -694,6 +694,30 @@ void RegisterOnUpdateMainMenuSelection() { } }); + GameInteractor::Instance->RegisterGameHook([](uint8_t optionIndex) { + if (!CVarGetInteger("gA11yTTS", 0)) return; + + switch (optionIndex) { + case LANGUAGE_ENG: { + auto translation = GetParameritizedText("language_english", TEXT_BANK_FILECHOOSE, nullptr); + SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); + break; + } + case LANGUAGE_GER: { + auto translation = GetParameritizedText("language_german", TEXT_BANK_FILECHOOSE, nullptr); + SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); + break; + } + case LANGUAGE_FRA: { + auto translation = GetParameritizedText("language_french", TEXT_BANK_FILECHOOSE, nullptr); + SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); + break; + } + default: + break; + } + }); + GameInteractor::Instance->RegisterGameHook([](uint8_t questIndex) { if (!CVarGetInteger("gA11yTTS", 0)) return; diff --git a/soh/src/overlays/gamestates/ovl_file_choose/file_choose.h b/soh/src/overlays/gamestates/ovl_file_choose/file_choose.h index f4a23d38b..3f76ebd0d 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/file_choose.h +++ b/soh/src/overlays/gamestates/ovl_file_choose/file_choose.h @@ -142,7 +142,8 @@ typedef enum { typedef enum { /* 0 */ FS_SETTING_AUDIO, - /* 1 */ FS_SETTING_TARGET + /* 1 */ FS_SETTING_TARGET, + /* 2 */ FS_SETTING_LANGUAGE, // PAL N64 only } SettingIndex; typedef enum { diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c index 44cb67987..377c23eb3 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c @@ -1,6 +1,7 @@ #include "file_choose.h" #include "textures/title_static/title_static.h" #include "assets/overlays/ovl_File_Choose/ovl_file_choose.h" +#include "assets/soh_assets.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" @@ -702,6 +703,11 @@ void FileChoose_UpdateOptionsMenu(GameState* thisx) { return; } + uint8_t languageChanged = 0; + uint8_t versionIndex = ResourceMgr_GameHasMasterQuest() && ResourceMgr_GameHasOriginal(); + uint8_t isPalN64 = ResourceMgr_GetGameRegion(versionIndex) == GAME_REGION_PAL && + ResourceMgr_GetGamePlatform(versionIndex) == GAME_PLATFORM_N64; + if ((this->stickRelX < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DLEFT))) { Audio_PlaySoundGeneral(NA_SE_SY_FSEL_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); @@ -712,6 +718,14 @@ void FileChoose_UpdateOptionsMenu(GameState* thisx) { if (gSaveContext.audioSetting > 0xF0) { gSaveContext.audioSetting = FS_AUDIO_SURROUND; } + } else if (sSelectedSetting == FS_SETTING_LANGUAGE) { + gSaveContext.language--; + + if (gSaveContext.language > 0xF0) { + gSaveContext.language = LANGUAGE_FRA; + } + + languageChanged = 1; } else { gSaveContext.zTargetSetting ^= 1; } @@ -724,29 +738,75 @@ void FileChoose_UpdateOptionsMenu(GameState* thisx) { if (gSaveContext.audioSetting > FS_AUDIO_SURROUND) { gSaveContext.audioSetting = FS_AUDIO_STEREO; } + } else if (sSelectedSetting == FS_SETTING_LANGUAGE) { + gSaveContext.language++; + + if (gSaveContext.language > LANGUAGE_FRA) { + gSaveContext.language = LANGUAGE_ENG; + } + + languageChanged = 1; } else { gSaveContext.zTargetSetting ^= 1; } } - if ((ABS(this->stickRelY) > 30) || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DDOWN | BTN_DUP))) { + // Persist the new language so it is not overridden on the next frame + if (languageChanged) { + CVarSetInteger("gLanguages", gSaveContext.language); + GameInteractor_ExecuteOnSetGameLanguage(); + } + + // NTSC and GC only has two rows and can just flip the setting bit + // Otherwise for PAL 64, handle the additional change language setting + if (!isPalN64 && ((ABS(this->stickRelY) > 30) || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DDOWN | BTN_DUP)))) { Audio_PlaySoundGeneral(NA_SE_SY_FSEL_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); sSelectedSetting ^= 1; + } else if (isPalN64 && ((this->stickRelY > 30) || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DUP)))) { + Audio_PlaySoundGeneral(NA_SE_SY_FSEL_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + sSelectedSetting--; + + if (sSelectedSetting > 0xF0) { + sSelectedSetting = FS_SETTING_LANGUAGE; + } + } else if (isPalN64 && ((this->stickRelY < -30) || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DDOWN)))) { + Audio_PlaySoundGeneral(NA_SE_SY_FSEL_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + sSelectedSetting++; + + if (sSelectedSetting > FS_SETTING_LANGUAGE) { + sSelectedSetting = FS_SETTING_AUDIO; + } } else if (CHECK_BTN_ALL(input->press.button, BTN_A)) { Audio_PlaySoundGeneral(NA_SE_SY_FSEL_DECIDE_L, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); - sSelectedSetting ^= 1; + if (isPalN64) { + sSelectedSetting++; + + if (sSelectedSetting > FS_SETTING_LANGUAGE) { + sSelectedSetting = FS_SETTING_AUDIO; + } + } else { + sSelectedSetting ^= 1; + } } - + if (sSelectedSetting == FS_SETTING_AUDIO) { if (sLastOptionButtonIndex != gSaveContext.audioSetting) { GameInteractor_ExecuteOnUpdateFileAudioSelection(gSaveContext.audioSetting); sLastOptionButtonIndex = gSaveContext.audioSetting; } + } else if (sSelectedSetting == FS_SETTING_TARGET) { + // offset to detect switching between modes + u8 optionOffset = gSaveContext.zTargetSetting + FS_AUDIO_SURROUND + FS_SETTING_TARGET; + if (sLastOptionButtonIndex != optionOffset) { + GameInteractor_ExecuteOnUpdateFileTargetSelection(gSaveContext.zTargetSetting); + sLastOptionButtonIndex = optionOffset; + } } else { // offset to detect switching between modes - if (sLastOptionButtonIndex != FS_BTN_SELECT_QUIT + gSaveContext.zTargetSetting + 1) { - GameInteractor_ExecuteOnUpdateFileTargetSelection(gSaveContext.zTargetSetting); - sLastOptionButtonIndex = FS_BTN_SELECT_QUIT + gSaveContext.zTargetSetting + 1; + u8 optionOffset = gSaveContext.language + FS_AUDIO_SURROUND + FS_TARGET_HOLD + FS_SETTING_LANGUAGE; + if (sLastOptionButtonIndex != optionOffset) { + GameInteractor_ExecuteOnUpdateFileLanguageSelection(gSaveContext.language); + sLastOptionButtonIndex = optionOffset; } } } @@ -778,6 +838,11 @@ static OptionsMenuTextureInfo gOptionsMenuHeaders[] = { { 128, 128, 128 }, 16, }, + { + { gFileSelLanguageENGTex, gFileSelLanguageGERTex, gFileSelLanguageFRATex }, + { 64, 64, 64 }, + 16, + }, }; static OptionsMenuTextureInfo gOptionsMenuSettings[] = { @@ -811,6 +876,21 @@ static OptionsMenuTextureInfo gOptionsMenuSettings[] = { { 48, 80, 48 }, 16, }, + { + { gFileSelLangEnglishENGTex, gFileSelLangEnglishENGTex, gFileSelLangEnglishENGTex }, + { 48, 48, 48 }, + 16, + }, + { + { gFileSelLangDeutschGERTex, gFileSelLangDeutschGERTex, gFileSelLangDeutschGERTex }, + { 48, 48, 48 }, + 16, + }, + { + { gFileSelLangFrancaisFRATex, gFileSelLangFrancaisFRATex, gFileSelLangFrancaisFRATex }, + { 48, 48, 48 }, + 16, + }, }; void FileChoose_DrawOptionsImpl(GameState* thisx) { @@ -943,12 +1023,22 @@ void FileChoose_DrawOptionsImpl(GameState* thisx) { } } + // Draw the change language header + if (isPalN64) { + gDPLoadTextureBlock(POLY_OPA_DISP++, gOptionsMenuHeaders[i].texture[gSaveContext.language], G_IM_FMT_IA, + G_IM_SIZ_8b, gOptionsMenuHeaders[i].width[gSaveContext.language], + gOptionsMenuHeaders[i].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); + + gSP1Quadrangle(POLY_OPA_DISP++, vtx, vtx + 2, vtx + 3, vtx + 1, 0); + } + if (gSaveContext.language == LANGUAGE_GER && isPalGC) { gSPVertex(POLY_OPA_DISP++, D_80812130, 32, 0); } else { // PAL N64 has extra german vertices combined in the regular array instead of a dedicated array if (isPalN64) { - gSPVertex(POLY_OPA_DISP++, D_80811F30, 40, 0); + gSPVertex(POLY_OPA_DISP++, D_80811F30, 52, 0); } else { gSPVertex(POLY_OPA_DISP++, D_80811F30, 32, 0); } @@ -981,7 +1071,7 @@ void FileChoose_DrawOptionsImpl(GameState* thisx) { gDPPipeSync(POLY_OPA_DISP++); if (i == (gSaveContext.zTargetSetting + 4)) { - if (sSelectedSetting != FS_SETTING_AUDIO) { + if (sSelectedSetting == FS_SETTING_TARGET) { gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, cursorPrimRed, cursorPrimGreen, cursorPrimBlue, this->titleAlpha[0]); gDPSetEnvColor(POLY_OPA_DISP++, cursorEnvRed, cursorEnvGreen, cursorEnvBlue, 0xFF); @@ -998,7 +1088,7 @@ void FileChoose_DrawOptionsImpl(GameState* thisx) { G_IM_SIZ_8b, gOptionsMenuSettings[i].width[gSaveContext.language], gOptionsMenuSettings[i].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); - // Pal N64 German vertices for z target options are offset an by 8 + // Pal N64 German vertices for z target options are offset by 8 if (gSaveContext.language == LANGUAGE_GER && isPalN64) { gSP1Quadrangle(POLY_OPA_DISP++, vtx + 8, vtx + 2 + 8, vtx + 3 + 8, vtx + 1 + 8, 0); } else { @@ -1030,6 +1120,33 @@ void FileChoose_DrawOptionsImpl(GameState* thisx) { vtx += 4; + // Draw the language options + if (isPalN64) { + for (; i < 9; i++, vtx += 4) { + gDPPipeSync(POLY_OPA_DISP++); + + if (i == (gSaveContext.language + 6)) { + if (sSelectedSetting == FS_SETTING_LANGUAGE) { + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, cursorPrimRed, cursorPrimGreen, cursorPrimBlue, + this->titleAlpha[0]); + gDPSetEnvColor(POLY_OPA_DISP++, cursorEnvRed, cursorEnvGreen, cursorEnvBlue, 0xFF); + } else { + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, this->titleAlpha[0]); + gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255); + } + } else { + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 120, 120, 120, this->titleAlpha[0]); + gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255); + } + + gDPLoadTextureBlock(POLY_OPA_DISP++, gOptionsMenuSettings[i].texture[gSaveContext.language], G_IM_FMT_IA, + G_IM_SIZ_8b, gOptionsMenuSettings[i].width[gSaveContext.language], + gOptionsMenuSettings[i].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); + gSP1Quadrangle(POLY_OPA_DISP++, vtx, vtx + 2, vtx + 3, vtx + 1, 0); + } + } + // blue divider lines gDPPipeSync(POLY_OPA_DISP++); gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 0, 255, 255, this->titleAlpha[0]); @@ -1064,6 +1181,17 @@ void FileChoose_DrawOptionsImpl(GameState* thisx) { gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0); Matrix_Pop(); + // Draw the divider for change language header + if (isPalN64) { + Matrix_Push(); + Matrix_Translate(0.0f, 0.3f, 0.0f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(this->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPVertex(POLY_OPA_DISP++, gOptionsDividerChangeLangVtx, 4, 0); + gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0); + Matrix_Pop(); + } + CLOSE_DISPS(this->state.gfxCtx); }