mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-07-11 21:21:57 -04:00
Add command line arguments for --develop, --load-save, and --stage (#2150)
* Add command line arguments for --develop, --load-save, and --stage * Include sstream so clang stops crying :( * Put stage load parsing in main, better load logic
This commit is contained in:
@@ -12,6 +12,18 @@ extern bool RestartRequested;
|
||||
extern std::filesystem::path ConfigPath;
|
||||
extern std::filesystem::path CachePath;
|
||||
|
||||
extern uint8_t SaveRequested;
|
||||
struct StageRequest {
|
||||
std::string stage;
|
||||
bool set;
|
||||
s8 room;
|
||||
s16 point;
|
||||
s8 layer;
|
||||
};
|
||||
extern StageRequest StageRequested;
|
||||
|
||||
|
||||
|
||||
#if defined(__ANDROID__) || (defined(TARGET_OS_IOS) && TARGET_OS_IOS) || \
|
||||
(defined(TARGET_OS_TV) && TARGET_OS_TV)
|
||||
inline constexpr bool SupportsProcessRestart = false;
|
||||
|
||||
+61
-1
@@ -23,8 +23,12 @@
|
||||
#include "m_Do/m_Do_main.h"
|
||||
#include "JSystem/JUtility/JUTConsole.h"
|
||||
|
||||
#ifdef TARGET_PC
|
||||
#include "dusk/logging.h"
|
||||
#include "dusk/version.hpp"
|
||||
#include "dusk/main.h"
|
||||
#include "m_Do/m_Do_MemCard.h"
|
||||
#endif
|
||||
|
||||
#if !PLATFORM_GCN
|
||||
#include <revolution/os.h>
|
||||
@@ -757,7 +761,63 @@ void dScnLogo_c::nextSceneChange() {
|
||||
if (!mDoRst::isReset()) {
|
||||
if (!isOpeningCut())
|
||||
{
|
||||
dComIfG_changeOpeningScene(this, fpcNm_OPENING_SCENE_e);
|
||||
#ifdef TARGET_PC
|
||||
// If we are requesting a save from the command line, load it here and set the scene to play instead of loading the LOGO SCENE
|
||||
if (dusk::SaveRequested >= 1 && dusk::SaveRequested <= 3) {
|
||||
u8 buf[SAVEDATA_SIZE * 3];
|
||||
mDoMemCd_Load();
|
||||
uint8_t status;
|
||||
do {
|
||||
status = mDoMemCd_LoadSync(buf, sizeof(buf), 0);
|
||||
// Wait until the card is loaded
|
||||
} while (status == 0);
|
||||
|
||||
if (status == 1) {
|
||||
dComIfGs_setCardToMemory(buf, dusk::SaveRequested - 1);
|
||||
} else {
|
||||
dComIfGs_init();
|
||||
}
|
||||
|
||||
dComIfGs_setNoFile(dusk::SaveRequested);
|
||||
dComIfGs_setDataNum(dusk::SaveRequested-1);
|
||||
|
||||
dComIfGs_gameStart();
|
||||
|
||||
fopScnM_ChangeReq(this, fpcNm_PLAY_SCENE_e, 0, 30);
|
||||
|
||||
dKy_clear_game_init();
|
||||
dComIfGs_resetDan();
|
||||
dComIfGs_setRestartRoomParam(0);
|
||||
|
||||
DuskLog.info("Loaded Save From Slot {}",dusk::SaveRequested);
|
||||
dusk::SaveRequested = 0xff;
|
||||
} else if (dusk::SaveRequested == 0xff) {
|
||||
// This indicates that the save has loaded, but we are waiting for the scene
|
||||
// manager to change to play
|
||||
} else if (dusk::StageRequested.set) {
|
||||
// Do nothing if we need to request a stage to load later in the function
|
||||
} else{
|
||||
#endif
|
||||
dComIfG_changeOpeningScene(this, fpcNm_OPENING_SCENE_e);
|
||||
#ifdef TARGET_PC
|
||||
}
|
||||
|
||||
if (dusk::StageRequested.set) {
|
||||
// If we aren't loading a save, initialize a blank save file and request the correct scene to load
|
||||
if (dusk::SaveRequested == 0) {
|
||||
dComIfGs_init();
|
||||
|
||||
fopScnM_ChangeReq(this, fpcNm_PLAY_SCENE_e, 0, 30);
|
||||
dusk::SaveRequested = 0xff; //Skip requesting the scene from above
|
||||
}
|
||||
|
||||
// Use both to force-set start stage
|
||||
dComIfGp_setNextStage(dusk::StageRequested.stage.c_str(), dusk::StageRequested.point, dusk::StageRequested.room, dusk::StageRequested.layer);
|
||||
g_dComIfG_gameInfo.play.mNextStage.getStartStage()->set(dusk::StageRequested.stage.c_str(), dusk::StageRequested.room, dusk::StageRequested.point, dusk::StageRequested.layer);
|
||||
|
||||
dusk::StageRequested.set = false; // Setting the stage should only happen once
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
#if DEBUG
|
||||
fopScnM_ChangeReq(this, fpcNm_MENU_SCENE_e, 0, 30);
|
||||
|
||||
+73
-9
@@ -42,6 +42,7 @@
|
||||
#include "m_Do/m_Do_ext2.h"
|
||||
#include "SSystem/SComponent/c_counter.h"
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
|
||||
#include <filesystem>
|
||||
#include <system_error>
|
||||
@@ -125,6 +126,8 @@ bool dusk::IsRunning = true;
|
||||
bool dusk::IsShuttingDown = false;
|
||||
bool dusk::IsGameLaunched = false;
|
||||
bool dusk::RestartRequested = false;
|
||||
uint8_t dusk::SaveRequested = 0;
|
||||
dusk::StageRequest dusk::StageRequested = {"",false};
|
||||
std::filesystem::path dusk::ConfigPath;
|
||||
std::filesystem::path dusk::CachePath;
|
||||
#endif
|
||||
@@ -502,8 +505,6 @@ int game_main(int argc, char* argv[]) {
|
||||
}
|
||||
mainCalled = true;
|
||||
|
||||
dusk::registerSettings();
|
||||
|
||||
cxxopts::ParseResult parsed_arg_options;
|
||||
|
||||
try {
|
||||
@@ -516,7 +517,10 @@ int game_main(int argc, char* argv[]) {
|
||||
("dvd", "Path to DVD image file", cxxopts::value<std::string>())
|
||||
("mods", "Path to mods directory", cxxopts::value<std::string>())
|
||||
("backend", "Graphics API backend to use (auto, d3d12, d3d11, metal, vulkan, null)", cxxopts::value<std::string>())
|
||||
("cvar", "Override configuration variables without modifying config", cxxopts::value<std::vector<std::string>>());
|
||||
("cvar", "Override configuration variables without modifying config", cxxopts::value<std::vector<std::string>>())
|
||||
("develop", "Enable the game's developer mode and OSReport for debugging", cxxopts::value<bool>()->default_value("false")->implicit_value("true"))
|
||||
("load-save", "Skip the opening and load a save from slot 1-3", cxxopts::value<uint8_t>()->default_value("0"))
|
||||
("stage", "Upon launching, load a stage, room, spawn point, and layer. When using --load-save, it uses the specified save on the loaded stage. Format (STAGE,ROOM,POINT,LAYER). Example: (STAGE) or (STAGE,0,0,-1)", cxxopts::value<std::string>());
|
||||
|
||||
arg_options.parse_positional({"dvd"});
|
||||
arg_options.positional_help("<dvd-image>");
|
||||
@@ -529,11 +533,52 @@ int game_main(int argc, char* argv[]) {
|
||||
printf("%s", (arg_options.help() + "\n").c_str());
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (parsed_arg_options.count("stage")) {
|
||||
std::stringstream ss(parsed_arg_options["stage"].as<std::string>());
|
||||
std::string token;
|
||||
|
||||
std::getline(ss,token,',');
|
||||
std::string stageName = token;
|
||||
s8 room = 0;
|
||||
s16 point = 0;
|
||||
s8 layer = -1;
|
||||
if (std::getline(ss,token,',')) {
|
||||
room = std::stoi(token);
|
||||
if (std::getline(ss,token,',')) {
|
||||
point = std::stoi(token);
|
||||
if (std::getline(ss,token,',')) {
|
||||
layer = std::stoi(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dusk::StageRequested = {stageName,true, room,point,layer};
|
||||
}
|
||||
}
|
||||
catch (const cxxopts::exceptions::exception& e) {
|
||||
fprintf(stderr, "Argument Error: %s\n", e.what());
|
||||
exit(1);
|
||||
}
|
||||
catch (const std::invalid_argument& e) {
|
||||
// Handle parsing std::stoi when loading a stage
|
||||
fprintf(stderr, "Fatal: Invalid Argument When Parsing Stage\n");
|
||||
exit(1);
|
||||
}
|
||||
catch (const std::out_of_range& e) {
|
||||
// Handle parsing std::stoi when loading a stage
|
||||
fprintf(stderr, "Fatal: Argument Out of Range In Parsing Stage\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (parsed_arg_options.contains("load-save")){
|
||||
uint8_t slot = parsed_arg_options["load-save"].as<uint8_t>();
|
||||
if (slot >= 1 && slot <= 3) {
|
||||
dusk::SaveRequested = slot;
|
||||
}
|
||||
}
|
||||
|
||||
dusk::registerSettings();
|
||||
|
||||
const auto startupLogLevel =
|
||||
static_cast<AuroraLogLevel>(parsed_arg_options["log-level"].as<uint8_t>());
|
||||
@@ -542,6 +587,12 @@ int game_main(int argc, char* argv[]) {
|
||||
dusk::CachePath = dataPaths.cachePath;
|
||||
dusk::InitializeFileLogging(dusk::CachePath, startupLogLevel);
|
||||
|
||||
// Development Mode
|
||||
if (parsed_arg_options.count("develop")) {
|
||||
mDoMain::developmentMode = parsed_arg_options["develop"].as<bool>(); // Enable Dev Mode for Debugging
|
||||
dusk::OSReportReallyForceEnable = parsed_arg_options["develop"].as<bool>(); // Print OSReport to console
|
||||
}
|
||||
|
||||
log_build_info();
|
||||
|
||||
dusk::config::load_from_user_preferences();
|
||||
@@ -682,7 +733,7 @@ int game_main(int argc, char* argv[]) {
|
||||
saveConfigBeforePrelaunch = true;
|
||||
}
|
||||
|
||||
std::string dvd_path;
|
||||
std::string dvd_path = dusk::getSettings().backend.isoPath;
|
||||
bool dvd_opened = false;
|
||||
if (parsed_arg_options.count("dvd")) {
|
||||
dvd_path = parsed_arg_options["dvd"].as<std::string>();
|
||||
@@ -705,6 +756,22 @@ int game_main(int argc, char* argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
bool skipPreLaunchUI = dusk::getSettings().backend.skipPreLaunchUI.getValue();
|
||||
|
||||
// If we can't load right into the game, stop requesting to load a stage or save
|
||||
if (forcePreLaunchUI || dvd_path.empty()) {
|
||||
if (dusk::StageRequested.set) {
|
||||
DuskLog.warn("Cannot load stage {} because no iso path is set, opening prelaunch UI",dusk::StageRequested.stage);
|
||||
dusk::StageRequested = {};
|
||||
}
|
||||
if (dusk::SaveRequested) {
|
||||
DuskLog.warn("Cannot load save {} because no iso path is set, opening prelaunch UI",dusk::SaveRequested);
|
||||
dusk::SaveRequested = 0;
|
||||
}
|
||||
}else if (dusk::StageRequested.set || dusk::SaveRequested) {
|
||||
skipPreLaunchUI = true;
|
||||
}
|
||||
|
||||
dusk::iso::log_verification_state(
|
||||
dusk::getSettings().backend.isoPath.getValue(),
|
||||
dusk::getSettings().backend.isoVerification.getValue());
|
||||
@@ -713,7 +780,7 @@ int game_main(int argc, char* argv[]) {
|
||||
if (dusk::getSettings().backend.isoPath.getValue().empty()) {
|
||||
forcePreLaunchUI = true;
|
||||
}
|
||||
if (forcePreLaunchUI && dusk::getSettings().backend.skipPreLaunchUI.getValue()) {
|
||||
if (forcePreLaunchUI && skipPreLaunchUI) {
|
||||
DuskLog.warn("Prelaunch UI was disabled with no usable DVD image, enabling prelaunch UI");
|
||||
dusk::getSettings().backend.skipPreLaunchUI.setValue(false);
|
||||
saveConfigBeforePrelaunch = true;
|
||||
@@ -722,7 +789,7 @@ int game_main(int argc, char* argv[]) {
|
||||
dusk::config::save();
|
||||
}
|
||||
|
||||
if (!dusk::getSettings().backend.skipPreLaunchUI) {
|
||||
if (!skipPreLaunchUI) {
|
||||
dusk::ui::push_document(std::make_unique<dusk::ui::Prelaunch>(), true);
|
||||
|
||||
// pre game launch ui main loop
|
||||
@@ -741,7 +808,6 @@ int game_main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
dvd_path = dusk::getSettings().backend.isoPath;
|
||||
|
||||
if (dvd_path.empty()) {
|
||||
DuskLog.fatal("No DVD image specified, unable to boot!");
|
||||
}
|
||||
@@ -784,8 +850,6 @@ int game_main(int argc, char* argv[]) {
|
||||
// Global Context Init
|
||||
dComIfG_ct();
|
||||
|
||||
// Development Mode
|
||||
// mDoMain::developmentMode = 1; // Force Dev Mode for Debugging
|
||||
mDoDvdThd::SyncWidthSound = false;
|
||||
|
||||
// Mod search directories, highest priority first: user dir (--mods replaces it), then
|
||||
|
||||
Reference in New Issue
Block a user