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
12 changes: 12 additions & 0 deletions include/dusk/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
62 changes: 61 additions & 1 deletion src/d/d_s_logo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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);
Expand Down
82 changes: 73 additions & 9 deletions src/m_Do/m_Do_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -502,8 +505,6 @@ int game_main(int argc, char* argv[]) {
}
mainCalled = true;

dusk::registerSettings();

cxxopts::ParseResult parsed_arg_options;

try {
Expand All @@ -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>");
Expand All @@ -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();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: I also moved this down just to fix a bug that crashed while unregistering settings if we exited while parsing arguments or displaying help.


const auto startupLogLevel =
static_cast<AuroraLogLevel>(parsed_arg_options["log-level"].as<uint8_t>());
Expand All @@ -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();
Expand Down Expand Up @@ -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>();
Expand All @@ -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());
Expand All @@ -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;
Expand All @@ -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
Expand All @@ -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!");
}
Expand Down Expand Up @@ -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
Expand Down
Loading