Skip to content

Commit a31b6d4

Browse files
patterns/zone: Add Minecraft Infdev 20100624 Zone file pattern (#516)
* patterns/zone: Add Minecraft Infdev 20100624 Zone file pattern * chore: add pattern to readme
1 parent cbebdbf commit a31b6d4

2 files changed

Lines changed: 138 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
254254
| ZIM | | [`patterns/zim.hexpat`](patterns/zim.hexpat) | [ZIM](https://openzim.org) file format |
255255
| ZIP | `application/zip` | [`patterns/zip.hexpat`](patterns/zip.hexpat) | End of Central Directory Header, Central Directory File Headers |
256256
| ZLIB | `application/zlib` | [`patterns/zlib.hexpat`](patterns/zlib.hexpat) | ZLIB compressed data format |
257+
| Zone | | [`patterns/zone.hexpat`](patterns/zone.hexpat) | Minecraft Infdev 20100624 Zone file |
257258
| ZSTD | `application/zstd` | [`patterns/zstd.hexpat`](patterns/zstd.hexpat) | Zstandard compressed data format |
258259
| MOD | `3d-model/mod` | [`patterns/DMC3HD-Mod.hexpat`](patterns/dmc3_hd_mod.hexpat) | 3D Model files used in Devil May Cry 3 HD Collection |
259260
| CBM BASIC | | [`commodore_basic.hexpat`](patterns/commodore_basic.hexpat) | Commodore BASIC |

patterns/zone.hexpat

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
#pragma author DexrnZacAttack
2+
#pragma description Minecraft Infdev 20100624 Zone File
3+
#pragma repo https://github.com/Team-Lodestone/ImHex-Patterns
4+
#pragma version 1.0.0
5+
6+
#pragma magic [13 73 70 00] @ 0x00
7+
#pragma endian big
8+
9+
import std.core;
10+
import std.io;
11+
import type.magic;
12+
13+
using long = s64;
14+
using int = s32;
15+
using short = s16;
16+
using byte = s8;
17+
18+
bitfield u4 {
19+
low : 4;
20+
high : 4;
21+
} [[static, inline]];
22+
23+
namespace InfdevZone {
24+
using ZoneFile;
25+
26+
namespace Slot {
27+
int CHUNKS_PER_ZONE_BITS = 5;
28+
int CHUNKS_PER_ZONE = 1 << CHUNKS_PER_ZONE_BITS;
29+
30+
int CHUNK_WIDTH = 16;
31+
int CHUNK_DEPTH = 16;
32+
int CHUNK_HEIGHT = 128;
33+
34+
int CHUNK_HEADER_SIZE = 256;
35+
int CHUNK_SIZE = CHUNK_WIDTH * CHUNK_DEPTH * CHUNK_HEIGHT;
36+
int CHUNK_LAYERS = 3;
37+
int CHUNK_SIZE_BYTES = CHUNK_SIZE * CHUNK_LAYERS + CHUNK_HEADER_SIZE;
38+
39+
/** Returns a slot from chunk coords
40+
*
41+
* @param cx Chunk X coordinate
42+
* @param cz Chunk Z coordinate
43+
* @return A slot for the given coords
44+
*/
45+
fn getSlot(int cx, int cz) {
46+
int zoneX = cx >> CHUNKS_PER_ZONE_BITS;
47+
int zoneZ = cz >> CHUNKS_PER_ZONE_BITS;
48+
int offX = cx - (zoneX << CHUNKS_PER_ZONE_BITS);
49+
int offZ = cz - (zoneZ << CHUNKS_PER_ZONE_BITS);
50+
51+
return offX + offZ * CHUNKS_PER_ZONE;
52+
};
53+
54+
bitfield Properties {
55+
unused : 63 [[hidden]];
56+
terrainPopulated : 1;
57+
};
58+
59+
struct Header {
60+
int x;
61+
int z;
62+
63+
long inhabitedTime;
64+
Properties properties;
65+
66+
padding[CHUNK_HEADER_SIZE - ($ - addressof(this))];
67+
};
68+
69+
// or should this be called Chunk?
70+
// We need to figure out the actual terminology lmao
71+
struct Slot {
72+
InfdevZone::Slot::Header header [[inline]];
73+
74+
byte blocks[CHUNK_SIZE];
75+
u4 data[CHUNK_SIZE / 2];
76+
u4 skyLight[CHUNK_SIZE / 2];
77+
u4 blockLight[CHUNK_SIZE / 2];
78+
byte heightmap[CHUNK_WIDTH * CHUNK_DEPTH] [[hex::visualize("bitmap", this, CHUNK_WIDTH, CHUNK_DEPTH)]];
79+
} [[name(std::format("Chunk @ {}, {}", header.x, header.z))]];
80+
}
81+
82+
namespace ZoneFile {
83+
int FILE_HEADER_SIZE = 4096;
84+
int MAGIC_NUMBER = 0x13737000;
85+
int VERSION = 0x0000;
86+
87+
struct Header {
88+
int magic;
89+
if (magic != MAGIC_NUMBER) {
90+
std::error(std::format("Magic value '{:#04x}' does not match expected magic '{:#04x}'", magic, MAGIC_NUMBER));
91+
}
92+
93+
short version;
94+
if (version != VERSION) {
95+
std::error(std::format("Version '{:#02x}' does not match expected version '{:#02x}'", version, VERSION));
96+
}
97+
98+
short slotCount;
99+
short slotLocations[slotCount];
100+
};
101+
102+
/** Returns the offset in the data where a slot should be written
103+
*
104+
* @param slot The slot to get the offset of
105+
*/
106+
fn getSlotOffset(int slot) {
107+
return (slot - 1) * CHUNK_SIZE_BYTES + FILE_HEADER_SIZE;
108+
};
109+
110+
struct SlotElement {
111+
// std::print("{}", std::core::array_index());
112+
113+
int loc = parent.header.slotLocations[std::core::array_index()];
114+
u64 idx = InfdevZone::ZoneFile::getSlotOffset(loc);
115+
116+
if (idx != 0 && idx <= std::mem::size()) {
117+
InfdevZone::Slot::Slot slot @ idx;
118+
} else {
119+
if (idx == 0) {
120+
std::warning(std::format("Skipping empty slot"));
121+
} else {
122+
std::warning(std::format("Skipping invalid slot {} (would place at index {:#06x})", loc, idx));
123+
}
124+
}
125+
} [[inline]];
126+
127+
struct ZoneFile {
128+
InfdevZone::ZoneFile::Header header [[inline]];
129+
130+
InfdevZone::ZoneFile::SlotElement slots[header.slotCount];
131+
};
132+
}
133+
}
134+
135+
#ifndef INF624_ZONE_USE_LIB
136+
InfdevZone::ZoneFile::ZoneFile zone @ 0x00;
137+
#endif

0 commit comments

Comments
 (0)