Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,6 @@ jobs:
gamecontrollerdb.txt

build-switch:
if: false
needs: generate-port-o2r
runs-on: ubuntu-latest
container:
Expand All @@ -307,22 +306,29 @@ jobs:
sudo apt-get update
sudo apt-get install -y ninja-build
sudo apt-get remove -y cmake
sudo dkp-pacman -R --noconfirm switch-tinyxml2 # devkitPro's tinyxml2 is too old and causes build issues
export CFLAGS="${CFLAGS} -include strings.h" # weird libzip error (pulled in by LUS) that only happens in CI and not for SoH
git -C libultraship remote add nx https://github.com/Net64DD/libultraship.git
git -C libultraship fetch nx
git -C libultraship checkout nx/main-nx-nightly
wget https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3-linux-x86_64.sh -O /tmp/cmake.sh
sudo sh /tmp/cmake.sh --prefix=/usr/local/ --exclude-subdir
cmake -H. -Bbuild-switch -GNinja -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake
cmake -H. -Bbuild-switch -GNinja -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake -DCMAKE_BUILD_TYPE:STRING=Release
cmake --build build-switch --config Release -j3
wget -O gamecontrollerdb.txt https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/refs/heads/master/gamecontrollerdb.txt
mv README.md readme.txt
mv build-switch/*.nro Ghostship.nro
- name: Download ghostship.o2r
uses: actions/download-artifact@v4
with:
name: ghostship.o2r
- name: Upload build
uses: actions/upload-artifact@v4
with:
name: Ghostship-switch
path: |
Ghostship.nro
ghostship.o2r
config.yml
assets
gamecontrollerdb.txt
5 changes: 3 additions & 2 deletions .github/workflows/switch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ on: [pull_request]

jobs:
build-switch:
if: false
runs-on: ubuntu-latest
container:
image: devkitpro/devkita64:20260219
Expand All @@ -16,12 +15,14 @@ jobs:
sudo apt-get update
sudo apt-get install -y ninja-build
sudo apt-get remove -y cmake
sudo dkp-pacman -R --noconfirm switch-tinyxml2 # devkitPro's tinyxml2 is too old and causes build issues
export CFLAGS="${CFLAGS} -include strings.h" # weird libzip error (pulled in by LUS) that only happens in CI and not for SoH
git -C libultraship remote add nx https://github.com/Net64DD/libultraship.git
git -C libultraship fetch nx
git -C libultraship checkout nx/main-nx-nightly
wget https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3-linux-x86_64.sh -O /tmp/cmake.sh
sudo sh /tmp/cmake.sh --prefix=/usr/local/ --exclude-subdir
cmake -H. -Bbuild-switch -GNinja -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake
cmake -H. -Bbuild-switch -GNinja -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake -DCMAKE_BUILD_TYPE:STRING=Release
cmake --build build-switch --config Release -j3
wget -O gamecontrollerdb.txt https://github.com/mdqinc/SDL_GameControllerDB/blob/master/gamecontrollerdb.txt
mv README.md readme.txt
Expand Down
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON)
if (CMAKE_SYSTEM_NAME STREQUAL "NintendoSwitch")
set(CMAKE_C_FLAGS_DEBUG "-g -ffast-math -DDEBUG")
set(CMAKE_CXX_FLAGS_DEBUG "-g -ffast-math -DDEBUG")
# Optimization level -O2 and higher cause graphical 3D glitches due to undefined behavior in some of the C code (on both PC and Switch).
# The optimization that causes this issue is -fstrict-aliasing. The camera is locked in place, often out-of-bounds, and renders the game unplayable.
set(CMAKE_C_FLAGS_RELEASE "-O3 -fno-strict-aliasing -DNDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -ffast-math -DNDEBUG")
add_compile_definitions(
Expand Down
1 change: 1 addition & 0 deletions cmake/lus-cvars.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ set(CVAR_GAME_OVERLAY_FONT "${CVAR_PREFIX_SETTING}.OverlayFont")
set(CVAR_MENU_BAR_OPEN "${CVAR_PREFIX_SETTING}.OpenMenuBar")
set(CVAR_PREFIX_CONTROLLERS "${CVAR_PREFIX_SETTING}.Controllers")
set(CVAR_PREFIX_ADVANCED_RESOLUTION "${CVAR_PREFIX_SETTING}.AdvancedResolution")
set(CVAR_SWITCH_PERF_MODE "${CVAR_PREFIX_SETTING}.SwitchPerfMode")
include("libultraship/cmake/cvars.cmake")
56 changes: 23 additions & 33 deletions src/port/Engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,6 @@ GameEngine::GameEngine() : dictionary(nullptr) {

#ifdef __SWITCH__
Ship::Switch::Init(Ship::PreInitPhase);
// Ship::Switch::Init(Ship::PostInitPhase); // TODO: Search why
#endif

this->context->InitConfiguration(); // without this line InitConsoleVariables fails at Config::Reload()
Expand Down Expand Up @@ -293,7 +292,7 @@ void CheckAndCreateModFolder() {
static void SetupScriptLoader(std::shared_ptr<Ship::Context> context) {
#ifdef __SWITCH__
return;
#endif
#else
constexpr int codeVersion = 1;
const std::unordered_map<std::string, std::string> defines = {
{ "VERSION_US", "1" }, { "ENABLE_RUMBLE", "1" }, { "F3D_OLD", "1" }, { "F3D_GBI", "1" },
Expand Down Expand Up @@ -338,13 +337,12 @@ static void SetupScriptLoader(std::shared_ptr<Ship::Context> context) {
#endif

context->GetScriptLoader()->SetCacheDir(Ship::Context::GetPathRelativeToAppDirectory("mods_cache"));
#endif
}

void GameEngine::LoadResourceFiles() {
SetupScriptLoader(context);

#ifndef __SWITCH__

std::string romPath = Ship::Context::LocateFileAcrossAppDirs("sm64.o2r", "sm64");
if (std::filesystem::exists(romPath)) {
context->GetResourceManager()->GetArchiveManager()->AddArchive(romPath);
Expand Down Expand Up @@ -382,6 +380,7 @@ void GameEngine::LoadResourceFiles() {
}
}

#ifndef __SWITCH__
auto archive = Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager();
auto list = archive->GetArchives();

Expand All @@ -390,9 +389,8 @@ void GameEngine::LoadResourceFiles() {
if (info.Main.empty()) {
continue;
}
#ifndef __SWITCH__

this->totalScripts++;
#endif
}
#endif // __SWITCH__
}
Expand Down Expand Up @@ -479,7 +477,7 @@ void GameEngine::FinishInit() {
Instance->LoadDictionary();
Instance->LoadPlayerAnims();
#if defined(__SWITCH__) || defined(__WIIU__)
CVarRegisterInteger("gControlNav", 1); // always enable controller nav on switch/wii u
CVarRegisterInteger(CVAR_IMGUI_CONTROLLER_NAV, 1); // always enable controller nav on switch/wii u
#endif
GhostshipGui::SetupGuiElements();
DevConsole_Init();
Expand All @@ -505,24 +503,9 @@ void GameEngine::RunExtract(int argc, char* argv[]) {

OTRVersion romArchiveVersion = DetectOTRVersion("sm64.o2r");

bool found = std::filesystem::exists(Ship::Context::LocateFileAcrossAppDirs("sm64.o2r"));
bool shouldRegen = !VerifyArchiveVersion(romArchiveVersion) && romArchiveVersion.major != INT16_MAX;

#ifdef __SWITCH__
{
const bool romO2RExists = std::filesystem::exists(Ship::Context::LocateFileAcrossAppDirs("sm64.o2r", "sm64"));
if (shouldRegen || !romO2RExists) {
SPDLOG_ERROR("ROM archive missing or outdated on Switch, please regenerate and relaunch.");
exit(1);
}
LoadResourceFiles();
Ship::Switch::Init(Ship::PreInitPhase);
if (menuWasVisible) {
gui->GetMenu()->Show();
}
return;
}
#endif

std::filesystem::path ownPath;
std::vector<std::string> args;
if (argc > 1) {
Expand All @@ -540,15 +523,18 @@ void GameEngine::RunExtract(int argc, char* argv[]) {
std::string installPath = Ship::Context::GetAppBundlePath();
std::string file;

#if defined(__WIIU__)
GhostshipGui::RegisterPopup("Outdated ROM Archives",
"You've launched the Ship with an old a ROM O2R file.\n\n"
"Please generate a ROM O2R and relaunch.\n\n"
"Press and hold the Power button to shutdown...",
"OK", "", [&]() { exit(1); });
OSFatal();
#endif

#if defined(__SWITCH__)
if (!found) {
Ship::Switch::ShowErrorApplet("Missing O2R ROM Archives\n\n"
"The sm64.o2r file is missing.\n"
"Please generate a ROM O2R using the PC version, place it on the SD card and relaunch.");
}
else if (shouldRegen) {
Ship::Switch::ShowErrorApplet("Outdated ROM Archives\n\n"
"Your sm64.o2r were created with incompatible versions of SoH.\n"
"Please regenerate a new ROM O2R using the PC version, place it on the SD card and relaunch.");
}
#else
if (!std::filesystem::exists(installPath + "/assets")) {
GhostshipGui::RegisterPopup("Extractor assets not found",
"No O2R files found. Missing 'assets/' folder needed to generate OTR file.\nPlease "
Expand All @@ -564,7 +550,7 @@ void GameEngine::RunExtract(int argc, char* argv[]) {
"now be redirected to re-extract them.");
std::filesystem::remove("sm64.o2r");
}

#endif
std::shared_ptr<BS::thread_pool> threadPool = std::make_shared<BS::thread_pool>(1);
while (true) {
#ifndef __SWITCH__
Expand Down Expand Up @@ -826,6 +812,8 @@ void GameEngine::RunExtract(int argc, char* argv[]) {
default:
break;
}
#else
extractStep = ES_VERIFY;
#endif
break;
}
Expand Down Expand Up @@ -854,6 +842,8 @@ void GameEngine::RunExtract(int argc, char* argv[]) {
extractStep = GS_LOAD;
});
extractStep = GS_WAIT;
#else
extractStep = GS_LOAD;
#endif
continue;
}
Expand Down
37 changes: 35 additions & 2 deletions src/port/ui/GhostshipMenuSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,18 @@ static const std::unordered_map<int32_t, const char*> notificationPosition = {
{ 0, "Top Left" }, { 1, "Top Right" }, { 2, "Bottom Left" }, { 3, "Bottom Right" }, { 4, "Hidden" },
};

#ifdef __SWITCH__
static const std::unordered_map<int32_t, const char*> switchPerformanceProfiles = {
{ Ship::MAXIMUM, SWITCH_CPU_PROFILES[Ship::MAXIMUM] },
{ Ship::HIGH, SWITCH_CPU_PROFILES[Ship::HIGH] },
{ Ship::BOOST, SWITCH_CPU_PROFILES[Ship::BOOST] },
{ Ship::STOCK, SWITCH_CPU_PROFILES[Ship::STOCK] },
{ Ship::POWERSAVINGM1, SWITCH_CPU_PROFILES[Ship::POWERSAVINGM1] },
{ Ship::POWERSAVINGM2, SWITCH_CPU_PROFILES[Ship::POWERSAVINGM2] },
{ Ship::POWERSAVINGM3, SWITCH_CPU_PROFILES[Ship::POWERSAVINGM3] }
};
#endif

void GhostshipMenu::AddMenuSettings() {
// Add Settings Menu
AddMenuEntry("Settings", CVAR_SETTING("Menu.SettingsSidebarSection"));
Expand All @@ -66,21 +78,25 @@ void GhostshipMenu::AddMenuSettings() {
.Tooltip("Changes the Theme of the Menu Widgets.")
.ComboMap(menuThemeOptions)
.DefaultIndex(Colors::LightBlue));
#if not defined(__SWITCH__) and not defined(__WIIU__)
AddWidget(path, "Menu Controller Navigation", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_IMGUI_CONTROLLER_NAV)
.RaceDisable(false)
.Options(CheckboxOptions().Tooltip(
"Allows controller navigation of the port menu (Settings, Enhancements,...)\nCAUTION: "
"This will disable game inputs while the menu is visible.\n\nD-pad to move between "
"items, A to select, B to move up in scope."));
"items, A to select, B to move up in scope.")
#ifdef __SWITCH__
.DefaultValue(true)
#endif
);
AddWidget(path, "Menu Background Opacity", WIDGET_CVAR_SLIDER_FLOAT)
.CVar(CVAR_SETTING("Menu.BackgroundOpacity"))
.RaceDisable(false)
.Options(FloatSliderOptions().DefaultValue(0.85f).IsPercentage().Tooltip(
"Sets the opacity of the background of the port menu."));

AddWidget(path, "General Settings", WIDGET_SEPARATOR_TEXT);
#if not defined(__SWITCH__) and not defined(__WIIU__)
AddWidget(path, "Cursor Always Visible", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_SETTING("CursorVisibility"))
.RaceDisable(false)
Expand All @@ -107,13 +123,28 @@ void GhostshipMenu::AddMenuSettings() {
.RaceDisable(false)
.Options(CheckboxOptions().Tooltip(
"Search input box gets autofocus when visible. Does not affect using other widgets."));
#ifdef __SWITCH__
AddWidget(path, "Hardware", WIDGET_SEPARATOR_TEXT);
AddWidget(path, "Switch performance mode", WIDGET_CVAR_COMBOBOX)
.CVar(CVAR_SWITCH_PERF_MODE)
.RaceDisable(false)
.Callback([](WidgetInfo& info) {
Ship::Switch::ApplyOverclock();
})
.Options(ComboboxOptions()
.DefaultIndex(Ship::MAXIMUM)
.ComboMap(switchPerformanceProfiles)
.Tooltip("Sets the Nintendo Switch CPU performance profile."));
#endif
#if not defined(__SWITCH__) and not defined(__WIIU__)
AddWidget(path, "Open App Files Folder", WIDGET_BUTTON)
.RaceDisable(false)
.Callback([](WidgetInfo& info) {
std::string filesPath = Ship::Context::GetInstance()->GetAppDirectoryPath();
SDL_OpenURL(std::string("file:///" + std::filesystem::absolute(filesPath).string()).c_str());
})
.Options(ButtonOptions().Tooltip("Opens the folder that contains the save and mods folders, etc."));
#endif
AddWidget(path, "EXPERIMENTAL", WIDGET_SEPARATOR_TEXT).Options(TextOptions().Color(Colors::Orange));
AddWidget(path, "ImGui Menu Scaling", WIDGET_CVAR_COMBOBOX)
.CVar(CVAR_SETTING("ImGuiScale"))
Expand Down Expand Up @@ -183,10 +214,12 @@ void GhostshipMenu::AddMenuSettings() {
path.sidebarName = "Graphics";
AddSidebarEntry("Settings", "Graphics", 3);
AddWidget(path, "Graphics Options", WIDGET_SEPARATOR_TEXT);
#ifndef __SWITCH__
AddWidget(path, "Toggle Fullscreen", WIDGET_BUTTON)
.RaceDisable(false)
.Callback([](WidgetInfo& info) { Ship::Context::GetInstance()->GetWindow()->ToggleFullscreen(); })
.Options(ButtonOptions().Tooltip("Toggles Fullscreen On/Off."));
#endif
AddWidget(path, "Internal Resolution", WIDGET_CVAR_SLIDER_FLOAT)
.CVar(CVAR_INTERNAL_RESOLUTION)
.RaceDisable(false)
Expand Down