Skip to content

Help wanted: macOS field-name/order dump (two text files, script provided — not the game binary) #363

Description

@AgentKush

What I need: two small text files from anyone who owns Crimson Desert on macOS. A script is provided; it takes a minute to run.

What I do NOT need, and please don't send: the game binary itself, or any game files. That would be redistributing a commercial game, which I'm not asking anyone to do. The script reads your own installed copy and writes out a list of field names — a few tens of KB of text.


Why

I've been decoding Crimson Desert's .pabgb data tables so CDUMM can read and edit more of them. Current state on the Windows build, all verified by exact tiling on 100% of each table's records through CDUMM's own walker:

  • 7 → 46 tables proven byte-exact (61,111 records)
  • five wrong layouts found and retracted, ten bugs fixed in the derivation itself

The method recovers each table's field order from the game's own Korean error strings — <Class>의 _<field>를 읽어들이는데 실패했다 ("Failed to read _<field> of <Class>") — ordered by the code that references them.

The wall I've hit is that the Windows build doesn't name every field. Measured, not guessed:

table records error strings in the exe body fields those cover
actionpointinfo 28,958 5 (2 are header fields) 3, for a 232-byte record
conditioninfo 10,529 6 4, and the record is variable-length
itemuseinfo 9,756 4 2, for a 29–65 byte record

ItemInfo has 115 strings for 113 known fields, so it's fine — but a table with 3 named fields covering 232 bytes cannot be completed from strings that don't exist. About 38 tables / ~62,000 records are blocked behind some version of this.

What the macOS build gives that Windows doesn't

Two separate things, and I want both:

  1. Read order. The same Korean strings exist on Windows (I count 516 classes / 4,421 field references), but they're pointer-referenced from descriptor structs, so the string table alone isn't ordered — on macOS they're reported to sit in the exact order fields are read. That's fields.json below.
  2. The names Windows never emits. The macOS binary is reported to be unstripped. Its symbol table may name the fields that have no error string on either platform — which is the actual blocker for actionpointinfo and friends. That's symbols.txt below.

If you'd rather not run anything, even just confirming whether the macOS binary is genuinely unstripped (nm -a <binary> | head) is useful.

How to help

You need the game installed on macOS. The binary is usually at:

~/Library/Application Support/Steam/steamapps/common/Crimson Desert/CrimsonDesert.app/Contents/MacOS/

1. Save this as extract_cd_fields.py:

#!/usr/bin/env python3
"""Extract Crimson Desert per-class field names from a game binary.

Reads ONLY your own installed copy and writes a JSON list of identifiers.
It does not copy, modify or redistribute any game data.
"""
import json, re, sys
from pathlib import Path

# "<Class>의 _<field>를"  --  의 = EC 9D 98, 를 = EB A5 BC in UTF-8.
PATTERN = re.compile(
    rb"([A-Za-z_][A-Za-z0-9_]{2,63})\xec\x9d\x98 "
    rb"(_[A-Za-z0-9_]{1,63})\xeb\xa5\xbc "
)

def main(argv):
    if len(argv) != 2:
        print(__doc__, file=sys.stderr); return 2
    p = Path(argv[1])
    if not p.is_file():
        print(f"not a file: {p}", file=sys.stderr); return 2
    data = p.read_bytes()
    order = [(m.start(), m.group(1).decode("ascii", "replace"),
              m.group(2).decode("ascii", "replace"))
             for m in PATTERN.finditer(data)]
    by_cls = {}
    for _off, cls, fld in order:
        f = by_cls.setdefault(cls, [])
        if fld not in f:
            f.append(fld)
    json.dump({"source_file": p.name, "source_size": len(data),
               "total_matches": len(order), "classes": len(by_cls),
               "fields_in_file_order": {c: f for c, f in sorted(by_cls.items())},
               "raw_order_sample": [{"offset": o, "class": c, "field": f}
                                    for o, c, f in order[:40]]},
              sys.stdout, indent=1, ensure_ascii=False)
    sys.stdout.write("\n")
    print(f"\n{len(by_cls)} classes, {len(order)} field references",
          file=sys.stderr)
    return 0

if __name__ == "__main__":
    raise SystemExit(main(sys.argv))

2. Run both commands (adjust the binary name — it's something like CrimsonDesert_Steam-*):

cd ~/Library/Application\ Support/Steam/steamapps/common/Crimson\ Desert/CrimsonDesert.app/Contents/MacOS
python3 /path/to/extract_cd_fields.py ./CrimsonDesert_Steam-* > ~/Desktop/cd_macos_fields.json
nm -a ./CrimsonDesert_Steam-* > ~/Desktop/cd_macos_symbols.txt

3. Share the two filescd_macos_fields.json and cd_macos_symbols.txt. Either attach them to this issue, or drop them here:

https://drive.google.com/drive/folders/1kkmG3JlAqPaoQHVeayAtZiDVtDB-kDcP?usp=drive_link

symbols.txt may be large-ish; gzip it if so. Again: text output only, not the binary.

The script is tested

I ran it against the Windows exe, where the same strings exist, and it returns 516 classes / 4,421 field references — so it works before it reaches your machine. It's standard library only, opens the file read-only, and writes nothing.

Sanity numbers from the Windows run, so you can compare what you get:

ItemInfo            115 fields
MaterialMatchInfo     8
ConditionInfo         6
ActionPointInfo       5     <- the problem table: 5 strings, 232-byte record

What happens to it

I can check any submission before trusting it, which is the part that makes this worth doing. There are 46 tables whose layout is already proven byte-exact, so a submitted field order has to reproduce all 46 or it gets rejected — the same gate everything else here goes through. If it passes, it unlocks the tables that are currently unreachable, and nothing gets shipped on the strength of "someone sent me a file".

Windows work continues in the meantime; this is a parallel ask, not a blocker.

Happy to answer questions if any of the above is unclear, and thanks in advance to anyone who has the game on a Mac.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions