diff --git a/README.md b/README.md index 8378e64..3ed4362 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi | Java Class | `application/x-java-applet` | [`patterns/java_class.hexpat`](patterns/java_class.hexpat) | Java Class files | | JPEG | `image/jpeg` | [`patterns/jpeg.hexpat`](patterns/jpeg.hexpat) | JPEG Image Format | | Lua 5.4 | | [`patterns/lua54.hexpat`](patterns/lua54.hexpat) | Lua 5.4 bytecode | +| LCE Savefile | | [`patterns/lcesave.hexpat`](patterns/lcesave.hexpat) | Minecraft Legacy Console Edition save file | | Mach-O | `application/x-mach-binary` | [`patterns/macho.hexpat`](patterns/macho.hexpat) | Mach-O executable | | MIDI | `audio/midi` | [`patterns/midi.hexpat`](patterns/midi.hexpat) | MIDI header, event fields provided | | MiniDump | `application/x-dmp` | [`patterns/minidump.hexpat`](patterns/minidump.hexpat) | Windows MiniDump files | diff --git a/patterns/lcesave.hexpat b/patterns/lcesave.hexpat new file mode 100644 index 0000000..a2400fd --- /dev/null +++ b/patterns/lcesave.hexpat @@ -0,0 +1,72 @@ +#pragma author DexrnZacAttack +#pragma description Pattern for Minecraft LCE Save Files (after decompression) +#pragma version 1.3.0 +#pragma disclaimer This pattern is not affiliated with Mojang Studios nor Microsoft. Minecraft is a trademark of Mojang Studios and Microsoft. +#pragma endian big +/* ^ switch this to little for Switch, PS4, or Xbox One */ + + +// NOTE: This pattern was only tested on Nightly@974c4ba, things may break/not work on older versions. +// ALSO NOTE: SPEGHETTI CODE! + +// TODO: re-add nbt pattern +// TODO: clean up getFileType + +import std.string; +#pragma pattern_limit 1000000 +#pragma array_limit 1000000 + +fn getFileType(str filename) { + // EWWWWWWW HOW DO I FIX THIS + match (std::string::substr(filename, std::string::length(filename) - 4, 4)) { + (".mcr"): + if (std::string::starts_with(filename, "r.")) + return "Overworld Region"; + else if (std::string::starts_with(filename, "DIM-1")) + return "Nether Region"; + else if (std::string::starts_with(filename, "DIM1")) + return "End Region"; + else + return "Unknown Region"; + (".dat"): + if (std::string::starts_with(filename, "players")) + return "Player"; + else if (std::string::starts_with(filename, "data/")) { + if (std::string::starts_with(filename, "data/map_")) + return "Map File"; + else + return "Other DAT File"; + } else if (std::string::starts_with(filename, "level")) + return "Level File"; + else + return "Unknown DAT"; + + (_): return "File"; + } +}; + +struct LCEIndex { + char16 filename[0x40] [[name("File Name")]]; // name of the file. + u32 filesize [[name("File Size")]]; // how big the file is + u32 offset [[name("File Offset")]]; // where the file is located + if (parent.header.curVersion > 1) + u64 timestamp [[name("File Timestamp")]]; // useless as it writes weirdly, and differently on certain consoles. (e.g using time since last reset, etc) + u8 file[filesize] @ offset [[name(this.filename),comment(getFileType(std::string::to_string(filename))),attribute_name(this.filename)]]; // files in the index +} [[name("(" + getFileType(std::string::to_string(filename)) + ") " + std::string::to_string(this.filename))]]; + +struct LCEHeader { + u32 offset [[name("Index Offset")]]; // where the index is located + u32 count [[name("Index File Count")]]; // amount of files in the index + u16 minVersion [[name("Minimum LCE file version")]]; // Minimum LCE version supported by file + u16 curVersion [[name("Current LCE file version")]]; // Version that the file was written with +}; + +struct LCESave { + LCEHeader header [[name("Header")]]; + if (header.curVersion > 1) + LCEIndex index[header.count] @ header.offset [[name("File Index")]]; // the index + else + LCEIndex index[header.count / 136] @ header.offset [[name("File Index")]]; // the index (pre-release) +} [[name("Save " + "(Version " + std::string::to_string(header.curVersion) + ")")]]; + +LCESave Save @ 0x00; diff --git a/tests/patterns/test_data/MC-TU033PreRelease_savegameDecompressed.dat b/tests/patterns/test_data/MC-TU033PreRelease_savegameDecompressed.dat new file mode 100644 index 0000000..1fc36af Binary files /dev/null and b/tests/patterns/test_data/MC-TU033PreRelease_savegameDecompressed.dat differ diff --git a/tests/patterns/test_data/MC-TU5-Release_savegameDecompressed.dat b/tests/patterns/test_data/MC-TU5-Release_savegameDecompressed.dat new file mode 100644 index 0000000..aa4ce9f Binary files /dev/null and b/tests/patterns/test_data/MC-TU5-Release_savegameDecompressed.dat differ