Lx_ReloD.cru carries the only complete list of the game's data files. Two
structures, back to back in the unpacked image:
0x1662-- 84 NUL-terminated filenames, twelve characters each, in load order.0x1AA6-- a table of 16-bit indices into those names, twelve rows of seven: one row per level slot, one entry per file a level needs.
Row 3 -- level 4 -- is seven 0xFFFF entries. See
../docs/11-leftovers.md.
Names in the table are reproduced here exactly as they appear in the loader,
including the case that does not match the disc (Lx_Sfx_* for Lx_SFX_*,
LA_/LB_/LC_ for La_/Lb_/Lc_).
The first seven names, indices 00-06, are the shared files and are not
addressed through the row table:
| Index | Name |
|---|---|
| 00 | Lx_TPage.cru |
| 01 | Lx_CompC.cru |
| 02 | Lx_CompE.cru |
| 03 | Lx_MSprM.cru |
| 04 | Lx_MSprF.cru |
| 05 | Lx_Sfx_M.bin |
| 06 | Lx_Sfx_F.bin |
| Slot | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|---|
| L1 | L1_LLoad.cru (07) |
L1_SprDR.cru (08) |
L1_GSBlk.cru (09) |
L1_Int_E.cru (0A) |
L1_Int_F.cru (0B) |
L1_Int_G.cru (0C) |
L1_XMemI.cru (0D) |
| L2 | L2_LLoad.cru (0E) |
L2_SprDR.cru (0F) |
L2_GSBlk.cru (10) |
L2_Int_E.cru (11) |
L2_Int_F.cru (12) |
L2_Int_G.cru (13) |
L2_XMemI.cru (14) |
| L3 | L3_LLoad.cru (15) |
L3_SprDR.cru (16) |
L3_GSBlk.cru (17) |
L3_Int_E.cru (18) |
L3_Int_F.cru (19) |
L3_Int_G.cru (1A) |
L3_XMemI.cru (1B) |
| L4 | FFFF | FFFF | FFFF | FFFF | FFFF | FFFF | FFFF |
| L5 | L5_LLoad.cru (1C) |
L5_SprDR.cru (1D) |
L5_GSBlk.cru (1E) |
L5_Int_E.cru (1F) |
L5_Int_F.cru (20) |
L5_Int_G.cru (21) |
L5_XMemI.cru (22) |
| L6 | L6_LLoad.cru (23) |
L6_SprDR.cru (24) |
L6_GSBlk.cru (25) |
L6_Int_E.cru (26) |
L6_Int_F.cru (27) |
L6_Int_G.cru (28) |
L6_XMemI.cru (29) |
| L7 | L7_LLoad.cru (2A) |
L7_SprDR.cru (2B) |
L7_GSBlk.cru (2C) |
L7_Int_E.cru (2D) |
L7_Int_F.cru (2E) |
L7_Int_G.cru (2F) |
L7_XMemI.cru (30) |
| L8 | L8_LLoad.cru (31) |
L8_SprDR.cru (32) |
L8_GSBlk.cru (33) |
L8_Int_E.cru (34) |
L8_Int_F.cru (35) |
L8_Int_G.cru (36) |
L8_XMemI.cru (37) |
| L9 | L9_LLoad.cru (38) |
L9_SprDR.cru (39) |
L9_GSBlk.cru (3A) |
L9_Int_E.cru (3B) |
L9_Int_F.cru (3C) |
L9_Int_G.cru (3D) |
L9_XMemI.cru (3E) |
| LA | LA_LLoad.cru (3F) |
LA_SprDR.cru (40) |
LA_GSBlk.cru (41) |
LA_Int_E.cru (42) |
LA_Int_F.cru (43) |
LA_Int_G.cru (44) |
LA_XMemI.cru (45) |
| LB | LB_LLoad.cru (46) |
LB_SprDR.cru (47) |
LB_GSBlk.cru (48) |
LB_Int_E.cru (49) |
LB_Int_F.cru (4A) |
LB_Int_G.cru (4B) |
LB_XMemI.cru (4C) |
| LC | LC_LLoad.cru (4D) |
LC_SprDR.cru (4E) |
LC_GSBlk.cru (4F) |
LC_Int_E.cru (50) |
LC_Int_F.cru (51) |
LC_Int_G.cru (52) |
LC_XMemI.cru (53) |
Regenerate with:
python tools/extract.py "...(Track 1 of 2)[!].iso" out/
python - <<'EOF'
import struct
d = open('out/Lx_ReloD.cru.bin', 'rb').read()
o, names = 0x1662, []
while True:
k = d.find(b'\x00', o)
if not d[o:k] or k - o > 16: break
names.append(d[o:k].decode()); o = k + 1
for r in range(12):
row = [struct.unpack_from('>H', d, 0x1AA6 + 2*(r*7+i))[0] for i in range(7)]
print(r, [names[v] if v != 0xFFFF else 'FFFF' for v in row])
EOF