SL2 Analyzer
Read a FromSoftware .sl2 save and report what is in it
Loading...
Searching...
No Matches
sl2.ds1 Namespace Reference

Functions

 ds1_derived_stats (stats)
 DS1 base derived stats that are closed-form functions of attributes only.
 
 load_ds1_bonfires (base_dir)
 
 load_ds1_boss_flags (base_dir)
 
 ds1_attach_flags (ch, buf, base_dir, game)
 Merge DS1 boss-defeat FLAGS into ch["bosses"] as flag evidence.
 
 load_ds1_known_flags (base_dir)
 
 load_ds1_world_events (base_dir)
 
 ds1_bonfires (buf, db)
 DS1 bonfires the character has found, grouped by area.
 
 ds1_augment (ch, data, entries, i, base_dir, dec)
 DS1-only augment: attach the bonfire list, which needs the db folder the parse function never sees.
 
 ds1_resolve (item_db, cat, iid)
 Resolve a DS1 item id to a display name, unwrapping any upgrade baked in.
 
 dsr_find_anchor (buf)
 Find the true DSR stat anchor.
 
 ds1_inventory (buf, item_db)
 Sort the DS1 inventory into categories.
 
 ds1_deaths (buf, game)
 Total deaths for a DS1 slot, or None when the struct isn't where expected.
 
 ds1_attach_playtime (ch, menu)
 Attach play time from DS1's load-screen roster block.
 
 ds1_character (buf, item_db, m, game, ng)
 Build the unified full-tier dict from a located DS1 stat anchor.
 
 dsr_parse (buf, item_db)
 Parse one DSR slot into the unified dict (full tier), or None if empty.
 
 ptde_find_anchor (buf)
 Find the PtDE stat anchor (full tier).
 
 ptde_parse (buf, item_db)
 Parse one PtDE slot (full tier).
 

Variables

dict _DS1_BONFIRE_CACHE = {}
 Load the DS1 bonfire table (db_ds1/bonfires.json, NetBonfireDb id → [name, area]).
 
dict _DS1_BOSSFLAG_CACHE = {}
 Load the DS1 boss-defeat flag table (db_ds1/boss_flags.json, canonical boss name → [region byte offset, uint32 mask]).
 
dict DS1_FLAG_BASE = {"dsr": 127721, "ptde": 127273}
 Where the event-flag region starts in a decrypted DS1 slot, per game.
 
 DS1_FLAG_MAX_DENSITY
 Sanity gate on that base.
 
 DS1_FLAG_SPAN
 Sanity gate on that base.
 
dict _KNOWN_FLAG_CACHE = {}
 Load the DS1 world-state flag table (category → [[offset, mask, name]]).
 
dict _WORLD_EVENT_CACHE = {}
 Load the DS1 world-event table (family → [[offset, mask, Japanese name]]).
 
 DS1_BONFIRE_REC
 DS1 bonfire record: 20 bytes, id then state (the rest is unread flags).
 
 DS1_BONFIRE_STATE_D
 DS1 bonfire record: 20 bytes, id then state (the rest is unread flags).
 
dict DS1_BONFIRE_STATE
 The state values a real record can hold, and what each means.
 
int DS1_BONFIRE_MIN_RUN = 5
 Shortest believable run, so a stray id in unrelated data cannot pass.
 
 DSR_MAGIC = bytes.fromhex("00FFFFFFFF000000000000000000000000FFFFFFFF")
 Anchor pattern that sits next to the DSR character block.
 
 DSR_SOULS_D
 DSR field distances from the anchor.
 
 DSR_HP_D
 DSR field distances from the anchor.
 
 DSR_STAM_D
 DSR field distances from the anchor.
 
 DSR_LEVEL_D
 DSR field distances from the anchor.
 
 DSR_CLASS_D
 DSR field distances from the anchor.
 
 DSR_HUM_D
 DSR field distances from the anchor.
 
 DSR_NG_D
 
 DSR_NAME_D
 
