feat(system): Add startup working directory options - #3149
feat(system): Add startup working directory options#3149CryoTheRenegade wants to merge 10 commits into
Conversation
… directory Co-authored-by: Cursor <cursoragent@cursor.com>
PR Summary by QodoAdd -cwd flag to control startup working directory across game and tools
AI Description
Diagram
High-Level Assessment
Files changed (9)
|
Code Review by Qodo
1.
|
Co-authored-by: Cursor <cursoragent@cursor.com>
…Line Co-authored-by: Cursor <cursoragent@cursor.com>
Have the game and tools share parseCommandLineForStartup so the working directory is applied in one place, without a GlobalData flag or a second tokenizer. Co-authored-by: Cursor <cursoragent@cursor.com>
|
| Filename | Overview |
|---|---|
| Core/GameEngine/Source/Common/CommandLine.cpp | Adds working-directory options, centralizes parsing on CRT arguments, and records startup-consumed positions for downstream tool parsers. |
| Core/GameEngine/Source/Common/WorkingDirectory.cpp | Implements Win32 helpers for selecting either the executable directory or an explicitly supplied directory. |
| Core/Tools/MapCacheBuilder/Source/WinMain.cpp | Routes startup through the shared parser and filters consumed startup options before treating remaining arguments as maps. |
| Generals/Code/Main/WinMain.cpp | Moves shared startup parsing to the former executable-directory setup point. |
| GeneralsMD/Code/Main/WinMain.cpp | Applies the same shared startup and working-directory flow to Zero Hour. |
| Generals/Code/Tools/WorldBuilder/src/WorldBuilder.cpp | Integrates startup parsing and excludes already-consumed arguments from WorldBuilder-specific parsing. |
| GeneralsMD/Code/Tools/WorldBuilder/src/WorldBuilder.cpp | Mirrors the WorldBuilder startup integration for the Zero Hour variant. |
| Generals/Code/Tools/GUIEdit/Source/WinMain.cpp | Initializes shared startup state before GUIEdit creates and initializes its engine services. |
| GeneralsMD/Code/Tools/GUIEdit/Source/WinMain.cpp | Mirrors the shared GUIEdit startup path for Zero Hour. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
Start[Process startup] --> Parse[Parse shared startup arguments]
Parse --> Choice{Working-directory option}
Choice -->|setCwd path| Explicit[Use explicit directory]
Choice -->|useCwd| Inherited[Keep inherited directory]
Choice -->|Neither| Executable[Use executable directory]
Explicit --> Record[Record consumed argument positions]
Inherited --> Record
Executable --> Record
Record --> App{Application}
App --> Game[Generals or Zero Hour startup]
App --> Tool[GUIEdit, WorldBuilder, or MapCacheBuilder]
Tool --> Filter[Filter startup-consumed arguments]
Filter --> ToolParse[Run tool-specific parsing]
Reviews (7): Last reviewed commit: "fix(system): Use CRT command-line argume..." | Re-trigger Greptile
VC6 does not support in-class member initializers, which broke the WorldBuilder command-line parser on CI. Co-authored-by: Cursor <cursoragent@cursor.com>
xezon
left a comment
There was a problem hiding this comment.
Becomes better, but it is still sloppy.
| static std::vector<Bool> s_startupParsedArguments; | ||
|
|
||
| static void parseCommandLine( | ||
| const CommandLineParam* params, int numParams, std::vector<Bool> *parsedArguments = nullptr) |
| } | ||
|
|
||
| int CommandLine::getStartupWorkingDirectoryOptionTokenCount(const char *arg) | ||
| bool CommandLine::isCommandLineArgumentParsedForStartup(int argIndex) |
There was a problem hiding this comment.
Does this need to be Startup specific? Maybe just make it cover all of them?
| char * str = strtrim(token); | ||
| const int cwdTokenCount = CommandLine::getStartupWorkingDirectoryOptionTokenCount(str); | ||
| if (cwdTokenCount > 0) | ||
| if (!CommandLine::isCommandLineArgumentParsedForStartup(argIndex)) |
| { | ||
| if (CommandLine::isCommandLineArgumentParsedForStartup(m_argIndex++)) | ||
| { | ||
| ParseLast(bLast); |
| constexpr const Int SIMULATE_REPLAYS_SEQUENTIAL = -1; | ||
|
|
||
| //------------------------------------------------------------------------------------------------- | ||
| class CommandLineData |
There was a problem hiding this comment.
While at it, add a comment above this class explaining why it is here instead of in CommandLine (The parsing result is bound to GlobalData)
|
|
||
| // Set when a working-directory option is present so parseCommandLineForStartup | ||
| // does not force the executable directory after parsing. | ||
| static Bool s_cwdOptionSpecified = FALSE; |
There was a problem hiding this comment.
Better move this state flag to WorkingDirectory, whether a working directory was already set, making it less dependent on CommandLine.
Summary
-useCwdto keep the inherited working directory and-setCwd <path>to select an explicit startup directoryCommandLine::parseCommandLineForStartup()for the games, GUIEdit, WorldBuilder, and MapCacheBuilderFor Visual Studio, add
-useCwdto Command Arguments and set Working Directory to the game install path.To select an explicit directory, pass its path after
-setCwd. Quote paths that contain spaces:This recreates the abandoned #1445 feature and applies the review feedback from that PR:
GlobalDatamiddleman flagWorkingDirectoryConsiderations from #1445:
mss32.dllandBINKW32.DLLare not system DLLs. See Win32 DLL search order.LoadImageAandLoadCursorFromFilesearch the executable path, then the current working directory, then%PATH%. See OpenFile remarks.fopenuse the current working directory.This change was drafted with LLM assistance.