Labyrinth of Galleria: The Moon Society

The main forum for Cheat Table database collections.


Moderator: Table Moderator

Post Reply
zhancc
Curious
Curious
Posts: 6
Joined: Mon Oct 20, 2025 6:09 am
Answers: 0
x 2

Labyrinth of Galleria: The Moon Society

Post by zhancc »

I've added some cheats based on the cheats on the following website.
https://fearlessrevolution.com/viewtopic.php?t=23502

・fixed the issue where the HP and DP cheats weren't working.
・Add the following cheats

  • Inventory Editor (Item / Soul Pact / Catalyst / Equip).
  • Max Soul Pact Stars when selected
  • Set Selected Item to 50
  • Set All Inventory Items to 50 (Exclude Valuables)
  • Mana & Silver Coin Editor
► Show Spoiler

You can extract the master data (CSV/TSV) from data.dat. This contains information useful for cheat analysis.

The game data isn't simply compressed into a ZIP file or folder;
it has a triple-layered structure: "proprietary archive structure" + "LZ4 compression" + "PhyreEngine binary container".
The method for obtaining it is described below.

Code: Select all

data.dat (Full Archive)
 │
 ├── [1. Header & Metadata Table] … File List, Placement Offset, Size
 │
 └── [2. YKCMP_V1 (LZ4 Compressed Data)]
       │
       ▼ (Decompress with lz4.dll)
       [3. .csv.phyre (Sony PhyreEngine Binary)]
             │
             ▼ (Header Removed & Raw Text Extracted)
             Actual Data CSV (TSV / Tab-Delimited Text)

Specific Extraction Procedure (4 Steps)

Step 1: Index Analysis of data.dat (Reading the Table of Contents)
The first 64 bytes of data.dat (header) contain the table of contents information for the entire archive.

  • Header Structure (64-bit Little Endian):

    • 0x08–0x0F: Total number of files (num_files)

    • 0x10–0x17: Start offset of the filename table (name_table_off)

    • 0x18–0x1F: Size of the filename table (name_table_sz)

    • 0x20–0x27: Start offset of the metadata table (meta_table_off)

  • Metadata Table:

    • Each entry consists of 48 bytes (8 bytes × 6 numbers), recording the "filename offset," "data storage offset," and "file size" for each file.

Step 2: Identify the Path to the Target CSV File
Expand the filename table and find the path where the game parameters are stored.

  • Internal path: data/win/bin/csv/ (Example: data/win/bin/csv/equip/equip_table.csv.phyre)

  • Exclude dialogue text (adv/) and UI data (ui/), and list master data (approximately 100 files) such as equipment, items, soul books, and catalysts.

Step 3: Data extraction and LZ4 decompression
Read the binary from data.dat based on the identified offset and size.

  • If the signature YKCMP_V1 is present near the beginning of the data (offset 0x0C to 0x14), it is LZ4 compressed data with Nippon Ichi Software's proprietary compression header.

  • Call lz4.dll located in the game's installation folder via Python's ctypes and decompress it into memory using the LZ4_decompress_safe function.

Step 4: Recovering the Raw CSV Text from the .phyre Container
The unzipped data is in a binary format (.phyre) specific to the game engine (Sony PhyreEngine).

  • A binary scan of the binary revealed that the tab-separated CSV body, written in UTF-8, is embedded directly after the internal path name (csv/.../*.csv).

  • By slicing from the first tab character (\t) immediately following the path to the terminating null byte (\x00\x00), the data was written to a file as a pure .csv (TSV format) text file.

The following is a Python script that combines the above steps into one:
Before use, please specify the data.dat, l4z.dll, and the output folder for multiple CSV files according to your environment.

Code: Select all

import struct, os, re, ctypes


dat_path = r"Please enter the path to the data.dat file located directly under the game folder."
lz4_dll = ctypes.cdll.LoadLibrary(r"Please enter the path to the lz4.dll file located directly under the game folder.")
out_dir = r"Please specify multiple output destinations for the CSV files."

# 1. ヘッダーとメタデータを読む (Read the header and metadata)
with open(dat_path, "rb") as f:
    hdr = f.read(64)
    num_files = struct.unpack("<Q", hdr[8:16])[0]
    name_table_off = struct.unpack("<Q", hdr[16:24])[0]
    name_table_sz = struct.unpack("<Q", hdr[24:32])[0]
    meta_table_off = struct.unpack("<Q", hdr[32:40])[0]

f.seek(name_table_off)
name_table = f.read(name_table_sz)

f.seek(meta_table_off)
meta_table = f.read(num_files * 48)

# 2. メタデータの対応付け(Metadata mapping)
name_to_meta = {}
for i in range(num_files):
    chunk = meta_table[i*48:(i+1)*48]
    vals = struct.unpack("<QQQQQQ", chunk)
    name_to_meta[vals[1]] = (vals[3], vals[4]) # (サイズ(size), オフセット(offset))

# 3. data/win/bin/csv/ 以下のファイルを対象にする(The files under data/win/bin/csv/ are targeted.)
prefix = b"data/win/bin/csv/"
with open(dat_path, "rb") as f:
    for n_pos, (sz, foff) in name_to_meta.items():
        null_idx = name_table.find(b"\x00", n_pos)
        fn_bytes = name_table[n_pos:null_idx]
        if not fn_bytes.startswith(prefix):
            continue

    rel_path = fn_bytes[len(prefix):].decode("ascii", errors="ignore")
    if rel_path.startswith("adv/") or rel_path.startswith("ui/"):
        continue

    # 4. 切り出し & LZ4 解凍(Cutting & LZ4 Defrosting)
    f.seek(foff)
    comp_data = f.read(sz)
    if comp_data[0x0C:0x14] == b"YKCMP_V1":
        uncomp_sz = struct.unpack("<I", comp_data[0x1C:0x20])[0]
        payload = comp_data[0x20:]
        dst = ctypes.create_string_buffer(uncomp_sz + 4096)
        ret = lz4_dll.LZ4_decompress_safe(payload, dst, len(payload), len(dst))
        data = dst.raw[:ret]
    else:
        data = comp_data

    # 5. .phyre 内から CSV テキスト領域を切り出して保存(Extract and save the CSV text area from within the .phyre file.)
    m = re.search(rb"csv/[a-zA-Z0-9_\-/]+\.csv", data)
    if m:
        null_pos = data.find(b"\x00", m.start())
        first_tab = data.find(b"\t", null_pos)
        text_start = data.rfind(b"\x00", null_pos, first_tab) + 1
        end_pos = data.find(b"\x00\x00", text_start)
        csv_bytes = data[text_start:end_pos if end_pos != -1 else len(data)]

        save_path = os.path.join(out_dir, rel_path.replace(".phyre", ""))
        os.makedirs(os.path.dirname(save_path), exist_ok=True)
        with open(save_path, "wb") as out:
            out.write(csv_bytes)
Attachments
Labyrinth_of_Galleria.CT
(334.97 KiB) Downloaded 1 time

Tags:

Post Reply