int DSR_GENDER_D = -237
 Gender (u8) distance from the anchor.
 
dict DS1_GENDER = {0: "Female", 1: "Male"}
 DS1 gender enum.
 
dict DS1_DEATHS_OFF = {"ptde": 0x1F118, "dsr": 0x1F2D8}
 Total deaths (u32), at a slot-absolute offset per release rather than a distance from the moving anchor — the counter lives in a fixed struct near the event-flag region, not in the character block.
 
 DS1_DEATHS_SENTINEL
 
 DS1_DEATHS_SENTINEL_D
 
int DS1_MENU_ENTRY = 10
 DS1's load-screen roster lives in BND4 entry 10, one fixed record per slot: name at +0 (UTF-16), soul level at +36, play time at +40 as a uint32 of SECONDS.
 
 DS1_MENU_LEVEL_D
 
 DS1_MENU_PLAYTIME_D
 
int DS1_EQUIP_BASE = 40
 DS1 derived values that are pure functions of one attribute, so they can be computed exactly rather than guessed.
 
tuple DS1_SLOT_BREAKS = (10, 12, 14, 16, 19, 23, 28, 34, 41, 50)
 
 DSR_STAT_D
 DSR attribute distances from the anchor (uint8 each), in display order.
 
dict DS1_CLASS
 DS1 class ids to names.
 
dict DS1_CAT
 DS1 inventory slot type (top nibble) to category.
 
 DS1_INV_START
 Where the DS1 inventory scan begins, and the anchor that marks the first real slot.
 
 DS1_INV_ANCHOR
 Where the DS1 inventory scan begins, and the anchor that marks the first real slot.
 
 DS1_INV_END = bytes.fromhex("00000000FFFFFFFFFFFFFFFF")
 End-of-inventory marker.
 
dict DS1_INFUSION
 DS1 weapon infusion paths, keyed by the hundreds digit of the id's upgrade suffix (id = base + path*100 + level).
 

Detailed Description

Dark Souls 1 family: Remastered and Prepare to Die Edition.

Function Documentation

◆ ds1_derived_stats()

sl2.ds1.ds1_derived_stats (   stats)

DS1 base derived stats that are closed-form functions of attributes only.

