mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Headless: Add --dump-file to copy a file out of a disc image
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
cae623f4e6
commit
e015977f3c
5 files changed
+60
No files matched your search
@@ -224,6 +224,8 @@ static const CommandLineParam g_autoParams[] = {
|
||||
{POFF(reRawBase), CmdParamType::String, "re-raw-base", '\0', "Treat --re-module as a raw code image loaded at this address, e.g. 0x08300000", CmdLineMode::Headless},
|
||||
{POFF(reDecrypt), CmdParamType::String, "re-decrypt", '\0', "Decrypt one encrypted PSP file (PRX or ME image) and exit", CmdLineMode::Headless},
|
||||
{POFF(reDecryptOut), CmdParamType::String, "re-decrypt-out", '\0', "Output file for --re-decrypt (default: decrypted.bin)", CmdLineMode::Headless},
|
||||
{POFF(dumpFile), CmdParamType::String, "dump-file", '\0', "Copy one file out of the disc image, e.g. disc0:/PSP_GAME/USRDIR/MOVIE.PMF, and exit", CmdLineMode::Headless},
|
||||
{POFF(dumpFileOut), CmdParamType::String, "dump-file-out", '\0', "Output file for --dump-file (default: the file's own name)", CmdLineMode::Headless},
|
||||
{POFF(odsLog), CmdParamType::Bool, "odslog", 'o', "Also log through OutputDebugString (Windows)", CmdLineMode::Headless},
|
||||
{POFF(generateInterpreterDispatch), CmdParamType::Bool, "generate-interpreter-dispatch", '\0', "Generate C++ interpreter dispatch code (ExecInstruction) to stdout and exit", CmdLineMode::Headless},
|
||||
{POFF(resolutionScale), CmdParamType::Int, "resolution-scale", '\0', "Set the resolution scale factor"},
|
||||
|
||||
@@ -126,6 +126,10 @@ struct CommandLineOptions {
|
||||
std::optional<std::string> reDecrypt;
|
||||
// Where the plaintext goes. Defaults to "decrypted.bin".
|
||||
std::optional<std::string> reDecryptOut;
|
||||
// Headless: copy one file out of the disc image given as the positional argument, to
|
||||
// --dump-file-out, and exit.
|
||||
std::optional<std::string> dumpFile;
|
||||
std::optional<std::string> dumpFileOut;
|
||||
|
||||
std::optional<int> memReadAction;
|
||||
std::optional<int> memWriteAction;
|
||||
|
||||
@@ -1065,6 +1065,14 @@ int main(int argc, const char* argv[]) {
|
||||
if (cmdLineOptions.reDecrypt.has_value()) {
|
||||
return RunDecryptFile(cmdLineOptions.reDecrypt.value(), cmdLineOptions.reDecryptOut.value_or("decrypted.bin"));
|
||||
}
|
||||
if (cmdLineOptions.dumpFile.has_value()) {
|
||||
if (cmdLineOptions.bootFilenames.empty()) {
|
||||
fprintf(stderr, "--dump-file needs the disc image as the positional argument\n");
|
||||
return 1;
|
||||
}
|
||||
const std::string &inPath = cmdLineOptions.dumpFile.value();
|
||||
return RunDumpDiscFile(cmdLineOptions.bootFilenames[0], inPath, cmdLineOptions.dumpFileOut.value_or(Path(inPath.substr(inPath.find(':') + 1)).GetFilename()));
|
||||
}
|
||||
if (cmdLineOptions.reModule.has_value()) {
|
||||
ReverseEngineerOptions reOptions;
|
||||
reOptions.modulePath = cmdLineOptions.reModule.value();
|
||||
|
||||
@@ -393,6 +393,48 @@ int RunDecryptFile(const std::string &inPath, const std::string &outPath) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RunDumpDiscFile(const std::string &discPath, const std::string &inPath, const std::string &outPath) {
|
||||
std::string insideDisc = inPath;
|
||||
const size_t colon = insideDisc.find(':');
|
||||
if (colon != std::string::npos) {
|
||||
insideDisc = insideDisc.substr(colon + 1);
|
||||
}
|
||||
if (insideDisc.empty() || insideDisc[0] != '/') {
|
||||
insideDisc = "/" + insideDisc;
|
||||
}
|
||||
|
||||
std::unique_ptr<FileLoader> loader(ConstructFileLoader(Path(discPath)));
|
||||
std::string blockError;
|
||||
std::shared_ptr<BlockDevice> device(loader ? ConstructBlockDevice(loader.get(), &blockError) : nullptr);
|
||||
if (!device) {
|
||||
fprintf(stderr, "dump-file: %s isn't a disc image we can read: %s\n", discPath.c_str(), blockError.c_str());
|
||||
return 1;
|
||||
}
|
||||
// The ISO filesystem takes ownership of the block device, which owns the loader.
|
||||
loader.release();
|
||||
ISOFileSystem isoFs(&pspFileSystem, device);
|
||||
|
||||
const int handle = isoFs.OpenFile(insideDisc, FILEACCESS_READ);
|
||||
if (handle < 0) {
|
||||
fprintf(stderr, "dump-file: no such file on the disc: %s\n", insideDisc.c_str());
|
||||
return 1;
|
||||
}
|
||||
const PSPFileInfo info = isoFs.GetFileInfoByHandle(handle);
|
||||
std::vector<u8> data((size_t)info.size);
|
||||
const size_t readBytes = data.empty() ? 0 : isoFs.ReadFile(handle, data.data(), (s64)data.size());
|
||||
isoFs.CloseFile(handle);
|
||||
if (readBytes != data.size()) {
|
||||
fprintf(stderr, "dump-file: short read, %d of %d bytes\n", (int)readBytes, (int)data.size());
|
||||
return 1;
|
||||
}
|
||||
if (!File::WriteDataToFile(false, data.data(), data.size(), Path(outPath))) {
|
||||
fprintf(stderr, "dump-file: couldn't write %s\n", outPath.c_str());
|
||||
return 1;
|
||||
}
|
||||
printf("dump-file: wrote %d bytes of %s to %s\n", (int)data.size(), insideDisc.c_str(), outPath.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RunReverseEngineer(const ReverseEngineerOptions &opts) {
|
||||
// A module inside a disc image rather than on the host - see ReverseEngineerOptions.
|
||||
const bool fromDisc = startsWithNoCase(opts.modulePath, "disc0:") || startsWithNoCase(opts.modulePath, "umd0:");
|
||||
|
||||
@@ -50,3 +50,7 @@ int RunReverseEngineer(const ReverseEngineerOptions &opts);
|
||||
// flash0:/kd/resource, which are ordinary tagged containers with the signature blanked, so the
|
||||
// normal module loader won't touch them. Returns a process exit code.
|
||||
int RunDecryptFile(const std::string &inPath, const std::string &outPath);
|
||||
|
||||
// Copies one file out of a disc image (ISO/CSO/...) as-is, e.g. "disc0:/PSP_GAME/USRDIR/MOVIE.PMF".
|
||||
// Returns a process exit code.
|
||||
int RunDumpDiscFile(const std::string &discPath, const std::string &inPath, const std::string &outPath);
|
||||
Reference in new issue
Block a user