Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Faster episode booting #70

Open
wants to merge 71 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
8b4660c
Wip redo
Jan 20, 2024
5684f54
Merge branch 'WohlSoft:master' into faster-episode-booting
Jan 20, 2024
69b24c4
Merge branch 'WohlSoft:master' into faster-episode-booting
Jan 21, 2024
2460364
Finally works, geez
Jan 21, 2024
667bc61
Fix Misc.loadEpisode()
Jan 21, 2024
4a92497
Oops
Jan 21, 2024
de2f75a
Oops again
Jan 21, 2024
2f5eb71
Whoops, again
Jan 21, 2024
52b5e41
Fix this check
Jan 21, 2024
0cc2ca9
Switch isBootingSinglePlayer bools, in case. Also add episodeLoadedOn…
Jan 21, 2024
279a12d
Add a check for the world path, if not found it doesn't load the episode
Jan 21, 2024
63770b0
Oops
Jan 21, 2024
6f3aecd
Oops x2
Jan 21, 2024
b836f2d
Oops x3
Jan 21, 2024
a98c27e
Let's shorten and fix this
Jan 21, 2024
df02b5e
Even MORE checks ugh
Jan 21, 2024
18416ba
Meh
Jan 21, 2024
d3db113
Idk how to make Misc.loadEpisode work at this point...
Jan 22, 2024
65a5cff
Fix autostart level loading (Kinda), and add episode list generation …
Jan 22, 2024
5b4217c
Ugh
Jan 22, 2024
201d3fb
Add gLunaLua.exitContext() when loading episode from Lua
Jan 22, 2024
85df082
Remove unused P2 functions, use playerStoredCharacters if after boote…
Jan 22, 2024
090bf6b
Make world.getEpisodeList global everywhere
Jan 22, 2024
12f9485
Add GameAutostart things into Misc.loadEpisode
Jan 22, 2024
11443bf
Add GameAutostart.setSelectedEpisodePath
Jan 22, 2024
5633156
Resort world-related global functions, bring GameAutostart functions …
Jan 22, 2024
4f09594
Oops
Jan 22, 2024
a15aae0
Forgot to remove this
Jan 22, 2024
f90bf7e
Add support for autostart.ini on boot, make error message when nothin…
Jan 22, 2024
1a2d960
Oops, again
Jan 22, 2024
44378a3
Add ANSI Windows path check to LaunchEpisode
Jan 22, 2024
2a3f0b2
Remove COMBOOL on the if statements
Jan 22, 2024
90b6ba5
Massive commit. Not completely finished yet though
Jan 23, 2024
f65b54b
Move LaunchEpisode to a new cpp/h file, add playerCount setting to Ga…
Jan 24, 2024
1de67bc
Epiodes now finally boot, but there's still a lot to do before I can …
Jan 24, 2024
edcd7db
Make LunaDLL compilable again
Jan 24, 2024
5ab9c3d
Remove level load stuff, will be moved to another branch
Jan 24, 2024
666ed5e
CMD has a new argument ("--playSfxOnStartup"), which can be used to p…
Jan 24, 2024
add9f7d
Fix potential issues with unused functions
Jan 24, 2024
121ee6f
Fix up "tempLocation = WorldPath(A).Location" mess
Jan 25, 2024
7501760
Fix for loop error
Jan 25, 2024
5d400d4
Fix templates, add GM_SAVE_PERCENTAGE_PTR (For later)
Jan 25, 2024
51e7222
Extended way to check for a wld file
Jan 25, 2024
f52eb10
Fix compile issues
Jan 25, 2024
8e91a30
More code reworking mess. Also added EpisodeMain::FindSaves
Jan 26, 2024
deb44c2
Oops
Jan 26, 2024
b20d601
Idk why world.getEpisodeList is nil... will have to check later
Jan 26, 2024
8fafc92
Make episode setting values private again, also fix Misc.loadEpisode …
Jan 26, 2024
0d3930a
Merge branch 'WohlSoft:master' into faster-episode-booting
Jan 27, 2024
7c0dcd5
Remove unused LunaLua loadEpisode function
Jan 27, 2024
b8a2ab1
Merge branch 'faster-episode-booting' of https://github.com/SpencerEv…
Jan 27, 2024
7d5e28e
Merge branch 'WohlSoft:master' into faster-episode-booting
Jan 28, 2024
c2b126a
Fix issue with episode booting wrong
Jan 28, 2024
2799bc3
Move getEpisodeList to Misc, and fix no world existence error
Jan 28, 2024
31717d1
Extend Misc.loadEpisode to also have a save slot, number of players, …
Jan 28, 2024
0d50c13
Specify GM_MAX_CHARACTERS instead of just 5, and fix something with t…
Jan 28, 2024
1cc7069
Move the private variables from GameAutostart back to the top
Jan 28, 2024
a739917
Remove unused canExecuteViaLua variables
Jan 28, 2024
df3de97
Fix some line spaces and comments
Jan 28, 2024
c1341f3
External wld files on Misc.loadEpisode can now be specified, but just…
Jan 30, 2024
bd8553c
Fix possible episodeName issue on Misc.loadEpisode
Jan 30, 2024
e28c757
Forgot this
Jan 30, 2024
1e891be
Fix things for episodes if the GM_EP_LIST_COUNT is more than 100, als…
Jan 30, 2024
99e97b3
Actually fix more than 100 episode booting
Jan 30, 2024
b9b9025
Attempt to fix everything to satisfy the devs (Part 1, after this com…
Feb 14, 2024
5593876
Merge remote-tracking branch 'upstream/master' into faster-episode-bo…
Feb 14, 2024
5fbe9d8
Make it compilable again
Feb 14, 2024
9703243
Merge remote-tracking branch 'upstream/master' into faster-episode-bo…
Jun 20, 2024
3d82193
Put this pull request's new GlobalFuncs functions in the cpp file to …
Jun 20, 2024
773c7e9
See description for changes
Jun 20, 2024
2b04f44
Remove useless "For(A, From, To)" function, since it's now unused
Jun 20, 2024
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
17 changes: 8 additions & 9 deletions LunaDll/GameConfig/GameAutostart.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,6 @@ struct StartupEpisodeSettings;

class GameAutostart
{
private:
//Settings
std::string selectedEpisode;
std::wstring selectedWldPath;
bool singleplayer;
Characters firstCharacter;
Characters secondCharacter;
int saveSlot;

public:
GameAutostart();
~GameAutostart();
Expand All @@ -29,6 +20,14 @@ class GameAutostart
void setSaveSlot(int val) { saveSlot = val; }

bool applyAutostart();

//Settings
SolaceEllery marked this conversation as resolved.
Show resolved Hide resolved
std::string selectedEpisode;
std::wstring selectedWldPath;
bool singleplayer;
Characters firstCharacter;
Characters secondCharacter;
int saveSlot;
};

#endif
71 changes: 71 additions & 0 deletions LunaDll/GlobalFuncs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <iomanip>
#include <fstream>
#include <mutex>
#include <cstddef>

#include "Misc/MiscFuncs.h"
#include "Input/Input.h"
Expand Down Expand Up @@ -727,6 +728,20 @@ std::string resolveIfNotAbsolutePath(std::string filename) {
return filename;
}

std::string splitPathFromFilename(std::string str)
{
replaceSubStr(str, "/", "\\");
std::string finalStr = str.substr(str.find_last_of("/\\") + 1);
return finalStr;
}

std::string splitFilenameFromPath(std::string str)
{
replaceSubStr(str, "/", "\\");
std::string finalStr = str.substr(0, str.find_last_of("/\\"));
return finalStr;
}


std::string generateTimestamp(std::string format)
{
Expand Down Expand Up @@ -852,6 +867,62 @@ std::wstring getCustomFolderPath()
return full_path;
}

int findEpisodeIDFromWorldFileAndPath(std::string worldName)
{
int id = 0;
for (int i = 1; i <= 100; i++) {
auto ep = EpisodeListItem::Get(i - 1);
if(worldName == std::string(ep->episodePath) + std::string(ep->episodeWorldFile))
{
id = i;
break;
}
}
return id - 1;
}

std::string findEpisodeWorldPathFromName(std::string name)
{
if(name.empty())
{
return "";
}
std::string finalWldPath;
for (int i = 1; i <= 100; i++) {
auto ep = EpisodeListItem::Get(i - 1);
if(name == std::string(ep->episodeName))
{
finalWldPath = std::string(ep->episodePath) + std::string(ep->episodeWorldFile);
break;
}
}
return finalWldPath;
}

bool isBootingSinglePlayer()
{
if(GM_PLAYERS_COUNT <= 1)
{
return true;
}
else if(GM_PLAYERS_COUNT > 1)
{
return false;
}
}

int getPlayer2Character()
{
if(GM_PLAYERS_COUNT > 1)
{
return static_cast<int>(Player::Get(2)->Identity);
}
else
{
return 0;
}
}

std::wstring getLatestFile(const std::initializer_list<std::wstring>& paths)
{
FILETIME newest = { 0 };
Expand Down
6 changes: 6 additions & 0 deletions LunaDll/GlobalFuncs.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ bool isAbsolutePath(const std::string& path);
std::wstring resolveCwdOrWorldsPath(const std::wstring& path);
std::wstring resolveIfNotAbsolutePath(std::wstring filename);
std::string resolveIfNotAbsolutePath(std::string filename);
std::string splitPathFromFilename(std::string str);
std::string splitFilenameFromPath(std::string str);

extern void removeFilePathW(std::wstring &path);
extern void removeFilePathW(wchar_t*path, int length);
Expand Down Expand Up @@ -122,6 +124,10 @@ std::wstring getEpisodeFolderPath();
std::wstring getCustomFolderPath();
std::wstring getLatestFile(const std::initializer_list<std::wstring>& paths);
std::wstring getLatestConfigFile(const std::wstring& configname);
int findEpisodeIDFromWorldFileAndPath(std::string worldName);
std::string findEpisodeWorldPathFromName(std::string name);
bool isBootingSinglePlayer();
int getPlayer2Character();

template <typename T>
T normalizeToBackslashAndResolvePath(const T& path)
Expand Down
2 changes: 2 additions & 0 deletions LunaDll/Globals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,5 @@ void printBoxA(const char *fmt, ...)

std::string gEditorPlacedItem = "nil";
std::mutex g_editorIPCMutex;

bool episodeLoadedOnBoot = false;
2 changes: 2 additions & 0 deletions LunaDll/Globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,5 @@ return;

extern std::string gEditorPlacedItem;
extern std::mutex g_editorIPCMutex;

extern bool episodeLoadedOnBoot;
2 changes: 1 addition & 1 deletion LunaDll/LuaMain/LuaProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -909,7 +909,7 @@ namespace LuaProxy {
void exitGame();
void exitEngine();
bool didGameOver();
bool loadEpisode(const std::string& episodeName);
bool loadEpisode(std::string episodeName);
void pause();
void pause(bool atFrameEnd);
void unpause();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,17 +234,36 @@ bool LuaProxy::Misc::didGameOver()
return luaDidGameOverFlag;
}

bool LuaProxy::Misc::loadEpisode(const std::string& episodeName)
bool LuaProxy::Misc::loadEpisode(std::string episodeName)
{
GameAutostart autoStartEpisode;
autoStartEpisode.setSelectedEpisode(episodeName);
autoStartEpisode.setSaveSlot(GM_CUR_SAVE_SLOT);
bool success = autoStartEpisode.applyAutostart();
if (success)
bool success = false;

Characters storedIdentity1 = Player::Get(1)->Identity;
Characters storedIdentity2;

if(GM_PLAYERS_COUNT > 1)
{
storedIdentity2 = Player::Get(2)->Identity;
}
else if(GM_PLAYERS_COUNT <= 1)
{
GM_EPISODE_MODE = 0;
GM_LEVEL_MODE = 0xFFFF;
storedIdentity2 = static_cast<Characters>(0);
}

std::string worldPth = findEpisodeWorldPathFromName(episodeName);

if(!worldPth.empty() || worldPth != "")
{
success = true;
}

std::wstring finalWorldPth = Str2WStr(worldPth);

if(success)
{
LaunchEpisode(finalWorldPth, GM_CUR_SAVE_SLOT, isBootingSinglePlayer(), storedIdentity1, storedIdentity2);
}

return success;
}

Expand Down
140 changes: 140 additions & 0 deletions LunaDll/LuaMain/LunaLuaMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
#include "LunaPathValidator.h"
#include "../Misc/CollisionMatrix.h"

#include "../FileManager/SMBXFileManager.h"

/*static*/ DWORD CLunaFFILock::currentLockTlsIdx = TlsAlloc();

extern bool luaDidGameOverFlag;
Expand Down Expand Up @@ -1606,3 +1608,141 @@ void CLunaLua::queuePlayerSectionChangeEvent(int playerIdx) {
m_playerSectionChangeList.push_back(playerIdx);
m_executeSectionChangeFlag = true;
}

extern PlayerMOB* getTemplateForCharacter(int id);
extern "C" void __cdecl LunaLuaSetGameData(const char* dataPtr, int dataLen);

void LaunchEpisode(std::wstring wldPath, int saveSlot, bool singleplayer, Characters firstCharacter, Characters secondCharacter)
{
// make sure the game unpauses and Lua is gone before starting after the episode has loaded successfully after boot
if(episodeLoadedOnBoot)
{
g_EventHandler.requestUnpause();

gLunaLua.exitContext();
gCachedFileMetadata.purge();
}

if(!episodeLoadedOnBoot)
{
// cleanup the level
native_cleanupLevel();
}

if(episodeLoadedOnBoot)
{
// cleanup either the level or world, depending on where we are at
if(GM_EPISODE_MODE && GM_LEVEL_MODE) // level
{
native_cleanupLevel();
}

if(GM_EPISODE_MODE && !GM_LEVEL_MODE) // world
{
runtimeHookCleanupWorld();
}
}

// setup SFXs
native_setupSFX();

// show loadscreen while loading everything
LunaLoadScreenStart();

// clear gamedata
LunaLuaSetGameData(0, 0);

// put the world together
std::wstring fullPath = resolveCwdOrWorldsPath(wldPath);

// make sure we also get the path without the wld file
std::string fullPathStr = WStr2Str(fullPath);
std::string fullPathNoWorldPth = splitFilenameFromPath(fullPathStr);
std::string fullPathNoWorldPthWithEndSlash = fullPathNoWorldPth + "\\";

VB6StrPtr pathVb6 = WStr2Str(fullPath);
VB6StrPtr pathNoWldVb6 = Str2WStr(fullPathNoWorldPthWithEndSlash);

// specify the save slot, the fulldir, and the menu level for the wld file
SMBXWorldFileBase::PopulateEpisodeList();
GM_CUR_MENULEVEL = findEpisodeIDFromWorldFileAndPath(WStr2Str(fullPath));
GM_CUR_SAVE_SLOT = saveSlot;
GM_FULLDIR = pathNoWldVb6;

// implement player count if it's 0
if(GM_PLAYERS_COUNT == 0)
{
if(singleplayer)
{
GM_PLAYERS_COUNT = 1;
}
else if(!singleplayer)
{
GM_PLAYERS_COUNT = 2;
}
}

native_loadWorld(&pathVb6);

// load save
if (saveFileExists())
{
native_loadGame();
}

// put the player on the world map
GM_EPISODE_MODE = COMBOOL(true);
GM_TITLE_INTRO_MODE = COMBOOL(false);
GM_LEVEL_MODE = COMBOOL(false);

// reset checkpoints
GM_STR_CHECKPOINT = "";

// add players' characters
auto p = Player::Get(1);
// implement the 1st player's character
p->Identity = firstCharacter;
// implement the 2nd player's character
if(!singleplayer && GM_PLAYERS_COUNT >= 2)
{
auto p2 = Player::Get(2);
if(secondCharacter != static_cast<Characters>(0))
{
p2->Identity = secondCharacter;
}
else
{
p2->Identity = static_cast<Characters>(1);
}
}

// unlikely that we'll get more than 3 players loading on boot, but Misc.loadEpisode exists, so this check needs to exist
if(GM_PLAYERS_COUNT > 2)
{
for (int i = 3; i <= GM_PLAYERS_COUNT; i++) {
auto p = Player::Get(i);
p->Identity = firstCharacter;
}
}

// apply templates
if(!episodeLoadedOnBoot)
{
for (int i = 1; i <= GM_PLAYERS_COUNT; i++) {

auto t = getTemplateForCharacter(p->Identity);
if (t != nullptr) {
memcpy(p, t, sizeof(PlayerMOB));
}
}
}

// make sure that lunadll knows the game loaded on boot, so that loadEpisode can know
if(!episodeLoadedOnBoot)
{
episodeLoadedOnBoot = true;
}

// hide loadscreen
LunaLoadScreenKill();
}
2 changes: 2 additions & 0 deletions LunaDll/LuaMain/LunaLuaMain.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,6 @@ namespace CachedReadFile {
void releaseCached(bool isWorld);
};

extern void LaunchEpisode(std::wstring wldPath, int saveSlot, bool singleplayer, Characters firstCharacter, Characters secondCharacter);

#endif
21 changes: 21 additions & 0 deletions LunaDll/Misc/RuntimeHookComponents/RuntimeHookHooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1602,6 +1602,27 @@ Characters playerStoredCharacters[] = {CHARACTER_MARIO,CHARACTER_MARIO,CHARACTER

void __stdcall runtimeHookLoadLevel(VB6StrPtr* filename)
{
std::wstring filenameWS = static_cast<std::wstring>(*filename);
size_t findLastSlash = filenameWS.find_last_of(L"/\\");
std::wstring dirWS = filenameWS.substr(0U, findLastSlash);
std::wstring nameWS = filenameWS.substr(findLastSlash + 1);
std::string dirST = WStr2Str(dirWS);
std::string nameST = WStr2Str(nameWS);

//If the legacy title screen is about to boot, prevent that and go straight to loading the episode
if(nameST == "intro.lvl" && dirST == gAppPathUTF8)
SolaceEllery marked this conversation as resolved.
Show resolved Hide resolved
{
GameAutostart autostarter = GameAutostart::createGameAutostartByStartupEpisodeSettings(gStartupSettings.epSettings);
if(autostarter.selectedWldPath == L"")
{
std::string msg = "There is no world file loaded on starting the engine. This means that you booted LunaLoader.exe with no arguments regarding selecting a world or level. Please load a world or level with SMBX2 by loading the X2 launcher instead.";
MessageBoxA(gMainWindowHwnd, msg.c_str(), "Error", MB_ICONWARNING | MB_OK);
_exit(0);
}
LaunchEpisode(autostarter.selectedWldPath, autostarter.saveSlot, autostarter.singleplayer, autostarter.firstCharacter, autostarter.secondCharacter);
return;
}

if (!GM_CREDITS_MODE)
{
for (int i = 1; i <= min(GM_PLAYERS_COUNT, (WORD)4); i++) {
Expand Down