Only the two the equipment screen shows that need no gear: base Equip Load (40 + Endurance — fextralife's table is dead linear, END 10 -> 50.0, 99 -> 139.0) and attunement slots (DS1_SLOT_BREAKS). Stamina and Max HP are read from the save, so they are not recomputed; poise comes from armour alone and item discovery needs covenant/gear, so neither is derived.

Parameters
statsThe attribute dict.

Definition at line 19 of file ds1.py.

◆ load_ds1_bonfires()

sl2.ds1.load_ds1_bonfires (   base_dir)

Definition at line 33 of file ds1.py.

Referenced by sl2.ds1.ds1_augment().

Here is the caller graph for this function:

◆ load_ds1_boss_flags()

sl2.ds1.load_ds1_boss_flags (   base_dir)

Definition at line 51 of file ds1.py.

◆ ds1_attach_flags()

sl2.ds1.ds1_attach_flags (   ch,
  buf,
  base_dir,
  game 
)

Merge DS1 boss-defeat FLAGS into ch["bosses"] as flag evidence.

Unlike the held-soul floor this sees a boss whose soul was long since consumed. Guarded twice: the region base must be known for the game, and the region must actually read sparse (DS1_FLAG_MAX_DENSITY) — a moved region fails that and nothing is reported. Boss names are canonicalised to the boss_souls.json spelling in the db, so a flag kill and a soul kill dedup onto one boss.

Definition at line 87 of file ds1.py.

References sl2.ds1.load_ds1_known_flags(), and sl2.ds1.load_ds1_world_events().

Referenced by sl2.ds1.ds1_augment().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ load_ds1_known_flags()

sl2.ds1.load_ds1_known_flags (   base_dir)

Definition at line 135 of file ds1.py.

Referenced by sl2.ds1.ds1_attach_flags().

Here is the caller graph for this function:

◆ load_ds1_world_events()

sl2.ds1.load_ds1_world_events (   base_dir)

Definition at line 156 of file ds1.py.

Referenced by sl2.ds1.ds1_attach_flags().

Here is the caller graph for this function:

◆ ds1_bonfires()

sl2.ds1.ds1_bonfires (   buf,
  db 
)

DS1 bonfires the character has found, grouped by area.

The list's offset moves between saves, so it is located BY CONTENT: the longest run of consecutive 20-byte records whose id is a real bonfire and whose state is one of DS1_BONFIRE_STATE, with no id repeating. Shared by DSR and PtDE — the layout is identical, only the decryption differs.

Returns
[(area, count, [names])] in the DS3 shape so it renders the same way, or None when no believable run exists.

Definition at line 196 of file ds1.py.

Referenced by sl2.ds1.ds1_augment().

Here is the caller graph for this function:

◆ ds1_augment()

sl2.ds1.ds1_augment (   ch,
  data,
  entries,
  i,
  base_dir,
  dec 
)

DS1-only augment: attach the bonfire list, which needs the db folder the parse function never sees.

Re-decrypts the slot rather than threading the buffer through, so the generic loop keeps its (ch, data, entries, i, base_dir) shape.

Parameters
decThe game's decrypt callable (DSR is encrypted, PtDE is not).

Definition at line 236 of file ds1.py.

References sl2.ds1.ds1_attach_flags(), sl2.ds1.ds1_attach_playtime(), sl2.ds1.ds1_bonfires(), and sl2.ds1.load_ds1_bonfires().

Here is the call graph for this function:

◆ ds1_resolve()

sl2.ds1.ds1_resolve (   item_db,
  cat,
  iid 
)

Resolve a DS1 item id to a display name, unwrapping any upgrade baked in.

Weapons and armour store their reinforcement — and, for weapons, their infusion — inside the id as base+path*100+level, where base ends in 000. A direct hit is tried first; failing that, the base is looked up and a "+N" (with the infusion name for weapons) suffix is appended. Rings and goods do not upgrade, so they only ever match directly.

Returns
The display name, or None if even the base is unknown.

Definition at line 400 of file ds1.py.

Referenced by sl2.ds1.ds1_inventory().

Here is the caller graph for this function:

◆ dsr_find_anchor()

sl2.ds1.dsr_find_anchor (   buf)

Find the true DSR stat anchor.

The magic pattern recurs inside runs of empty inventory slots, so a match is not enough — the right one is where the whole stat block also reads as plausible (level in range, every attribute 0..99). This is why a wrong anchor never slips through on an all-items save.

Parameters
bufThe decrypted slot data.
Returns
The anchor offset, or None if no sane one exists.

Definition at line 426 of file ds1.py.

Referenced by sl2.ds1.dsr_parse().

Here is the caller graph for this function:

◆ ds1_inventory()

sl2.ds1.ds1_inventory (   buf,
  item_db 
)

Sort the DS1 inventory into categories.

Shared by DSR and PtDE.

Returns
(buckets, unknown_count).

Definition at line 446 of file ds1.py.

References sl2.ds1.ds1_resolve().

Referenced by sl2.ds1.ds1_character().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ds1_deaths()

sl2.ds1.ds1_deaths (   buf,
  game 
)

Total deaths for a DS1 slot, or None when the struct isn't where expected.

Guarded by the sentinel that follows the counter in both releases: if the uint32 at +4 isn't 0xFFFFFFFF the struct has moved and the field is dropped rather than read from the wrong place.

Parameters
bufThe decrypted slot.
game"dsr" or "ptde".
Returns
The death count, or None.

Definition at line 481 of file ds1.py.

Referenced by sl2.ds1.ds1_character().

Here is the caller graph for this function:

◆ ds1_attach_playtime()

sl2.ds1.ds1_attach_playtime (   ch,
  menu 
)

Attach play time from DS1's load-screen roster block.

The roster record is found by the character's own name and accepted only when the level stored beside it matches the level already parsed from the slot, so a renamed/duplicate name or a shifted block turns the field off instead of attaching another character's clock.

Parameters
chThe parsed character (read for name/level, written for play_time).
menuThe decrypted menu block, or None.

Definition at line 498 of file ds1.py.

Referenced by sl2.ds1.ds1_augment().

Here is the caller graph for this function:

◆ ds1_character()

sl2.ds1.ds1_character (   buf,
  item_db,
  m,
  game,
  ng 
)

Build the unified full-tier dict from a located DS1 stat anchor.

Shared by DSR and PtDE: the two games carry the same stat block — same fields at the same signed distances from the same anchor point (proven by reading a real PtDE save byte-for-byte against the DSR distances). Only the way the anchor is found differs, and NG+ is DSR-file-specific, so the caller passes it (PtDE has no calibrated NG+ field and passes None).

Parameters
mThe stat anchor (a DSR-equivalent anchor position).
ngNew Game+ count, or None to omit the field.

Definition at line 519 of file ds1.py.

References sl2.ds1.ds1_deaths(), and sl2.ds1.ds1_inventory().

Referenced by sl2.ds1.dsr_parse(), and sl2.ds1.ptde_parse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ dsr_parse()

sl2.ds1.dsr_parse (   buf,
  item_db 
)

Parse one DSR slot into the unified dict (full tier), or None if empty.

Definition at line 547 of file ds1.py.

References sl2.ds1.ds1_character(), and sl2.ds1.dsr_find_anchor().

Here is the call graph for this function:

◆ ptde_find_anchor()

sl2.ds1.ptde_find_anchor (   buf)

Find the PtDE stat anchor (full tier).

PtDE has no DSR_MAGIC to key on, but its stat block is laid out exactly like DSR's around the character name. So the name is the anchor: for each position that decodes as a valid name, treat it as DSR's name field, back out the equivalent anchor, and accept it only if the whole stat block there also reads sane (level in range, every attribute 0..99). Requiring a valid name and a valid stat block is what stops a false match inside the repeating inventory runs of an all-items save — the real block sits before the inventory, so the first such match from the top is the character.

Returns
The anchor offset, or None if no sane one exists.

Definition at line 565 of file ds1.py.

Referenced by sl2.ds1.ptde_parse().

Here is the caller graph for this function:

◆ ptde_parse()

sl2.ds1.ptde_parse (   buf,
  item_db 
)

Parse one PtDE slot (full tier).

Unencrypted DS1. Same stat layout as DSR (see ds1_character), found via the name anchor. NG+ is not calibrated for PtDE, so it is omitted.

Definition at line 587 of file ds1.py.

References sl2.ds1.ds1_character(), and sl2.ds1.ptde_find_anchor().

Here is the call graph for this function:

Variable Documentation

◆ _DS1_BONFIRE_CACHE

dict sl2.ds1._DS1_BONFIRE_CACHE = {}
protected

Load the DS1 bonfire table (db_ds1/bonfires.json, NetBonfireDb id → [name, area]).

Cached. Returns {} if absent.

Definition at line 30 of file ds1.py.

◆ _DS1_BOSSFLAG_CACHE

dict sl2.ds1._DS1_BOSSFLAG_CACHE = {}
protected

Load the DS1 boss-defeat flag table (db_ds1/boss_flags.json, canonical boss name → [region byte offset, uint32 mask]).

Cached. Returns {} if absent.

Definition at line 48 of file ds1.py.

◆ DS1_FLAG_BASE

dict sl2.ds1.DS1_FLAG_BASE = {"dsr": 127721, "ptde": 127273}

Where the event-flag region starts in a decrypted DS1 slot, per game.

The published DS1 flag addressing (group base + area*0x500 + section*128 + number/8, MSB-first mask) gives offsets INSIDE the region; the region's own position is not published, so it was searched for. In the DSR mule — an NG+2 character with all 43 bonfires — exactly ONE offset in the whole 393216-byte slot has all twelve boss flags and both Bells of Awakening set, and both PtDE saves independently agree on their own single value, so the base is a per-game constant rather than a per-save search.

Definition at line 70 of file ds1.py.

◆ DS1_FLAG_MAX_DENSITY

sl2.ds1.DS1_FLAG_MAX_DENSITY

Sanity gate on that base.

A real flag region is overwhelmingly zero — it measures ~0.006 set bits at the true base against ~0.32 for ordinary save data — so anything denser than this means the region moved and the feature turns itself off rather than reporting bosses off the wrong bytes.

Definition at line 77 of file ds1.py.

◆ DS1_FLAG_SPAN

sl2.ds1.DS1_FLAG_SPAN

Sanity gate on that base.

A real flag region is overwhelmingly zero — it measures ~0.006 set bits at the true base against ~0.32 for ordinary save data — so anything denser than this means the region moved and the feature turns itself off rather than reporting bosses off the wrong bytes.

Definition at line 77 of file ds1.py.

◆ _KNOWN_FLAG_CACHE

dict sl2.ds1._KNOWN_FLAG_CACHE = {}
protected

Load the DS1 world-state flag table (category → [[offset, mask, name]]).

Generated by tools/gen_ds1_known_flags.py, whose id→(offset, mask) function reproduces all twelve hand-checked entries of boss_flags.json exactly — which is why these 44 are trusted without each being verified on its own. Cached per dir.

Definition at line 132 of file ds1.py.

◆ _WORLD_EVENT_CACHE

dict sl2.ds1._WORLD_EVENT_CACHE = {}
protected

Load the DS1 world-event table (family → [[offset, mask, Japanese name]]).

Generated by tools/gen_ds1_world_events.py from the committed .emevd plus FromSoft's own .emeld event names. Every row is derived and none is verified against a save here — it decodes and it discriminates, and that is all that is claimed. Read the generator before believing a family name: Levers reads 0 on a finished run and Boss-fight flags counts flags rather than bosses. Cached per dir.

Definition at line 153 of file ds1.py.

◆ DS1_BONFIRE_REC

sl2.ds1.DS1_BONFIRE_REC

DS1 bonfire record: 20 bytes, id then state (the rest is unread flags).

Unlike DS2 and DS3, DS1 does NOT keep bonfires as event flags — they are a NetBonfireDb list of {id, state} records, so this walks records rather than bits.

Definition at line 170 of file ds1.py.

◆ DS1_BONFIRE_STATE_D

sl2.ds1.DS1_BONFIRE_STATE_D

DS1 bonfire record: 20 bytes, id then state (the rest is unread flags).

Unlike DS2 and DS3, DS1 does NOT keep bonfires as event flags — they are a NetBonfireDb list of {id, state} records, so this walks records rather than bits.

Definition at line 170 of file ds1.py.

◆ DS1_BONFIRE_STATE

dict sl2.ds1.DS1_BONFIRE_STATE
Initial value:
1= {
2 0: "discovered",
3 10: "lit",
4 20: "kindled +1",
5 30: "kindled +2",
6 40: "kindled +3",
7}

The state values a real record can hold, and what each means.

Anything else ends the walk, which is what keeps a misaligned start from inventing bonfires.

Definition at line 175 of file ds1.py.

◆ DS1_BONFIRE_MIN_RUN

int sl2.ds1.DS1_BONFIRE_MIN_RUN = 5

Shortest believable run, so a stray id in unrelated data cannot pass.

Definition at line 185 of file ds1.py.

◆ DSR_MAGIC

sl2.ds1.DSR_MAGIC = bytes.fromhex("00FFFFFFFF000000000000000000000000FFFFFFFF")

Anchor pattern that sits next to the DSR character block.

Stats are read at signed distances from wherever this is found.

Definition at line 258 of file ds1.py.

◆ DSR_SOULS_D

sl2.ds1.DSR_SOULS_D

DSR field distances from the anchor.

Definition at line 262 of file ds1.py.

◆ DSR_HP_D

sl2.ds1.DSR_HP_D

DSR field distances from the anchor.

Definition at line 262 of file ds1.py.

◆ DSR_STAM_D

sl2.ds1.DSR_STAM_D

DSR field distances from the anchor.

Definition at line 262 of file ds1.py.

◆ DSR_LEVEL_D

sl2.ds1.DSR_LEVEL_D

DSR field distances from the anchor.

Definition at line 262 of file ds1.py.

◆ DSR_CLASS_D

sl2.ds1.DSR_CLASS_D

DSR field distances from the anchor.

Definition at line 262 of file ds1.py.

◆ DSR_HUM_D

sl2.ds1.DSR_HUM_D

DSR field distances from the anchor.

Definition at line 262 of file ds1.py.

◆ DSR_NG_D

sl2.ds1.DSR_NG_D

Definition at line 272 of file ds1.py.

◆ DSR_NAME_D

sl2.ds1.DSR_NAME_D

Definition at line 272 of file ds1.py.

◆ DSR_GENDER_D

int sl2.ds1.DSR_GENDER_D = -237

Gender (u8) distance from the anchor.

Two independent sources agree, which is what makes this shippable without a differential save: alfizari's DSR editor puts Gender at magic-237, and tarvitz/dsfp (a PtDE parser) has a boolean male field 34 bytes past the name — the same byte, since the name sits at magic-271. Both call 1 Male, so DS1's polarity is the OPPOSITE of DS2's (where 1 is Female). Cross-read on a real save: dsfp's frame and ours both report male=1 for the same character.

Definition at line 281 of file ds1.py.

◆ DS1_GENDER

dict sl2.ds1.DS1_GENDER = {0: "Female", 1: "Male"}

DS1 gender enum.

Note the inverted polarity against DS2_GENDER.

Definition at line 285 of file ds1.py.

◆ DS1_DEATHS_OFF

dict sl2.ds1.DS1_DEATHS_OFF = {"ptde": 0x1F118, "dsr": 0x1F2D8}

Total deaths (u32), at a slot-absolute offset per release rather than a distance from the moving anchor — the counter lives in a fixed struct near the event-flag region, not in the character block.

PtDE's offset is dsfp's (0x1F128 in its frame, which is 16 bytes ahead of ours), verified on two real saves: an all-items mule reads 459 and a real playthrough reads 39. DSR shifts this struct by the same 448 bytes its event-flag region moves (see DS1_FLAG_BASE), and the neighbouring fields confirm it: both releases read [deaths][0xFFFFFFFF][~1.5M][2048] in that order. DS1_DEATHS_SENTINEL is checked before the value is used, so a moved struct omits the field instead of printing whatever is there.

Definition at line 297 of file ds1.py.

◆ DS1_DEATHS_SENTINEL

sl2.ds1.DS1_DEATHS_SENTINEL

Definition at line 300 of file ds1.py.

◆ DS1_DEATHS_SENTINEL_D

sl2.ds1.DS1_DEATHS_SENTINEL_D

Definition at line 300 of file ds1.py.

◆ DS1_MENU_ENTRY

int sl2.ds1.DS1_MENU_ENTRY = 10

DS1's load-screen roster lives in BND4 entry 10, one fixed record per slot: name at +0 (UTF-16), soul level at +36, play time at +40 as a uint32 of SECONDS.

dsfp documents the 0x170 record stride, which its own play-time constant confirms (its file-absolute index minus the record base is exactly this +40). The block's start differs between the releases, so the record is located by the character's own name and only accepted when the level at +36 matches the level parsed from the slot — a self-consistency gate, the same trick DS3's equip slots use. Verified on three saves: 25:16:39 at level 95 (DSR), 19:25:30 at 81 (PtDE), 151h on a mule.

Definition at line 311 of file ds1.py.

◆ DS1_MENU_LEVEL_D

sl2.ds1.DS1_MENU_LEVEL_D

Definition at line 314 of file ds1.py.

◆ DS1_MENU_PLAYTIME_D

sl2.ds1.DS1_MENU_PLAYTIME_D

Definition at line 314 of file ds1.py.

◆ DS1_EQUIP_BASE

int sl2.ds1.DS1_EQUIP_BASE = 40

DS1 derived values that are pure functions of one attribute, so they can be computed exactly rather than guessed.

Equip Load is 40 + Endurance (fextralife's table: END 10 -> 50.0, 40 -> 80.0, 99 -> 139.0, dead linear with base 40). Attunement slots are the documented breakpoints, 10 slots max at 50. Stamina and HP are NOT computed — DS1 stores both in the save, so they are read. Poise is armour- only and everything else is gear-scaled, so nothing else is derived.

Definition at line 323 of file ds1.py.

◆ DS1_SLOT_BREAKS

tuple sl2.ds1.DS1_SLOT_BREAKS = (10, 12, 14, 16, 19, 23, 28, 34, 41, 50)

Definition at line 326 of file ds1.py.

◆ DSR_STAT_D

sl2.ds1.DSR_STAT_D
Initial value:
1= OrderedDict(
2 [
3 ("Vitality", -375),
4 ("Attunement", -367),
5 ("Endurance", -359),
6 ("Strength", -351),
7 ("Dexterity", -343),
8 ("Resistance", -303),
9 ("Intelligence", -335),
10 ("Faith", -327),
11 ]
12)

DSR attribute distances from the anchor (uint8 each), in display order.

Definition at line 330 of file ds1.py.

◆ DS1_CLASS

dict sl2.ds1.DS1_CLASS
Initial value:
1= {
2 0: "Warrior",
3 1: "Knight",
4 2: "Wanderer",
5 3: "Thief",
6 4: "Bandit",
7 5: "Hunter",
8 6: "Sorcerer",
9 7: "Pyromancer",
10 8: "Cleric",
11 9: "Deprived",
12}

DS1 class ids to names.

Definition at line 345 of file ds1.py.

◆ DS1_CAT

dict sl2.ds1.DS1_CAT
Initial value:
1= {
2 0x00000000: "weapons",
3 0x10000000: "armors",
4 0x20000000: "rings",
5 0x40000000: "goods",
6}

DS1 inventory slot type (top nibble) to category.

Definition at line 360 of file ds1.py.

◆ DS1_INV_START

sl2.ds1.DS1_INV_START

Where the DS1 inventory scan begins, and the anchor that marks the first real slot.

Definition at line 370 of file ds1.py.

◆ DS1_INV_ANCHOR

sl2.ds1.DS1_INV_ANCHOR

Where the DS1 inventory scan begins, and the anchor that marks the first real slot.

Definition at line 370 of file ds1.py.

◆ DS1_INV_END

sl2.ds1.DS1_INV_END = bytes.fromhex("00000000FFFFFFFFFFFFFFFF")

End-of-inventory marker.

Definition at line 374 of file ds1.py.

◆ DS1_INFUSION

dict sl2.ds1.DS1_INFUSION
Initial value:
1= {
2 1: "Crystal",
3 2: "Lightning",
4 3: "Raw",
5 4: "Magic",
6 5: "Enchanted",
7 6: "Divine",
8 7: "Occult",
9 8: "Fire",
10 9: "Chaos",
11}

DS1 weapon infusion paths, keyed by the hundreds digit of the id's upgrade suffix (id = base + path*100 + level).

Path 0 is plain reinforcement.

Definition at line 379 of file ds1.py.