Skip to content

Commit

Permalink
Added subsistence support
Browse files Browse the repository at this point in the history
  • Loading branch information
Jayveer committed Feb 19, 2021
1 parent 7fe03ed commit dbe93e4
Show file tree
Hide file tree
Showing 12 changed files with 111 additions and 12 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ This project uses [Zlib](https://github.com/madler/zlib) by [Mark Adler](https:/

## Usage

Currently only a CLI version of the application exists. The program is primitive and just takes the filename as the only required argument. An optional output directory can also be added. It is also possible to just drag the file you wish to extract on the executable. A dictionary file is also included in order to resolve a lot of the hashes, the result is incomplete.
Currently only a CLI version of the application exists. If you wish to extract from the subsistence version of the game use the '-sub' option. An optional output directory can also be added. If extracting from the base game it is possible to just drag the file you wish to extract on the executable. A dictionary file is also included in order to resolve a lot of the hashes, the result is incomplete.

If you wish to use the dictionary to resolve filenames place it alonside Shagohod.exe, please note this program is designed to work with the PS2 version of MGS3.

Expand All @@ -23,6 +23,11 @@ Shagohod.exe "path\to\STAGE.DAT"
```
The above instruction will extract all files from STAGE.DAT to the current directory.

```
Shagohod.exe -sub "path\to\STAGE.DAT"
```
The above instruction will extract all files from STAGE.DAT for the subsistence version of the game.

```
Shagohod.exe "path\to\SLOT.DAT" "path\to\output"
```
Expand Down
2 changes: 2 additions & 0 deletions Shagohod.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@
<ClCompile Include="mgs\archive\slot\stage\stage.cpp" />
<ClCompile Include="mgs\common\decryptor\decryptor.cpp" />
<ClCompile Include="mgs\archive\slot\slot.cpp" />
<ClCompile Include="mgs\common\game\game.cpp" />
<ClCompile Include="mgs\config\cnf.cpp" />
</ItemGroup>
<ItemGroup>
Expand All @@ -168,6 +169,7 @@
<ClInclude Include="mgs\common\decryptor\decryptor.h" />
<ClInclude Include="mgs\common\ext_table.h" />
<ClInclude Include="mgs\common\fileutil.h" />
<ClInclude Include="mgs\common\game\game.h" />
<ClInclude Include="mgs\common\strcode.h" />
<ClInclude Include="mgs\common\util.h" />
<ClInclude Include="mgs\archive\slot\slot.h" />
Expand Down
6 changes: 6 additions & 0 deletions Shagohod.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@
<ClCompile Include="mgs\archive\slot\stage\stage.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mgs\common\game\game.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="interface\cli\cli.h">
Expand Down Expand Up @@ -83,6 +86,9 @@
<ClInclude Include="mgs\archive\slot\stage\stage.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mgs\common\game\game.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Library Include="mgs\3rdparty\zlib\zlib.lib" />
Expand Down
2 changes: 1 addition & 1 deletion Shagohod.vcxproj.user
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<ShowAllFiles>true</ShowAllFiles>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LocalDebuggerCommandArguments>SLOT.DAT</LocalDebuggerCommandArguments>
<LocalDebuggerCommandArguments>STAGE.DAT</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>
42 changes: 38 additions & 4 deletions interface/cli/cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,23 @@ CLI::~CLI() {
}

bool CLI::isStage(const std::string& filepath) {
return filenameContainsString(filepath, "STAGE");
if (filenameContainsString(filepath, "STAGE") || filenameContainsString(filepath, "stage"))
return true;

return false;
}

bool CLI::isSlot(const std::string& filepath) {
return filenameContainsString(filepath, "SLOT");
if (filenameContainsString(filepath, "SLOT") || filenameContainsString(filepath, "slot"))
return true;

return false;
}

bool CLI::isDat(const std::string& filepath) {
if (getExtension(filepath) == ".DAT") return true;
if (getExtension(filepath) == ".DAT" || getExtension(filepath) == ".dat")
return true;

printf("Unsupported file type\n");
exit();
return false;
Expand All @@ -32,7 +40,29 @@ void CLI::extractArchive(Archive& archive) {
archive.extractAll(output);
}

void CLI::processCommands() {
while (currentArg < 2 && isCommand(argv[currentArg])) {
setCommand(argv[currentArg]);
currentArg++;
}
}

void CLI::setCommand(char* arg) {

if (!strcmp(arg, "-SUBSISTENCE") || !strcmp(arg, "-sub") || !strcmp(arg, "-SUB") || !strcmp(arg, "-subsistence")) {
GAME = SUBSISTENCE;
return;
}

printf("command not recognised\n");
}

void CLI::processArgs() {
processCommands();
processFile();
}

void CLI::processFile() {
std::string input = argv[currentArg];
currentArg++;

Expand All @@ -55,7 +85,7 @@ void CLI::processArgs() {
}

bool CLI::checkInput() {
if (argc > 1 && argc < 4) return true;
if (argc > 1 && argc < 5) return true;
printUsage();
return false;
}
Expand All @@ -67,6 +97,10 @@ void CLI::run(std::string programName, std::string version) {
processArgs();
}

bool CLI::isCommand(char* arg) {
return arg[0] == 0x2D;
}

void CLI::printUsage() {
printf(this->USAGE_MESSAGE);
}
Expand Down
8 changes: 7 additions & 1 deletion interface/cli/cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,19 @@ class CLI {
void printUsage();
bool checkInput();
void processArgs();
void processFile();
void processCommands();
bool isCommand(char* arg);
void setCommand(char* arg);
void extractArchive(Archive& archive);


bool isDat(const std::string& filepath);
bool isSlot(const std::string& filepath);
bool isStage(const std::string& filepath);


const char* EXIT_MESSAGE = "Exiting\n";
const char* USAGE_MESSAGE = "Usage:\t Shagohod.exe <SLOT.DAT | STAGE.DAT> [OUTPUTDIRECTORY] \n";
const char* USAGE_MESSAGE = "Usage:\t Shagohod.exe [-OPT] <SLOT.DAT | STAGE.DAT> [OUTPUTDIRECTORY] \n"
"To extract from the subsistence version of mgs3 please use the -sub option";
};
2 changes: 1 addition & 1 deletion main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

int main(int argc, char** argv) {
CLI cli = CLI(argc, argv);
cli.run("Shagohod", "1.0");
cli.run("Shagohod", "1.1");
}
1 change: 1 addition & 0 deletions mgs/archive/slot/slot.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "../archive.h"
#include "../../config/cnf.h"
#include "../../common/game/game.h"
#include "../../common/decryptor/decryptor.h"
#include "../../3rdparty/zlib/wrapper/ZlibWrapper.h"

Expand Down
26 changes: 23 additions & 3 deletions mgs/archive/slot/stage/stage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@ int64_t Stage::getNextPageOffset(uint16_t pageID) {
return (pageID == header.numPages - 1) ? getFileSize(filename) : table[pageID + 1].offset * sector;
}

void Stage::populateTable(uint8_t* data) {
int stride = GAME == SUBSISTENCE ? 0x14 : 0x0C;

for (int i = 0; i < header.numPages; i++) {
int pos = i * stride;
int s = 0;
while (data[pos + s] != '\0') { s++; }
table[i].name.reserve(s);
table[i].name.assign((char*)&data[pos], s);
pos = pos + (stride - 4);
table[i].offset = *(uint32_t*)&data[pos];
}
}

void Stage::open() {
std::ifstream stageDat;
stageDat.open(filename, std::ios::binary);
Expand All @@ -20,10 +34,16 @@ void Stage::open() {
uint32_t keyB = keyA ^ 0xF0F0;
keyA = decryptor.decodeBuffer(keyA, keyB, 0, 0x0C, (uint8_t*)&header.version);

int stride = GAME == SUBSISTENCE ? 0x14 : 0x0C;
size = stride * header.numPages;
table.resize(header.numPages);
size = sizeof(StageTable) * header.numPages;
stageDat.read((char*)&table[0], size);
keyA = decryptor.decodeBuffer(keyA, keyB, 0, size, (uint8_t*)&table[0]);

uint8_t* tableData = new uint8_t[size];
stageDat.read((char*)tableData, size);
keyA = decryptor.decodeBuffer(keyA, keyB, 0, size, tableData);

populateTable(tableData);
delete[] tableData;
}

void Stage::extract(uint16_t pageID, std::string output) {
Expand Down
9 changes: 8 additions & 1 deletion mgs/archive/slot/stage/stage.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@

#pragma pack(push, 4)
struct StageTable {
char name[8];
std::string name;
int32_t offset;
};

struct StageTableS {
char name[16];
int32_t offset;
};

#pragma pop

class Stage : public Slot {
Expand All @@ -19,5 +25,6 @@ class Stage : public Slot {
void extract(uint16_t pageID, std::string output = "");
private:
std::vector<StageTable> table;
void populateTable(uint8_t* data);
int64_t getNextPageOffset(uint16_t pageID);
};
4 changes: 4 additions & 0 deletions mgs/common/game/game.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#include "game.h"

_GAME GAME = SNAKE_EATER;
_PLATFORM PLATFORM = PS2;
14 changes: 14 additions & 0 deletions mgs/common/game/game.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

enum _PLATFORM {
PS2,
NDS
};

enum _GAME {
SNAKE_EATER,
SUBSISTENCE
};

extern _GAME GAME;
extern _PLATFORM PLATFORM;

0 comments on commit dbe93e4

Please sign in to comment.