Merge branch 'develop' into hud_color_mod

This commit is contained in:
Baoulettes 2022-05-02 01:53:41 +02:00 committed by GitHub
commit f133017463
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 1384 additions and 775 deletions

99
Jenkinsfile vendored Normal file
View File

@ -0,0 +1,99 @@
pipeline {
environment {
MSBUILD='C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\Msbuild\\Current\\Bin\\msbuild.exe'
CONFIG='Release'
OTRPLATFORM='x64'
PLATFORM='x86'
ZIP='C:\\Program Files\\7-Zip\\7z.exe'
PYTHON='C:\\Users\\jenkins\\AppData\\Local\\Programs\\Python\\Python310\\python.exe'
TOOLSET='v142'
EMAILTO=''
}
agent {
label 'SoH-Builders'
}
options {
timestamps()
timeout(time: 15, unit: 'MINUTES')
skipDefaultCheckout(true)
}
stages {
stage ('Checkout') {
steps {
checkout([
$class: 'GitSCM',
branches: scm.branches,
doGenerateSubmoduleConfigurations: scm.doGenerateSubmoduleConfigurations,
extensions: scm.extensions,
userRemoteConfigs: scm.userRemoteConfigs
])
}
}
stage ('Build OTRExporter') {
steps {
bat """
"${env.MSBUILD}" ".\\OTRExporter\\OTRExporter.sln" -t:restore,build -p:Configuration=${env.CONFIG};Platform=${env.OTRPLATFORM};PlatformToolset=${env.TOOLSET};RestorePackagesConfig=true /nodeReuse:false
"""
}
}
stage ('Extract assets') {
steps {
bat """
xcopy "..\\..\\ZELOOTD.z64" "OTRExporter\\"
cd "OTRExporter"
"${env.PYTHON}" ".\\extract_assets.py"
cd "${env.WORKSPACE}"
"""
}
}
stage ('Build SoH') {
steps {
bat """
"${env.MSBUILD}" ".\\soh\\soh.sln" -t:build -p:Configuration=${env.CONFIG};Platform=${env.PLATFORM};PlatformToolset=${env.TOOLSET} /nodeReuse:false
"""
}
}
stage ('Archive artifacts') {
steps {
bat """
"${env.ZIP}" a "soh.zip" ".\\soh\\Release\\soh.exe"
"""
archiveArtifacts allowEmptyArchive: false,
artifacts: 'soh.zip',
caseSensitive: true,
defaultExcludes: true,
fingerprint: false,
onlyIfSuccessful: true
}
}
}
post {
always {
step([$class: 'Mailer',
notifyEveryUnstableBuild: true,
recipients: "${env.EMAILTO}",
sendToIndividuals: false])
step([$class: 'WsCleanup']) // Clean workspace
}
}
}

View File

@ -12,6 +12,7 @@ REGISTER_ZFILENODE(Text, ZText);
ZText::ZText(ZFile* nParent) : ZResource(nParent)
{
RegisterRequiredAttribute("CodeOffset");
RegisterOptionalAttribute("LangOffset", "0");
}
void ZText::ParseRawData()
@ -20,6 +21,16 @@ void ZText::ParseRawData()
const auto& rawData = parent->GetRawData();
uint32_t currentPtr = StringHelper::StrToL(registeredAttributes.at("CodeOffset").value, 16);
uint32_t langPtr = currentPtr;
bool isPalLang = false;
if (StringHelper::StrToL(registeredAttributes.at("LangOffset").value, 16) != 0)
{
langPtr = StringHelper::StrToL(registeredAttributes.at("LangOffset").value, 16);
if (langPtr != currentPtr)
isPalLang = true;
}
std::vector<uint8_t> codeData;
@ -34,8 +45,18 @@ void ZText::ParseRawData()
msgEntry.id = BitConverter::ToInt16BE(codeData, currentPtr + 0);
msgEntry.textboxType = (codeData[currentPtr + 2] & 0xF0) >> 4;
msgEntry.textboxYPos = (codeData[currentPtr + 2] & 0x0F);
msgEntry.segmentId = (codeData[currentPtr + 4]);
msgEntry.msgOffset = BitConverter::ToInt32BE(codeData, currentPtr + 4) & 0x00FFFFFF;
if (isPalLang)
{
msgEntry.segmentId = (codeData[langPtr + 0]);
msgEntry.msgOffset = BitConverter::ToInt32BE(codeData, langPtr + 0) & 0x00FFFFFF;
}
else
{
msgEntry.segmentId = (codeData[langPtr + 4]);
msgEntry.msgOffset = BitConverter::ToInt32BE(codeData, langPtr + 4) & 0x00FFFFFF;
}
uint32_t msgPtr = msgEntry.msgOffset;
unsigned char c = rawData[msgPtr];
@ -82,6 +103,11 @@ void ZText::ParseRawData()
break;
currentPtr += 8;
if (isPalLang)
langPtr += 4;
else
langPtr += 8;
}
int bp2 = 0;

View File

