SL2 Analyzer
Read a FromSoftware .sl2 save and report what is in it
Loading...
Searching...
No Matches
roster.py
Go to the documentation of this file.
1"""The header roster block: character names, and DS3's play-time field."""
2
3from .keys import DS3_KEY
4from .reader import read_utf16, u8
5
6## @brief Header-entry index, occupancy-flag offset, first-descriptor offset,
7# descriptor stride, and max name length, per game.
8ROSTER_PARAMS = {
9 "ds3": {
10 "menu": 10,
11 "occ": 4244,
12 "desc": 4254,
13 "stride": 554,
14 "namelen": 16,
15 "decrypt": DS3_KEY,
16 },
17 "er": {
18 "menu": 10,
19 "occ": 6484,
20 "desc": 6494,
21 "stride": 588,
22 "namelen": 16,
23 "decrypt": None,
24 },
25}
26
27
28##
29# @brief Read the character roster from a DS3 or ER header entry.
30# @details These games keep a load-screen table of ten slots — an occupancy byte
31# each, then fixed-stride descriptors that begin with the character name. That
32# name is trustworthy; the deeper stat and inventory blocks are not mapped in
33# this build, so only the roster is returned.
34# @param menu_data The decrypted header entry.
35# @param game @c "ds3" or @c "er".
36# @return A list of @c (slot_index, name).
37def parse_roster(menu_data, game):
38 p = ROSTER_PARAMS[game]
39 roster = []
40 for i in range(10):
41 occ = u8(menu_data, p["occ"] + i)
42 if not occ:
43 continue
44 name = read_utf16(menu_data, p["desc"] + p["stride"] * i, p["namelen"])
45 roster.append((i, name if name else "(unnamed)"))
46 return roster