@ -1,4 +1,4 @@
#include "GameSettings.h"
#include "GameSettings.h"
// Audio
#include <PR/ultra64/sptask.h>
@ -14,6 +14,7 @@
#include "../../soh/include/z64audio.h"
#include <string>
#include "SohHooks.h"
#include "../../soh/soh/Enhancements/debugconsole.h"
#include "Window.h"
@ -34,14 +35,13 @@ namespace Game {
void UpdateAudio() {
Audio_SetGameVolume(SEQ_BGM_MAIN, Settings.audio.music_main);
Audio_SetGameVolume(SEQ_BGM_SUB, Settings.audio.music_sub);
Audio_SetGameVolume(SEQ_FANFARE, Settings.audio.fanfare);
Audio_SetGameVolume(SEQ_SFX, Settings.audio.sfx);
Audio_SetGameVolume(SEQ_BGM_MAIN, CVar_GetFloat("gMainMusicVolume", 1));
Audio_SetGameVolume(SEQ_BGM_SUB, CVar_GetFloat("gSubMusicVolume", 1));
Audio_SetGameVolume(SEQ_FANFARE, CVar_GetFloat("gSFXMusicVolume", 1));
Audio_SetGameVolume(SEQ_SFX, CVar_GetFloat("gFanfareVolume", 1));
}
void LoadSettings() {
const std::shared_ptr<ConfigFile> pConf = GlobalCtx2::GetInstance()->GetConfig();
ConfigFile& Conf = *pConf;
@ -50,119 +50,6 @@ namespace Game {
Settings.debug.menu_bar = stob(Conf[ConfSection]["menu_bar"]);
Settings.debug.soh = stob(Conf[ConfSection]["soh_debug"]);
Settings.debug.n64mode = stob(Conf[ConfSection]["n64_mode"]);
// Enhancements
Settings.enhancements.skip_text = stob(Conf[EnhancementSection]["skip_text"]);
CVar_SetS32("gSkipText", Settings.enhancements.skip_text);
Settings.enhancements.text_speed = Ship::stoi(Conf[EnhancementSection]["text_speed"]);
CVar_SetS32("gTextSpeed", Settings.enhancements.text_speed);
Settings.enhancements.disable_lod = stob(Conf[EnhancementSection]["disable_lod"]);
CVar_SetS32("gDisableLOD", Settings.enhancements.disable_lod);
Settings.enhancements.animated_pause_menu = stob(Conf[EnhancementSection]["animated_pause_menu"]);
CVar_SetS32("gPauseLiveLink", Settings.enhancements.animated_pause_menu);
Settings.enhancements.dynamic_wallet_icon = stob(Conf[EnhancementSection]["dynamic_wallet_icon"]);
CVar_SetS32("gDynamicWalletIcon", Settings.enhancements.dynamic_wallet_icon);
Settings.enhancements.minimal_ui = stob(Conf[EnhancementSection]["minimal_ui"]);
CVar_SetS32("gMinimalUI", Settings.enhancements.minimal_ui);
Settings.enhancements.visualagony = stob(Conf[EnhancementSection]["visualagony"]);
CVar_SetS32("gVisualAgony", Settings.enhancements.visualagony);
Settings.enhancements.mm_bunny_hood = stob(Conf[EnhancementSection]["mm_bunny_hood"]);
CVar_SetS32("gMMBunnyHood", Settings.enhancements.mm_bunny_hood);
Settings.enhancements.uniform_lr = stob(Conf[EnhancementSection]["uniform_lr"]);
//CVar_SetS32("gUniformLR", Settings.enhancements.uniform_lr);
CVar_SetS32("gUniformLR", 1);
Settings.enhancements.newdrops = stob(Conf[EnhancementSection]["newdrops"]);
CVar_SetS32("gNewDrops", Settings.enhancements.newdrops);
// Audio
Settings.audio.master = Ship::stof(Conf[AudioSection]["master"]);
CVar_SetFloat("gGameMasterVolume", Settings.audio.master);
Settings.audio.music_main = Ship::stof(Conf[AudioSection]["music_main"]);
CVar_SetFloat("gMainMusicVolume", Settings.audio.music_main);
Settings.audio.music_sub = Ship::stof(Conf[AudioSection]["music_sub"]);
CVar_SetFloat("gSubMusicVolume", Settings.audio.music_sub);
Settings.audio.sfx = Ship::stof(Conf[AudioSection]["sfx"]);
CVar_SetFloat("gSFXMusicVolume", Settings.audio.sfx);
Settings.audio.fanfare = Ship::stof(Conf[AudioSection]["fanfare"]);
CVar_SetFloat("gFanfareVolume", Settings.audio.fanfare);
// Controllers
Settings.controller.rumble_enabled = Ship::stof(Conf[ControllerSection]["rumble_enabled"]);
CVar_SetS32("gRumbleEnabled", Settings.controller.rumble_enabled);
Settings.controller.input_scale = Ship::stof(Conf[ControllerSection]["input_scale"]);
CVar_SetFloat("gInputScale", Settings.controller.input_scale);
Settings.controller.input_enabled = stob(Conf[ControllerSection]["input_enabled"]);
CVar_SetS32("gInputEnabled", Settings.controller.input_enabled);
Settings.controller.dpad_pause_name = stob(Conf[ControllerSection]["dpad_pause_name"]);
CVar_SetS32("gDpadPauseName", Settings.controller.dpad_pause_name);
Settings.controller.dpad_ocarina_text = stob(Conf[ControllerSection]["dpad_ocarina_text"]);
CVar_SetS32("gDpadOcarinaText", Settings.controller.dpad_ocarina_text);
Settings.controller.dpad_shop = stob(Conf[ControllerSection]["dpad_shop"]);
CVar_SetS32("gDpadShop", Settings.controller.dpad_shop);
// Cheats
Settings.cheats.debug_mode = stob(Conf[CheatSection]["debug_mode"]);
CVar_SetS32("gDebugEnabled", Settings.cheats.debug_mode);
Settings.cheats.infinite_money = stob(Conf[CheatSection]["infinite_money"]);
CVar_SetS32("gInfiniteMoney", Settings.cheats.infinite_money);
Settings.cheats.infinite_health = stob(Conf[CheatSection]["infinite_health"]);
CVar_SetS32("gInfiniteHealth", Settings.cheats.infinite_health);
Settings.cheats.infinite_ammo = stob(Conf[CheatSection]["infinite_ammo"]);
CVar_SetS32("gInfiniteAmmo", Settings.cheats.infinite_ammo);
Settings.cheats.infinite_magic = stob(Conf[CheatSection]["infinite_magic"]);
CVar_SetS32("gInfiniteMagic", Settings.cheats.infinite_magic);
Settings.cheats.infinite_nayru = stob(Conf[CheatSection]["infinite_nayru"]);
CVar_SetS32("gInfiniteNayru", Settings.cheats.infinite_nayru);
Settings.cheats.no_clip = stob(Conf[CheatSection]["no_clip"]);
CVar_SetS32("gNoClip", Settings.cheats.no_clip);
Settings.cheats.climb_everything = stob(Conf[CheatSection]["climb_everything"]);
CVar_SetS32("gClimbEverything", Settings.cheats.climb_everything);
Settings.cheats.moon_jump_on_l = stob(Conf[CheatSection]["moon_jump_on_l"]);
CVar_SetS32("gMoonJumpOnL", Settings.cheats.moon_jump_on_l);
Settings.cheats.super_tunic = stob(Conf[CheatSection]["super_tunic"]);
CVar_SetS32("gSuperTunic", Settings.cheats.super_tunic);
Settings.cheats.ez_isg = stob(Conf[CheatSection]["ez_isg"]);
CVar_SetS32("gEzISG", Settings.cheats.ez_isg);
Settings.cheats.no_restrict_item = stob(Conf[CheatSection]["no_restrict_item"]);
CVar_SetS32("gNoRestrictItems", Settings.cheats.no_restrict_item);
Settings.cheats.freeze_time = stob(Conf[CheatSection]["freeze_time"]);
CVar_SetS32("gFreezeTime", Settings.cheats.freeze_time);
// Per-Controller
LoadPadSettings();
UpdateAudio();
}
@ -173,10 +60,6 @@ namespace Game {
for (const auto& [i, controllers] : Ship::Window::Controllers) {
for (const auto& controller : controllers) {
if (auto padConfSection = controller->GetPadConfSection()) {
Settings.controller.extra[i].gyro_sensitivity = Ship::stof(Conf[*padConfSection]["gyro_sensitivity"]);
Settings.controller.extra[i].rumble_strength = Ship::stof(Conf[*padConfSection]["rumble_strength"]);
Settings.controller.extra[i].gyro_drift_x = Ship::stof(Conf[*padConfSection]["gyro_drift_x"], 0.0f);
Settings.controller.extra[i].gyro_drift_y = Ship::stof(Conf[*padConfSection]["gyro_drift_y"], 0.0f);
}
}
}
@ -190,60 +73,9 @@ namespace Game {
Conf[ConfSection]["console"] = std::to_string(SohImGui::console->opened);
Conf[ConfSection]["menu_bar"] = std::to_string(Settings.debug.menu_bar);
Conf[ConfSection]["soh_debug"] = std::to_string(Settings.debug.soh);
Conf[ConfSection]["n64_mode"] = std::to_string(Settings.debug.n64mode);
// Audio
Conf[AudioSection]["master"] = std::to_string(Settings.audio.master);
Conf[AudioSection]["music_main"] = std::to_string(Settings.audio.music_main);
Conf[AudioSection]["music_sub"] = std::to_string(Settings.audio.music_sub);
Conf[AudioSection]["sfx"] = std::to_string(Settings.audio.sfx);
Conf[AudioSection]["fanfare"] = std::to_string(Settings.audio.fanfare);
// Enhancements
Conf[EnhancementSection]["skip_text"] = std::to_string(Settings.enhancements.skip_text);
Conf[EnhancementSection]["text_speed"] = std::to_string(Settings.enhancements.text_speed);
Conf[EnhancementSection]["disable_lod"] = std::to_string(Settings.enhancements.disable_lod);
Conf[EnhancementSection]["animated_pause_menu"] = std::to_string(Settings.enhancements.animated_pause_menu);
Conf[EnhancementSection]["dynamic_wallet_icon"] = std::to_string(Settings.enhancements.dynamic_wallet_icon);
Conf[EnhancementSection]["minimal_ui"] = std::to_string(Settings.enhancements.minimal_ui);
Conf[EnhancementSection]["newdrops"] = std::to_string(Settings.enhancements.newdrops);
Conf[EnhancementSection]["visualagony"] = std::to_string(Settings.enhancements.visualagony);
Conf[EnhancementSection]["mm_bunny_hood"] = std::to_string(Settings.enhancements.mm_bunny_hood);
Conf[EnhancementSection]["uniform_lr"] = std::to_string(Settings.enhancements.uniform_lr);
// Controllers
Conf[ControllerSection]["rumble_enabled"] = std::to_string(Settings.controller.rumble_enabled);
Conf[ControllerSection]["input_scale"] = std::to_string(Settings.controller.input_scale);
Conf[ControllerSection]["input_enabled"] = std::to_string(Settings.controller.input_enabled);
Conf[ControllerSection]["dpad_pause_name"] = std::to_string(Settings.controller.dpad_pause_name);
Conf[ControllerSection]["dpad_ocarina_text"] = std::to_string(Settings.controller.dpad_ocarina_text);
Conf[ControllerSection]["dpad_shop"] = std::to_string(Settings.controller.dpad_shop);
// Cheats
Conf[CheatSection]["debug_mode"] = std::to_string(Settings.cheats.debug_mode);
Conf[CheatSection]["infinite_money"] = std::to_string(Settings.cheats.infinite_money);
Conf[CheatSection]["infinite_health"] = std::to_string(Settings.cheats.infinite_health);
Conf[CheatSection]["infinite_ammo"] = std::to_string(Settings.cheats.infinite_ammo);
Conf[CheatSection]["infinite_magic"] = std::to_string(Settings.cheats.infinite_magic);
Conf[CheatSection]["no_clip"] = std::to_string(Settings.cheats.no_clip);
Conf[CheatSection]["climb_everything"] = std::to_string(Settings.cheats.climb_everything);
Conf[CheatSection]["moon_jump_on_l"] = std::to_string(Settings.cheats.moon_jump_on_l);
Conf[CheatSection]["super_tunic"] = std::to_string(Settings.cheats.super_tunic);
// Per-Controller
for (const auto& [i, controllers] : Ship::Window::Controllers) {
for (const auto& controller : controllers) {
if (auto padConfSection = controller->GetPadConfSection()) {
Conf[*padConfSection]["gyro_sensitivity"] = std::to_string(Settings.controller.extra[i].gyro_sensitivity);
Conf[*padConfSection]["rumble_strength"] = std::to_string(Settings.controller.extra[i].rumble_strength);
Conf[*padConfSection]["gyro_drift_x"] = std::to_string(Settings.controller.extra[i].gyro_drift_x);
Conf[*padConfSection]["gyro_drift_y"] = std::to_string(Settings.controller.extra[i].gyro_drift_y);
}
}
}
Conf.Save();
DebugConsole_SaveCVars();
}
void InitSettings() {
@ -255,4 +87,4 @@ namespace Game {
void SetSeqPlayerVolume(SeqPlayers playerId, float volume) {
Audio_SetGameVolume(playerId, volume);
}
}
}

View File

@ -1,74 +1,23 @@
#pragma once
#pragma once
struct SoHConfigType {
// Debug
struct {
bool soh = false;
bool n64mode = false;
bool menu_bar = false;
bool soh_sink = true;
} debug;
// Audio
struct {
float master = 1.0f;
float music_main = 1.0f;
float fanfare = 1.0f;
float sfx = 1.0f;
float music_sub = 1.0f;
} audio;
// Enhancements
struct {
int text_speed = 1;
bool skip_text = false;
bool disable_lod = false;
bool animated_pause_menu = false;
bool dynamic_wallet_icon = false;
bool minimal_ui = false;
bool newdrops = false;
bool visualagony = false;
bool mm_bunny_hood = false;
bool uniform_lr = true;
} enhancements;
// Controller
struct {
struct {
float gyro_sensitivity = 1.0f;
float rumble_strength = 1.0f;
float gyro_drift_x = 0.0f;
float gyro_drift_y = 0.0f;
} extra[4];
bool rumble_enabled = true;
float input_scale = 1.0f;
bool input_enabled = false;
bool dpad_pause_name = false;
bool dpad_ocarina_text = false;
bool dpad_shop = false;
} controller;
// Cheats
struct {
bool debug_mode = false;
bool infinite_money = false;
bool infinite_health = false;
bool infinite_ammo = false;
bool infinite_magic = false;
bool infinite_nayru = false;
bool no_clip = false;
bool climb_everything = false;
bool moon_jump_on_l = false;
bool super_tunic = false;
bool ez_isg = false;
bool no_restrict_item = false;
bool freeze_time = false;
} cheats;
// Graphics
struct {
bool show = false;
} graphics;
//Interface editor
struct {
bool uiedit = false;
} cosmetics;
};
enum SeqPlayers {
@ -93,4 +42,4 @@ namespace Game {
void LoadPadSettings();
void SaveSettings();
void SetSeqPlayerVolume(SeqPlayers playerId, float volume);
}
}

View File

@ -610,6 +610,7 @@ static void gfx_opengl_init(void) {
glGenBuffers(1, &opengl_vbo);
glBindBuffer(GL_ARRAY_BUFFER, opengl_vbo);
glEnable(GL_DEPTH_CLAMP);
glDepthFunc(GL_LEQUAL);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@ -775,8 +776,13 @@ static std::map<std::pair<float, float>, uint16_t> gfx_opengl_get_pixel_depth(in
res.emplace(*coordinates.begin(), (depth_stencil_value >> 18) << 2);
} else {
if (pixel_depth_rb_size < coordinates.size()) {
// Resizing a renderbuffer seems broken with Intel's driver, so recreate one instead.
glBindFramebuffer(GL_FRAMEBUFFER, pixel_depth_fb);
glDeleteRenderbuffers(1, &pixel_depth_rb);
glGenRenderbuffers(1, &pixel_depth_rb);
glBindRenderbuffer(GL_RENDERBUFFER, pixel_depth_rb);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, coordinates.size(), 1);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, pixel_depth_rb);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
pixel_depth_rb_size = coordinates.size();
@ -813,6 +819,7 @@ static std::map<std::pair<float, float>, uint16_t> gfx_opengl_get_pixel_depth(in
}
glBindFramebuffer(GL_FRAMEBUFFER, current_framebuffer);
return res;
}

View File

@ -5,6 +5,8 @@
#include "spdlog/spdlog.h"
#include "stox.h"
#include "Window.h"
#include "Cvar.h"
#include <Utils/StringHelper.h>
extern "C" uint8_t __osMaxControllers;
@ -188,15 +190,15 @@ namespace Ship {
if (SDL_GameControllerHasSensor(Cont, SDL_SENSOR_GYRO))
{
size_t contNumber = GetControllerNumber();
float& gyro_drift_x = Game::Settings.controller.extra[contNumber].gyro_drift_x;
float& gyro_drift_y = Game::Settings.controller.extra[contNumber].gyro_drift_y;
const float gyro_sensitivity = Game::Settings.controller.extra[contNumber].gyro_sensitivity;
float gyroData[3];
SDL_GameControllerGetSensorData(Cont, SDL_SENSOR_GYRO, gyroData, 3);
const char* contName = SDL_GameControllerName(Cont);
const int isSpecialController = !strcmp("PS5 Controller", contName);
float gyro_drift_x = CVar_GetFloat(StringHelper::Sprintf("gCont%i_GyroDriftX", contNumber).c_str(), 0.0f);
float gyro_drift_y = CVar_GetFloat(StringHelper::Sprintf("gCont%i_GyroDriftY", contNumber).c_str(), 0.0f);
const float gyro_sensitivity = CVar_GetFloat(StringHelper::Sprintf("gCont%i_GyroSensitivity", contNumber).c_str(), 1.0f);
if (gyro_drift_x == 0) {
gyro_drift_x = gyroData[0];
@ -211,6 +213,9 @@ namespace Ship {
}
}
CVar_SetFloat(StringHelper::Sprintf("gCont%i_GyroDriftX", contNumber).c_str(), gyro_drift_x);
CVar_SetFloat(StringHelper::Sprintf("gCont%i_GyroDriftY", contNumber).c_str(), gyro_drift_y);
if (isSpecialController == 1) {
wGyroX = gyroData[0] - gyro_drift_x;
wGyroY = -gyroData[2] - gyro_drift_y;
@ -344,7 +349,7 @@ namespace Ship {
{
if (SDL_GameControllerHasRumble(Cont)) {
if (controller->rumble > 0) {
float rumble_strength = Game::Settings.controller.extra[GetControllerNumber()].rumble_strength;
float rumble_strength = CVar_GetFloat(StringHelper::Sprintf("gCont%i_RumbleStrength", GetControllerNumber()).c_str(), 1.0f);
SDL_GameControllerRumble(Cont, 0xFFFF * rumble_strength, 0xFFFF * rumble_strength, 0);
} else {
SDL_GameControllerRumble(Cont, 0, 0, 0);
@ -412,11 +417,6 @@ namespace Ship {
std::shared_ptr<ConfigFile> pConf = GlobalCtx2::GetInstance()->GetConfig();
ConfigFile& Conf = *pConf.get();
Conf[ConfSection]["gyro_sensitivity"] = std::to_string(1.0f);
Conf[ConfSection]["rumble_strength"] = std::to_string(1.0f);
Conf[ConfSection]["gyro_drift_x"] = std::to_string(0.0f);
Conf[ConfSection]["gyro_drift_y"] = std::to_string(0.0f);
Conf.Save();
}

View File

@ -56,26 +56,7 @@ namespace SohImGui {
Console* console = new Console;
bool p_open = false;
bool needs_save = false;
float kokiri_col[3] = { 0.118f, 0.41f, 0.106f };
float goron_col[3] = { 0.392f, 0.078f, 0.0f };
float zora_col[3] = { 0.0f, 0.235f, 0.392f };
float navi_idle_i_col[3] = { 0.0f, 0.0f, 0.0f };
float navi_idle_o_col[3] = { 0.0f, 0.0f, 0.0f };
float navi_npc_i_col[3] = { 0.0f, 0.0f, 0.0f };
float navi_npc_o_col[3] = { 0.0f, 0.0f, 0.0f };
float navi_enemy_i_col[3] = { 0.0f, 0.0f, 0.0f };
float navi_enemy_o_col[3] = { 0.0f, 0.0f, 0.0f };
float navi_prop_i_col[3] = { 0.0f, 0.0f, 0.0f };
float navi_prop_o_col[3] = { 0.0f, 0.0f, 0.0f };
std::map<std::string, std::vector<std::string>> windowCategories;
std::map<std::string, CustomWindow> customWindows;
//Custom color menu vars init
int SelectedHUD = CVar_GetS32("gHudColors", 1); //Default colors to Gamecube.
float hearts_colors[3] = {0,0,0};
float hearts_dd_colors[3] = {0,0,0};
float a_btn_colors[3] = {0,0,0};
@ -87,6 +68,20 @@ namespace SohImGui {
float magic_use_colors[3] = {0,0,0};
float minimap_colors[3] = {0,0,0};
float rupee_colors[3] = {0,0,0};
float kokiri_col[3] = { 0.118f, 0.41f, 0.106f };
float goron_col[3] = { 0.392f, 0.078f, 0.0f };
float zora_col[3] = { 0.0f, 0.235f, 0.392f };
float navi_idle_i_col[3] = { 0.0f, 0.0f, 0.0f };
float navi_idle_o_col[3] = { 0.0f, 0.0f, 0.0f };
float navi_npc_i_col[3] = { 0.0f, 0.0f, 0.0f };
float navi_npc_o_col[3] = { 0.0f, 0.0f, 0.0f };
float navi_enemy_i_col[3] = { 0.0f, 0.0f, 0.0f };
float navi_enemy_o_col[3] = { 0.0f, 0.0f, 0.0f };
float navi_prop_i_col[3] = { 0.0f, 0.0f, 0.0f };
float navi_prop_o_col[3] = { 0.0f, 0.0f, 0.0f };
std::map<std::string, std::vector<std::string>> windowCategories;
std::map<std::string, CustomWindow> customWindows;
void ImGuiWMInit() {
switch (impl.backend) {
@ -97,6 +92,7 @@ namespace SohImGui {
ImGui_ImplWin32_Init(impl.dx11.window);
break;
}
}
void ImGuiBackendInit() {
@ -202,78 +198,6 @@ namespace SohImGui {
stbi_image_free(img_data);
}
void LoadCosmeticColors(){//This function is necessary as without it IMGui wont load the updated float array.
hearts_colors[0] = (float)CVar_GetS32("gCCHeartsPrimR", 255)/255;
hearts_colors[1] = (float)CVar_GetS32("gCCHeartsPrimG", 10)/255;
hearts_colors[2] = (float)CVar_GetS32("gCCHeartsPrimB", 10)/255;
hearts_dd_colors[0] = (float)CVar_GetS32("gDDCCHeartsPrimR", 255)/255;
hearts_dd_colors[1] = (float)CVar_GetS32("gDDCCHeartsPrimG", 255)/255;
hearts_dd_colors[2] = (float)CVar_GetS32("gDDCCHeartsPrimB", 255)/255;
a_btn_colors[0] = (float)CVar_GetS32("gCCABtnPrimR", 90)/255;
a_btn_colors[1] = (float)CVar_GetS32("gCCABtnPrimG", 90)/255;
a_btn_colors[2] = (float)CVar_GetS32("gCCABtnPrimB", 255)/255;
b_btn_colors[0] = (float)CVar_GetS32("gCCBBtnPrimR", 0)/255;
b_btn_colors[1] = (float)CVar_GetS32("gCCBBtnPrimG", 150)/255;
b_btn_colors[2] = (float)CVar_GetS32("gCCBBtnPrimB", 0)/255;
c_btn_colors[0] = (float)CVar_GetS32("gCCCBtnPrimR", 255)/255;
c_btn_colors[1] = (float)CVar_GetS32("gCCCBtnPrimG", 160)/255;
c_btn_colors[2] = (float)CVar_GetS32("gCCCBtnPrimB", 0)/255;
start_btn_colors[0] = (float)CVar_GetS32("gCCStartBtnPrimR", 120)/255;
start_btn_colors[1] = (float)CVar_GetS32("gCCStartBtnPrimG", 120)/255;
start_btn_colors[2] = (float)CVar_GetS32("gCCStartBtnPrimB", 120)/255;
magic_border_colors[0] = (float)CVar_GetS32("gCCMagicBorderPrimR", 255)/255;
magic_border_colors[1] = (float)CVar_GetS32("gCCMagicBorderPrimG", 255)/255;
magic_border_colors[2] = (float)CVar_GetS32("gCCMagicBorderPrimB", 255)/255;
magic_remaining_colors[0] = (float)CVar_GetS32("gCCMagicPrimR", 250)/255;
magic_remaining_colors[1] = (float)CVar_GetS32("gCCMagicPrimG", 250)/255;
magic_remaining_colors[2] = (float)CVar_GetS32("gCCMagicPrimB", 0)/255;
magic_remaining_colors[0] = (float)CVar_GetS32("gCCMagicUsePrimR", 0)/255;
magic_remaining_colors[1] = (float)CVar_GetS32("gCCMagicUsePrimG", 200)/255;
magic_remaining_colors[2] = (float)CVar_GetS32("gCCMagicUsePrimB", 0)/255;
minimap_colors[0] = (float)CVar_GetS32("gCCMinimapPrimR", 0)/255;
minimap_colors[1] = (float)CVar_GetS32("gCCMinimapPrimG", 255)/255;
minimap_colors[2] = (float)CVar_GetS32("gCCMinimapPrimB", 255)/255;
rupee_colors[0] = (float)CVar_GetS32("gCCRupeePrimR", 120)/255;
rupee_colors[1] = (float)CVar_GetS32("gCCRupeePrimG", 120)/255;
rupee_colors[2] = (float)CVar_GetS32("gCCRupeePrimB", 120)/255;
kokiri_col[0] = (float)CVar_GetS32("gTunic_Kokiri_R", 30)/255;
kokiri_col[1] = (float)CVar_GetS32("gTunic_Kokiri_G", 105)/255;
kokiri_col[2] = (float)CVar_GetS32("gTunic_Kokiri_B", 27)/255;
kokiri_col[1] = (float)CVar_GetS32("gTunic_Kokiri_G", 105)/255;
kokiri_col[2] = (float)CVar_GetS32("gTunic_Kokiri_B", 27)/255;
zora_col[0] = (float)CVar_GetS32("gTunic_Zora_R", 0)/255;
zora_col[1] = (float)CVar_GetS32("gTunic_Zora_G", 60)/255;
zora_col[2] = (float)CVar_GetS32("gTunic_Zora_B", 100)/255;
navi_idle_i_col[0] = (float)CVar_GetS32("gNavi_Idle_Inner_R", 255)/255;
navi_idle_i_col[1] = (float)CVar_GetS32("gNavi_Idle_Inner_G", 255)/255;
navi_idle_i_col[2] = (float)CVar_GetS32("gNavi_Idle_Inner_B", 255)/255;
navi_idle_o_col[0] = (float)CVar_GetS32("gNavi_Idle_Outer_R", 115)/255;
navi_idle_o_col[1] = (float)CVar_GetS32("gNavi_Idle_Outer_G", 230)/255;
navi_idle_o_col[2] = (float)CVar_GetS32("gNavi_Idle_Outer_B", 255)/255;
navi_npc_i_col[0] = (float)CVar_GetS32("gNavi_NPC_Inner_R", 100)/255;
navi_npc_i_col[1] = (float)CVar_GetS32("gNavi_NPC_Inner_G", 100)/255;
navi_npc_i_col[2] = (float)CVar_GetS32("gNavi_NPC_Inner_B", 255)/255;
navi_npc_o_col[0] = (float)CVar_GetS32("gNavi_NPC_Outer_R", 90)/255;
navi_npc_o_col[1] = (float)CVar_GetS32("gNavi_NPC_Outer_G", 90)/255;
navi_npc_o_col[2] = (float)CVar_GetS32("gNavi_NPC_Outer_B", 255)/255;
navi_enemy_i_col[0] = (float)CVar_GetS32("gNavi_Enemy_Inner_R", 255)/255;
navi_enemy_i_col[1] = (float)CVar_GetS32("gNavi_Enemy_Inner_G", 255)/255;
navi_enemy_i_col[2] = (float)CVar_GetS32("gNavi_Enemy_Inner_B", 0)/255;
navi_enemy_o_col[0] = (float)CVar_GetS32("gNavi_Enemy_Outer_R", 220)/255;
navi_enemy_o_col[1] = (float)CVar_GetS32("gNavi_Enemy_Outer_G", 220)/255;
navi_enemy_o_col[2] = (float)CVar_GetS32("gNavi_Enemy_Outer_B", 0)/255;
navi_prop_i_col[0] = (float)CVar_GetS32("gNavi_Prop_Inner_R", 0)/255;
navi_prop_i_col[1] = (float)CVar_GetS32("gNavi_Prop_Inner_G", 255)/255;
navi_prop_i_col[2] = (float)CVar_GetS32("gNavi_Prop_Inner_B", 0)/255;
navi_prop_o_col[0] = (float)CVar_GetS32("gNavi_Prop_Outer_R", 0)/255;
navi_prop_o_col[1] = (float)CVar_GetS32("gNavi_Prop_Outer_G", 220)/255;
navi_prop_o_col[2] = (float)CVar_GetS32("gNavi_Prop_Outer_B", 0)/255;
}
int ClampFloatToInt(float value, int min, int max){
return fmin(fmax(value,min),max);
}
void LoadResource(const std::string& name, const std::string& path, const ImVec4& tint) {
GfxRenderingAPI* api = gfx_get_current_rendering_api();
const auto res = static_cast<Ship::Texture*>(GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(normalize(path)).get());
@ -318,6 +242,79 @@ namespace SohImGui {
DefaultAssets[name] = asset;
}
void LoadCosmeticColors(){//This function is necessary as without it IMGui wont load the updated float array.
hearts_colors[0] = (float)CVar_GetS32("gCCHeartsPrimR", 255)/255;
hearts_colors[1] = (float)CVar_GetS32("gCCHeartsPrimG", 10)/255;
hearts_colors[2] = (float)CVar_GetS32("gCCHeartsPrimB", 10)/255;
hearts_dd_colors[0] = (float)CVar_GetS32("gDDCCHeartsPrimR", 255)/255;
hearts_dd_colors[1] = (float)CVar_GetS32("gDDCCHeartsPrimG", 255)/255;
hearts_dd_colors[2] = (float)CVar_GetS32("gDDCCHeartsPrimB", 255)/255;
a_btn_colors[0] = (float)CVar_GetS32("gCCABtnPrimR", 90)/255;
a_btn_colors[1] = (float)CVar_GetS32("gCCABtnPrimG", 90)/255;
a_btn_colors[2] = (float)CVar_GetS32("gCCABtnPrimB", 255)/255;
b_btn_colors[0] = (float)CVar_GetS32("gCCBBtnPrimR", 0)/255;
b_btn_colors[1] = (float)CVar_GetS32("gCCBBtnPrimG", 150)/255;
b_btn_colors[2] = (float)CVar_GetS32("gCCBBtnPrimB", 0)/255;
c_btn_colors[0] = (float)CVar_GetS32("gCCCBtnPrimR", 255)/255;
c_btn_colors[1] = (float)CVar_GetS32("gCCCBtnPrimG", 160)/255;
c_btn_colors[2] = (float)CVar_GetS32("gCCCBtnPrimB", 0)/255;
start_btn_colors[0] = (float)CVar_GetS32("gCCStartBtnPrimR", 120)/255;
start_btn_colors[1] = (float)CVar_GetS32("gCCStartBtnPrimG", 120)/255;
start_btn_colors[2] = (float)CVar_GetS32("gCCStartBtnPrimB", 120)/255;
magic_border_colors[0] = (float)CVar_GetS32("gCCMagicBorderPrimR", 255)/255;
magic_border_colors[1] = (float)CVar_GetS32("gCCMagicBorderPrimG", 255)/255;
magic_border_colors[2] = (float)CVar_GetS32("gCCMagicBorderPrimB", 255)/255;
magic_remaining_colors[0] = (float)CVar_GetS32("gCCMagicPrimR", 250)/255;
magic_remaining_colors[1] = (float)CVar_GetS32("gCCMagicPrimG", 250)/255;
magic_remaining_colors[2] = (float)CVar_GetS32("gCCMagicPrimB", 0)/255;
magic_remaining_colors[0] = (float)CVar_GetS32("gCCMagicUsePrimR", 0)/255;
magic_remaining_colors[1] = (float)CVar_GetS32("gCCMagicUsePrimG", 200)/255;
magic_remaining_colors[2] = (float)CVar_GetS32("gCCMagicUsePrimB", 0)/255;
minimap_colors[0] = (float)CVar_GetS32("gCCMinimapPrimR", 0)/255;
minimap_colors[1] = (float)CVar_GetS32("gCCMinimapPrimG", 255)/255;
minimap_colors[2] = (float)CVar_GetS32("gCCMinimapPrimB", 255)/255;
rupee_colors[0] = (float)CVar_GetS32("gCCRupeePrimR", 120)/255;
rupee_colors[1] = (float)CVar_GetS32("gCCRupeePrimG", 120)/255;
rupee_colors[2] = (float)CVar_GetS32("gCCRupeePrimB", 120)/255;
kokiri_col[0] = (float)CVar_GetS32("gTunic_Kokiri_R", 30)/255;
kokiri_col[1] = (float)CVar_GetS32("gTunic_Kokiri_G", 105)/255;
kokiri_col[2] = (float)CVar_GetS32("gTunic_Kokiri_B", 27)/255;
goron_col[0] = (float)CVar_GetS32("gTunic_Goron_R", 100)/255;
goron_col[1] = (float)CVar_GetS32("gTunic_Goron_G", 20)/255;
goron_col[2] = (float)CVar_GetS32("gTunic_Goron_B", 0)/255;
zora_col[0] = (float)CVar_GetS32("gTunic_Zora_R", 0)/255;
zora_col[1] = (float)CVar_GetS32("gTunic_Zora_G", 60)/255;
zora_col[2] = (float)CVar_GetS32("gTunic_Zora_B", 100)/255;
navi_idle_i_col[0] = (float)CVar_GetS32("gNavi_Idle_Inner_R", 255)/255;
navi_idle_i_col[1] = (float)CVar_GetS32("gNavi_Idle_Inner_G", 255)/255;
navi_idle_i_col[2] = (float)CVar_GetS32("gNavi_Idle_Inner_B", 255)/255;
navi_idle_o_col[0] = (float)CVar_GetS32("gNavi_Idle_Outer_R", 115)/255;
navi_idle_o_col[1] = (float)CVar_GetS32("gNavi_Idle_Outer_G", 230)/255;
navi_idle_o_col[2] = (float)CVar_GetS32("gNavi_Idle_Outer_B", 255)/255;
navi_npc_i_col[0] = (float)CVar_GetS32("gNavi_NPC_Inner_R", 100)/255;
navi_npc_i_col[1] = (float)CVar_GetS32("gNavi_NPC_Inner_G", 100)/255;
navi_npc_i_col[2] = (float)CVar_GetS32("gNavi_NPC_Inner_B", 255)/255;
navi_npc_o_col[0] = (float)CVar_GetS32("gNavi_NPC_Outer_R", 90)/255;
navi_npc_o_col[1] = (float)CVar_GetS32("gNavi_NPC_Outer_G", 90)/255;
navi_npc_o_col[2] = (float)CVar_GetS32("gNavi_NPC_Outer_B", 255)/255;
navi_enemy_i_col[0] = (float)CVar_GetS32("gNavi_Enemy_Inner_R", 255)/255;
navi_enemy_i_col[1] = (float)CVar_GetS32("gNavi_Enemy_Inner_G", 255)/255;
navi_enemy_i_col[2] = (float)CVar_GetS32("gNavi_Enemy_Inner_B", 0)/255;
navi_enemy_o_col[0] = (float)CVar_GetS32("gNavi_Enemy_Outer_R", 220)/255;
navi_enemy_o_col[1] = (float)CVar_GetS32("gNavi_Enemy_Outer_G", 220)/255;
navi_enemy_o_col[2] = (float)CVar_GetS32("gNavi_Enemy_Outer_B", 0)/255;
navi_prop_i_col[0] = (float)CVar_GetS32("gNavi_Prop_Inner_R", 0)/255;
navi_prop_i_col[1] = (float)CVar_GetS32("gNavi_Prop_Inner_G", 255)/255;
navi_prop_i_col[2] = (float)CVar_GetS32("gNavi_Prop_Inner_B", 0)/255;
navi_prop_o_col[0] = (float)CVar_GetS32("gNavi_Prop_Outer_R", 0)/255;
navi_prop_o_col[1] = (float)CVar_GetS32("gNavi_Prop_Outer_G", 220)/255;
navi_prop_o_col[2] = (float)CVar_GetS32("gNavi_Prop_Outer_B", 0)/255;
}
int ClampFloatToInt(float value, int min, int max){
return fmin(fmax(value,min),max);
}
void Init(WindowImpl window_impl) {
impl = window_impl;
Game::LoadSettings();
@ -331,7 +328,6 @@ namespace SohImGui {
console->Init();
ImGuiWMInit();
ImGuiBackendInit();
LoadCosmeticColors(); //Fill custom colors array for Cosmetics tabs
ModInternal::registerHookListener({ GFX_INIT, [](const HookEvent ev) {
@ -351,10 +347,18 @@ namespace SohImGui {
LoadTexture("C-Down", "assets/ship_of_harkinian/buttons/CDown.png");
} });
for (const auto& [i, controllers] : Ship::Window::Controllers)
{
CVar_SetFloat(StringHelper::Sprintf("gCont%i_GyroDriftX", i).c_str(), 0);
CVar_SetFloat(StringHelper::Sprintf("gCont%i_GyroDriftY", i).c_str(), 0);
needs_save = true;
}
ModInternal::registerHookListener({ CONTROLLER_READ, [](const HookEvent ev) {
pads = static_cast<OSContPad*>(ev->baseArgs["cont_pad"]);
} });
Game::InitSettings();
LoadCosmeticColors();
}
void Update(EventImpl event) {
@ -367,31 +371,92 @@ namespace SohImGui {
#define BindButton(btn, status) ImGui::Image(GetTextureByID(DefaultAssets[btn]->textureId), ImVec2(16.0f * scale, 16.0f * scale), ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, (status) ? 255 : 0));
void BindAudioSlider(const char* name, const char* key, float* value, SeqPlayers playerId) {
ImGui::Text(name, static_cast<int>(100 * *(value)));
if (ImGui::SliderFloat((std::string("##") + key).c_str(), value, 0.0f, 1.0f, "")) {
const float volume = floorf(*(value) * 100) / 100;
void BindAudioSlider(const char* name, const char* key, float defaultValue, SeqPlayers playerId)
{
float value = CVar_GetFloat(key, defaultValue);
ImGui::Text(name, static_cast<int>(100 * value));
if (ImGui::SliderFloat((std::string("##") + key).c_str(), &value, 0.0f, 1.0f, "")) {
const float volume = floorf(value * 100) / 100;
CVar_SetFloat(key, volume);
needs_save = true;
Game::SetSeqPlayerVolume(playerId, volume);
}
}
void EnhancementColorEdit3(std::string text, std::string cvarName, float ColorRGB[3]) {
if (ImGui::ColorEdit3(text.c_str(), ColorRGB)) {
CVar_SetS32((cvarName+"R").c_str(), ClampFloatToInt(ColorRGB[0]*255,0,255));
CVar_SetS32((cvarName+"G").c_str(), ClampFloatToInt(ColorRGB[1]*255,0,255));
CVar_SetS32((cvarName+"B").c_str(), ClampFloatToInt(ColorRGB[2]*255,0,255));
void EnhancementCheckbox(std::string text, std::string cvarName)
{
bool val = (bool)CVar_GetS32(cvarName.c_str(), 0);
if (ImGui::Checkbox(text.c_str(), &val)) {
CVar_SetS32(cvarName.c_str(), val);
needs_save = true;
}
}
void EnhancementCheckbox(std::string text, std::string cvarName) {
bool val = (bool)CVar_GetS32(cvarName.c_str(), 0);
if (ImGui::Checkbox(text.c_str(), &val)) {
void EnhancementSliderInt(std::string text, std::string id, std::string cvarName, int min, int max, std::string format)
{
int val = CVar_GetS32(cvarName.c_str(), 0);
ImGui::Text(text.c_str(), val);
if (ImGui::SliderInt(id.c_str(), &val, min, max, format.c_str()))
{
CVar_SetS32(cvarName.c_str(), val);
needs_save = true;
}
if (val < min)
{
val = min;
CVar_SetS32(cvarName.c_str(), val);
needs_save = true;
}
if (val > max)
{
val = max;
CVar_SetS32(cvarName.c_str(), val);
needs_save = true;
}
}
void EnhancementSliderFloat(std::string text, std::string id, std::string cvarName, float min, float max, std::string format, float defaultValue, bool isPercentage)
{
float val = CVar_GetFloat(cvarName.c_str(), defaultValue);
if (!isPercentage)
ImGui::Text(text.c_str(), val);
else
ImGui::Text(text.c_str(), static_cast<int>(100 * val));
if (ImGui::SliderFloat(id.c_str(), &val, min, max, format.c_str()))
{
CVar_SetFloat(cvarName.c_str(), val);
needs_save = true;
}
if (val < min)
{
val = min;
CVar_SetFloat(cvarName.c_str(), val);
needs_save = true;
}
if (val > max)
{
val = max;
CVar_SetFloat(cvarName.c_str(), val);
needs_save = true;
}
}
void EnhancementColor3(std::string text, std::string cvarName, float ColorRGB[3]) {
if (ImGui::ColorEdit3(text.c_str(), ColorRGB)) {
CVar_SetS32((cvarName+"R").c_str(), ClampFloatToInt(ColorRGB[0]*255,0,255));
CVar_SetS32((cvarName+"G").c_str(), ClampFloatToInt(ColorRGB[1]*255,0,255));
CVar_SetS32((cvarName+"B").c_str(), ClampFloatToInt(ColorRGB[2]*255,0,255));
needs_save = true;
}
}
void DrawMainMenuAndCalculateGameSize() {
@ -449,224 +514,127 @@ namespace SohImGui {
ImGui::Separator();
if (ImGui::BeginMenu("Audio")) {
const float volume = Game::Settings.audio.master;
ImGui::Text("Master Volume: %d %%", static_cast<int>(100 * volume));
if (ImGui::SliderFloat("##Master_Vol", &Game::Settings.audio.master, 0.0f, 1.0f, "")) {
CVar_SetFloat("gGameMasterVolume", volume);
needs_save = true;
}
EnhancementSliderFloat("Master Volume: %d %%", "##Master_Vol", "gGameMasterVolume", 0.0f, 1.0f, "", 1.0f, true);
BindAudioSlider("Main Music Volume: %d %%", "gMainMusicVolume", &Game::Settings.audio.music_main, SEQ_BGM_MAIN);
BindAudioSlider("Sub Music Volume: %d %%", "gSubMusicVolume", &Game::Settings.audio.music_sub, SEQ_BGM_SUB);
BindAudioSlider("Sound Effects Volume: %d %%", "gSFXMusicVolume", &Game::Settings.audio.sfx, SEQ_SFX);
BindAudioSlider("Fanfare Volume: %d %%", "gFanfareVolume", &Game::Settings.audio.fanfare, SEQ_FANFARE);
BindAudioSlider("Main Music Volume: %d %%", "gMainMusicVolume", 1.0f, SEQ_BGM_MAIN);
BindAudioSlider("Sub Music Volume: %d %%", "gSubMusicVolume", 1.0f, SEQ_BGM_SUB);
BindAudioSlider("Sound Effects Volume: %d %%", "gSFXMusicVolume", 1.0f, SEQ_SFX);
BindAudioSlider("Fanfare Volume: %d %%", "gFanfareVolume", 1.0f, SEQ_FANFARE);
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Controller")) {
for (const auto& [i, controllers] : Ship::Window::Controllers) {
if (ImGui::BeginMenu("Controller"))
{
for (const auto& [i, controllers] : Ship::Window::Controllers)
{
bool hasPad = std::find_if(controllers.begin(), controllers.end(), [](const auto& c) {
return c->HasPadConf() && c->Connected();
}) != controllers.end();
}) != controllers.end();
if (!hasPad) continue;
if (!hasPad) continue;
auto menuLabel = "Controller " + std::to_string(i + 1);
if (ImGui::BeginMenu(menuLabel.c_str())) {
ImGui::Text("Gyro Sensitivity: %d %%", static_cast<int>(100 * Game::Settings.controller.extra[i].gyro_sensitivity));
if (ImGui::SliderFloat("##GYROSCOPE", &Game::Settings.controller.extra[i].gyro_sensitivity, 0.0f, 1.0f, "")) {
needs_save = true;
auto menuLabel = "Controller " + std::to_string(i + 1);
if (ImGui::BeginMenu(menuLabel.c_str()))
{
EnhancementSliderFloat("Gyro Sensitivity: %d %%", "##GYROSCOPE", StringHelper::Sprintf("gCont%i_GyroSensitivity", i), 0.0f, 1.0f, "", 1.0f, true);
if (ImGui::Button("Recalibrate Gyro"))
{
CVar_SetFloat(StringHelper::Sprintf("gCont%i_GyroDriftX", i).c_str(), 0);
CVar_SetFloat(StringHelper::Sprintf("gCont%i_GyroDriftY", i).c_str(), 0);
needs_save = true;
}
ImGui::Separator();
EnhancementSliderFloat("Rumble Strength: %d %%", "##RUMBLE", StringHelper::Sprintf("gCont%i_RumbleStrength", i), 0.0f, 1.0f, "", 1.0f, true);
ImGui::EndMenu();
}
if (ImGui::Button("Recalibrate Gyro")) {
Game::Settings.controller.extra[i].gyro_drift_x = 0;
Game::Settings.controller.extra[i].gyro_drift_y = 0;
needs_save = true;
}
ImGui::Separator();
ImGui::Text("Rumble Strength: %d %%", static_cast<int>(100 * Game::Settings.controller.extra[i].rumble_strength));
if (ImGui::SliderFloat("##RUMBLE", &Game::Settings.controller.extra[i].rumble_strength, 0.0f, 1.0f, "")) {
needs_save = true;
}
ImGui::EndMenu();
}
}
EnhancementCheckbox("Show Inputs", "gInputEnabled");
EnhancementCheckbox("Rumble Enabled", "gRumbleEnabled");
EnhancementSliderFloat("Input Scale: %.1f", "##Input", "gInputScale", 1.0f, 3.0f, "", 1.0f, false);
ImGui::Separator();
if (ImGui::Checkbox("Rumble Enabled", &Game::Settings.controller.rumble_enabled)) {
CVar_SetS32("gRumbleEnabled", Game::Settings.controller.rumble_enabled);
needs_save = true;
}
if (ImGui::Checkbox("Show Inputs", &Game::Settings.controller.input_enabled)) {
needs_save = true;
}
ImGui::Text("Input Scale: %.1f", Game::Settings.controller.input_scale);
if (ImGui::SliderFloat("##Input", &Game::Settings.controller.input_scale, 1.0f, 3.0f, "")) {
needs_save = true;
}
ImGui::Separator();
if (ImGui::Checkbox("Dpad Support on Pause and File Select", &Game::Settings.controller.dpad_pause_name)) {
CVar_SetS32("gDpadPauseName", Game::Settings.controller.dpad_pause_name);
needs_save = true;
}
if (ImGui::Checkbox("DPad Support in Ocarina and Text Choice", &Game::Settings.controller.dpad_ocarina_text)) {
CVar_SetS32("gDpadOcarinaText", Game::Settings.controller.dpad_ocarina_text);
needs_save = true;
}
if (ImGui::Checkbox("DPad Support for Browsing Shop Items", &Game::Settings.controller.dpad_shop)) {
CVar_SetS32("gDpadShop", Game::Settings.controller.dpad_shop);
needs_save = true;
}
EnhancementCheckbox("Dpad Support on Pause and File Select", "gDpadPauseName");
EnhancementCheckbox("DPad Support in Ocarina and Text Choice", "gDpadOcarinaText");
EnhancementCheckbox("DPad Support for Browsing Shop Items", "gDpadShop");
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Enhancements")) {
if (ImGui::BeginMenu("Enhancements"))
{
ImGui::Text("Gameplay");
ImGui::Separator();
ImGui::Text("Text Speed: %dx", Game::Settings.enhancements.text_speed);
if (ImGui::SliderInt("##TEXTSPEED", &Game::Settings.enhancements.text_speed, 1, 5, "")) {
CVar_SetS32("gTextSpeed", Game::Settings.enhancements.text_speed);
needs_save = true;
}
EnhancementSliderInt("Text Speed: %dx", "##TEXTSPEED", "gTextSpeed", 1, 5, "");
if (ImGui::Checkbox("Skip Text", &Game::Settings.enhancements.skip_text)) {
CVar_SetS32("gSkipText", Game::Settings.enhancements.skip_text);
needs_save = true;
}
if (ImGui::Checkbox("Minimal UI", &Game::Settings.enhancements.minimal_ui)) {
CVar_SetS32("gMinimalUI", Game::Settings.enhancements.minimal_ui);
needs_save = true;
}
if (ImGui::Checkbox("MM Bunny Hood", &Game::Settings.enhancements.mm_bunny_hood)) {
CVar_SetS32("gMMBunnyHood", Game::Settings.enhancements.mm_bunny_hood);
needs_save = true;
}
/*if (ImGui::Checkbox("Fix L&R Pause menu", &Game::Settings.enhancements.uniform_lr)) {
CVar_SetS32("gUniformLR", Game::Settings.enhancements.uniform_lr);
needs_save = true;
}*/
if (ImGui::Checkbox("Visual Stone of Agony", &Game::Settings.enhancements.visualagony)) {
CVar_SetS32("gVisualAgony", Game::Settings.enhancements.visualagony);
needs_save = true;
}
EnhancementCheckbox("Skip Text", "gSkipText");
EnhancementCheckbox("Minimal UI", "gMinimalUI");
EnhancementCheckbox("MM Bunny Hood", "gMMBunnyHood");
EnhancementCheckbox("Visual Stone of Agony", "gVisualAgony");
ImGui::Text("Graphics");
ImGui::Separator();
HOOK(ImGui::Checkbox("N64 Mode", &Game::Settings.debug.n64mode));
EnhancementCheckbox("N64 Mode", "gN64Mode");
if (ImGui::Checkbox("Animated Link in Pause Menu", &Game::Settings.enhancements.animated_pause_menu)) {
CVar_SetS32("gPauseLiveLink", Game::Settings.enhancements.animated_pause_menu);
needs_save = true;
}
if (ImGui::Checkbox("Disable LOD", &Game::Settings.enhancements.disable_lod)) {
CVar_SetS32("gDisableLOD", Game::Settings.enhancements.disable_lod);
needs_save = true;
}
if (ImGui::Checkbox("Enable 3D Dropped items", &Game::Settings.enhancements.newdrops)) {
CVar_SetS32("gNewDrops", Game::Settings.enhancements.newdrops);
needs_save = true;
}
if (ImGui::Checkbox("Dynamic Wallet Icon", &Game::Settings.enhancements.dynamic_wallet_icon)) {
CVar_SetS32("gDynamicWalletIcon", Game::Settings.enhancements.dynamic_wallet_icon);
needs_save = true;
}
EnhancementCheckbox("Animated Link in Pause Menu", "gPauseLiveLink");
EnhancementCheckbox("Disable LOD", "gDisableLOD");
EnhancementCheckbox("Enable 3D Dropped items", "gNewDrops");
EnhancementCheckbox("Dynamic Wallet Icon", "gDynamicWalletIcon");
ImGui::EndMenu();
}
ImGui::EndMenuBar();
if (ImGui::BeginMenu("Developer Tools")) {
if (ImGui::BeginMenu("Developer Tools"))
{
HOOK(ImGui::MenuItem("Stats", nullptr, &Game::Settings.debug.soh));
HOOK(ImGui::MenuItem("Console", nullptr, &console->opened));
ImGui::Text("Debug");
ImGui::Separator();
if (ImGui::Checkbox("Debug Mode", &Game::Settings.cheats.debug_mode)) {
CVar_SetS32("gDebugEnabled", Game::Settings.cheats.debug_mode);
needs_save = true;
}
EnhancementCheckbox("Debug Mode", "gDebugEnabled");
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Graphics")) {
if (ImGui::BeginMenu("Graphics"))
{
HOOK(ImGui::MenuItem("Anti-aliasing", nullptr, &Game::Settings.graphics.show));
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Cheats")) {
if (ImGui::BeginMenu("Cheats"))
{
if (ImGui::BeginMenu("Infinite...")) {
if (ImGui::Checkbox("Money", &Game::Settings.cheats.infinite_money)) {
CVar_SetS32("gInfiniteMoney", Game::Settings.cheats.infinite_money);
needs_save = true;
}
EnhancementCheckbox("Money", "gInfiniteMoney");
EnhancementCheckbox("Health", "gInfiniteHealth");
EnhancementCheckbox("Ammo", "gInfiniteAmmo");
EnhancementCheckbox("Magic", "gInfiniteMagic");
EnhancementCheckbox("Nayru's Love", "gInfiniteNayru");
if (ImGui::Checkbox("Health", &Game::Settings.cheats.infinite_health)) {
CVar_SetS32("gInfiniteHealth", Game::Settings.cheats.infinite_health);
needs_save = true;
}
if (ImGui::Checkbox("Ammo", &Game::Settings.cheats.infinite_ammo)) {
CVar_SetS32("gInfiniteAmmo", Game::Settings.cheats.infinite_ammo);
needs_save = true;
}
if (ImGui::Checkbox("Magic", &Game::Settings.cheats.infinite_magic)) {
CVar_SetS32("gInfiniteMagic", Game::Settings.cheats.infinite_magic);
needs_save = true;
}
if (ImGui::Checkbox("Nayru's Love", &Game::Settings.cheats.infinite_nayru)) {
CVar_SetS32("gInfiniteNayru", Game::Settings.cheats.infinite_nayru);
needs_save = true;
}
ImGui::EndMenu();
}
if (ImGui::Checkbox("No Clip", &Game::Settings.cheats.no_clip)) {
CVar_SetS32("gNoClip", Game::Settings.cheats.no_clip);
needs_save = true;
}
EnhancementCheckbox("No Clip", "gNoClip");
EnhancementCheckbox("Climb Everything", "gClimbEverything");
EnhancementCheckbox("Moon Jump on L", "gMoonJumpOnL");
EnhancementCheckbox("Super Tunic", "gSuperTunic");
EnhancementCheckbox("Easy ISG", "gEzISG");
EnhancementCheckbox("Unrestricted Items", "gNoRestrictItems");
EnhancementCheckbox("Freeze Time", "gFreezeTime");
if (ImGui::Checkbox("Climb Everything", &Game::Settings.cheats.climb_everything)) {
CVar_SetS32("gClimbEverything", Game::Settings.cheats.climb_everything);
needs_save = true;
}
if (ImGui::Checkbox("Moon Jump on L", &Game::Settings.cheats.moon_jump_on_l)) {
CVar_SetS32("gMoonJumpOnL", Game::Settings.cheats.moon_jump_on_l);
needs_save = true;
}
if (ImGui::Checkbox("Super Tunic", &Game::Settings.cheats.super_tunic)) {
CVar_SetS32("gSuperTunic", Game::Settings.cheats.super_tunic);
needs_save = true;
}
ImGui::EndMenu();
}
if (CVar_GetS32("gHudColors", 1) ==0) {
@ -678,23 +646,25 @@ namespace SohImGui {
}
if (ImGui::BeginMenu("Cosmetics")) {
if (ImGui::BeginMenu("Tunics")) {
EnhancementColorEdit3("Kokiri Tunic", "gTunic_Kokiri_", kokiri_col);
EnhancementColorEdit3("Goron Tunic", "gTunic_Goron_", goron_col);
EnhancementColorEdit3("Zora Tunic", "gTunic_Zora_", zora_col);
EnhancementCheckbox("Custom colors on tunics", "gUseTunicsCol");
EnhancementColor3("Kokiri Tunic", "gTunic_Kokiri_", kokiri_col);
EnhancementColor3("Goron Tunic", "gTunic_Goron_", goron_col);
EnhancementColor3("Zora Tunic", "gTunic_Zora_", zora_col);
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Navi")) {
EnhancementColorEdit3("Navi Idle Inner", "gNavi_Idle_Inner_", navi_idle_i_col);
EnhancementColorEdit3("Navi Idle Outer", "gNavi_Idle_Outer_", navi_idle_o_col);
EnhancementCheckbox("Custom colors for Navi", "gUseNaviCol");
EnhancementColor3("Navi Idle Inner", "gNavi_Idle_Inner_", navi_idle_i_col);
EnhancementColor3("Navi Idle Outer", "gNavi_Idle_Outer_", navi_idle_o_col);
ImGui::Separator();
EnhancementColorEdit3("Navi NPC Inner", "gNavi_NPC_Inner_", navi_npc_i_col);
EnhancementColorEdit3("Navi NPC Outer", "gNavi_NPC_Outer_", navi_npc_o_col);
EnhancementColor3("Navi NPC Inner", "gNavi_NPC_Inner_", navi_npc_i_col);
EnhancementColor3("Navi NPC Outer", "gNavi_NPC_Outer_", navi_npc_o_col);
ImGui::Separator();
EnhancementColorEdit3("Navi Enemy Inner", "gNavi_Enemy_Inner_", navi_enemy_i_col);
EnhancementColorEdit3("Navi Enemy Outer", "gNavi_Enemy_Outer_", navi_enemy_o_col);
EnhancementColor3("Navi Enemy Inner", "gNavi_Enemy_Inner_", navi_enemy_i_col);
EnhancementColor3("Navi Enemy Outer", "gNavi_Enemy_Outer_", navi_enemy_o_col);
ImGui::Separator();
EnhancementColorEdit3("Navi Prop Inner", "gNavi_Prop_Inner_", navi_prop_i_col);
EnhancementColorEdit3("Navi Prop Outer", "gNavi_Prop_Outer_", navi_prop_o_col);
EnhancementColor3("Navi Prop Inner", "gNavi_Prop_Inner_", navi_prop_i_col);
EnhancementColor3("Navi Prop Outer", "gNavi_Prop_Outer_", navi_prop_o_col);
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Interface")) {
@ -703,54 +673,46 @@ namespace SohImGui {
EnhancementRadioButton("Custom Colors", "gHudColors", 2);
if (ImGui::BeginMenu("Edit HUD Colors")) {
if (ImGui::BeginMenu("Hearts")) {
EnhancementColorEdit3("Hearts normals", "gCCHeartsPrim", hearts_colors);
EnhancementColorEdit3("Hearts double def", "gDDCCHeartsPrim", hearts_dd_colors);
EnhancementColor3("Hearts normals", "gCCHeartsPrim", hearts_colors);
EnhancementColor3("Hearts double def", "gDDCCHeartsPrim", hearts_dd_colors);
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Buttons")) {
EnhancementColorEdit3("A Buttons", "gCCABtnPrim", a_btn_colors);
EnhancementColorEdit3("B Buttons", "gCCBBtnPrim", b_btn_colors);
EnhancementColorEdit3("C Buttons", "gCCCBtnPrim", c_btn_colors);
EnhancementColorEdit3("Start Buttons", "gCCStartBtnPrim", start_btn_colors);
EnhancementColor3("A Buttons", "gCCABtnPrim", a_btn_colors);
EnhancementColor3("B Buttons", "gCCBBtnPrim", b_btn_colors);
EnhancementColor3("C Buttons", "gCCCBtnPrim", c_btn_colors);
EnhancementColor3("Start Buttons", "gCCStartBtnPrim", start_btn_colors);
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Magic Bar")) {
EnhancementColorEdit3("Magic bar borders", "gCCMagicBorderPrim", magic_border_colors);
EnhancementColorEdit3("Magic bar main color", "gCCMagicPrim", magic_remaining_colors);
EnhancementColorEdit3("Magic bar being used", "gCCMagicUsePrim", magic_use_colors);
EnhancementColor3("Magic bar borders", "gCCMagicBorderPrim", magic_border_colors);
EnhancementColor3("Magic bar main color", "gCCMagicPrim", magic_remaining_colors);
EnhancementColor3("Magic bar being used", "gCCMagicUsePrim", magic_use_colors);
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Misc")) {
EnhancementColorEdit3("Minimap color", "gCCMinimapPrim", minimap_colors);
EnhancementColorEdit3("Rupee icon color", "gCCRupeePrim", rupee_colors);
EnhancementColor3("Minimap color", "gCCMinimapPrim", minimap_colors);
EnhancementColor3("Rupee icon color", "gCCRupeePrim", rupee_colors);
ImGui::EndMenu();
}
ImGui::EndMenu();
}
HOOK(ImGui::MenuItem("Interface edit", nullptr, &Game::Settings.cosmetics.uiedit));
ImGui::EndMenu();
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Developer Tools")) {
HOOK(ImGui::MenuItem("Stats", nullptr, &Game::Settings.debug.soh));
HOOK(ImGui::MenuItem("Console", nullptr, &console->opened));
if (ImGui::Checkbox("Easy ISG", &Game::Settings.cheats.ez_isg)) {
CVar_SetS32("gEzISG", Game::Settings.cheats.ez_isg);
needs_save = true;
}
if (ImGui::Checkbox("Unrestricted Items", &Game::Settings.cheats.no_restrict_item)) {
CVar_SetS32("gNoRestrictItems", Game::Settings.cheats.no_restrict_item);
needs_save = true;
}
if (ImGui::Checkbox("Freeze Time", &Game::Settings.cheats.freeze_time)) {
CVar_SetS32("gFreezeTime", Game::Settings.cheats.freeze_time);
needs_save = true;
}
ImGui::EndMenu();
if (Game::Settings.cosmetics.uiedit) {
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0));
ImGui::Begin("Interface modifier", nullptr, ImGuiWindowFlags_None);
EnhancementCheckbox("Use margins", "gHUDMargins");
EnhancementSliderInt("Top : %dx", "##UIMARGINT", "gHUDMargin_T", -20, 20, "");
EnhancementSliderInt("Left: %dx", "##UIMARGINL", "gHUDMargin_L", -25, 25, "");
EnhancementSliderInt("Right: %dx", "##UIMARGINR", "gHUDMargin_R", -25, 25, "");
EnhancementSliderInt("Bottom: %dx", "##UIMARGINB", "gHUDMargin_B", -20, 20, "");
ImGui::End();
ImGui::PopStyleColor();
}
for (const auto& category : windowCategories) {
@ -818,7 +780,9 @@ namespace SohImGui {
gfx_current_game_window_viewport.y = main_pos.y;
gfx_current_game_window_viewport.width = size.x;
gfx_current_game_window_viewport.height = size.y;
if (Game::Settings.debug.n64mode) {
if (CVar_GetS32("gN64Mode", 0))
{
gfx_current_dimensions.width = 320;
gfx_current_dimensions.height = 240;
const int sw = size.y * 320 / 240;
@ -833,7 +797,7 @@ namespace SohImGui {
ImVec2 main_pos = ImGui::GetWindowPos();
ImVec2 size = ImGui::GetContentRegionAvail();
ImVec2 pos = ImVec2(0, 0);
if (Game::Settings.debug.n64mode) {
if (CVar_GetS32("gN64Mode", 0)) {
const int sw = size.y * 320 / 240;
pos = ImVec2(size.x / 2 - sw / 2, 0);
size = ImVec2(sw, size.y);
@ -848,10 +812,10 @@ namespace SohImGui {
ImGui::End();
const float scale = Game::Settings.controller.input_scale;
const float scale = CVar_GetFloat("gInputScale", 1.0f);
ImVec2 BtnPos = ImVec2(160 * scale, 85 * scale);
if (Game::Settings.controller.input_enabled) {
if (CVar_GetS32("gInputEnabled", 0)) {
ImGui::SetNextWindowSize(BtnPos);
ImGui::SetNextWindowPos(ImVec2(main_pos.x + size.x - BtnPos.x - 20, main_pos.y + size.y - BtnPos.y - 20));
@ -936,4 +900,4 @@ namespace SohImGui {
ImTextureID GetTextureByName(const std::string& name) {
return GetTextureByID(DefaultAssets[name]->textureId);
}
}
}

View File

@ -60,10 +60,15 @@ namespace SohImGui {
extern Console* console;
void Init(WindowImpl window_impl);
void Update(EventImpl event);
void EnhancementColorEdit3(std::string text, std::string cvarName, float ColorRGB[3]);
void EnhancementCheckbox(std::string text, std::string cvarName);
int ClampFloatToInt(float value, int min, int max);
void EnhancementCheckbox(std::string text, std::string cvarName);
void EnhancementSliderInt(std::string text, std::string id, std::string cvarName, int min, int max, std::string format);
void EnhancementSliderFloat(std::string text, std::string id, std::string cvarName, float min, float max, std::string format, float defaultValue);
void DrawMainMenuAndCalculateGameSize(void);
void DrawFramebufferAndGameInput(void);
void Render(void);
void CancelFrame(void);

View File

@ -275,8 +275,11 @@ namespace Ship {
WmApi->set_keyboard_callbacks(Window::KeyDown, Window::KeyUp, Window::AllKeysUp);
}
void Window::RunCommands(Gfx* Commands) {
void Window::StartFrame() {
gfx_start_frame();
}
void Window::RunCommands(Gfx* Commands) {
gfx_run(Commands);
gfx_end_frame();
}

View File

@ -18,6 +18,7 @@ namespace Ship {
~Window();
void MainLoop(void (*MainFunction)(void));
void Init();
void StartFrame();
void RunCommands(Gfx* Commands);
void SetFrameDivisor(int divisor);
void GetPixelDepthPrepare(float x, float y);

View File

@ -0,0 +1,14 @@
<Root>
<File Name="nes_message_data_static">
<Text Name="nes_message_data_static" CodeOffset="0x12E4E0"/>
</File>
<File Name="ger_message_data_static">
<Text Name="ger_message_data_static" CodeOffset="0x12E4E0" LangOffset="0x132708"/>
</File>
<File Name="fra_message_data_static">
<Text Name="fra_message_data_static" CodeOffset="0x12E4E0" LangOffset="0x134818"/>
</File>
<File Name="staff_message_data_static">
<Text Name="staff_message_data_static" CodeOffset="0x136928"/>
</File>
</Root>

View File

@ -1,5 +0,0 @@
<Root>
<File Name="nes_message_data_static">
<Text Name="nes_message_data_static" CodeOffset="0x12E4E0"/>
</File>
</Root>

View File

@ -1,5 +0,0 @@
<Root>
<File Name="staff_message_data_static">
<Text Name="staff_message_data_static" CodeOffset="0x136928"/>
</File>
</Root>

View File

@ -0,0 +1,14 @@
<Root>
<File Name="nes_message_data_static">
<Text Name="nes_message_data_static" CodeOffset="0xF6910"/>
</File>
<File Name="ger_message_data_static">
<Text Name="ger_message_data_static" CodeOffset="0xF6910" LangOffset="0xFAB38"/>
</File>
<File Name="fra_message_data_static">
<Text Name="fra_message_data_static" CodeOffset="0xF6910" LangOffset="0xFCC48"/>
</File>
<File Name="staff_message_data_static">
<Text Name="staff_message_data_static" CodeOffset="0xFED58"/>
</File>
</Root>

View File

@ -1,5 +0,0 @@
<Root>
<File Name="nes_message_data_static">
<Text Name="nes_message_data_static" CodeOffset="0xF6910"/>
</File>
</Root>

View File

@ -1,5 +0,0 @@
<Root>
<File Name="staff_message_data_static">
<Text Name="staff_message_data_static" CodeOffset="0xFED58"/>
</File>
</Root>

View File

@ -656,10 +656,12 @@ Vec3s* SurfaceType_GetCamPosData(CollisionContext* colCtx, CollisionPoly* poly,
u32 SurfaceType_GetSceneExitIndex(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId);
u32 func_80041D4C(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId);
u32 func_80041D70(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId);
u32 func_80041D94(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId);
s32 func_80041DB8(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId);
s32 func_80041DE4(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId);
s32 func_80041E18(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId);
s32 func_80041E4C(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId);
s32 func_80041E80(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId);
u32 func_80041EA4(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId);
u32 func_80041EC8(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId);
u32 SurfaceType_IsHorseBlocked(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId);

View File

@ -126,12 +126,12 @@
extern GraphicsContext* __gfxCtx;
#define WORK_DISP __gfxCtx->work.p
#define POLY_OPA_DISP __gfxCtx->polyOpa.p
#define POLY_XLU_DISP __gfxCtx->polyXlu.p
#define TITLE_CARD_DISP __gfxCtx->titlecard.p
#define POLY_KAL_DISP __gfxCtx->polyKal.p
#define OVERLAY_DISP __gfxCtx->overlay.p
#define WORK_DISP __gfxCtx->work.p
#define POLY_OPA_DISP __gfxCtx->polyOpa.p
#define POLY_XLU_DISP __gfxCtx->polyXlu.p
#define WORLD_OVERLAY_DISP __gfxCtx->worldOverlay.p
#define POLY_KAL_DISP __gfxCtx->polyKal.p
#define OVERLAY_DISP __gfxCtx->overlay.p
// __gfxCtx shouldn't be used directly.
// Use the DISP macros defined above when writing to display buffers.

View File

@ -83,7 +83,7 @@ typedef struct {
/* 0x00000 */ u16 headMagic; // GFXPOOL_HEAD_MAGIC
/* 0x00008 */ Gfx polyOpaBuffer[0x2FC0];
/* 0x0BF08 */ Gfx polyXluBuffer[0x1000];
/* 0xXXXXX */ Gfx titlecardBuffer[0x1000];
/* 0xXXXXX */ Gfx worldOverlayBuffer[0x1000];
/* 0x0BF08 */ Gfx polyKalBuffer[0x1000];
/* 0x0FF08 */ Gfx overlayBuffer[0x800];
/* 0x11F08 */ Gfx workBuffer[0x100];
@ -131,7 +131,7 @@ typedef struct OSScTask {
typedef struct GraphicsContext {
/* 0x0000 */ Gfx* polyOpaBuffer; // Pointer to "Zelda 0"
/* 0x0004 */ Gfx* polyXluBuffer; // Pointer to "Zelda 1"
/* 0xXXX */ Gfx* titlecardBuffer; // Pointer to "Paris"
/* 0xXXX */ Gfx* worldOverlayBuffer; // Pointer to "Paris"
/* 0xXXX */ Gfx* polyKalBuffer; // Pointer to "Rome"
/* 0x0008 */ char unk_008[0x08]; // Unused, could this be pointers to "Zelda 2" / "Zelda 3"
/* 0x0010 */ Gfx* overlayBuffer; // Pointer to "Zelda 4"
@ -151,7 +151,7 @@ typedef struct GraphicsContext {
/* 0x02A8 */ TwoHeadGfxArena overlay; // "Zelda 4"
/* 0x02B8 */ TwoHeadGfxArena polyOpa; // "Zelda 0"
/* 0x02C8 */ TwoHeadGfxArena polyXlu; // "Zelda 1"
/* 0x0XXX */ TwoHeadGfxArena titlecard; // When in Paris...
/* 0x0XXX */ TwoHeadGfxArena worldOverlay; // When in Paris...
/* 0x0XXX */ TwoHeadGfxArena polyKal; // When in Rome...
/* 0x02D8 */ u32 gfxPoolIdx;
/* 0x02DC */ u16* curFrameBuffer;

View File

@ -175,8 +175,10 @@
<ItemGroup>
<ClCompile Include="soh\Enhancements\bootcommands.c" />
<ClCompile Include="soh\Enhancements\debugconsole.cpp" />
<ClCompile Include="soh\Enhancements\debugger\colViewer.cpp" />
<ClCompile Include="soh\Enhancements\debugger\debugger.cpp" />
<ClCompile Include="soh\Enhancements\debugger\debugSaveEditor.cpp" />
<ClCompile Include="soh\Enhancements\debugger\ImGuiHelpers.cpp" />
<ClCompile Include="soh\Enhancements\gameconsole.c" />
<ClCompile Include="soh\GbiWrap.cpp" />
<ClCompile Include="soh\gu_pc.c" />
@ -922,8 +924,10 @@
<ClInclude Include="soh\Enhancements\bootcommands.h" />
<ClInclude Include="soh\Enhancements\cvar.h" />
<ClInclude Include="soh\Enhancements\debugconsole.h" />
<ClInclude Include="soh\Enhancements\debugger\colViewer.h" />
<ClInclude Include="soh\Enhancements\debugger\debugger.h" />
<ClInclude Include="soh\Enhancements\debugger\debugSaveEditor.h" />
<ClInclude Include="soh\Enhancements\debugger\ImGuiHelpers.h" />
<ClInclude Include="soh\gameconsole.h" />
<ClInclude Include="soh\OTRGlobals.h" />
<ClInclude Include="soh\util.h" />

View File

@ -2184,6 +2184,12 @@
<ClCompile Include="soh\util.cpp">
<Filter>Source Files\soh</Filter>
</ClCompile>
<ClCompile Include="soh\Enhancements\debugger\colViewer.cpp">
<Filter>Source Files\soh\Enhancements\debugger</Filter>
</ClCompile>
<ClCompile Include="soh\Enhancements\debugger\ImGuiHelpers.cpp">
<Filter>Source Files\soh\Enhancements\debugger</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\overlays\actors\ovl_kaleido_scope\z_kaleido_scope.h">
@ -3734,6 +3740,12 @@
<ClInclude Include="soh\util.h">
<Filter>Header Files\soh</Filter>
</ClInclude>
<ClInclude Include="soh\Enhancements\debugger\colViewer.h">
<Filter>Header Files\soh\Enhancements\debugger</Filter>
</ClInclude>
<ClInclude Include="soh\Enhancements\debugger\ImGuiHelpers.h">
<Filter>Header Files\soh\Enhancements\debugger</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="include\macro.inc">

View File

@ -327,9 +327,6 @@ static int CheckVarType(const std::string& input)
return result;
}
void DebugConsole_LoadCVars();
void DebugConsole_SaveCVars();
static bool SetCVarHandler(const std::vector<std::string>& args) {
if (args.size() < 3)
return CMD_FAILED;

View File

@ -1,3 +1,5 @@
#pragma once
void DebugConsole_Init(void);
void DebugConsole_Init(void);
void DebugConsole_LoadCVars();
void DebugConsole_SaveCVars();

View File

@ -0,0 +1,21 @@
#include "ImGuiHelpers.h"
// Adds a text tooltip for the previous ImGui item
void SetLastItemHoverText(const std::string& text) {
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text(text.c_str());
ImGui::EndTooltip();
}
}
// Adds a "?" next to the previous ImGui item with a custom tooltip
void InsertHelpHoverText(const std::string& text) {
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "?");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text(text.c_str());
ImGui::EndTooltip();
}
}

View File

@ -0,0 +1,8 @@
#pragma once
#include "../libultraship/Lib/ImGui/imgui.h"
#include <string>
void SetLastItemHoverText(const std::string& text);
void InsertHelpHoverText(const std::string& text);

View File

@ -0,0 +1,719 @@
#include "colViewer.h"
#include "../libultraship/SohImGuiImpl.h"
#include "ImGuiHelpers.h"
#include <vector>
#include <string>
extern "C" {
#include <z64.h>
#include "variables.h"
#include "functions.h"
#include "macros.h"
extern GlobalContext* gGlobalCtx;
}
enum class ColRenderSetting {
Disabled,
Solid,
Transparent,
NumSettings
};
std::string ColRenderSettingNames[] = {
"Disabled",
"Solid",
"Transparent",
};
static ColRenderSetting showSceneColSetting = ColRenderSetting::Disabled;
static ColRenderSetting showBgActorSetting = ColRenderSetting::Disabled;
static ColRenderSetting showColCheckSetting = ColRenderSetting::Disabled;
static ColRenderSetting showWaterboxSetting = ColRenderSetting::Disabled;
static uint32_t sceneColor = 0xFFFFFFFF;
static uint32_t hookshotColor = 0x8080FFFF;
static uint32_t entranceColor = 0x00FF00FF;
static uint32_t specialSurfaceColor = 0xC0FFC0FF;
static uint32_t interactableColor = 0xC000C0FF;
static uint32_t slopeColor = 0xFFFF80FF;
static uint32_t voidColor = 0xFF0000FF;
static uint32_t ocColor = 0xFFFFFFFF;
static uint32_t acColor = 0x0000FFFF;
static uint32_t atColor = 0xFF0000FF;
static uint32_t waterboxColor = 0x0000FFFF;
static bool applyAsDecal = false;
static bool isShaded = false;
static std::vector<Gfx> opaDl;
static std::vector<Gfx> xluDl;
static std::vector<Vtx> vtxDl;
static std::vector<Mtx> mtxDl;
// These DLs contain a cylinder/sphere model scaled to 128x (to have less error)
// The idea is to push a model view matrix, then draw the DL, to draw the shape somewhere with a certain size
static std::vector<Gfx> cylinderGfx;
static std::vector<Vtx> cylinderVtx;
static std::vector<Gfx> sphereGfx;
static std::vector<Vtx> sphereVtx;
// Create a dropdown menu to set a ColRenderSetting
void DrawColRenderSetting(const std::string& name, ColRenderSetting& setting) {
if (ImGui::BeginCombo(name.c_str(), ColRenderSettingNames[static_cast<int>(setting)].c_str())) {
for (int32_t settingIndex = 0; settingIndex < static_cast<int>(ColRenderSetting::NumSettings); settingIndex++) {
if (ImGui::Selectable(ColRenderSettingNames[settingIndex].c_str())) {
setting = static_cast<ColRenderSetting>(settingIndex);
}
}
ImGui::EndCombo();
}
}
// Draw a color picker box
void DrawColorPicker(const std::string& name, uint32_t& color) {
float colorAsFloat[4];
colorAsFloat[0] = ((color >> 24) & 0xFF) / 255.0f;
colorAsFloat[1] = ((color >> 16) & 0xFF) / 255.0f;
colorAsFloat[2] = ((color >> 8) & 0xFF) / 255.0f;
colorAsFloat[3] = (color & 0xFF) / 255.0f;
if (ImGui::ColorEdit4(name.c_str(), colorAsFloat, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel)) {
color = static_cast<uint8_t>(colorAsFloat[3] * 255) |
static_cast<uint8_t>(colorAsFloat[2] * 255) << 8 |
static_cast<uint8_t>(colorAsFloat[1] * 255) << 16 |
static_cast<uint8_t>(colorAsFloat[0] * 255) << 24;
}
ImGui::SameLine();
ImGui::Text(name.c_str());
}
// Draws the ImGui window for the collision viewer
void DrawColViewerWindow(bool& open) {
if (!open) {
return;
}
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Collision Viewer", &open)) {
ImGui::End();
return;
}
DrawColRenderSetting("Scene", showSceneColSetting);
DrawColRenderSetting("Bg Actors", showBgActorSetting);
DrawColRenderSetting("Col Check", showColCheckSetting);
DrawColRenderSetting("Waterbox", showWaterboxSetting);
ImGui::Checkbox("Apply as decal", &applyAsDecal);
InsertHelpHoverText("Applies the collision as a decal display. This can be useful if there is z-fighting occuring "
"with the scene geometry, but can cause other artifacts.");
ImGui::Checkbox("Shaded", &isShaded);
InsertHelpHoverText("Applies the scene's shading to the collision display.");
// This has to be duplicated in both code paths due to the nature of ImGui::IsItemHovered()
const std::string colorHelpText = "View and change the colors used for collision display.";
if (ImGui::TreeNode("Colors")) {
InsertHelpHoverText(colorHelpText);
DrawColorPicker("Normal", sceneColor);
DrawColorPicker("Hookshot", hookshotColor);
DrawColorPicker("Entrance", entranceColor);
DrawColorPicker("Special Surface (Grass/Sand/Etc)", specialSurfaceColor);
DrawColorPicker("Interactable (Vines/Crawlspace/Etc)", interactableColor);
DrawColorPicker("Slope", slopeColor);
DrawColorPicker("Void", voidColor);
DrawColorPicker("OC", ocColor);
DrawColorPicker("AC", acColor);
DrawColorPicker("AT", atColor);
DrawColorPicker("Waterbox", waterboxColor);
ImGui::TreePop();
} else {
InsertHelpHoverText(colorHelpText);
}
ImGui::End();
}
// Calculates the normal for a triangle at the 3 specified points
void CalcTriNorm(const Vec3f& v1, const Vec3f& v2, const Vec3f& v3, Vec3f& norm) {
norm.x = (v2.y - v1.y) * (v3.z - v1.z) - (v2.z - v1.z) * (v3.y - v1.y);
norm.y = (v2.z - v1.z) * (v3.x - v1.x) - (v2.x - v1.x) * (v3.z - v1.z);
norm.z = (v2.x - v1.x) * (v3.y - v1.y) - (v2.y - v1.y) * (v3.x - v1.x);
float norm_d = sqrtf(norm.x * norm.x + norm.y * norm.y + norm.z * norm.z);
if (norm_d != 0.f) {
norm.x *= 127.f / norm_d;
norm.y *= 127.f / norm_d;
norm.z *= 127.f / norm_d;
}
}
// Various macros used for creating verticies and rendering that aren't in gbi.h
#define G_CC_MODULATERGB_PRIM_ENVA PRIMITIVE, 0, SHADE, 0, 0, 0, 0, ENVIRONMENT
#define G_CC_PRIMITIVE_ENVA 0, 0, 0, PRIMITIVE, 0, 0, 0, ENVIRONMENT
#define qs105(n) ((int16_t)((n)*0x0020))
#define gdSPDefVtxN(x, y, z, s, t, nx, ny, nz, ca) \
{ \
.n = {.ob = { x, y, z }, .tc = { qs105(s), qs105(t) }, .n = { nx, ny, nz }, .a = ca } \
}
void CreateCylinderData() {
constexpr int32_t CYL_DIVS = 12;
cylinderGfx.reserve(5 + CYL_DIVS * 2);
cylinderVtx.reserve(2 + CYL_DIVS * 2);
cylinderVtx.push_back(gdSPDefVtxN(0, 0, 0, 0, 0, 0, -127, 0, 0xFF)); // Bottom center vertex
cylinderVtx.push_back(gdSPDefVtxN(0, 128, 0, 0, 0, 0, 127, 0, 0xFF)); // Top center vertex
// Create two rings of vertices
for (int i = 0; i < CYL_DIVS; ++i) {
short vtx_x = floorf(0.5f + cosf(2.f * M_PI * i / CYL_DIVS) * 128.f);
short vtx_z = floorf(0.5f - sinf(2.f * M_PI * i / CYL_DIVS) * 128.f);
signed char norm_x = cosf(2.f * M_PI * i / CYL_DIVS) * 127.f;
signed char norm_z = -sinf(2.f * M_PI * i / CYL_DIVS) * 127.f;
cylinderVtx.push_back(gdSPDefVtxN(vtx_x, 0, vtx_z, 0, 0, norm_x, 0, norm_z, 0xFF));
cylinderVtx.push_back(gdSPDefVtxN(vtx_x, 128, vtx_z, 0, 0, norm_x, 0, norm_z, 0xFF));
}
// Draw edges
cylinderGfx.push_back(gsSPSetGeometryMode(G_CULL_BACK | G_SHADING_SMOOTH));
cylinderGfx.push_back(gsSPVertex((uintptr_t)cylinderVtx.data(), 2 + CYL_DIVS * 2, 0));
for (int i = 0; i < CYL_DIVS; ++i) {
int p = (i + CYL_DIVS - 1) % CYL_DIVS;
int v[4] = {
2 + p * 2 + 0,
2 + i * 2 + 0,
2 + i * 2 + 1,
2 + p * 2 + 1,
};
cylinderGfx.push_back(gsSP2Triangles(v[0], v[1], v[2], 0, v[0], v[2], v[3], 0));
}
// Draw top & bottom
cylinderGfx.push_back(gsSPClearGeometryMode(G_SHADING_SMOOTH));
for (int i = 0; i < CYL_DIVS; ++i) {
int p = (i + CYL_DIVS - 1) % CYL_DIVS;
int v[4] = {
2 + p * 2 + 0,
2 + i * 2 + 0,
2 + i * 2 + 1,
2 + p * 2 + 1,
};
cylinderGfx.push_back(gsSP2Triangles(0, v[1], v[0], 0, 1, v[3], v[2], 0));
}
cylinderGfx.push_back(gsSPClearGeometryMode(G_CULL_BACK));
cylinderGfx.push_back(gsSPEndDisplayList());
}
// This subdivides a face into four tris by placing new verticies at the midpoints of the sides (Like a triforce!), then blowing up the
// verticies so they are on the unit sphere
void CreateSphereFace(std::vector<std::tuple<size_t, size_t, size_t>>& faces, int32_t v0Index, int32_t v1Index, int32_t v2Index) {
size_t nextIndex = sphereVtx.size();
size_t v01Index = nextIndex;
size_t v12Index = nextIndex + 1;
size_t v20Index = nextIndex + 2;
faces.emplace_back(v0Index, v01Index, v20Index);
faces.emplace_back(v1Index, v12Index, v01Index);
faces.emplace_back(v2Index, v20Index, v12Index);
faces.emplace_back(v01Index, v12Index, v20Index);
const Vtx& v0 = sphereVtx[v0Index];
const Vtx& v1 = sphereVtx[v1Index];
const Vtx& v2 = sphereVtx[v2Index];
// Create 3 new verticies at the midpoints
Vec3f vs[3] = {
Vec3f((v0.n.ob[0] + v1.n.ob[0]) / 2.0f, (v0.n.ob[1] + v1.n.ob[1]) / 2.0f, (v0.n.ob[2] + v1.n.ob[2]) / 2.0f),
Vec3f((v1.n.ob[0] + v2.n.ob[0]) / 2.0f, (v1.n.ob[1] + v2.n.ob[1]) / 2.0f, (v1.n.ob[2] + v2.n.ob[2]) / 2.0f),
Vec3f((v2.n.ob[0] + v0.n.ob[0]) / 2.0f, (v2.n.ob[1] + v0.n.ob[1]) / 2.0f, (v2.n.ob[2] + v0.n.ob[2]) / 2.0f)
};
// Normalize vertex positions so they are on the sphere
for (int32_t vAddIndex = 0; vAddIndex < 3; vAddIndex++) {
Vec3f& v = vs[vAddIndex];
float mag = sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
v.x /= mag;
v.y /= mag;
v.z /= mag;
sphereVtx.push_back(gdSPDefVtxN((short)(v.x * 127), (short)(v.y * 127), (short)(v.z * 127), 0, 0,
(signed char)(v.x * 127), (signed char)(v.y * 127), (signed char)(v.z * 127),
0xFF));
}
}
// Creates a sphere following the idea in here: http://blog.andreaskahler.com/2009/06/creating-icosphere-mesh-in-code.html
// Spcifically, create a icosahedron by realizing that the points can be placed on 3 rectangles that are on each unit plane.
// Then, subdividing each face.
void CreateSphereData() {
std::vector<Vec3f> base;
float d = (1.0f + sqrtf(5.0f)) / 2.0f;
// Create the 12 starting verticies, 4 on each rectangle
base.emplace_back(-1, d, 0);
base.emplace_back(1, d, 0);
base.emplace_back(-1, -d, 0);
base.emplace_back(1, -d, 0);
base.emplace_back(0, -1, d);
base.emplace_back(0, 1, d);
base.emplace_back(0, -1, -d);
base.emplace_back(0, 1, -d);
base.emplace_back(d, 0, -1);
base.emplace_back(d, 0, 1);
base.emplace_back(-d, 0, -1);
base.emplace_back(-d, 0, 1);
// Normalize verticies so they are on the unit sphere
for (Vec3f& v : base) {
float mag = sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
v.x /= mag;
v.y /= mag;
v.z /= mag;
sphereVtx.push_back(gdSPDefVtxN((short)(v.x * 128), (short)(v.y * 128), (short)(v.z * 128), 0, 0,
(signed char)(v.x * 127), (signed char)(v.y * 127), (signed char)(v.z * 127),
0xFF));
}
std::vector<std::tuple<size_t, size_t, size_t>> faces;
// Subdivide faces
CreateSphereFace(faces, 0, 11, 5);
CreateSphereFace(faces, 0, 5, 1);
CreateSphereFace(faces, 0, 1, 7);
CreateSphereFace(faces, 0, 7, 10);
CreateSphereFace(faces, 0, 10, 11);
CreateSphereFace(faces, 1, 5, 9);
CreateSphereFace(faces, 5, 11, 4);
CreateSphereFace(faces, 11, 10, 2);
CreateSphereFace(faces, 10, 7, 6);
CreateSphereFace(faces, 7, 1, 8);
CreateSphereFace(faces, 3, 9, 4);
CreateSphereFace(faces, 3, 4, 2);
CreateSphereFace(faces, 3, 2, 6);
CreateSphereFace(faces, 3, 6, 8);
CreateSphereFace(faces, 3, 8, 9);
CreateSphereFace(faces, 4, 9, 5);
CreateSphereFace(faces, 2, 4, 11);
CreateSphereFace(faces, 6, 2, 10);
CreateSphereFace(faces, 8, 6, 7);
CreateSphereFace(faces, 9, 8, 1);
size_t vtxStartIndex = sphereVtx.size();
sphereVtx.reserve(sphereVtx.size() + faces.size() * 3);
for (int32_t faceIndex = 0; faceIndex < faces.size(); faceIndex++) {
sphereVtx.push_back(sphereVtx[std::get<0>(faces[faceIndex])]);
sphereVtx.push_back(sphereVtx[std::get<1>(faces[faceIndex])]);
sphereVtx.push_back(sphereVtx[std::get<2>(faces[faceIndex])]);
sphereGfx.push_back(gsSPVertex((uintptr_t)(sphereVtx.data() + vtxStartIndex + faceIndex * 3), 3, 0));
sphereGfx.push_back(gsSP1Triangle(0, 1, 2, 0));
}
sphereGfx.push_back(gsSPEndDisplayList());
}
void InitColViewer() {
SohImGui::AddWindow("Debug", "Collision Viewer", DrawColViewerWindow);
CreateCylinderData();
CreateSphereData();
}
// Initializes the display list for a ColRenderSetting
void InitGfx(std::vector<Gfx>& gfx, ColRenderSetting setting) {
uint32_t rm;
uint32_t blc1;
uint32_t blc2;
uint8_t alpha;
uint64_t cm;
uint32_t gm;
if (setting == ColRenderSetting::Transparent) {
rm = Z_CMP | IM_RD | CVG_DST_FULL | FORCE_BL;
blc1 = GBL_c1(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA);
blc2 = GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA);
alpha = 0x80;
} else {
rm = Z_CMP | Z_UPD | CVG_DST_CLAMP | FORCE_BL;
blc1 = GBL_c1(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1);
blc2 = GBL_c2(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1);
alpha = 0xFF;
}
if (applyAsDecal) {
rm |= ZMODE_DEC;
} else if (setting == ColRenderSetting::Transparent) {
rm |= ZMODE_XLU;
} else {
rm |= ZMODE_OPA;
}
gfx.push_back(gsSPTexture(0, 0, 0, G_TX_RENDERTILE, G_OFF));
gfx.push_back(gsDPSetCycleType(G_CYC_1CYCLE));
gfx.push_back(gsDPSetRenderMode(rm | blc1, rm | blc2));
if (isShaded) {
gfx.push_back(gsDPSetCombineMode(G_CC_MODULATERGB_PRIM_ENVA, G_CC_MODULATERGB_PRIM_ENVA));
gfx.push_back(gsSPLoadGeometryMode(G_CULL_BACK | G_ZBUFFER | G_LIGHTING));
} else {
gfx.push_back(gsDPSetCombineMode(G_CC_PRIMITIVE_ENVA, G_CC_PRIMITIVE_ENVA));
gfx.push_back(gsSPLoadGeometryMode(G_ZBUFFER));
}
gfx.push_back(gsDPSetEnvColor(0xFF, 0xFF, 0xFF, alpha));
}
// Draws a dynapoly structure (scenes or Bg Actors)
void DrawDynapoly(std::vector<Gfx>& dl, CollisionHeader* col, int32_t bgId) {
uint32_t color = sceneColor;
uint32_t lastColor = color;
dl.push_back(gsDPSetPrimColor(0, 0, (color >> 24) & 0xFF, (color >> 16) & 0xFF, (color >> 8) & 0xFF,
(color >> 0) & 0xFF));
// This keeps track of if we have processed a poly, but not drawn it yet so we can batch them.
// This saves several hundred commands in larger scenes
bool previousPoly = false;
for (int i = 0; i < col->numPolygons; i++) {
CollisionPoly* poly = &col->polyList[i];
if (SurfaceType_IsHookshotSurface(&gGlobalCtx->colCtx, poly, bgId)) {
color = hookshotColor;
} else if (func_80041D94(&gGlobalCtx->colCtx, poly, bgId) > 0x01) {
color = interactableColor;
} else if (func_80041E80(&gGlobalCtx->colCtx, poly, bgId) == 0x0C) {
color = voidColor;
} else if (SurfaceType_GetSceneExitIndex(&gGlobalCtx->colCtx, poly, bgId) ||
func_80041E80(&gGlobalCtx->colCtx, poly, bgId) == 0x05) {
color = entranceColor;
} else if (func_80041D4C(&gGlobalCtx->colCtx, poly, bgId) != 0 ||
SurfaceType_IsWallDamage(&gGlobalCtx->colCtx, poly, bgId)) {
color = specialSurfaceColor;
} else if (SurfaceType_GetSlope(&gGlobalCtx->colCtx, poly, bgId) == 0x01) {
color = slopeColor;
} else {
color = sceneColor;
}
if (lastColor != color) {
// Color changed, flush previous poly
if (previousPoly) {
dl.push_back(gsSPVertex((uintptr_t)&vtxDl.at(vtxDl.size() - 3), 3, 0));
dl.push_back(gsSP1Triangle(0, 1, 2, 0));
previousPoly = false;
}
dl.push_back(gsDPSetPrimColor(0, 0, (color >> 24) & 0xFF, (color >> 16) & 0xFF, (color >> 8) & 0xFF,
(color >> 0) & 0xFF));
}
lastColor = color;
Vec3s* va = &col->vtxList[COLPOLY_VTX_INDEX(poly->flags_vIA)];
Vec3s* vb = &col->vtxList[COLPOLY_VTX_INDEX(poly->flags_vIB)];
Vec3s* vc = &col->vtxList[COLPOLY_VTX_INDEX(poly->vIC)];
vtxDl.push_back(gdSPDefVtxN(va->x, va->y, va->z, 0, 0, (signed char)(poly->normal.x / 0x100),
(signed char)(poly->normal.y / 0x100), (signed char)(poly->normal.z / 0x100),
0xFF));
vtxDl.push_back(gdSPDefVtxN(vb->x, vb->y, vb->z, 0, 0, (signed char)(poly->normal.x / 0x100),
(signed char)(poly->normal.y / 0x100), (signed char)(poly->normal.z / 0x100),
0xFF));
vtxDl.push_back(gdSPDefVtxN(vc->x, vc->y, vc->z, 0, 0, (signed char)(poly->normal.x / 0x100),
(signed char)(poly->normal.y / 0x100), (signed char)(poly->normal.z / 0x100),
0xFF));
if (previousPoly) {
dl.push_back(gsSPVertex((uintptr_t)&vtxDl.at(vtxDl.size() - 6), 6, 0));
dl.push_back(gsSP2Triangles(0, 1, 2, 0, 3, 4, 5, 0));
previousPoly = false;
} else {
previousPoly = true;
}
}
// Flush previous poly if this is the end and there's no more coming
if (previousPoly) {
dl.push_back(gsSPVertex((uintptr_t)&vtxDl.at(vtxDl.size() - 3), 3, 0));
dl.push_back(gsSP1Triangle(0, 1, 2, 0));
previousPoly = false;
}
}
// Draws the scene
void DrawSceneCollision() {
if (showSceneColSetting == ColRenderSetting::Disabled) {
return;
}
std::vector<Gfx>& dl = (showSceneColSetting == ColRenderSetting::Transparent) ? xluDl : opaDl;
InitGfx(dl, showSceneColSetting);
dl.push_back(gsSPMatrix(&gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH));
DrawDynapoly(dl, gGlobalCtx->colCtx.colHeader, BGCHECK_SCENE);
}
// Draws all Bg Actors
void DrawBgActorCollision() {
if (showBgActorSetting == ColRenderSetting::Disabled) {
return;
}
std::vector<Gfx>& dl = (showBgActorSetting == ColRenderSetting::Transparent) ? xluDl : opaDl;
InitGfx(dl, showBgActorSetting);
dl.push_back(gsSPMatrix(&gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH));
for (int32_t bgIndex = 0; bgIndex < BG_ACTOR_MAX; bgIndex++) {
if (gGlobalCtx->colCtx.dyna.bgActorFlags[bgIndex] & 1) {
BgActor& bg = gGlobalCtx->colCtx.dyna.bgActors[bgIndex];
Mtx m;
MtxF mf;
SkinMatrix_SetTranslateRotateYXZScale(&mf, bg.curTransform.scale.x, bg.curTransform.scale.y,
bg.curTransform.scale.z, bg.curTransform.rot.x, bg.curTransform.rot.y,
bg.curTransform.rot.z, bg.curTransform.pos.x, bg.curTransform.pos.y,
bg.curTransform.pos.z);
guMtxF2L(&mf, &m);
mtxDl.push_back(m);
dl.push_back(gsSPMatrix(&mtxDl.back(), G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_PUSH));
DrawDynapoly(dl, bg.colHeader, bgIndex);
dl.push_back(gsSPPopMatrix(G_MTX_MODELVIEW));
}
}
}
// Draws a quad
void DrawQuad(std::vector<Gfx>& dl, Vec3f& v0, Vec3f& v1, Vec3f& v2, Vec3f& v3) {
Vec3f norm;
CalcTriNorm(v0, v1, v2, norm);
vtxDl.push_back(gdSPDefVtxN((short)v0.x, (short)v0.y, (short)v0.z, 0, 0, (signed char)norm.x, (signed char)norm.y,
(signed char)norm.z, 0xFF));
vtxDl.push_back(gdSPDefVtxN((short)v1.x, (short)v1.y, (short)v1.z, 0, 0, (signed char)norm.x, (signed char)norm.y,
(signed char)norm.z, 0xFF));
vtxDl.push_back(gdSPDefVtxN((short)v2.x, (short)v2.y, (short)v2.z, 0, 0, (signed char)norm.x, (signed char)norm.y,
(signed char)norm.z, 0xFF));
vtxDl.push_back(gdSPDefVtxN((short)v3.x, (short)v3.y, (short)v3.z, 0, 0, (signed char)norm.x, (signed char)norm.y,
(signed char)norm.z, 0xFF));
dl.push_back(gsSPVertex((uintptr_t)&vtxDl.at(vtxDl.size() - 4), 4, 0));
dl.push_back(gsSP2Triangles(0, 1, 2, 0, 0, 2, 3, 0));
}
// Draws a list of Col Check objects
void DrawColCheckList(std::vector<Gfx>& dl, Collider** objects, int32_t count) {
for (int32_t colIndex = 0; colIndex < count; colIndex++) {
Collider* col = objects[colIndex];
switch (col->shape) {
case COLSHAPE_JNTSPH: {
ColliderJntSph* jntSph = (ColliderJntSph*)col;
for (int32_t sphereIndex = 0; sphereIndex < jntSph->count; sphereIndex++) {
ColliderJntSphElement* sph = &jntSph->elements[sphereIndex];
Mtx m;
MtxF mf;
SkinMatrix_SetTranslate(&mf, sph->dim.worldSphere.center.x, sph->dim.worldSphere.center.y,
sph->dim.worldSphere.center.z);
MtxF ms;
int32_t radius = sph->dim.worldSphere.radius == 0 ? 1 : sph->dim.worldSphere.radius;
SkinMatrix_SetScale(&ms, radius / 128.0f, radius / 128.0f, radius / 128.0f);
MtxF dest;
SkinMatrix_MtxFMtxFMult(&mf, &ms, &dest);
guMtxF2L(&dest, &m);
mtxDl.push_back(m);
dl.push_back(gsSPMatrix(&mtxDl.back(), G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_PUSH));
dl.push_back(gsSPDisplayList(sphereGfx.data()));
dl.push_back(gsSPPopMatrix(G_MTX_MODELVIEW));
}
} break;
case COLSHAPE_CYLINDER: {
ColliderCylinder* cyl = (ColliderCylinder*)col;
Mtx m;
MtxF mt;
SkinMatrix_SetTranslate(&mt, cyl->dim.pos.x, cyl->dim.pos.y, cyl->dim.pos.z);
MtxF ms;
int32_t radius = cyl->dim.radius == 0 ? 1 : cyl->dim.radius;
SkinMatrix_SetScale(&ms, radius / 128.0f, cyl->dim.height / 128.0f, radius / 128.0f);
MtxF dest;
SkinMatrix_MtxFMtxFMult(&mt, &ms, &dest);
guMtxF2L(&dest, &m);
mtxDl.push_back(m);
dl.push_back(gsSPMatrix(&mtxDl.back(), G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_PUSH));
dl.push_back(gsSPDisplayList(cylinderGfx.data()));
dl.push_back(gsSPPopMatrix(G_MTX_MODELVIEW));
} break;
case COLSHAPE_TRIS: {
ColliderTris* tris = (ColliderTris*)col;
for (int32_t triIndex = 0; triIndex < tris->count; triIndex++) {
ColliderTrisElement* tri = &tris->elements[triIndex];
vtxDl.push_back(gdSPDefVtxN((short)tri->dim.vtx[0].x, (short)tri->dim.vtx[0].y,
(short)tri->dim.vtx[0].z, 0, 0, (signed char)tri->dim.plane.normal.x,
(signed char)tri->dim.plane.normal.y,
(signed char)tri->dim.plane.normal.z, 0xFF));
vtxDl.push_back(gdSPDefVtxN((short)tri->dim.vtx[1].x, (short)tri->dim.vtx[1].y,
(short)tri->dim.vtx[1].z, 0, 0, (signed char)tri->dim.plane.normal.x,
(signed char)tri->dim.plane.normal.y,
(signed char)tri->dim.plane.normal.z, 0xFF));
vtxDl.push_back(gdSPDefVtxN((short)tri->dim.vtx[2].x, (short)tri->dim.vtx[2].y,
(short)tri->dim.vtx[2].z, 0, 0, (signed char)tri->dim.plane.normal.x,
(signed char)tri->dim.plane.normal.y,
(signed char)tri->dim.plane.normal.z, 0xFF));
dl.push_back(gsSPVertex((uintptr_t)&vtxDl.at(vtxDl.size() - 3), 3, 0));
dl.push_back(gsSP1Triangle(0, 1, 2, 0));
}
} break;
case COLSHAPE_QUAD: {
ColliderQuad* quad = (ColliderQuad*)col;
DrawQuad(dl, quad->dim.quad[0], quad->dim.quad[2], quad->dim.quad[3], quad->dim.quad[1]);
} break;
default:
break;
}
}
}
// Draws all Col Check objects
void DrawColCheckCollision() {
if (showColCheckSetting == ColRenderSetting::Disabled) {
return;
}
std::vector<Gfx>& dl = (showColCheckSetting == ColRenderSetting::Transparent) ? xluDl : opaDl;
InitGfx(dl, showColCheckSetting);
dl.push_back(gsSPMatrix(&gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH));
CollisionCheckContext& col = gGlobalCtx->colChkCtx;
dl.push_back(gsDPSetPrimColor(0, 0, (ocColor >> 24) & 0xFF, (ocColor >> 16) & 0xFF, (ocColor >> 8) & 0xFF,
(ocColor >> 0) & 0xFF));
DrawColCheckList(dl, col.colOC, col.colOCCount);
dl.push_back(gsDPSetPrimColor(0, 0, (acColor >> 24) & 0xFF, (acColor >> 16) & 0xFF, (acColor >> 8) & 0xFF,
(acColor >> 0) & 0xFF));
DrawColCheckList(dl, col.colAC, col.colACCount);
dl.push_back(gsDPSetPrimColor(0, 0, (atColor >> 24) & 0xFF, (atColor >> 16) & 0xFF, (atColor >> 8) & 0xFF,
(atColor >> 0) & 0xFF));
DrawColCheckList(dl, col.colAT, col.colATCount);
}
// Draws a waterbox
void DrawWaterbox(std::vector<Gfx>& dl, WaterBox* water, float water_max_depth = -4000.0f) {
// Skip waterboxes that would be disabled in current room
int32_t room = ((water->properties >> 13) & 0x3F);
if ((room != gGlobalCtx->roomCtx.curRoom.num) && (room != 0x3F)) {
return;
}
Vec3f vtx[] = {
{ water->xMin, water->ySurface, water->zMin + water->zLength },
{ water->xMin + water->xLength, water->ySurface, water->zMin + water->zLength },
{ water->xMin + water->xLength, water->ySurface, water->zMin },
{ water->xMin, water->ySurface, water->zMin },
{ water->xMin, water_max_depth, water->zMin + water->zLength },
{ water->xMin + water->xLength, water_max_depth, water->zMin + water->zLength },
{ water->xMin + water->xLength, water_max_depth, water->zMin },
{ water->xMin, water_max_depth, water->zMin },
};
DrawQuad(dl, vtx[0], vtx[1], vtx[2], vtx[3]);
DrawQuad(dl, vtx[0], vtx[3], vtx[7], vtx[4]);
DrawQuad(dl, vtx[1], vtx[0], vtx[4], vtx[5]);
DrawQuad(dl, vtx[2], vtx[1], vtx[5], vtx[6]);
DrawQuad(dl, vtx[3], vtx[2], vtx[6], vtx[7]);
}
extern "C" WaterBox zdWaterBox;
extern "C" f32 zdWaterBoxMinY;
// Draws all waterboxes
void DrawWaterboxList() {
if (showWaterboxSetting == ColRenderSetting::Disabled) {
return;
}
std::vector<Gfx>& dl = (showWaterboxSetting == ColRenderSetting::Transparent) ? xluDl : opaDl;
InitGfx(dl, showWaterboxSetting);
dl.push_back(gsSPMatrix(&gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH));
dl.push_back(gsDPSetPrimColor(0, 0, (waterboxColor >> 24) & 0xFF, (waterboxColor >> 16) & 0xFF,
(waterboxColor >> 8) & 0xFF, (waterboxColor >> 0) & 0xFF));
CollisionHeader* col = gGlobalCtx->colCtx.colHeader;
for (int32_t waterboxIndex = 0; waterboxIndex < col->numWaterBoxes; waterboxIndex++) {
WaterBox* water = &col->waterBoxes[waterboxIndex];
DrawWaterbox(dl, water);
}
// Zora's Domain has a special, hard-coded waterbox with a bottom so you can go under the waterfall
if (gGlobalCtx->sceneNum == SCENE_SPOT07) {
DrawWaterbox(dl, &zdWaterBox, zdWaterBoxMinY);
}
}
// Resets a vector for the next frame and returns the capacity
template<typename T>
size_t ResetVector(T& vec) {
size_t oldSize = vec.size();
vec.clear();
// Reserve slightly more space than last frame to account for variance (such as different amounts of bg actors)
vec.reserve(oldSize * 1.2);
return vec.capacity();
}
void DrawColViewer() {
if (gGlobalCtx == nullptr) {
return;
}
ResetVector(opaDl);
ResetVector(xluDl);
size_t vtxDlCapacity = ResetVector(vtxDl);
size_t mtxDlCapacity = ResetVector(mtxDl);
DrawSceneCollision();
DrawBgActorCollision();
DrawColCheckCollision();
DrawWaterboxList();
// Check if we used up more space than we reserved. If so, redo the drawing with our new sizes.
// This is because we resized the vectors while drawing, invalidating pointers to them.
// This only matters for the Vtx and Mtx vectors.
if ((vtxDl.size() > vtxDlCapacity) || (mtxDl.size() > mtxDlCapacity)) {
ResetVector(opaDl);
ResetVector(xluDl);
vtxDlCapacity = ResetVector(vtxDl);
mtxDlCapacity = ResetVector(mtxDl);
DrawSceneCollision();
DrawBgActorCollision();
DrawColCheckCollision();
DrawWaterboxList();
}
if ((vtxDl.size() > vtxDlCapacity) || (mtxDl.size() > mtxDlCapacity)) {
// If the sizes somehow changed between the two draws, we can't continue because we may be using invalid data
printf("Error drawing collision, vertex/matrix sizes didn't settle.\n");
return;
}
OPEN_DISPS(gGlobalCtx->state.gfxCtx, "", 0);
opaDl.push_back(gsSPEndDisplayList());
gSPDisplayList(POLY_OPA_DISP++, opaDl.data());
xluDl.push_back(gsSPEndDisplayList());
gSPDisplayList(POLY_XLU_DISP++, xluDl.data());
CLOSE_DISPS(gGlobalCtx->state.gfxCtx, "", 0);
}

View File

@ -0,0 +1,4 @@
#pragma once
void InitColViewer();
void DrawColViewer();

View File

@ -1,6 +1,7 @@
#include "debugSaveEditor.h"
#include "../../util.h"
#include "../libultraship/SohImGuiImpl.h"
#include "ImGuiHelpers.h"
#include <array>
#include <bit>
@ -224,26 +225,6 @@ std::array<SongMapEntry, 12> songMapping = { {
SONG_MAP_ENTRY(QUEST_SONG_PRELUDE, 255, 240, 100),
} };
// Adds a text tooltip for the previous ImGui item
void SetLastItemHoverText(const std::string& text) {
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text(text.c_str());
ImGui::EndTooltip();
}
}
// Adds a "?" next to the previous ImGui item with a custom tooltip
void InsertHelpHoverText(const std::string& text) {
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "?");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text(text.c_str());
ImGui::EndTooltip();
}
}
// Encapsulates what is drawn by the passed-in function within a border
template<typename T>
void DrawGroupWithBorder(T&& drawFunc) {

View File

@ -1,6 +1,16 @@
#include "debugger.h"
#include "debugSaveEditor.h"
#include "colViewer.h"
extern "C" {
void Debug_Init(void) {
InitSaveEditor();
InitColViewer();
}
void Debug_Draw(void) {
DrawColViewer();
}
}

View File

@ -1,3 +1,12 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void Debug_Init(void);
void Debug_Draw(void);
#ifdef __cplusplus
}
#endif

View File

@ -5,6 +5,7 @@
extern "C" {
void InitOTR();
void Graph_ProcessFrame(void (*run_one_game_iter)(void));
void Graph_StartFrame();
void Graph_ProcessGfxCommands(Gfx* commands);
void OTRLogString(const char* src);
void OTRGfxPrint(const char* str, void* printer, void (*printImpl)(void*, char));

View File

@ -26,6 +26,7 @@
#include "../soh/Enhancements/debugger/debugger.h"
#include "Utils/BitConverter.h"
#include "variables.h"
#include <Utils/StringHelper.h>
OTRGlobals* OTRGlobals::Instance;
@ -91,6 +92,10 @@ extern "C" void Graph_ProcessFrame(void (*run_one_game_iter)(void)) {
OTRGlobals::Instance->context->GetWindow()->MainLoop(run_one_game_iter);
}
extern "C" void Graph_StartFrame() {
OTRGlobals::Instance->context->GetWindow()->StartFrame();
}
// C->C++ Bridge
extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
OTRGlobals::Instance->context->GetWindow()->SetFrameDivisor(R_UPDATE_RATE);
@ -888,8 +893,11 @@ extern "C" void AudioPlayer_Play(const uint8_t* buf, uint32_t len) {
}
extern "C" int Controller_ShouldRumble(size_t i) {
for (const auto& controller : Ship::Window::Controllers.at(i)) {
if (controller->CanRumble() && Game::Settings.controller.extra[i].rumble_strength > 0.001f) {
for (const auto& controller : Ship::Window::Controllers.at(i))
{
float rumble_strength = CVar_GetFloat(StringHelper::Sprintf("gCont%i_RumbleStrength", i).c_str(), 1.0f);
if (controller->CanRumble() && rumble_strength > 0.001f) {
return 1;
}
}

View File

@ -21,6 +21,7 @@ private:
#ifndef __cplusplus
void InitOTR();
void Graph_ProcessFrame(void (*run_one_game_iter)(void));
void Graph_StartFrame();
void Graph_ProcessGfxCommands(Gfx* commands);
void OTRLogString(const char* src);
void OTRGfxPrint(const char* str, void* printer, void (*printImpl)(void*, char));

View File

@ -8,27 +8,37 @@
#include <Text.h>
extern "C" MessageTableEntry* sNesMessageEntryTablePtr;
extern "C" MessageTableEntry* sGerMessageEntryTablePtr;
extern "C" MessageTableEntry* sFraMessageEntryTablePtr;
extern "C" MessageTableEntry* sStaffMessageEntryTablePtr;
//extern "C" MessageTableEntry* _message_0xFFFC_nes;
//extern "C" MessageTableEntry* _message_0xFFFC_nes;
MessageTableEntry* OTRMessage_LoadTable(const char* filePath, bool isNES) {
auto file = std::static_pointer_cast<Ship::Text>(OTRGlobals::Instance->context->GetResourceManager()->LoadResource(filePath));
if (file == nullptr)
return nullptr;
MessageTableEntry* table = (MessageTableEntry*)malloc(sizeof(MessageTableEntry) * file->messages.size());
for (int i = 0; i < file->messages.size(); i++) {
table[i].textId = file->messages[i].id;
table[i].typePos = (file->messages[i].textboxType << 4) | file->messages[i].textboxYPos;
table[i].segment = file->messages[i].msg.c_str();
table[i].msgSize = file->messages[i].msg.size();
if (isNES && file->messages[i].id == 0xFFFC)
_message_0xFFFC_nes = (char*)file->messages[i].msg.c_str();
}
return table;
}
extern "C" void OTRMessage_Init()
{
auto file = std::static_pointer_cast<Ship::Text>(OTRGlobals::Instance->context->GetResourceManager()->LoadResource("text/nes_message_data_static/nes_message_data_static"));
sNesMessageEntryTablePtr = (MessageTableEntry*)malloc(sizeof(MessageTableEntry) * file->messages.size());
for (int i = 0; i < file->messages.size(); i++)
{
sNesMessageEntryTablePtr[i].textId = file->messages[i].id;
sNesMessageEntryTablePtr[i].typePos = (file->messages[i].textboxType << 4) | file->messages[i].textboxYPos;
sNesMessageEntryTablePtr[i].segment = file->messages[i].msg.c_str();
sNesMessageEntryTablePtr[i].msgSize = file->messages[i].msg.size();
if (file->messages[i].id == 0xFFFC)
{
_message_0xFFFC_nes = (char*)file->messages[i].msg.c_str();
}
}
sNesMessageEntryTablePtr = OTRMessage_LoadTable("text/nes_message_data_static/nes_message_data_static", true);
sGerMessageEntryTablePtr = OTRMessage_LoadTable("text/ger_message_data_static/ger_message_data_static", false);
sFraMessageEntryTablePtr = OTRMessage_LoadTable("text/fra_message_data_static/fra_message_data_static", false);
auto file2 = std::static_pointer_cast<Ship::Text>(OTRGlobals::Instance->context->GetResourceManager()->LoadResource("text/staff_message_data_static/staff_message_data_static"));

View File

@ -5,6 +5,7 @@
#include <string.h>
#include "soh/Enhancements/gameconsole.h"
#include "soh/Enhancements/debugger/debugger.h"
#define GFXPOOL_HEAD_MAGIC 0x1234
#define GFXPOOL_TAIL_MAGIC 0x5678
@ -95,14 +96,14 @@ void Graph_InitTHGA(GraphicsContext* gfxCtx) {
pool->tailMagic = GFXPOOL_TAIL_MAGIC;
THGA_Ct(&gfxCtx->polyOpa, pool->polyOpaBuffer, sizeof(pool->polyOpaBuffer));
THGA_Ct(&gfxCtx->polyXlu, pool->polyXluBuffer, sizeof(pool->polyXluBuffer));
THGA_Ct(&gfxCtx->titlecard, pool->titlecardBuffer, sizeof(pool->titlecardBuffer));
THGA_Ct(&gfxCtx->worldOverlay, pool->worldOverlayBuffer, sizeof(pool->worldOverlayBuffer));
THGA_Ct(&gfxCtx->polyKal, pool->polyKalBuffer, sizeof(pool->polyKalBuffer));
THGA_Ct(&gfxCtx->overlay, pool->overlayBuffer, sizeof(pool->overlayBuffer));
THGA_Ct(&gfxCtx->work, pool->workBuffer, sizeof(pool->workBuffer));
gfxCtx->polyOpaBuffer = pool->polyOpaBuffer;
gfxCtx->polyXluBuffer = pool->polyXluBuffer;
gfxCtx->titlecardBuffer = pool->titlecardBuffer;
gfxCtx->worldOverlayBuffer = pool->worldOverlayBuffer;
gfxCtx->polyKalBuffer = pool->polyKalBuffer;
gfxCtx->overlayBuffer = pool->overlayBuffer;
gfxCtx->workBuffer = pool->workBuffer;
@ -276,20 +277,19 @@ void Graph_Update(GraphicsContext* gfxCtx, GameState* gameState) {
gDPNoOpString(WORK_DISP++, "WORK_DISP 開始", 0);
gDPNoOpString(POLY_OPA_DISP++, "POLY_OPA_DISP 開始", 0);
gDPNoOpString(POLY_XLU_DISP++, "POLY_XLU_DISP 開始", 0);
gDPNoOpString(TITLE_CARD_DISP++, "TITLE_CARD_DISP 開始", 0);//unsure if needed
gDPNoOpString(OVERLAY_DISP++, "OVERLAY_DISP 開始", 0);
CLOSE_DISPS(gfxCtx, "../graph.c", 975);
GameState_ReqPadData(gameState);
GameState_Update(gameState);
Debug_Draw();
OPEN_DISPS(gfxCtx, "../graph.c", 987);
gDPNoOpString(WORK_DISP++, "WORK_DISP 終了", 0);
gDPNoOpString(POLY_OPA_DISP++, "POLY_OPA_DISP 終了", 0);
gDPNoOpString(POLY_XLU_DISP++, "POLY_XLU_DISP 終了", 0);
gDPNoOpString(TITLE_CARD_DISP++, "TITLE_CARD_DISP 終了", 0);
gDPNoOpString(OVERLAY_DISP++, "OVERLAY_DISP 終了", 0);
CLOSE_DISPS(gfxCtx, "../graph.c", 996);
@ -298,8 +298,8 @@ void Graph_Update(GraphicsContext* gfxCtx, GameState* gameState) {
gSPBranchList(WORK_DISP++, gfxCtx->polyOpaBuffer);
gSPBranchList(POLY_OPA_DISP++, gfxCtx->polyXluBuffer);
gSPBranchList(POLY_XLU_DISP++, gfxCtx->titlecardBuffer);
gSPBranchList(TITLE_CARD_DISP++, gfxCtx->polyKalBuffer);
gSPBranchList(POLY_XLU_DISP++, gfxCtx->worldOverlayBuffer);
gSPBranchList(WORLD_OVERLAY_DISP++, gfxCtx->polyKalBuffer);
gSPBranchList(POLY_KAL_DISP++, gfxCtx->overlayBuffer);
gDPPipeSync(OVERLAY_DISP++);
gDPFullSync(OVERLAY_DISP++);
@ -474,6 +474,7 @@ static void RunFrame()
uint64_t ticksA, ticksB;
ticksA = GetPerfCounter();
Graph_StartFrame();
PadMgr_ThreadEntry(&gPadMgr);

View File

@ -1022,31 +1022,30 @@ void TitleCard_Draw(GlobalContext* globalCtx, TitleCardContext* titleCtx) {
height = (width * height > 0x1000) ? 0x1000 / width : height;
titleSecondY = titleY + (height * 4);
//TITLE_CARD_DISP Goes over POLY_XLU_DISP but under POLY_KAL_DISP
TITLE_CARD_DISP = func_80093808(TITLE_CARD_DISP);
// WORLD_OVERLAY_DISP Goes over POLY_XLU_DISP but under POLY_KAL_DISP
WORLD_OVERLAY_DISP = func_80093808(WORLD_OVERLAY_DISP);
gDPSetPrimColor(TITLE_CARD_DISP++, 0, 0, (u8)titleCtx->intensity, (u8)titleCtx->intensity, (u8)titleCtx->intensity,
gDPSetPrimColor(WORLD_OVERLAY_DISP++, 0, 0, (u8)titleCtx->intensity, (u8)titleCtx->intensity, (u8)titleCtx->intensity,
(u8)titleCtx->alpha);
gDPLoadTextureBlock(TITLE_CARD_DISP++, (uintptr_t)titleCtx->texture, G_IM_FMT_IA,
gDPLoadTextureBlock(WORLD_OVERLAY_DISP++, (uintptr_t)titleCtx->texture, G_IM_FMT_IA,
G_IM_SIZ_8b,
width, 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);
gSPTextureRectangle(TITLE_CARD_DISP++, titleX, titleY, ((doubleWidth * 2) + titleX) - 4, titleY + (height * 4) - 1,
gSPTextureRectangle(WORLD_OVERLAY_DISP++, titleX, titleY, ((doubleWidth * 2) + titleX) - 4, titleY + (height * 4) - 1,
G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
height = titleCtx->height - height;
// If texture is bigger than 0x1000, display the rest
if (height > 0) {
gDPLoadTextureBlock(TITLE_CARD_DISP++, (uintptr_t)titleCtx->texture + 0x1000,
gDPLoadTextureBlock(WORLD_OVERLAY_DISP++, (uintptr_t)titleCtx->texture + 0x1000,
G_IM_FMT_IA,
G_IM_SIZ_8b, width, 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);
gSPTextureRectangle(TITLE_CARD_DISP++, titleX, titleSecondY, ((doubleWidth * 2) + titleX) - 4,
gSPTextureRectangle(WORLD_OVERLAY_DISP++, titleX, titleSecondY, ((doubleWidth * 2) + titleX) - 4,
titleSecondY + (height * 4) - 1, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
}

View File

@ -33,47 +33,12 @@ s16 sMessageHasSetSfx = false;
u16 sOcarinaSongBitFlags = 0; // ocarina bit flags
MessageTableEntry* sNesMessageEntryTablePtr;
MessageTableEntry* sGerMessageEntryTablePtr;
MessageTableEntry* sFraMessageEntryTablePtr;
MessageTableEntry* sStaffMessageEntryTablePtr;
char* _message_0xFFFC_nes;
//MessageTableEntry sNesMessageEntryTable[] = {
//#define DEFINE_MESSAGE(textId, type, yPos, nesMessage, gerMessage, fraMessage) \
// { textId, (_SHIFTL(type, 4, 8) | _SHIFTL(yPos, 0, 8)), _message_##textId##_nes },
//#define DEFINE_MESSAGE_FFFC
//#include "text/message_data.h"
//#undef DEFINE_MESSAGE_FFFC
//#undef DEFINE_MESSAGE
// { 0xFFFF, 0, NULL },
//};
//
//const char* sGerMessageEntryTable[] = {
//#define DEFINE_MESSAGE(textId, type, yPos, nesMessage, gerMessage, fraMessage) _message_##textId##_ger,
//#include "text/message_data.h"
//#undef DEFINE_MESSAGE
// NULL,
//};
//
//const char* sFraMessageEntryTable[] = {
//#define DEFINE_MESSAGE(textId, type, yPos, nesMessage, gerMessage, fraMessage) _message_##textId##_fra,
//#include "text/message_data.h"
//#undef DEFINE_MESSAGE
// NULL,
//};
//
//MessageTableEntry sStaffMessageEntryTable[] = {
//#define DEFINE_MESSAGE(textId, type, yPos, staffMessage) \
// { textId, (_SHIFTL(type, 4, 8) | _SHIFTL(yPos, 0, 8)), _message_##textId##_staff },
//#include "text/message_data_staff.h"
//#undef DEFINE_MESSAGE
// { 0xFFFF, 0, NULL },
//};
//MessageTableEntry* sNesMessageEntryTablePtr = sNesMessageEntryTable;
//const char** sGerMessageEntryTablePtr = sGerMessageEntryTable;
//const char** sFraMessageEntryTablePtr = sFraMessageEntryTable;
//MessageTableEntry* sStaffMessageEntryTablePtr = sStaffMessageEntryTable;
s16 sTextboxBackgroundForePrimColors[][3] = {
{ 255, 255, 255 }, { 50, 20, 0 }, { 255, 60, 0 }, { 255, 255, 255 },
{ 255, 255, 255 }, { 255, 255, 255 }, { 255, 255, 255 }, { 255, 255, 255 },
@ -235,8 +200,6 @@ void Message_DrawTextChar(GlobalContext* globalCtx, void* textureImage, Gfx** p)
s16 x = msgCtx->textPosX;
s16 y = msgCtx->textPosY;
//gSPInvalidateTexCache(gfx++, 0);
//gSPInvalidateTexCache(gfx++, msgCtx->textboxSegment);
gSPInvalidateTexCache(gfx++, textureImage);
gDPPipeSync(gfx++);
@ -310,69 +273,46 @@ void Message_FindMessage(GlobalContext* globalCtx, u16 textId) {
Font* font;
const char* seg;
if (gSaveContext.language == LANGUAGE_ENG) {
seg = messageTableEntry->segment;
if (gSaveContext.language == LANGUAGE_GER)
messageTableEntry = sGerMessageEntryTablePtr;
else if (gSaveContext.language == LANGUAGE_FRA)
messageTableEntry = sFraMessageEntryTablePtr;
while (messageTableEntry->textId != 0xFFFF) {
font = &globalCtx->msgCtx.font;
// If PAL languages are not present in the OTR file, default to English
if (messageTableEntry == NULL)
messageTableEntry = sNesMessageEntryTablePtr;
if (messageTableEntry->textId == textId) {
foundSeg = messageTableEntry->segment;
font->charTexBuf[0] = messageTableEntry->typePos;
//messageTableEntry++;
nextSeg = messageTableEntry->segment;
font->msgOffset = messageTableEntry->segment;
font->msgLength = messageTableEntry->msgSize;
// "Message found!!!"
osSyncPrintf(" メッセージが,見つかった!!! = %x "
"(data=%x) (data0=%x) (data1=%x) (data2=%x) (data3=%x)\n",
textId, font->msgOffset, font->msgLength, foundSeg, seg, nextSeg);
return;
}
messageTableEntry++;
}
} else {
//languageSegmentTable = (gSaveContext.language == LANGUAGE_GER) ? sGerMessageEntryTablePtr : sFraMessageEntryTablePtr; // OTRTODO
seg = messageTableEntry->segment;
while (messageTableEntry->textId != 0xFFFF) {
font = &globalCtx->msgCtx.font;
if (messageTableEntry->textId == textId) {
foundSeg = *languageSegmentTable;
font->charTexBuf[0] = messageTableEntry->typePos;
languageSegmentTable++;
nextSeg = *languageSegmentTable;
font->msgOffset = foundSeg - seg;
font->msgLength = nextSeg - foundSeg;
// "Message found!!!"
osSyncPrintf(" メッセージが,見つかった!!! = %x "
"(data=%x) (data0=%x) (data1=%x) (data2=%x) (data3=%x)\n",
textId, font->msgOffset, font->msgLength, foundSeg, seg, nextSeg);
return;
}
messageTableEntry++;
languageSegmentTable++;
seg = messageTableEntry->segment;
while (messageTableEntry->textId != 0xFFFF) {
font = &globalCtx->msgCtx.font;
if (messageTableEntry->textId == textId) {
foundSeg = messageTableEntry->segment;
font->charTexBuf[0] = messageTableEntry->typePos;
nextSeg = messageTableEntry->segment;
font->msgOffset = messageTableEntry->segment;
font->msgLength = messageTableEntry->msgSize;
// "Message found!!!"
osSyncPrintf(" メッセージが,見つかった!!! = %x "
"(data=%x) (data0=%x) (data1=%x) (data2=%x) (data3=%x)\n",
textId, font->msgOffset, font->msgLength, foundSeg, seg, nextSeg);
return;
}
messageTableEntry++;
}
// "Message not found!!!"
osSyncPrintf(" メッセージが,見つからなかった!!! = %x\n", textId);
font = &globalCtx->msgCtx.font;
messageTableEntry = sNesMessageEntryTablePtr;
if (gSaveContext.language == LANGUAGE_ENG) {
foundSeg = messageTableEntry->segment;
font->charTexBuf[0] = messageTableEntry->typePos;
messageTableEntry++;
nextSeg = messageTableEntry->segment;
} else {
//languageSegmentTable = (gSaveContext.language == LANGUAGE_GER) ? sGerMessageEntryTablePtr : sFraMessageEntryTablePtr; // OTRTODO
foundSeg = *languageSegmentTable;
font->charTexBuf[0] = messageTableEntry->typePos;
languageSegmentTable++;
nextSeg = *languageSegmentTable;
}
foundSeg = messageTableEntry->segment;
font->charTexBuf[0] = messageTableEntry->typePos;
messageTableEntry++;
nextSeg = messageTableEntry->segment;
font->msgOffset = foundSeg - seg;
font->msgLength = nextSeg - foundSeg;
}
@ -391,7 +331,6 @@ void Message_FindCreditsMessage(GlobalContext* globalCtx, u16 textId) {
if (messageTableEntry->textId == textId) {
foundSeg = messageTableEntry->segment;
font->charTexBuf[0] = messageTableEntry->typePos;
//messageTableEntry++;
nextSeg = messageTableEntry->segment;
font->msgOffset = messageTableEntry->segment;
font->msgLength = messageTableEntry->msgSize;
@ -993,7 +932,7 @@ void Message_DrawText(GlobalContext* globalCtx, Gfx** gfxP) {
}
}
i = j - 1;
msgCtx->textDrawPos = i + CVar_GetS32("gTextSpeed", 1);
msgCtx->textDrawPos = i + 1;
if (character) {}
}
@ -1187,7 +1126,7 @@ void Message_DrawText(GlobalContext* globalCtx, Gfx** gfxP) {
}
}
if (msgCtx->textDelayTimer == 0) {
msgCtx->textDrawPos = i + 1;
msgCtx->textDrawPos = i + CVar_GetS32("gTextSpeed", 1);
msgCtx->textDelayTimer = msgCtx->textDelay;
} else {
msgCtx->textDelayTimer--;
@ -1682,26 +1621,10 @@ void Message_OpenText(GlobalContext* globalCtx, u16 textId) {
//DmaMgr_SendRequest1(font->msgBuf, (uintptr_t)(_staff_message_data_staticSegmentRomStart + 4 + font->msgOffset),
//font->msgLength, "../z_message_PAL.c", 1954);
} else {
if (gSaveContext.language == LANGUAGE_ENG)
{
Message_FindMessage(globalCtx, textId);
msgCtx->msgLength = font->msgLength;
char* src = (uintptr_t)font->msgOffset;
memcpy(font->msgBuf, src, font->msgLength);
} else if (gSaveContext.language == LANGUAGE_GER) {
// OTRTODO
//Message_FindMessage(globalCtx, textId);
//msgCtx->msgLength = font->msgLength;
//DmaMgr_SendRequest1(font->msgBuf, (uintptr_t)(_ger_message_data_staticSegmentRomStart + font->msgOffset),
//font->msgLength, "../z_message_PAL.c", 1978);
} else
{
// OTRTODO
//Message_FindMessage(globalCtx, textId);
//msgCtx->msgLength = font->msgLength;
//DmaMgr_SendRequest1(font->msgBuf, (uintptr_t)(_fra_message_data_staticSegmentRomStart + font->msgOffset),
//font->msgLength, "../z_message_PAL.c", 1990);
}
Message_FindMessage(globalCtx, textId);
msgCtx->msgLength = font->msgLength;
char* src = (uintptr_t)font->msgOffset;
memcpy(font->msgBuf, src, font->msgLength);
}
msgCtx->textBoxProperties = font->charTexBuf[0];

View File

@ -743,6 +743,7 @@ void func_8008F470(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTable,
#else
gSPSegment(POLY_OPA_DISP++, 0x09, SEGMENTED_TO_VIRTUAL(sMouthTextures[eyeIndex]));
#endif
if (CVar_GetS32("gUseTunicsCol",0) != 1) { //Mod is not on bring back original colors.
color = &sTunicColors[tunic];
}
@ -1218,7 +1219,7 @@ void Player_DrawHookshotReticle(GlobalContext* globalCtx, Player* this, f32 arg2
if (BgCheck_AnyLineTest3(&globalCtx->colCtx, &sp8C, &sp80, &sp74, &sp9C, 1, 1, 1, 1, &bgId)) {
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_player_lib.c", 2572);
OVERLAY_DISP = Gfx_CallSetupDL(OVERLAY_DISP, 0x07);
WORLD_OVERLAY_DISP = Gfx_CallSetupDL(WORLD_OVERLAY_DISP, 0x07);
SkinMatrix_Vec3fMtxFMultXYZW(&globalCtx->viewProjectionMtxF, &sp74, &sp68, &sp64);
@ -1227,10 +1228,10 @@ void Player_DrawHookshotReticle(GlobalContext* globalCtx, Player* this, f32 arg2
Matrix_Translate(sp74.x, sp74.y, sp74.z, MTXMODE_NEW);
Matrix_Scale(sp60, sp60, sp60, MTXMODE_APPLY);
gSPMatrix(OVERLAY_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_player_lib.c", 2587),
gSPMatrix(WORLD_OVERLAY_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_player_lib.c", 2587),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPSegment(OVERLAY_DISP++, 0x06, globalCtx->objectCtx.status[this->actor.objBankIndex].segment);
gSPDisplayList(OVERLAY_DISP++, gLinkAdultHookshotReticleDL);
gSPSegment(WORLD_OVERLAY_DISP++, 0x06, globalCtx->objectCtx.status[this->actor.objBankIndex].segment);
gSPDisplayList(WORLD_OVERLAY_DISP++, gLinkAdultHookshotReticleDL);
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_player_lib.c", 2592);
}

View File

@ -166,6 +166,10 @@ void BgSpot06Objects_Init(Actor* thisx, GlobalContext* globalCtx) {
}
} else {
this->lakeHyliaWaterLevel = 0.0f;
WaterBox* water_boxes = globalCtx->colCtx.colHeader->waterBoxes;
water_boxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].ySurface = WATER_LEVEL_RIVER_RAISED;
water_boxes[LHWB_MAIN_1].ySurface = WATER_LEVEL_RAISED;
water_boxes[LHWB_MAIN_2].ySurface = WATER_LEVEL_RAISED;
this->actionFunc = BgSpot06Objects_DoNothing;
}
break;

View File

@ -1668,9 +1668,9 @@ void KaleidoScope_DrawInfoPanel(GlobalContext* globalCtx) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 180, 210, 255, 255);
}
}
gSPDisplayList(POLY_KAL_DISP++, gLButtonIconDL);
if (CVar_GetS32("gUniformLR", 0) == 0) { //Restore the misplace gDPSetPrimColor
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 180, 210, 255, 255);
}
@ -4071,8 +4071,6 @@ void KaleidoScope_Update(GlobalContext* globalCtx)
R_UPDATE_RATE = 3;
R_PAUSE_MENU_MODE = 0;
ResourceMgr_DirtyDirectory("textures/icon_item_24_static*");
ResourceMgr_DirtyDirectory("textures/icon_item_static*");
CVar_SetS32("gPauseTriforce", 0);
func_800981B8(&globalCtx->objectCtx);