Commit 3409b841c6efce52121c2976f90c03836ede3a2a

Authored by Imanol-Mikel Barba Sabariego
1 parent 67c0083b

Added all the TODOs needed up to item code. Modified a bunch of functions to be …

…safer and do more sanity checks

Too many changes to show.

To preserve performance only 18 of 23 files are displayed.

TODO 0 → 100644
  1 +// TODO: Error codes
  2 +// TODO: Func documentation
0 \ No newline at end of file 3 \ No newline at end of file
d2char.c
@@ -28,19 +28,35 @@ int isHardcore(D2CharHeader* c) { @@ -28,19 +28,35 @@ int isHardcore(D2CharHeader* c) {
28 return c->charStatus & D2S_CHARSTATUS_HARDCORE; 28 return c->charStatus & D2S_CHARSTATUS_HARDCORE;
29 } 29 }
30 30
  31 +void setHardcore(D2CharHeader* c) {
  32 +
  33 +}
  34 +
31 int hasDied(D2CharHeader* c) { 35 int hasDied(D2CharHeader* c) {
32 return c->charStatus & D2S_CHARSTATUS_DIED; 36 return c->charStatus & D2S_CHARSTATUS_DIED;
33 } 37 }
34 38
  39 +void setDied(D2CharHeader* c) {
  40 +
  41 +}
  42 +
35 int isExpansion(D2CharHeader* c) { 43 int isExpansion(D2CharHeader* c) {
36 return c->charStatus & D2S_CHARSTATUS_EXPANSION; 44 return c->charStatus & D2S_CHARSTATUS_EXPANSION;
37 } 45 }
38 46
  47 +void setExpansion(D2CharHeader* c) {
  48 +
  49 +}
  50 +
39 int isLadder(D2CharHeader* c) { 51 int isLadder(D2CharHeader* c) {
40 return c->charStatus & D2S_CHARSTATUS_LADDER; 52 return c->charStatus & D2S_CHARSTATUS_LADDER;
41 } 53 }
42 54
43 -int getCurrentAct(D2CharHeader* c) { 55 +void setLadder(D2CharHeader* c) {
  56 +
  57 +}
  58 +
  59 +D2S_ACT getCurrentAct(D2CharHeader* c) {
44 if(isExpansion(c)) { 60 if(isExpansion(c)) {
45 return c->charProgress % 5; 61 return c->charProgress % 5;
46 } else { 62 } else {
@@ -135,15 +151,7 @@ size_t getLastPlayed(D2CharHeader* c, char* buf, size_t bufLen) { @@ -135,15 +151,7 @@ size_t getLastPlayed(D2CharHeader* c, char* buf, size_t bufLen) {
135 return ret; 151 return ret;
136 } 152 }
137 153
138 -const char* getSkillName(int skillID) {  
139 - if(skillID > D2S_SKILL_NUMSKILLS) {  
140 - fprintf(stderr,"libd2char error: skillID %d doesn't exist\n",skillID);  
141 - return NULL;  
142 - }  
143 - return skills[skillID];  
144 -}  
145 -  
146 -int getCurrentDifficulty(D2CharHeader* c) { 154 +D2S_DIFFICULTY getCurrentDifficulty(D2CharHeader* c) {
147 for(int i = D2S_DIFFICULTY_NORMAL; i <= D2S_DIFFICULTY_HELL; ++i) { 155 for(int i = D2S_DIFFICULTY_NORMAL; i <= D2S_DIFFICULTY_HELL; ++i) {
148 if(c->difficulty[i] & D2S_DIFFICULTY_ACTIVE) { 156 if(c->difficulty[i] & D2S_DIFFICULTY_ACTIVE) {
149 return i; 157 return i;
@@ -152,10 +160,18 @@ int getCurrentDifficulty(D2CharHeader* c) { @@ -152,10 +160,18 @@ int getCurrentDifficulty(D2CharHeader* c) {
152 return D2S_DIFFICULTY_UNKNOWN; 160 return D2S_DIFFICULTY_UNKNOWN;
153 } 161 }
154 162
155 -const char* getMercName(D2CharHeader* c) {  
156 - return _getMercName(c->mercenaryType, c->mercenaryNameID); 163 +int setProgress(D2S_ACT act, D2S_DIFFICULTY difficulty) {
  164 + // TODO
  165 + // set c->difficulty and c->progress?
  166 + return 0;
  167 +}
  168 +
  169 +int getAttribute(D2S_STAT attr) {
  170 + // TODO
  171 + return 0;
157 } 172 }
158 173
159 -const char* getMercType(D2CharHeader* c) {  
160 - return mercTypes[c->mercenaryType]; 174 +int setAttribute(D2S_STAT attr, unsigned int value) {
  175 + // TODO
  176 + return 0;
161 } 177 }
162 \ No newline at end of file 178 \ No newline at end of file
d2char.h
@@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
8 8
9 #include "d2quest.h" 9 #include "d2quest.h"
10 #include "d2strings.h" 10 #include "d2strings.h"
  11 +#include "d2waypoints.h"
11 12
12 #define D2S_HEADER_LENGTH 765 13 #define D2S_HEADER_LENGTH 765
13 #define D2S_SIGNATURE 0xAA55AA55 14 #define D2S_SIGNATURE 0xAA55AA55
@@ -26,21 +27,24 @@ @@ -26,21 +27,24 @@
26 #define D2S_CHARSTATUS_LADDER 0x40 27 #define D2S_CHARSTATUS_LADDER 0x40
27 28
28 #define D2S_DIFFICULTY_ACTIVE 0x80 29 #define D2S_DIFFICULTY_ACTIVE 0x80
29 -#define D2S_DIFFICULTY_NORMAL 0  
30 -#define D2S_DIFFICULTY_NIGHTMARE 1  
31 -#define D2S_DIFFICULTY_HELL 2  
32 -#define D2S_DIFFICULTY_UNKNOWN -1  
33 30
34 -enum D2S_VERSION { 31 +typedef enum D2S_DIFFICULTY {
  32 + D2S_DIFFICULTY_UNKNOWN = -1,
  33 + D2S_DIFFICULTY_NORMAL = 0,
  34 + D2S_DIFFICULTY_NIGHTMARE = 1,
  35 + D2S_DIFFICULTY_HELL = 2
  36 +} D2S_DIFFICULTY;
  37 +
  38 +typedef enum D2S_VERSION {
35 VER_106 = 71, 39 VER_106 = 71,
36 VER_107 = 87, 40 VER_107 = 87,
37 VER_108XP = 87, 41 VER_108XP = 87,
38 VER_108 = 89, 42 VER_108 = 89,
39 VER_109 = 92, 43 VER_109 = 92,
40 VER_110 = 96 44 VER_110 = 96
41 -}; 45 +} D2S_VERSION;
42 46
43 -enum D2S_CHARCLASS { 47 +typedef enum D2S_CHARCLASS {
44 D2S_CHARCLASS_AMAZON = 0, 48 D2S_CHARCLASS_AMAZON = 0,
45 D2S_CHARCLASS_SORCERESS = 1, 49 D2S_CHARCLASS_SORCERESS = 1,
46 D2S_CHARCLASS_NECROMANCER = 2, 50 D2S_CHARCLASS_NECROMANCER = 2,
@@ -48,15 +52,34 @@ enum D2S_CHARCLASS { @@ -48,15 +52,34 @@ enum D2S_CHARCLASS {
48 D2S_CHARCLASS_BARBARIAN = 4, 52 D2S_CHARCLASS_BARBARIAN = 4,
49 D2S_CHARCLASS_DRUID = 5, 53 D2S_CHARCLASS_DRUID = 5,
50 D2S_CHARCLASS_ASSASSIN = 6 54 D2S_CHARCLASS_ASSASSIN = 6
51 -};  
52 -  
53 -enum D2S_ACT { 55 +} D2S_CHARCLASS;
  56 +
  57 +typedef enum D2S_STAT {
  58 + D2S_STAT_STRENGTH = 0x00,
  59 + D2S_STAT_ENERGY = 0x01,
  60 + D2S_STAT_DEXTERITY = 0x02,
  61 + D2S_STAT_VITALITY = 0x03,
  62 + D2S_STAT_STATPTS = 0x04,
  63 + D2S_STAT_SKILLPTS = 0x05,
  64 + D2S_STAT_LIFE = 0x06,
  65 + D2S_STAT_MAXLIFE = 0x07,
  66 + D2S_STAT_MANA = 0x08,
  67 + D2S_STAT_MAXMANA = 0x09,
  68 + D2S_STAT_STAMINA = 0x0a,
  69 + D2S_STAT_MAXSTAMINA = 0x0b,
  70 + D2S_STAT_LEVEL = 0x0c,
  71 + D2S_STAT_EXPERIENCE = 0x0d,
  72 + D2S_STAT_GOLD = 0x0e,
  73 + D2S_STAT_GOLDSTASH = 0x0f,
  74 +} D2S_STAT;
  75 +
  76 +typedef enum D2S_ACT {
54 D2S_ACT1 = 0, 77 D2S_ACT1 = 0,
55 D2S_ACT2, 78 D2S_ACT2,
56 D2S_ACT3, 79 D2S_ACT3,
57 D2S_ACT4, 80 D2S_ACT4,
58 D2S_ACT5 81 D2S_ACT5
59 -}; 82 +} D2S_ACT;
60 83
61 // TODO: Add file hex offsets for each field 84 // TODO: Add file hex offsets for each field
62 typedef struct __attribute__((packed)){ 85 typedef struct __attribute__((packed)){
@@ -91,12 +114,14 @@ typedef struct __attribute__((packed)){ @@ -91,12 +114,14 @@ typedef struct __attribute__((packed)){
91 uint32_t mercenaryExp; 114 uint32_t mercenaryExp;
92 uint8_t unknown6[144]; // TODO 115 uint8_t unknown6[144]; // TODO
93 D2QuestData questData; 116 D2QuestData questData;
94 - uint8_t waypointData[D2S_WAYPOINTS_LENGTH]; 117 + D2WaypointsData waypointsData;
95 uint8_t unknown7; // TODO. Apparently this is always 0x01 118 uint8_t unknown7; // TODO. Apparently this is always 0x01
96 uint8_t NPCIntroductions[D2S_NPCDATA_LENGTH]; // TODO: Not implemented 119 uint8_t NPCIntroductions[D2S_NPCDATA_LENGTH]; // TODO: Not implemented
  120 + // TODO Add stats
  121 + // TODO Add skills
97 } D2CharHeader; 122 } D2CharHeader;
98 123
99 -// TODO: All setX functions 124 +
100 125
101 // TODO: Load from file. 126 // TODO: Load from file.
102 // int loadD2CharFromFile(const char* file, D2CharHeader** header, void** data); 127 // int loadD2CharFromFile(const char* file, D2CharHeader** header, void** data);
@@ -107,12 +132,16 @@ typedef struct __attribute__((packed)){ @@ -107,12 +132,16 @@ typedef struct __attribute__((packed)){
107 uint32_t calcChecksum(D2CharHeader* c, void* charData); 132 uint32_t calcChecksum(D2CharHeader* c, void* charData);
108 int checkChecksum(D2CharHeader* c, void* charData); 133 int checkChecksum(D2CharHeader* c, void* charData);
109 int isHardcore(D2CharHeader* c); 134 int isHardcore(D2CharHeader* c);
  135 +void setHardcore(D2CharHeader* c);
110 int hasDied(D2CharHeader* c); 136 int hasDied(D2CharHeader* c);
  137 +void setDied(D2CharHeader* c);
111 int isExpansion(D2CharHeader* c); 138 int isExpansion(D2CharHeader* c);
  139 +void setExpansion(D2CharHeader* c);
112 int isLadder(D2CharHeader* c); 140 int isLadder(D2CharHeader* c);
  141 +void setLadder(D2CharHeader* c);
113 142
114 // 0 = Act I, 4 = Act V (Expansion) 143 // 0 = Act I, 4 = Act V (Expansion)
115 -int getCurrentAct(D2CharHeader* c); 144 +D2S_ACT getCurrentAct(D2CharHeader* c);
116 145
117 int isFemale(D2CharHeader* c); 146 int isFemale(D2CharHeader* c);
118 147
@@ -122,16 +151,12 @@ const char* getCharacterTitle(D2CharHeader* c); @@ -122,16 +151,12 @@ const char* getCharacterTitle(D2CharHeader* c);
122 // Writes to user-allocated string. Format is default locale's time representation 151 // Writes to user-allocated string. Format is default locale's time representation
123 size_t getLastPlayed(D2CharHeader* c, char* buf, size_t bufLen); 152 size_t getLastPlayed(D2CharHeader* c, char* buf, size_t bufLen);
124 153
125 -// Returns static string from library memory, no need to free  
126 -const char* getSkillName(int skillID);  
127 -  
128 // 0 = Normal, 2 = Hell 154 // 0 = Normal, 2 = Hell
129 -int getCurrentDifficulty(D2CharHeader* c); 155 +D2S_DIFFICULTY getCurrentDifficulty(D2CharHeader* c);
130 156
131 -// Returns static string from library memory, no need to free  
132 -const char* getMercName(D2CharHeader* c); 157 +int setProgress(D2S_ACT act, D2S_DIFFICULTY difficulty);
133 158
134 -// Returns static string from library memory, no need to free  
135 -const char* getMercType(D2CharHeader* c); 159 +int getAttribute(D2S_STAT attr);
  160 +int setAttribute(D2S_STAT attr, unsigned int value);
136 161
137 #endif 162 #endif
138 \ No newline at end of file 163 \ No newline at end of file
d2mercs.c
1 #include "d2mercs.h" 1 #include "d2mercs.h"
2 2
  3 +#include <stdio.h>
3 #include <stdlib.h> 4 #include <stdlib.h>
4 5
5 -int _getMercType(int mercID) { 6 +const char* getMercName(uint16_t mercID, uint16_t mercNameID) {
  7 + int offset = getMercType(mercID);
  8 + if(offset == D2S_MERCTYPE_UNKNOWN) {
  9 + fprintf(stderr,"libd2char error: Unable to retrieve name for mercID %d, mercNameID %d\n",mercID, mercNameID);
  10 + return NULL;
  11 + }
  12 + return mercNames[mercNameID + offset];
  13 +}
  14 +
  15 +D2S_MERCTYPE getMercType(uint16_t mercID) {
6 if(mercID >= 0 && mercID <= 5) { 16 if(mercID >= 0 && mercID <= 5) {
7 return D2S_MERCTYPE_ROGUE; 17 return D2S_MERCTYPE_ROGUE;
8 } else if(mercID >= 6 && mercID <= 14) { 18 } else if(mercID >= 6 && mercID <= 14) {
@@ -16,10 +26,14 @@ int _getMercType(int mercID) { @@ -16,10 +26,14 @@ int _getMercType(int mercID) {
16 } 26 }
17 } 27 }
18 28
19 -const char* _getMercName(int mercID, int mercNameID) {  
20 - int offset = _getMercType(mercID);  
21 - if(offset == D2S_MERCTYPE_UNKNOWN) {  
22 - return NULL;  
23 - }  
24 - return mercNames[mercNameID + offset]; 29 +D2S_MERCSUBTYPE getMercSubType(uint16_t mercID) {
  30 + // TODO
  31 +}
  32 +
  33 +D2S_DIFFICULTY getMercDifficulty(uint16_t mercID) {
  34 + // TODO
  35 +}
  36 +
  37 +int setMerc(D2S_MERCTYPE type, D2S_MERCSUBTYPE subtype, D2S_DIFFICULTY difficulty) {
  38 + // TODO
25 } 39 }
26 \ No newline at end of file 40 \ No newline at end of file
d2mercs.h
1 #ifndef D2MERCS_H 1 #ifndef D2MERCS_H
2 #define D2MERCS_H 2 #define D2MERCS_H
3 3
  4 +#include "d2char.h"
4 #include "d2strings.h" 5 #include "d2strings.h"
5 6
6 -// TODO: return compound data (type, subtype, difficulty, not just a string)  
7 -  
8 // The values here are the offsets of each merc's names in the table. 7 // The values here are the offsets of each merc's names in the table.
9 // i.e: Merc names from pos 41 to 61 are Desert mercs 8 // i.e: Merc names from pos 41 to 61 are Desert mercs
10 // 9 //
11 // We use these values as offsets later to get the correct name using the relative ID the game provides 10 // We use these values as offsets later to get the correct name using the relative ID the game provides
12 -enum D2S_MERCTYPES { 11 +typedef enum D2S_MERCTYPE {
13 D2S_MERCTYPE_UNKNOWN = -1, 12 D2S_MERCTYPE_UNKNOWN = -1,
14 D2S_MERCTYPE_ROGUE = 0, 13 D2S_MERCTYPE_ROGUE = 0,
15 D2S_MERCTYPE_DESERT = 41, 14 D2S_MERCTYPE_DESERT = 41,
16 D2S_MERCTYPE_SORCEROR = 62, 15 D2S_MERCTYPE_SORCEROR = 62,
17 D2S_MERCTYPE_BARBARIAN = 82 16 D2S_MERCTYPE_BARBARIAN = 82
18 -}; 17 +} D2S_MERCTYPE;
19 18
20 -const char* const mercTypes[] = {  
21 - D2S_MERC_ID_0,  
22 - D2S_MERC_ID_1,  
23 - D2S_MERC_ID_2,  
24 - D2S_MERC_ID_3,  
25 - D2S_MERC_ID_4,  
26 - D2S_MERC_ID_5,  
27 - D2S_MERC_ID_6,  
28 - D2S_MERC_ID_7,  
29 - D2S_MERC_ID_8,  
30 - D2S_MERC_ID_9,  
31 - D2S_MERC_ID_10,  
32 - D2S_MERC_ID_11,  
33 - D2S_MERC_ID_12,  
34 - D2S_MERC_ID_13,  
35 - D2S_MERC_ID_14,  
36 - D2S_MERC_ID_15,  
37 - D2S_MERC_ID_16,  
38 - D2S_MERC_ID_17,  
39 - D2S_MERC_ID_18,  
40 - D2S_MERC_ID_19,  
41 - D2S_MERC_ID_20,  
42 - D2S_MERC_ID_21,  
43 - D2S_MERC_ID_22,  
44 - D2S_MERC_ID_23,  
45 - D2S_MERC_ID_24,  
46 - D2S_MERC_ID_25,  
47 - D2S_MERC_ID_26,  
48 - D2S_MERC_ID_27,  
49 - D2S_MERC_ID_28,  
50 - D2S_MERC_ID_29  
51 -}; 19 +typedef enum D2S_MERCSUBTYPE {
  20 + D2S_MERCSUBTYPE_NONE = 0,
  21 + D2S_MERCSUBTYPE_FIRE_ARROW = 1,
  22 + D2S_MERCSUBTYPE_COLD_ARROW = 2,
  23 + D2S_MERCSUBTYPE_COMBAT = 3,
  24 + D2S_MERCSUBTYPE_DEFENSIVE = 4,
  25 + D2S_MERCSUBTYPE_OFFENSIVE = 5,
  26 + D2S_MERCSUBTYPE_FIRE = 6,
  27 + D2S_MERCSUBTYPE_COLD = 7,
  28 + D2S_MERCSUBTYPE_LIGHTNING = 8
  29 +} D2S_MERCSUBTYPE;
52 30
53 const char* const mercNames[] = { 31 const char* const mercNames[] = {
54 D2S_MERC_NAME_0, 32 D2S_MERC_NAME_0,
@@ -202,7 +180,12 @@ const char* const mercNames[] = { @@ -202,7 +180,12 @@ const char* const mercNames[] = {
202 D2S_MERC_NAME_148 180 D2S_MERC_NAME_148
203 }; 181 };
204 182
205 -int _getMercType(int mercID);  
206 -const char* _getMercName(int mercID, int mercNameID); 183 +// Returns static string from library memory, no need to free
  184 +const char* getMercName(uint16_t mercID, uint16_t mercNameID);
  185 +
  186 +D2S_MERCTYPE getMercType(uint16_t mercID);
  187 +D2S_MERCSUBTYPE getMercSubType(uint16_t mercID);
  188 +D2S_DIFFICULTY getMercDifficulty(uint16_t mercID);
  189 +int setMerc(D2S_MERCTYPE type, D2S_MERCSUBTYPE subtype, D2S_DIFFICULTY difficulty);
207 190
208 #endif 191 #endif
209 \ No newline at end of file 192 \ No newline at end of file
d2quest.c
@@ -3,31 +3,43 @@ @@ -3,31 +3,43 @@
3 3
4 #include <stdio.h> 4 #include <stdio.h>
5 5
6 -void getCheckpointDescriptions(unsigned int quest, const char* *descriptions[16]) { 6 +const char* getQuestName(D2S_QUEST quest) {
7 if(quest > D2S_QUESTDATA_NUMQUESTS) { 7 if(quest > D2S_QUESTDATA_NUMQUESTS) {
8 fprintf(stderr,"libd2char error: quest %d doesn't exist\n",quest); 8 fprintf(stderr,"libd2char error: quest %d doesn't exist\n",quest);
9 - return; 9 + return NULL;
  10 + }
  11 + return questName[quest];
  12 +}
  13 +
  14 +int getCheckpointDescriptions(D2S_QUEST quest, const char* *descriptions[16]) {
  15 + if(quest > D2S_QUESTDATA_NUMQUESTS) {
  16 + fprintf(stderr,"libd2char error: quest %d doesn't exist\n",quest);
  17 + return -1;
10 } 18 }
11 memcpy(descriptions,(&checkpointDescriptions) + (quest * 16 * sizeof(const char*)), 16 * sizeof(const char*)); 19 memcpy(descriptions,(&checkpointDescriptions) + (quest * 16 * sizeof(const char*)), 16 * sizeof(const char*));
12 } 20 }
13 21
14 -uint16_t getQuestStatus(D2QuestData* d, unsigned int quest, unsigned int difficulty) { 22 +int getQuestStatus(D2QuestData* d, D2S_QUEST quest, D2S_DIFFICULTY difficulty, uint16_t* data) {
  23 + // TODO sanity check diff and quest
15 if(quest >= D2S_QUEST_DEN_OF_EVIL && quest <= D2S_QUEST_SISTERS_TO_THE_SLAUGHTER) { 24 if(quest >= D2S_QUEST_DEN_OF_EVIL && quest <= D2S_QUEST_SISTERS_TO_THE_SLAUGHTER) {
16 - return d->quests[difficulty].actData[D2S_ACT1].questCheckpoints[quest]; 25 + *data = d->quests[difficulty].actData[D2S_ACT1].questCheckpoints[quest];
17 } else if(quest >= D2S_QUEST_RADAMENT_LAIR && quest <= D2S_QUEST_SEVEN_TOMBS) { 26 } else if(quest >= D2S_QUEST_RADAMENT_LAIR && quest <= D2S_QUEST_SEVEN_TOMBS) {
18 - return d->quests[difficulty].actData[D2S_ACT2].questCheckpoints[quest - D2S_QUEST_RADAMENT_LAIR]; 27 + *data = d->quests[difficulty].actData[D2S_ACT2].questCheckpoints[quest - D2S_QUEST_RADAMENT_LAIR];
19 } else if(quest >= D2S_QUEST_GOLDEN_BIRD && quest <= D2S_QUEST_GUARDIAN) { 28 } else if(quest >= D2S_QUEST_GOLDEN_BIRD && quest <= D2S_QUEST_GUARDIAN) {
20 - return d->quests[difficulty].actData[D2S_ACT3].questCheckpoints[quest - D2S_QUEST_GOLDEN_BIRD]; 29 + *data = d->quests[difficulty].actData[D2S_ACT3].questCheckpoints[quest - D2S_QUEST_GOLDEN_BIRD];
21 } else if(quest >= D2S_QUEST_FALLEN_ANGEL && quest <= D2S_QUEST_TERROR_END) { 30 } else if(quest >= D2S_QUEST_FALLEN_ANGEL && quest <= D2S_QUEST_TERROR_END) {
22 - return d->quests[difficulty].actData[D2S_ACT4].questCheckpoints[quest - D2S_QUEST_FALLEN_ANGEL]; 31 + *data = d->quests[difficulty].actData[D2S_ACT4].questCheckpoints[quest - D2S_QUEST_FALLEN_ANGEL];
23 } else if(quest >= D2S_QUEST_SIEGE_ON_HARROGATH && quest <= D2S_QUEST_EVE_OF_DESTRUCTION) { 32 } else if(quest >= D2S_QUEST_SIEGE_ON_HARROGATH && quest <= D2S_QUEST_EVE_OF_DESTRUCTION) {
24 - return d->quests[difficulty].expansionAct.questCheckpoints[quest - D2S_QUEST_SIEGE_ON_HARROGATH]; 33 + *data = d->quests[difficulty].expansionAct.questCheckpoints[quest - D2S_QUEST_SIEGE_ON_HARROGATH];
  34 + } else {
  35 + fprintf(stderr,"libd2char error: quest %d doesn't exist\n",quest);
  36 + return -1;
25 } 37 }
26 - fprintf(stderr,"libd2char error: quest %d doesn't exist\n",quest);  
27 return 0; 38 return 0;
28 } 39 }
29 40
30 -void setQuestStatus(D2QuestData* d, unsigned int quest, unsigned int difficulty, uint16_t questData) { 41 +int setQuestStatus(D2QuestData* d, D2S_QUEST quest, D2S_DIFFICULTY difficulty, uint16_t questData) {
  42 + // TODO sanity check diff and quest
31 if(quest >= D2S_QUEST_DEN_OF_EVIL && quest <= D2S_QUEST_SISTERS_TO_THE_SLAUGHTER) { 43 if(quest >= D2S_QUEST_DEN_OF_EVIL && quest <= D2S_QUEST_SISTERS_TO_THE_SLAUGHTER) {
32 d->quests[difficulty].actData[D2S_ACT1].questCheckpoints[quest] = questData; 44 d->quests[difficulty].actData[D2S_ACT1].questCheckpoints[quest] = questData;
33 } else if(quest >= D2S_QUEST_RADAMENT_LAIR && quest <= D2S_QUEST_SEVEN_TOMBS) { 45 } else if(quest >= D2S_QUEST_RADAMENT_LAIR && quest <= D2S_QUEST_SEVEN_TOMBS) {
@@ -40,51 +52,76 @@ void setQuestStatus(D2QuestData* d, unsigned int quest, unsigned int difficulty, @@ -40,51 +52,76 @@ void setQuestStatus(D2QuestData* d, unsigned int quest, unsigned int difficulty,
40 d->quests[difficulty].expansionAct.questCheckpoints[quest - D2S_QUEST_SIEGE_ON_HARROGATH] = questData; 52 d->quests[difficulty].expansionAct.questCheckpoints[quest - D2S_QUEST_SIEGE_ON_HARROGATH] = questData;
41 } else { 53 } else {
42 fprintf(stderr,"libd2char error: quest %d doesn't exist\n",quest); 54 fprintf(stderr,"libd2char error: quest %d doesn't exist\n",quest);
  55 + return -1;
43 } 56 }
  57 + return 0;
44 } 58 }
45 59
46 -int isQuestStarted(D2QuestData* d, unsigned int quest, unsigned int difficulty) {  
47 - return getQuestStatus(d,quest,difficulty) & D2S_QUEST_STATUS_STARTED; 60 +int isQuestStarted(D2QuestData* d, D2S_QUEST quest, D2S_DIFFICULTY difficulty) {
  61 + uint16_t data = 0;
  62 + if(getQuestStatus(d,quest,difficulty,&data) < 0) {
  63 + return -1;
  64 + }
  65 + return data & D2S_QUEST_STATUS_STARTED;
48 } 66 }
49 67
50 -int isQuestRewardCollected(D2QuestData* d, unsigned int quest, unsigned int difficulty) {  
51 - return !(getQuestStatus(d,quest,difficulty) & D2S_QUEST_STATUS_REWARD_AVAILABLE); 68 +int isQuestRewardCollected(D2QuestData* d, D2S_QUEST quest, D2S_DIFFICULTY difficulty) {
  69 + uint16_t data = 0;
  70 + if(getQuestStatus(d,quest,difficulty,&data) < 0) {
  71 + return -1;
  72 + }
  73 + return data & D2S_QUEST_STATUS_REWARD_AVAILABLE;
52 } 74 }
53 75
54 -int isQuestCompleted(D2QuestData* d, unsigned int quest, unsigned int difficulty) {  
55 - return getQuestStatus(d,quest,difficulty) & D2S_QUEST_STATUS_COMPLETED; 76 +int isQuestCompleted(D2QuestData* d, D2S_QUEST quest, D2S_DIFFICULTY difficulty) {
  77 + uint16_t data = 0;
  78 + if(getQuestStatus(d,quest,difficulty,&data) < 0) {
  79 + return -1;
  80 + }
  81 + return data & D2S_QUEST_STATUS_COMPLETED;
56 } 82 }
57 83
58 -void setQuestStarted(D2QuestData* d, unsigned int quest, unsigned int difficulty, int bool) { 84 +int setQuestStarted(D2QuestData* d, D2S_QUEST quest, D2S_DIFFICULTY difficulty, int bool) {
59 // To reset the quest, just zero out the whole thing 85 // To reset the quest, just zero out the whole thing
60 // To set as started, just set bit 2 and clear the rest 86 // To set as started, just set bit 2 and clear the rest
61 - uint16_t questData = getQuestStatus(d,quest,difficulty); 87 + uint16_t questData = 0;
  88 + if(getQuestStatus(d,quest,difficulty,&questData) < 0) {
  89 + return -1;
  90 + }
62 if(bool) { 91 if(bool) {
63 questData = D2S_QUEST_STATUS_STARTED; 92 questData = D2S_QUEST_STATUS_STARTED;
64 } else { 93 } else {
65 questData = 0x0000; 94 questData = 0x0000;
66 } 95 }
67 - setQuestStatus(d,quest,difficulty,questData); 96 + return setQuestStatus(d,quest,difficulty,questData);
68 } 97 }
69 98
70 -void setQuestRewardCollected(D2QuestData* d, unsigned int quest, unsigned int difficulty, int bool) { 99 +int setQuestRewardCollected(D2QuestData* d, D2S_QUEST quest, D2S_DIFFICULTY difficulty, int bool) {
71 // To reset, just clear bit 0 and set bit 1. 100 // To reset, just clear bit 0 and set bit 1.
72 // Do the inverse to set reward as collected (but why whould you tho???) 101 // Do the inverse to set reward as collected (but why whould you tho???)
73 if(bool) { 102 if(bool) {
74 - setQuestCompleted(d,quest,difficulty,1); 103 + return setQuestCompleted(d,quest,difficulty,1);
75 } else { 104 } else {
76 - setQuestCompleted(d,quest,difficulty,0);  
77 - uint16_t questData = getQuestStatus(d,quest,difficulty); 105 + if(setQuestCompleted(d,quest,difficulty,0) < 0) {
  106 + return -1;
  107 + }
  108 + uint16_t questData;
  109 + if(getQuestStatus(d,quest,difficulty,&questData) < 0) {
  110 + return -1;
  111 + }
78 questData |= D2S_QUEST_STATUS_REWARD_AVAILABLE; 112 questData |= D2S_QUEST_STATUS_REWARD_AVAILABLE;
79 - setQuestStatus(d,quest,difficulty,questData); 113 + return setQuestStatus(d,quest,difficulty,questData);
80 } 114 }
81 } 115 }
82 116
83 -void setQuestCompleted(D2QuestData* d, unsigned int quest, unsigned int difficulty, int bool) { 117 +int setQuestCompleted(D2QuestData* d, D2S_QUEST quest, D2S_DIFFICULTY difficulty, int bool) {
84 // To reset, clear bit 0, bit 12 and bit 13 (13 is kinda optional since it will be cleared by 118 // To reset, clear bit 0, bit 12 and bit 13 (13 is kinda optional since it will be cleared by
85 // the game when loading the savegame). 119 // the game when loading the savegame).
86 // To set as completed, just set bit 0 and bit 12 and clear bit 1 120 // To set as completed, just set bit 0 and bit 12 and clear bit 1
87 - uint16_t questData = getQuestStatus(d,quest,difficulty); 121 + uint16_t questData;
  122 + if(getQuestStatus(d,quest,difficulty,&questData) < 0) {
  123 + return -1;
  124 + }
88 if(bool) { 125 if(bool) {
89 questData &= ~D2S_QUEST_STATUS_REWARD_AVAILABLE; 126 questData &= ~D2S_QUEST_STATUS_REWARD_AVAILABLE;
90 questData |= D2S_QUEST_STATUS_COMPLETED; 127 questData |= D2S_QUEST_STATUS_COMPLETED;
@@ -93,10 +130,10 @@ void setQuestCompleted(D2QuestData* d, unsigned int quest, unsigned int difficul @@ -93,10 +130,10 @@ void setQuestCompleted(D2QuestData* d, unsigned int quest, unsigned int difficul
93 questData &= ~D2S_QUEST_STATUS_COMPLETED; 130 questData &= ~D2S_QUEST_STATUS_COMPLETED;
94 questData &= ~D2S_QUEST_STATUS_SEEN_FINISH_ANIMATION; 131 questData &= ~D2S_QUEST_STATUS_SEEN_FINISH_ANIMATION;
95 } 132 }
96 - setQuestStatus(d,quest,difficulty,questData); 133 + return setQuestStatus(d,quest,difficulty,questData);
97 } 134 }
98 135
99 -int getSpecialQuestStatus(D2QuestData* d, unsigned int specialQuestState, unsigned int difficulty) { 136 +int getSpecialQuestStatus(D2QuestData* d, unsigned int specialQuestState, D2S_DIFFICULTY difficulty) {
100 int ret = 0; 137 int ret = 0;
101 switch(specialQuestState) { 138 switch(specialQuestState) {
102 case D2S_SPECIALQUEST_AKARA_RESPEC: 139 case D2S_SPECIALQUEST_AKARA_RESPEC:
@@ -106,7 +143,7 @@ int getSpecialQuestStatus(D2QuestData* d, unsigned int specialQuestState, unsign @@ -106,7 +143,7 @@ int getSpecialQuestStatus(D2QuestData* d, unsigned int specialQuestState, unsign
106 return ret; 143 return ret;
107 } 144 }
108 145
109 -void setSpecialQuestStatus(D2QuestData* d, unsigned int specialQuestState, unsigned int difficulty, int bool) { 146 +int setSpecialQuestStatus(D2QuestData* d, unsigned int specialQuestState, D2S_DIFFICULTY difficulty, int bool) {
110 if(difficulty != D2S_DIFFICULTY_NORMAL || 147 if(difficulty != D2S_DIFFICULTY_NORMAL ||
111 difficulty != D2S_DIFFICULTY_NIGHTMARE || 148 difficulty != D2S_DIFFICULTY_NIGHTMARE ||
112 difficulty != D2S_DIFFICULTY_HELL) { 149 difficulty != D2S_DIFFICULTY_HELL) {
d2quest.h
1 #ifndef D2QUEST_H 1 #ifndef D2QUEST_H
2 #define D2QUEST_H 2 #define D2QUEST_H
3 3
  4 +// Forward declaration
  5 +typedef enum D2S_DIFFICULTY D2S_DIFFICULTY;
  6 +
4 #include <stdint.h> 7 #include <stdint.h>
5 8
  9 +#include "d2char.h"
6 #include "d2strings.h" 10 #include "d2strings.h"
7 11
8 #define D2S_QUESTDATA_HEADER_LENGTH 4 12 #define D2S_QUESTDATA_HEADER_LENGTH 4
9 #define D2S_QUESTDATA_NUMQUESTS 27 13 #define D2S_QUESTDATA_NUMQUESTS 27
10 14
11 -enum D2S_QUEST { 15 +typedef enum D2S_QUEST {
12 D2S_QUEST_UNKNOWN = -1, 16 D2S_QUEST_UNKNOWN = -1,
13 D2S_QUEST_DEN_OF_EVIL = 0, 17 D2S_QUEST_DEN_OF_EVIL = 0,
14 D2S_QUEST_SISTER_BURIAL_GROUNDS, 18 D2S_QUEST_SISTER_BURIAL_GROUNDS,
@@ -37,6 +41,10 @@ enum D2S_QUEST { @@ -37,6 +41,10 @@ enum D2S_QUEST {
37 D2S_QUEST_BETRAYAL_OF_HARROGATH, 41 D2S_QUEST_BETRAYAL_OF_HARROGATH,
38 D2S_QUEST_RITE_OF_PASSAGE, 42 D2S_QUEST_RITE_OF_PASSAGE,
39 D2S_QUEST_EVE_OF_DESTRUCTION 43 D2S_QUEST_EVE_OF_DESTRUCTION
  44 +} D2S_QUEST;
  45 +
  46 +const char* const questName[] = {
  47 +
40 }; 48 };
41 49
42 enum D2S_QUEST_STATUS { 50 enum D2S_QUEST_STATUS {
@@ -47,9 +55,9 @@ enum D2S_QUEST_STATUS { @@ -47,9 +55,9 @@ enum D2S_QUEST_STATUS {
47 D2S_QUEST_STATUS_JUST_FINISHED = 0x2000 55 D2S_QUEST_STATUS_JUST_FINISHED = 0x2000
48 }; 56 };
49 57
50 -enum D2S_SPECIALQUEST { 58 +typedef enum D2S_SPECIALQUEST {
51 D2S_SPECIALQUEST_AKARA_RESPEC 59 D2S_SPECIALQUEST_AKARA_RESPEC
52 -}; 60 +} D2S_SPECIALQUEST;
53 61
54 const char* const checkpointDescriptions[] = { 62 const char* const checkpointDescriptions[] = {
55 D2S_QUEST_CHECKPOINT_0, 63 D2S_QUEST_CHECKPOINT_0,
@@ -306,8 +314,6 @@ const char* const checkpointDescriptions[] = { @@ -306,8 +314,6 @@ const char* const checkpointDescriptions[] = {
306 D2S_QUEST_CHECKPOINT_251, 314 D2S_QUEST_CHECKPOINT_251,
307 D2S_QUEST_CHECKPOINT_252, 315 D2S_QUEST_CHECKPOINT_252,
308 D2S_QUEST_CHECKPOINT_253, 316 D2S_QUEST_CHECKPOINT_253,
309 - D2S_QUEST_CHECKPOINT_254,  
310 - D2S_QUEST_CHECKPOINT_255,  
311 D2S_QUEST_CHECKPOINT_256, 317 D2S_QUEST_CHECKPOINT_256,
312 D2S_QUEST_CHECKPOINT_257, 318 D2S_QUEST_CHECKPOINT_257,
313 D2S_QUEST_CHECKPOINT_258, 319 D2S_QUEST_CHECKPOINT_258,
@@ -515,34 +521,35 @@ typedef struct __attribute__((packed)) { @@ -515,34 +521,35 @@ typedef struct __attribute__((packed)) {
515 D2Quests quests[3]; // 1 set for each difficulty 521 D2Quests quests[3]; // 1 set for each difficulty
516 } D2QuestData; 522 } D2QuestData;
517 523
518 -// TODO: These functions are completely unsafe, and don't return success 524 +// Returns static string from library memory, no need to free
  525 +const char* getQuestName(D2S_QUEST quest);
519 526
520 // Populates `descriptions` with static strings from library memory, no need to free. 527 // Populates `descriptions` with static strings from library memory, no need to free.
521 // `descriptions` contains one string for each bit field of the quest's uint16_t data. 528 // `descriptions` contains one string for each bit field of the quest's uint16_t data.
522 // Empty entries (non-existant or unknown checkpoints) will have NULL value. Be careful! 529 // Empty entries (non-existant or unknown checkpoints) will have NULL value. Be careful!
523 -void getCheckpointDescriptions(unsigned int quest, const char* *descriptions[16]); 530 +int getCheckpointDescriptions(D2S_QUEST quest, const char* *descriptions[16]);
524 531
525 // Returns quest status for the specified quest and act. 532 // Returns quest status for the specified quest and act.
526 -uint16_t getQuestStatus(D2QuestData* d, unsigned int quest, unsigned int difficulty);  
527 -void setQuestStatus(D2QuestData* d, unsigned int quest, unsigned int difficulty, uint16_t questData); 533 +int getQuestStatus(D2QuestData* d, D2S_QUEST quest, D2S_DIFFICULTY difficulty, uint16_t* data);
  534 +int setQuestStatus(D2QuestData* d, D2S_QUEST quest, D2S_DIFFICULTY difficulty, uint16_t questData);
528 535
529 -int isQuestStarted(D2QuestData* d, unsigned int quest, unsigned int difficulty);  
530 -int isQuestRewardCollected(D2QuestData* d, unsigned int quest, unsigned int difficulty);  
531 -int isQuestCompleted(D2QuestData* d, unsigned int quest, unsigned int difficulty); 536 +int isQuestStarted(D2QuestData* d, D2S_QUEST quest, D2S_DIFFICULTY difficulty);
  537 +int isQuestRewardCollected(D2QuestData* d, D2S_QUEST quest, D2S_DIFFICULTY difficulty);
  538 +int isQuestCompleted(D2QuestData* d, D2S_QUEST quest, D2S_DIFFICULTY difficulty);
532 539
533 // Set bool to 1 to set the status or 0 to remove it 540 // Set bool to 1 to set the status or 0 to remove it
534 -void setQuestStarted(D2QuestData* d, unsigned int quest, unsigned int difficulty, int bool);  
535 -void setQuestRewardCollected(D2QuestData* d, unsigned int quest, unsigned int difficulty, int bool); 541 +int setQuestStarted(D2QuestData* d, D2S_QUEST quest, D2S_DIFFICULTY difficulty, int bool);
  542 +int setQuestRewardCollected(D2QuestData* d, D2S_QUEST quest, D2S_DIFFICULTY difficulty, int bool);
536 543
537 // When called to set the request to NOT completed (`bool` = 0), this will NOT set the reward collected status 544 // When called to set the request to NOT completed (`bool` = 0), this will NOT set the reward collected status
538 // which *may* render the quest unobtainable, this is done in case we may want to further modify the quest state. 545 // which *may* render the quest unobtainable, this is done in case we may want to further modify the quest state.
539 // If you want to mark the quest as not completed just to get the reward, please use `setQuestRewardCollected(,,0)` 546 // If you want to mark the quest as not completed just to get the reward, please use `setQuestRewardCollected(,,0)`
540 // instead. 547 // instead.
541 -void setQuestCompleted(D2QuestData* d, unsigned int quest, unsigned int difficulty, int bool); 548 +int setQuestCompleted(D2QuestData* d, D2S_QUEST quest, D2S_DIFFICULTY difficulty, int bool);
542 549
543 // Some quests have extra fields outside their quest data that govern certain states of the quest 550 // Some quests have extra fields outside their quest data that govern certain states of the quest
544 // So far, I only know of the respec that Akara offers when clearing Den of Evil 551 // So far, I only know of the respec that Akara offers when clearing Den of Evil
545 -int getSpecialQuestStatus(D2QuestData* d, unsigned int specialQuestState, unsigned int difficulty);  
546 -void setSpecialQuestStatus(D2QuestData* d, unsigned int specialQuestState, unsigned int difficulty, int bool); 552 +int getSpecialQuestStatus(D2QuestData* d, D2S_SPECIALQUEST specialQuestState, D2S_DIFFICULTY difficulty);
  553 +int setSpecialQuestStatus(D2QuestData* d, D2S_SPECIALQUEST specialQuestState, D2S_DIFFICULTY difficulty, int bool);
547 554
548 #endif 555 #endif
549 \ No newline at end of file 556 \ No newline at end of file
d2skills.c 0 → 100644
  1 +#include "d2char.h"
  2 +#include "d2skills.h"
  3 +
  4 +#include <stdio.h>
  5 +#include <stdlib.h>
  6 +
  7 +D2S_CHARCLASS getSkillClass(D2S_SKILL skillID) {
  8 + // TODO
  9 +}
  10 +
  11 +const char* getSkillName(D2S_SKILL skillID) {
  12 + if(skillID > D2S_SKILL_NUMSKILLS) {
  13 + fprintf(stderr,"libd2char error: skillID %d doesn't exist\n",skillID);
  14 + return NULL;
  15 + }
  16 + return skills[skillID];
  17 +}
0 \ No newline at end of file 18 \ No newline at end of file
d2skills.h
@@ -7,6 +7,9 @@ @@ -7,6 +7,9 @@
7 7
8 #define D2S_SKILL_NUMSKILLS 357 8 #define D2S_SKILL_NUMSKILLS 357
9 9
  10 +// TODO skill class trees
  11 +typedef int D2S_SKILL;
  12 +
10 const char* const skills[] = { 13 const char* const skills[] = {
11 D2S_SKILL_0, 14 D2S_SKILL_0,
12 D2S_SKILL_1, 15 D2S_SKILL_1,
@@ -367,4 +370,8 @@ const char* const skills[] = { @@ -367,4 +370,8 @@ const char* const skills[] = {
367 D2S_SKILL_356 370 D2S_SKILL_356
368 }; 371 };
369 372
  373 +// Returns static string from library memory, no need to free
  374 +const char* getSkillName(D2S_SKILL skillID);
  375 +D2S_CHARCLASS getSkillClass(D2S_SKILL skillID);
  376 +
370 #endif 377 #endif
371 \ No newline at end of file 378 \ No newline at end of file
d2strings.h
@@ -534,37 +534,6 @@ const char* D2S_CHARPROGRESS_EXPANSION_TIER3_NAME_HARDCORE = &quot;Guardian&quot;; @@ -534,37 +534,6 @@ const char* D2S_CHARPROGRESS_EXPANSION_TIER3_NAME_HARDCORE = &quot;Guardian&quot;;
534 #define D2S_MERC_NAME_147 "Bill" 534 #define D2S_MERC_NAME_147 "Bill"
535 #define D2S_MERC_NAME_148 "Theodoric" 535 #define D2S_MERC_NAME_148 "Theodoric"
536 536
537 -#define D2S_MERC_ID_0 "Rogue Scout Fire Arrow [Normal"  
538 -#define D2S_MERC_ID_1 "Rogue Scout Cold Arrow [Normal"  
539 -#define D2S_MERC_ID_2 "Rogue Scout Fire Arrow [Nightmare]"  
540 -#define D2S_MERC_ID_3 "Rogue Scout Cold Arrow [Nightmare]"  
541 -#define D2S_MERC_ID_4 "Rogue Scout Fire Arrow [Hell]"  
542 -#define D2S_MERC_ID_5 "Rogue Scout Cold Arrow [Hell]"  
543 -#define D2S_MERC_ID_6 "Desert Mercenary Combat [Normal]"  
544 -#define D2S_MERC_ID_7 "Desert Mercenary Defensive [Normal]"  
545 -#define D2S_MERC_ID_8 "Desert Mercenary Offensive [Normal]"  
546 -#define D2S_MERC_ID_9 "Desert Mercenary Combat [Nightmare]"  
547 -#define D2S_MERC_ID_10 "Desert Mercenary Defensive [Nightmare]"  
548 -#define D2S_MERC_ID_11 "Desert Mercenary Offensive [Nightmare]"  
549 -#define D2S_MERC_ID_12 "Desert Mercenary Combat [Hell]"  
550 -#define D2S_MERC_ID_13 "Desert Mercenary Defensive [Hell]"  
551 -#define D2S_MERC_ID_14 "Desert Mercenary Offensive [Hell]"  
552 -#define D2S_MERC_ID_15 "Eastern Sorceror Fire Spells [Normal]"  
553 -#define D2S_MERC_ID_16 "Eastern Sorceror Cold Spells [Normal]"  
554 -#define D2S_MERC_ID_17 "Eastern Sorceror Lightning Spells [Normal]"  
555 -#define D2S_MERC_ID_18 "Eastern Sorceror Fire Spells [Nightmare]"  
556 -#define D2S_MERC_ID_19 "Eastern Sorceror Cold Spells [Nightmare]"  
557 -#define D2S_MERC_ID_20 "Eastern Sorceror Lightning Spells [Nightmare]"  
558 -#define D2S_MERC_ID_21 "Eastern Sorceror Fire Spells [Hell]"  
559 -#define D2S_MERC_ID_22 "Eastern Sorceror Cold Spells [Hell]"  
560 -#define D2S_MERC_ID_23 "Eastern Sorceror Lightning Spells [Hell]"  
561 -#define D2S_MERC_ID_24 "Barbarian [Normal]"  
562 -#define D2S_MERC_ID_25 "Barbarian [Normal]"  
563 -#define D2S_MERC_ID_26 "Barbarian [Nightmare]"  
564 -#define D2S_MERC_ID_27 "Barbarian [Nightmare]"  
565 -#define D2S_MERC_ID_28 "Barbarian [Hell]"  
566 -#define D2S_MERC_ID_29 "Barbarian [Hell]"  
567 -  
568 // Quest checkpoints 537 // Quest checkpoints
569 // Note: Some quests don't have many checkpoints, but unfortunately lots of checkpoints are 538 // Note: Some quests don't have many checkpoints, but unfortunately lots of checkpoints are
570 // missing here. Documentation is pretty much scarce and I'm afraid we won't be able to find 539 // missing here. Documentation is pretty much scarce and I'm afraid we won't be able to find
d2waypoints.c
1 #include "d2waypoints.h" 1 #include "d2waypoints.h"
  2 +#include "d2char.h"
2 3
3 -int isWaypointActivated(D2WaypointsData* d, unsigned int waypoint, unsigned int difficulty) { 4 +int isWaypointActivated(D2WaypointsData* d, D2S_WAYPOINT waypoint, D2S_DIFFICULTY difficulty) {
4 if(waypoint > D2S_WAYPOINTSDATA_NUMWAYPOINTS) { 5 if(waypoint > D2S_WAYPOINTSDATA_NUMWAYPOINTS) {
5 return -1; 6 return -1;
6 } 7 }
@@ -10,7 +11,7 @@ int isWaypointActivated(D2WaypointsData* d, unsigned int waypoint, unsigned int @@ -10,7 +11,7 @@ int isWaypointActivated(D2WaypointsData* d, unsigned int waypoint, unsigned int
10 } 11 }
11 12
12 // TODO: Return success 13 // TODO: Return success
13 -void setWaypointActivated(D2WaypointsData* d, unsigned int waypoint, unsigned int difficulty, int activated) { 14 +void setWaypointActivated(D2WaypointsData* d, D2S_WAYPOINT waypoint, D2S_DIFFICULTY difficulty, int activated) {
14 if(waypoint > D2S_WAYPOINTSDATA_NUMWAYPOINTS) { 15 if(waypoint > D2S_WAYPOINTSDATA_NUMWAYPOINTS) {
15 return; 16 return;
16 } 17 }
d2waypoints.h
1 #ifndef D2WAYPOINTS_H 1 #ifndef D2WAYPOINTS_H
2 #define D2WAYPOINTS_H 2 #define D2WAYPOINTS_H
3 3
  4 +// Forward declaration
  5 +typedef enum D2S_DIFFICULTY D2S_DIFFICULTY;
  6 +
4 #include <stdint.h> 7 #include <stdint.h>
5 8
6 #include "d2strings.h" 9 #include "d2strings.h"
@@ -9,6 +12,10 @@ @@ -9,6 +12,10 @@
9 #define D2S_WAYPOINTSDATA_LENGTH 5 12 #define D2S_WAYPOINTSDATA_LENGTH 5
10 #define D2S_WAYPOINTSDATA_NUMWAYPOINTS 39 13 #define D2S_WAYPOINTSDATA_NUMWAYPOINTS 39
11 14
  15 +typedef enum D2S_WAYPOINT {
  16 +asd
  17 +} D2S_WAYPOINT;
  18 +
12 const char* const waypoints[] = { 19 const char* const waypoints[] = {
13 D2S_WAYPOINT_0, 20 D2S_WAYPOINT_0,
14 D2S_WAYPOINT_1, 21 D2S_WAYPOINT_1,
@@ -64,7 +71,7 @@ typedef struct __attribute__((packed)) { @@ -64,7 +71,7 @@ typedef struct __attribute__((packed)) {
64 D2Waypoints waypoints[3]; // 1 set for each difficulty 71 D2Waypoints waypoints[3]; // 1 set for each difficulty
65 } D2WaypointsData; 72 } D2WaypointsData;
66 73
67 -int isWaypointActivated(D2WaypointsData* d, unsigned int waypoint, unsigned int difficulty);  
68 -void setWaypointActivated(D2WaypointsData* d, unsigned int waypoint, unsigned int difficulty, int activated); 74 +int isWaypointActivated(D2WaypointsData* d, D2S_WAYPOINT waypoint, D2S_DIFFICULTY difficulty);
  75 +void setWaypointActivated(D2WaypointsData* d, D2S_WAYPOINT waypoint, D2S_DIFFICULTY difficulty, int activated);
69 76
70 #endif 77 #endif
71 \ No newline at end of file 78 \ No newline at end of file
docs/d2s_110_format_table.txt 0 → 100644
  1 +-------------------------------------------------------------------------------
  2 +originally extracted from here:
  3 +http://www.coreyh.org/diablo-2-files/documentation/d2s_110_format_table.htm
  4 +-------------------------------------------------------------------------------
  5 +
  6 +
  7 +D2S File Format - Version 1.10
  8 +
  9 +type name bits desc cond1 condvar1 condval1 cond2 condvar2 condval2 comment
  10 +ASC8 dwMajic 4 File ID +0
  11 +DWRD dwVersion 32 File Version +4
  12 +DWRD dwSize 32 File Size +8
  13 +DWRD dwCRC 32 File CRC +c
  14 +DWRD dwWeaponSet 32 Weapon Set +10
  15 +ASCI Name 16 Character Name +14
  16 +BYTE charType 8 Character Type +24 // 0x40 = ladder 0x20 = expansion 0x10 =? 0x08 = HasDied 0x04 = Hardcore
  17 + 0x02 = ? 0x01 = new character format
  18 +BYTE charTitle 8 Character Title +25
  19 +WORD unk1 16 Unknown +26 // 00 00
  20 +BYTE charClass 8 Character Class +28
  21 +WORD unk2 16 Unknown +29 // 10 1E
  22 +BYTE charLevel 8 Level +2b
  23 +DWRD unk3 32 Unknown +2c
  24 +DWRD dwTime 32 Time Stamp +30
  25 +DWRD unk4 32 Unknown // FF FF FF FF +34
  26 +DWRD dwSkillKey[16] 32 Skill Keys // No Array support in format !!! +38
  27 +DWRD dwLeftSkill1 32 Left Skill Weapon Set 1 +78
  28 +DWRD dwRightSkill1 32 Right Skill Weapon Set 1 +7c
  29 +DWRD dwLeftSkill2 32 Left Skill Weapon Set 2 +80
  30 +DWRD dwRightSkill2 32 Right Skill Weapon Set 2 +84
  31 +BYTE outfit[16] 8 Character Load graphics // No Array support in format !!! +88
  32 +BYTE colors[16] 8 Character Load Colors // No Array support in format !!! +98
  33 +BYTE Town1 8 Normal Town // Only town for last played mode is set
  34 +BYTE Town2 8 Nightmare Town
  35 +BYTE Town3 8 Hell Town
  36 +DWRD dwMapSeed 32 Map Random Seed
  37 +WORD unk5 16 Unknown // 00 00
  38 +BYTE bMercDead 8 Merc Dead Flag
  39 +BYTE unk6 8 Unknown
  40 +DWRD dwMercControl 32 Merc Control seed
  41 +WORD wMercName 16 Merc Name Index
  42 +WORD wMercType 16 Merc Type
  43 +DWRD dwMercExp 32 Merc Experience
  44 +BYTE unk7[0x90] 8 Unknown // No Array support in format !!!
  45 +
  46 +FILE d2Woo.txt 0 Questinfo Header // Act/Quest info header
  47 +
  48 +FILE d2Ws.txt 0 Waypoints // waypoints
  49 +
  50 +FILE d2W4.txt 0 Greetings // NPC greeting control
  51 +
  52 +PROP Stats 0 Player Stats // stats read like properties
  53 +
  54 +FILE d2if.txt 0 Player Skills // skills
  55 +
  56 +FILE itemlist.txt 0 Player Item List
  57 +
  58 +WORD iCorpses 16 Number of Corpses
  59 +FILE corpse.txt iCorpses Corpse List // need to add support for variable 'bits'
  60 +
  61 +ASC8 d2jf 2 Merc List majic // jf
  62 +FILE itemlist.txt 0 Merc Item List 0 bHasMerc 1
  63 +
  64 +ASC8 d2kf 2 Iron Golem majic // kf
  65 +BYTE bHasGolem 8 Iron Golem Flag
  66 +FILE fields.txt 0 Golem Item 0 bHasGolem 1
  67 +
  68 +
  69 +
  70 + //========== corpse.txt // dead body info
  71 +
  72 +BYTE bodyInfo[12] 8 Corpse Info
  73 +FILE itemlist.txt 0 Corpse Item List
  74 +
  75 +
  76 + //========== itemlist.txt // Item record list
  77 +
  78 +ASC8 dwMajic 2 Item List majic // JM
  79 +WORD nItems 16 Number of Items
  80 +FILE fields.txt nItems Item Records
  81 +
  82 +
  83 +
  84 +
  85 + //========== d2Woo.txt // Act/Quest info header
  86 +
  87 +ASC8 dwMajic 4 Record ID // Woo!
  88 +DWRD dwActs 32 Numer of acts
  89 +WORD wSize 16 Size in bytes
  90 +
  91 +FILE d2Act.txt 3*wActs Quest/Act states
  92 +
  93 + //========== d2Acts.txt // Act status flags
  94 +
  95 +WORD wActStart 16 Act Start info
  96 +WORD wQuestStatus[6] 16 Quest Status
  97 +WORD wActEnd 16 Act End flags
  98 +
  99 + //========== d2Ws.txt // waypoints
  100 +
  101 +ASC8 wMajic 2 Record ID // ws
  102 +BYTE unk[6] 8 Unknown
  103 +DWRD wp[3*6] 32 Waypoint Data
  104 +
  105 + //========== d2W4.txt // NPC state control
  106 +
  107 +ASC8 wMajic 2 Record ID (0x7701)
  108 +WORD wSize 16 size of struct
  109 +DWRD normal[2] 32 Normal
  110 +DWRD nightmare[2] 32 Nightmare
  111 +DWRD hell[2] 32 Hell
  112 +DWRD normal1[2] 32 Normal1
  113 +DWRD nightmare1[2] 32 Nightmare1
  114 +DWRD hell1[2] 32 Hell1
  115 +
  116 +
  117 + //========== d2if.txt // skills
  118 +
  119 +ASC8 wMajic 2 Record ID // if
  120 +BYTE skill_lvls[30] 8 Skill Levels
docs/d2s_mercenaries_1.09.html 0 → 100644
  1 +
  2 +<html>
  3 +<head>
  4 + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  5 + <meta name="Author" content="Trevin Beattie">
  6 + <meta name="Description" content="Your character's .d2s file decoded">
  7 + <meta name="Keywords" content="d2s, Diablo, v1.09, mercenary">
  8 + <meta name="Classification" content="binary file format">
  9 + <title>Diablo II v1.09 (English) Mercenary Names</title>
  10 +</head>
  11 +<body>
  12 +
  13 +<h1 align=center>Diablo II (English) Mercenary Names</h1>
  14 +
  15 +<h3 align=center>for Diablo II v1.09 and the Diablo II Expansion
  16 +Set: Lord of Destruction</h3>
  17 +
  18 +<h2 align=center>Rogue Scouts</h2>
  19 +
  20 +<table width="100%" border=0><tr>
  21 +<td valign=top><table align=center border>
  22 +<tr><th width="30%">Index</th><th width="70%">Name</th></tr>
  23 +<tr><td align=center>0</td><td align=center>Aliza</td></tr>
  24 +<tr><td align=center>1</td><td align=center>Amplisa</td></tr>
  25 +<tr><td align=center>2</td><td align=center>Annor</td></tr>
  26 +<tr><td align=center>3</td><td align=center>Abhaya</td></tr>
  27 +<tr><td align=center>4</td><td align=center>Elly</td></tr>
  28 +<tr><td align=center>5</td><td align=center>Paige</td></tr>
  29 +<tr><td align=center>6</td><td align=center>Basanti</td></tr>
  30 +<tr><td align=center>7</td><td align=center>Blaise</td></tr>
  31 +<tr><td align=center>8</td><td align=center>Kyoko</td></tr>
  32 +<tr><td align=center>9</td><td align=center>Klaudia</td></tr>
  33 +<tr><td align=center>10</td><td align=center>Kundri</td></tr>
  34 +<tr><td align=center>11</td><td align=center>Kyle</td></tr>
  35 +<tr><td align=center>12</td><td align=center>Visala</td></tr>
  36 +<tr><td align=center>13</td><td align=center>Elexa</td></tr>
  37 +</table></td>
  38 +
  39 +<td valign=top><table align=center border>
  40 +<tr><th width="30%">Index</th><th width="70%">Name</th></tr>
  41 +<tr><td align=center>14</td><td align=center>Floria</td></tr>
  42 +<tr><td align=center>15</td><td align=center>Fiona</td></tr>
  43 +<tr><td align=center>16</td><td align=center>Gwinni</td></tr>
  44 +<tr><td align=center>17</td><td align=center>Gaile</td></tr>
  45 +<tr><td align=center>18</td><td align=center>Hannah</td></tr>
  46 +<tr><td align=center>19</td><td align=center>Heather</td></tr>
  47 +<tr><td align=center>20</td><td align=center>Iantha</td></tr>
  48 +<tr><td align=center>21</td><td align=center>Diane</td></tr>
  49 +<tr><td align=center>22</td><td align=center>Isolde</td></tr>
  50 +<tr><td align=center>23</td><td align=center>Divo</td></tr>
  51 +<tr><td align=center>24</td><td align=center>Ithera</td></tr>
  52 +<tr><td align=center>25</td><td align=center>Itonya</td></tr>
  53 +<tr><td align=center>26</td><td align=center>Liene</td></tr>
  54 +<tr><td align=center>27</td><td align=center>Maeko</td></tr>
  55 +</table></td>
  56 +
  57 +<td valign=top><table align=center border>
  58 +<tr><th width="30%">Index</th><th width="70%">Name</th></tr>
  59 +<tr><td align=center>28</td><td align=center>Mahala</td></tr>
  60 +<tr><td align=center>29</td><td align=center>Liaza</td></tr>
  61 +<tr><td align=center>30</td><td align=center>Meghan</td></tr>
  62 +<tr><td align=center>31</td><td align=center>Olena</td></tr>
  63 +<tr><td align=center>32</td><td align=center>Oriana</td></tr>
  64 +<tr><td align=center>33</td><td align=center>Ryann</td></tr>
  65 +<tr><td align=center>34</td><td align=center>Rozene</td></tr>
  66 +<tr><td align=center>35</td><td align=center>Raissa</td></tr>
  67 +<tr><td align=center>36</td><td align=center>Sharyn</td></tr>
  68 +<tr><td align=center>37</td><td align=center>Shikha</td></tr>
  69 +<tr><td align=center>38</td><td align=center>Debi</td></tr>
  70 +<tr><td align=center>39</td><td align=center>Tylena</td></tr>
  71 +<tr><td align=center>40</td><td align=center>Wendy</td></tr>
  72 +</table></td>
  73 +</tr></table>
  74 +
  75 +<hr width="50%">
  76 +
  77 +<h2 align=center>Desert Mercenaries</h2>
  78 +
  79 +<table width="100%" border=0><tr>
  80 +<td valign=top><table align=center border>
  81 +<tr><th width="30%">Index</th><th width="70%">Name</th></tr>
  82 +<tr><td align=center>0</td><td align=center>Hazade</td></tr>
  83 +<tr><td align=center>1</td><td align=center>Alhizeer</td></tr>
  84 +<tr><td align=center>2</td><td align=center>Azrael</td></tr>
  85 +<tr><td align=center>3</td><td align=center>Ahsab</td></tr>
  86 +<tr><td align=center>4</td><td align=center>Chalan</td></tr>
  87 +<tr><td align=center>5</td><td align=center>Haseen</td></tr>
  88 +<tr><td align=center>6</td><td align=center>Razan</td></tr>
  89 +</table></td>
  90 +
  91 +<td valign=top><table align=center border>
  92 +<tr><th width="30%">Index</th><th width="70%">Name</th></tr>
  93 +<tr><td align=center>7</td><td align=center>Emilio</td></tr>
  94 +<tr><td align=center>8</td><td align=center>Pratham</td></tr>
  95 +<tr><td align=center>9</td><td align=center>Fazel</td></tr>
  96 +<tr><td align=center>10</td><td align=center>Jemali</td></tr>
  97 +<tr><td align=center>11</td><td align=center>Kasim</td></tr>
  98 +<tr><td align=center>12</td><td align=center>Gulzar</td></tr>
  99 +<tr><td align=center>13</td><td align=center>Mizan</td></tr>
  100 +</table></td>
  101 +
  102 +<td valign=top><table align=center border>
  103 +<tr><th width="30%">Index</th><th width="70%">Name</th></tr>
  104 +<tr><td align=center>14</td><td align=center>Leharas</td></tr>
  105 +<tr><td align=center>15</td><td align=center>Durga</td></tr>
  106 +<tr><td align=center>16</td><td align=center>Neeraj</td></tr>
  107 +<tr><td align=center>17</td><td align=center>Ilzan</td></tr>
  108 +<tr><td align=center>18</td><td align=center>Zanarhi</td></tr>
  109 +<tr><td align=center>19</td><td align=center>Waheed</td></tr>
  110 +<tr><td align=center>20</td><td align=center>Vikhyat</td></tr>
  111 +</table></td>
  112 +</tr></table>
  113 +
  114 +<hr width="50%">
  115 +
  116 +<h2 align=center>Eastern Sorcerors</h2>
  117 +
  118 +<table width="100%" border=0><tr>
  119 +<td valign=top><table align=center border>
  120 +<tr><th width="30%">Index</th><th width="70%">Name</th></tr>
  121 +<tr><td align=center>0</td><td align=center>Jelani</td></tr>
  122 +<tr><td align=center>1</td><td align=center>Barani</td></tr>
  123 +<tr><td align=center>2</td><td align=center>Jabari</td></tr>
  124 +<tr><td align=center>3</td><td align=center>Devak</td></tr>
  125 +<tr><td align=center>4</td><td align=center>Raldin</td></tr>
  126 +<tr><td align=center>5</td><td align=center>Telash</td></tr>
  127 +<tr><td align=center>6</td><td align=center>Ajheed</td></tr>
  128 +</table></td>
  129 +
  130 +<td valign=top><table align=center border>
  131 +<tr><th width="30%">Index</th><th width="70%">Name</th></tr>
  132 +<tr><td align=center>7</td><td align=center>Narphet</td></tr>
  133 +<tr><td align=center>8</td><td align=center>Khaleel</td></tr>
  134 +<tr><td align=center>9</td><td align=center>Phaet</td></tr>
  135 +<tr><td align=center>10</td><td align=center>Geshef</td></tr>
  136 +<tr><td align=center>11</td><td align=center>Vanji</td></tr>
  137 +<tr><td align=center>12</td><td align=center>Haphet</td></tr>
  138 +<tr><td align=center>13</td><td align=center>Thadar</td></tr>
  139 +</table></td>
  140 +
  141 +<td valign=top><table align=center border>
  142 +<tr><th width="30%">Index</th><th width="70%">Name</th></tr>
  143 +<tr><td align=center>14</td><td align=center>Yatiraj</td></tr>
  144 +<tr><td align=center>15</td><td align=center>Rhadge</td></tr>
  145 +<tr><td align=center>16</td><td align=center>Yashied</td></tr>
  146 +<tr><td align=center>17</td><td align=center>Jarulf</td></tr>
  147 +<tr><td align=center>18</td><td align=center>Flux</td></tr>
  148 +<tr><td align=center>19</td><td align=center>Scorch</td></tr>
  149 +</table></td>
  150 +</tr></table>
  151 +
  152 +<hr width="50%">
  153 +
  154 +<h2 align=center>Barbarians</h2>
  155 +
  156 +<table width="100%" border=0><tr>
  157 +<td valign=top><table align=center border>
  158 +<tr><th width="30%">Index</th><th width="70%">Name</th></tr>
  159 +<tr><td align=center>0</td><td align=center>Varaya</td></tr>
  160 +<tr><td align=center>1</td><td align=center>Khan</td></tr>
  161 +<tr><td align=center>2</td><td align=center>Klisk</td></tr>
  162 +<tr><td align=center>3</td><td align=center>Bors</td></tr>
  163 +<tr><td align=center>4</td><td align=center>Brom</td></tr>
  164 +<tr><td align=center>5</td><td align=center>Wiglaf</td></tr>
  165 +<tr><td align=center>6</td><td align=center>Hrothgar</td></tr>
  166 +<tr><td align=center>7</td><td align=center>Scyld</td></tr>
  167 +<tr><td align=center>8</td><td align=center>Healfdane</td></tr>
  168 +<tr><td align=center>9</td><td align=center>Heorogar</td></tr>
  169 +<tr><td align=center>10</td><td align=center>Halgaunt</td></tr>
  170 +<tr><td align=center>11</td><td align=center>Hygelac</td></tr>
  171 +<tr><td align=center>12</td><td align=center>Egtheow</td></tr>
  172 +<tr><td align=center>13</td><td align=center>Bohdan</td></tr>
  173 +<tr><td align=center>14</td><td align=center>Wulfgar</td></tr>
  174 +<tr><td align=center>15</td><td align=center>Hild</td></tr>
  175 +<tr><td align=center>16</td><td align=center>Heatholaf</td></tr>
  176 +</table></td>
  177 +
  178 +<td valign=top><table align=center border>
  179 +<tr><th width="30%">Index</th><th width="70%">Name</th></tr>
  180 +<tr><td align=center>17</td><td align=center>Weder</td></tr>
  181 +<tr><td align=center>18</td><td align=center>Vikhyat</td></tr>
  182 +<tr><td align=center>19</td><td align=center>Unferth</td></tr>
  183 +<tr><td align=center>20</td><td align=center>Sigemund</td></tr>
  184 +<tr><td align=center>21</td><td align=center>Heremod</td></tr>
  185 +<tr><td align=center>22</td><td align=center>Hengest</td></tr>
  186 +<tr><td align=center>23</td><td align=center>Folcwald</td></tr>
  187 +<tr><td align=center>24</td><td align=center>Frisian</td></tr>
  188 +<tr><td align=center>25</td><td align=center>Hnaef</td></tr>
  189 +<tr><td align=center>26</td><td align=center>Guthlaf</td></tr>
  190 +<tr><td align=center>27</td><td align=center>Oslaf</td></tr>
  191 +<tr><td align=center>28</td><td align=center>Yrmenlaf</td></tr>
  192 +<tr><td align=center>29</td><td align=center>Garmund</td></tr>
  193 +<tr><td align=center>30</td><td align=center>Freawaru</td></tr>
  194 +<tr><td align=center>31</td><td align=center>Eadgils</td></tr>
  195 +<tr><td align=center>32</td><td align=center>Onela</td></tr>
  196 +<tr><td align=center>33</td><td align=center>Damien</td></tr>
  197 +</table></td>
  198 +
  199 +<td valign=top><table align=center border>
  200 +<tr><th width="30%">Index</th><th width="70%">Name</th></tr>
  201 +<tr><td align=center>34</td><td align=center>Erfor</td></tr>
  202 +<tr><td align=center>35</td><td align=center>Weohstan</td></tr>
  203 +<tr><td align=center>36</td><td align=center>Wulf</td></tr>
  204 +<tr><td align=center>37</td><td align=center>Bulwye</td></tr>
  205 +<tr><td align=center>38</td><td align=center>Lief</td></tr>
  206 +<tr><td align=center>39</td><td align=center>Magnus</td></tr>
  207 +<tr><td align=center>40</td><td align=center>Klatu</td></tr>
  208 +<tr><td align=center>41</td><td align=center>Drus</td></tr>
  209 +<tr><td align=center>42</td><td align=center>Hoku</td></tr>
  210 +<tr><td align=center>43</td><td align=center>Kord</td></tr>
  211 +<tr><td align=center>44</td><td align=center>Uther</td></tr>
  212 +<tr><td align=center>45</td><td align=center>Ip</td></tr>
  213 +<tr><td align=center>46</td><td align=center>Ulf</td></tr>
  214 +<tr><td align=center>47</td><td align=center>Tharr</td></tr>
  215 +<tr><td align=center>48</td><td align=center>Kaelim</td></tr>
  216 +<tr><td align=center>49</td><td align=center>Ulric</td></tr>
  217 +<tr><td align=center>50</td><td align=center>Alaric</td></tr>
  218 +</table></td>
  219 +
  220 +<td valign=top><table align=center border>
  221 +<tr><th width="30%">Index</th><th width="70%">Name</th></tr>
  222 +<tr><td align=center>51</td><td align=center>Ethelred</td></tr>
  223 +<tr><td align=center>52</td><td align=center>Caden</td></tr>
  224 +<tr><td align=center>53</td><td align=center>Elgifu</td></tr>
  225 +<tr><td align=center>54</td><td align=center>Tostig</td></tr>
  226 +<tr><td align=center>55</td><td align=center>Alcuin</td></tr>
  227 +<tr><td align=center>56</td><td align=center>Emund</td></tr>
  228 +<tr><td align=center>57</td><td align=center>Sigurd</td></tr>
  229 +<tr><td align=center>58</td><td align=center>Gorm</td></tr>
  230 +<tr><td align=center>59</td><td align=center>Hollis</td></tr>
  231 +<tr><td align=center>60</td><td align=center>Ragnar</td></tr>
  232 +<tr><td align=center>61</td><td align=center>Torkel</td></tr>
  233 +<tr><td align=center>62</td><td align=center>Wulfstan</td></tr>
  234 +<tr><td align=center>63</td><td align=center>Alban</td></tr>
  235 +<tr><td align=center>64</td><td align=center>Barloc</td></tr>
  236 +<tr><td align=center>65</td><td align=center>Bill</td></tr>
  237 +<tr><td align=center>66</td><td align=center>Theodoric</td></tr>
  238 +</table></td>
  239 +</tr></table>
  240 +
  241 +<hr width="50%">
  242 +
  243 +<h2 align=center><a name="code">Mercenary Type Codes</a></h2>
  244 +
  245 +<table align=center border>
  246 +<tr><th width="7%">Code</th><th width="33%">Mercenary</th>
  247 +<th width="33%">Attribute</th><th width="27%">Difficulty</th></tr>
  248 +<tr><td align=center>0</td><td align=center>Rogue Scout</td>
  249 +<td align=center>Fire Arrow</td><td align=center>Normal</td></tr>
  250 +<tr><td align=center>1</td><td align=center>Rogue Scout</td>
  251 +<td align=center>Cold Arrow</td><td align=center>Normal</td></tr>
  252 +<tr><td align=center>2</td><td align=center>Rogue Scout</td>
  253 +<td align=center>Fire Arrow</td><td align=center>Nightmare</td></tr>
  254 +<tr><td align=center>3</td><td align=center>Rogue Scout</td>
  255 +<td align=center>Cold Arrow</td><td align=center>Nightmare</td></tr>
  256 +<tr><td align=center>4</td><td align=center>Rogue Scout</td>
  257 +<td align=center>Fire Arrow</td><td align=center>Hell</td></tr>
  258 +<tr><td align=center>5</td><td align=center>Rogue Scout</td>
  259 +<td align=center>Cold Arrow</td><td align=center>Hell</td></tr>
  260 +<tr><td align=center>6</td><td align=center>Desert Mercenary</td>
  261 +<td align=center>Combat</td><td align=center>Normal</td></tr>
  262 +<tr><td align=center>7</td><td align=center>Desert Mercenary</td>
  263 +<td align=center>Defensive</td><td align=center>Normal</td></tr>
  264 +<tr><td align=center>8</td><td align=center>Desert Mercenary</td>
  265 +<td align=center>Offensive</td><td align=center>Normal</td></tr>
  266 +<tr><td align=center>9</td><td align=center>Desert Mercenary</td>
  267 +<td align=center>Combat</td><td align=center>Nightmare</td></tr>
  268 +<tr><td align=center>10</td><td align=center>Desert Mercenary</td>
  269 +<td align=center>Defensive</td><td align=center>Nightmare</td></tr>
  270 +<tr><td align=center>11</td><td align=center>Desert Mercenary</td>
  271 +<td align=center>Offensive</td><td align=center>Nightmare</td></tr>
  272 +<tr><td align=center>12</td><td align=center>Desert Mercenary</td>
  273 +<td align=center>Combat</td><td align=center>Hell</td></tr>
  274 +<tr><td align=center>13</td><td align=center>Desert Mercenary</td>
  275 +<td align=center>Defensive</td><td align=center>Hell</td></tr>
  276 +<tr><td align=center>14</td><td align=center>Desert Mercenary</td>
  277 +<td align=center>Offensive</td><td align=center>Hell</td></tr>
  278 +<tr><td align=center>15</td><td align=center>Eastern Sorceror</td>
  279 +<td align=center>Fire Spells</td><td align=center>Normal</td></tr>
  280 +<tr><td align=center>16</td><td align=center>Eastern Sorceror</td>
  281 +<td align=center>Cold Spells</td><td align=center>Normal</td></tr>
  282 +<tr><td align=center>17</td><td align=center>Eastern Sorceror</td>
  283 +<td align=center>Lightning Spells</td><td align=center>Normal</td></tr>
  284 +<tr><td align=center>18</td><td align=center>Eastern Sorceror</td>
  285 +<td align=center>Fire Spells</td><td align=center>Nightmare</td></tr>
  286 +<tr><td align=center>19</td><td align=center>Eastern Sorceror</td>
  287 +<td align=center>Cold Spells</td><td align=center>Nightmare</td></tr>
  288 +<tr><td align=center>20</td><td align=center>Eastern Sorceror</td>
  289 +<td align=center>Lightning Spells</td><td align=center>Nightmare</td></tr>
  290 +<tr><td align=center>21</td><td align=center>Eastern Sorceror</td>
  291 +<td align=center>Fire Spells</td><td align=center>Hell</td></tr>
  292 +<tr><td align=center>22</td><td align=center>Eastern Sorceror</td>
  293 +<td align=center>Cold Spells</td><td align=center>Hell</td></tr>
  294 +<tr><td align=center>23</td><td align=center>Eastern Sorceror</td>
  295 +<td align=center>Lightning Spells</td><td align=center>Hell</td></tr>
  296 +<tr><td align=center>24</td><td align=center>Barbarian</td>
  297 +<td align=center></td><td align=center>Normal</td></tr>
  298 +<tr><td align=center>25</td><td align=center>Barbarian</td>
  299 +<td align=center></td><td align=center>Normal</td></tr>
  300 +<tr><td align=center>26</td><td align=center>Barbarian</td>
  301 +<td align=center></td><td align=center>Nightmare</td></tr>
  302 +<tr><td align=center>27</td><td align=center>Barbarian</td>
  303 +<td align=center></td><td align=center>Nightmare</td></tr>
  304 +<tr><td align=center>28</td><td align=center>Barbarian</td>
  305 +<td align=center></td><td align=center>Hell</td></tr>
  306 +<tr><td align=center>29</td><td align=center>Barbarian</td>
  307 +<td align=center></td><td align=center>Hell</td></tr>
  308 +</table>
  309 +
  310 +<hr>
  311 +
  312 +</body>
  313 +</html>
  314 +
docs/d2s_notes.txt 0 → 100644
  1 +-------------------------------------------------------------------------------
  2 +originally extracted from here:
  3 +http://www.coreyh.org/diablo-2-files/documentation/d2s_notes.txt
  4 +-------------------------------------------------------------------------------
  5 +
  6 +Summary of the various sections. Note the header's ID is actually a file ID, but you get the idea :)
  7 +
  8 +[color=blue]ID, content[/color]
  9 +0xaa55aa55, header
  10 +"Woo!", Quest info
  11 +"WS", Waypoint info
  12 +0x7701, NPC info
  13 +"gf", Main stats info
  14 +"if", Skill info
  15 +"JM", Main itemlist
  16 +"JM", Corpse item list
  17 +"jf", Mercenary section (expansion char only)
  18 +"kf", Iron Golem list (expansion char only)
  19 +
  20 +Note that individual items ALSO has the JM ID as do the Mercenary section if you have one. Confusing, yes :)
  21 +
  22 +
  23 +[color=blue]Header[/color]
  24 ++0000 file identifier, 0xaa55aa55
  25 ++0004 file version 92
  26 ++0008 file size
  27 ++000c checksum, d2fog.27f5
  28 ++0010 0 if [ptClient+428]b is 0, otherwise 1
  29 ++0014 character name, 16 bytes
  30 ++0024 flags from [ptClient+0a]b, bit 5 (of 0-7) is set by SAVE code if expansion game
  31 ++0025 acts done (see link in post below for more info)
  32 +(+0024 and +0025 is actually returned as a word from [ptClient+0a]w
  33 ++0026 empty filler to the 2 previous bytes, 0
  34 ++0027 empty filler to the 2 previous bytes, 0
  35 ++0028 character class from [ptClient+08]b, hopefully matches that of hUnit :)
  36 ++0029 hard coded to 0x10
  37 ++002a hard coded to 0x1e
  38 ++002b clvl from hUnit
  39 ++002c ? from [ptClient+454]dw
  40 ++0030 time
  41 ++0034 -1, function always return -1
  42 ++0038 32 2-byte values, supposedly skills assigned to function keys
  43 ++0078 8 2-byte values, supposedly skills assigned to mouse buttons
  44 ++0088 16 2-byte values (could be 8 4-byte values) set by d2common.283a, seems to relate to appearance of items/character
  45 ++00a8 act playing in normal difficulty
  46 ++00a9 act playing in nightmare difficulty
  47 ++00aa act playing in hell difficulty
  48 +
  49 +Of the three values above, 2 will be 0 the other will be the actual value with bit 7 set to indicate which difficulty is saved
  50 +
  51 ++00ab from [ptGame+78], should be initial seed of game
  52 ++00af start of mercenary info, much comes from 6fc71c10 (as ebx+xx), needs checking anyway:
  53 +
  54 ++00af flags, only 00100000 seems to be in use set if 6fcad880 returns non 0
  55 ++00b3 ebx+00
  56 ++00b7 ebx+04, then subtract [d2common.2957+148], should be from mercenary txt
  57 ++00b9 ebx+08
  58 ++00b9 exp of mercenary from hUnit
  59 +
  60 ++00bf to +014e empty, all 0. These bytes can be used for your own custom saved information. just make sure you load it properly too :)
  61 +
  62 +That concludes the main header of the save file. Next follow various sections of information.
  63 +
  64 +[color=blue]Quest info[/color]
  65 ++014f "Woo!"
  66 ++0153 version of block? 0x00000006
  67 ++0157 blocksize, 0x012a
  68 ++0159 quest info stuff (to come)
  69 +
  70 +[color=blue]Waypoint info[/color]
  71 ++0279 "WS"
  72 ++027b version of block? 0x00000001
  73 ++027f block size 0x0050
  74 ++0281 waypoint info stuff (to come)
  75 +
  76 +[color=blue]NPC info[/color]
  77 ++02c9 0x7701
  78 ++02cb block size, 0x0034
  79 ++02cd NPW info stuff (to come)
  80 +
  81 +[color=blue]Main stats info[/color]
  82 ++02fd "gf"
  83 ++02ff bitfield indicating which of the 16 main stats follow
  84 ++0301 stats (dw) indicated by bitfield, from hUnit
  85 +
  86 +The above section is of variable length
  87 +
  88 +[color=blue]Skill info[/color]
  89 ++03xx+00 "if"
  90 ++03xx+02 base slvl (b) for 30 skills
  91 +
  92 +[color=blue]Item info[/color]
  93 ++03xx+30 Start of item info
  94 +
  95 +The item info is mostly made up of various lists of items. A list will usually contain a header that has a two byte "string", for example "JM" (I would say many of those strings you find are actually short for various programmer names) followed by a word indicating the number of items in the list to follow. Next follow each item itself and I think most (all?) of them will start of with the "JM" string (yes confusing since it is used in two different cases so to speak) followed by item specific data. Socketed items follow right after the item they are socketed into and are not counted in the list header for number of items in the list.
  96 +
  97 +The various lists (of which not all need to be present) are:
  98 +
  99 +[color=blue]Main itemlist[/color]
  100 ++00 "JM"
  101 ++02 number of items in list
  102 ++04 List of items
  103 +
  104 +This includes all items your character have, including those in the stash.
  105 +
  106 +
  107 +[color=blue]Corpse item list[/color]
  108 ++00 "JM"
  109 ++02 number of corpses
  110 ++04 if coprse exists, 12 bytes not used
  111 ++10 if corpse exists, list of items
  112 +
  113 +The game obviously have had the ability to save several corpses for a character. Currently, only one corpse is supported though. The "number of corpses" can only be set to 0 or 1 and can thus be thought of as a flag for the existance of a corpse. If the corpse exists there follow 4 dwords of random data. The first value is actually set from an uninitialized local variable and can thus be anything that happens to sit on the stack. The next two values are x and y coordinates (not sure if they actually make any sense though). None of the three values are read by the code by the way. I guess the first value was once which map the coprse was on or something. In any case, thsoe 12 bytes can be ignored. Next follows a normal list of items if a corpse existed.
  114 +
  115 +[color=blue]Mercenary item list[/color]
  116 ++00 "jf" (only exists if expansion game regardless of if you have a mercenary or not)
  117 ++02 "JM" (only exists if you actually have a mercenary)
  118 ++04 number of items in list (only exists if you actuall have a mercenary)
  119 ++06 List of items (only exists if you actually have a mercenary)
  120 +
  121 +In an expansion game you then get:
  122 +
  123 +[color=blue]Iron Golem list[/color]
  124 ++00 "kf"
  125 ++02 0 or 1 (b), a 1 indictaing an Iron Golem exists
  126 ++03 if an Iron Golem eixts the item used to create it will follow here
  127 +
  128 +
  129 +
  130 +
  131 +Next to be added is detailed info on the data for each item saved in a list. It is a quite variable content depending on the item and also quite large. It will follow below. Note that the same function that compress an item for saving seems to be used to compress items for sending between server and client. It has the ability to mask many properties in such cases for non identified items for example when you gamble I would guess. I will not at all handle that here but only the case for actually saving an item.
  132 +
  133 +Since items are saved in a very compressed way on bit levels (and not bytes). In addition, what actually is saved varies with the item type and so on. I will thus not give offsetts but rather the number of bits (in decimal notation) something is saved in. The order would be the one the game places them though, so disregarding the fact that some section might be missing for some items the order should NEVER be another than the one I list below.
  134 +
  135 +
  136 +[color=blue]Common item data[/color]
  137 +16 "JM"
  138 +32 flags [ptItemstats+18], ptItemstats is [hUnit+70]
  139 +
  140 +Note, the flags are somewhat modified, some removed and some set by the save code but in much should be identical with the run time flags.
  141 +
  142 +10 version of item, 0, 1 or 100. 100 are new expansion items, 1 are new classic items and 0 is old pre expansion items. Note that all items should be converted to new ones in a current game (I think) at least no item should remain as version 0.
  143 +
  144 +3 mode, from hUnit+0c
  145 +
  146 +The mode of items seems to mostly be were the item actually is "located", as oposed to some action it performs. See the thread maping out the ptUnit (which I call hUnit in this thread) for more info. Although I can't imagine a situation were the item is in mode 3 (ground) or 5 (whatever that might be) the save file has a special case for them. In that case, the mode would be followed by 2 32 bit x and y coordinates (from d2common.2856 and 2859). For other items we instead have the three following entries.
  147 +
  148 +4 body location [ptItemstats+40]. This tells were, if at all, the item is equiped
  149 +
  150 +4 x coordinate in inventory (d2common.2856)
  151 +
  152 +4 y coordinate in inventory (d2common.2859)
  153 +
  154 +3 page number PLUS 1. The page tells where in the invenotry the item is. Example of different pages are stash cube, main invenotry on character and so on. Pages like trade screen and such should not matter although I am not sure what happens if the game tries to save your character while the trade screen is open, you might end up with items on that page too for example. Same with an item on the cursor.
  155 +
  156 +32 item code
  157 +
  158 +The 3 letter code each base item have. This is for non ears only (flag 00010000 in the flag data above is set for ears). Ears does not save the code, instead they have:
  159 +
  160 + 3 class of ear
  161 + n*7 name of ear. This is the character name of the ear and is ended by a 0 value. The name is stored at [ptItemstats+44] (first letter) and the following at [ptItemstats+46] and onwards.
  162 +
  163 +For the interested, in non saved structures, if the item is gold (which obviously never save as items), the ammount of gold is inserted after the item code. First comes a 1 bit indicating the size. A 1 indicate a 32 bit value a 0 indicate a 12 bit value. That 12/32 bit value then follows and specify the ammount of gold.
  164 +
  165 +Compact save items will have no other data than the above one. Flag 00200000 is set on compact save items. Note that flag is set only upon save, not normally in the flag register. It will be cleared in the process of loading. The compact saving info of an item is fetched from the appropriate item.txt file upon saving and checked for.
  166 +
  167 +
  168 +
  169 +
  170 +[color=blue]Non compact save item data[/color]
  171 +3 number of socketed items
  172 +32 creation seed, from [hUnit+34]
  173 +7 ilvl, from [ptItemstats+28]
  174 +4 quality, from [ptItemstats+00]
  175 +1 flag for variable picture (itemtypes "varinvgfx")
  176 +3 if flag=1, number indicating which picture to use
  177 +1 flag for autoprefix on item
  178 +11 if flag=1, info on which autoprefix
  179 +
  180 +Next follows data depending on the quality of the item.
  181 +
  182 +Low quality
  183 +3 type of low quality property
  184 +
  185 +Normal quality
  186 +No special data saved
  187 +
  188 +Superior
  189 +3 type of superiorproperty
  190 +
  191 +Magic
  192 +11 which prefix the item has
  193 +11 which suffix the item has
  194 +
  195 +In both cases it is the entry in the appropriate affix table (were a 0 value indicate none). This applies to the autoprefix above as well.
  196 +
  197 +Rare and Crafted
  198 +8 which prefix name the item has
  199 +8 which suffix name the item has
  200 +1 flag indicating if a prefix follows
  201 +11 if flag=1, which prefix the item has
  202 +1 flag indicating if a suffix follows
  203 +11 if flag=1, which suffix the item has
  204 +1 flag indicating if a prefix follows
  205 +11 if flag=1, which prefix the item has
  206 +1 flag indicating if a suffix follows
  207 +11 if flag=1, which suffix the item has
  208 +1 flag indicating if a prefix follows
  209 +11 if flag=1, which prefix the item has
  210 +1 flag indicating if a suffix follows
  211 +11 if flag=1, which suffix the item has
  212 +
  213 +Each rare item can have up to 3 prefixes and 3 suffixes.
  214 +
  215 +Set
  216 +12 which set (in setitems.txt) the item is part of
  217 +
  218 +Unique
  219 +12 which unique (in unqiue.txt) the item is
  220 +
  221 +
  222 +...more to come
  223 +
docs/d2s_save_file_format_1.13d.html 0 → 100644
  1 +<html>
  2 +<h1 align="center">Diablo II Save Game File Format</h1>
  3 +<h3 align="center">for Diablo II Expansion Set v1.13d</h3>
  4 +<div align="center">Updated July 1, 2012</div>
  5 +<p>This page was originally written by Trevin Beattie, whose site is no more (his latest version of this page is available
  6 +<a href="https://web.archive.org/web/20161224202623/http://web.archive.org/web/20070831101200/http://www.xmission.com/~trevin/DiabloIIv1.09_File_Format.shtml">here</a> though).<br/>
  7 +Now this page is maintained by me, Yuri Sakhno (George1).</p>
  8 +
  9 +<h2>Introduction</h2>
  10 +<p>This page describes the format of saved game files for the game Diablo II Expansion Set v1.13d.
  11 +While the information presented here is mostly aplicable to earlier versions of the game, there were some drastic
  12 +changes in version 1.10 (particularly, in how character stats are saved), so if you intend to read files of the versions
  13 +of the game erlier than that, you would probably be better off opening that save in some recent version of the game and
  14 +then saving it again (upgrading the saved game file).</p>
  15 +<p><i>(Note: all values larger than a byte are stored in x86 little-endian order &#x2014;
  16 +i.e., least significant byte first. A &quot;<tt>short</tt>&quot; is 2 bytes long,
  17 +and a &quot;<tt>long</tt>&quot; is 4 bytes long. Values starting with &quot;0x&quot; are given
  18 +in hexadecimal notation; otherwise they are decimal.)</i></p>
  19 +
  20 +<h2>File Header</h2>
  21 +<p>Each save file starts with a file header. Depending on the circumstances, this may be the only section present in saved game file.</p>
  22 +<table width="100%" border="1">
  23 +<tbody>
  24 + <tr>
  25 + <th width="8%">Byte Position</th>
  26 + <th width="8%">Size</th>
  27 + <th>Contents</th>
  28 + </tr>
  29 + <tr>
  30 + <td align="middle">0</td>
  31 + <td align="middle"><tt>long</tt></td>
  32 + <td>File identifier. This must be the value <tt>0xAA55AA55</tt>.</td>
  33 + </tr>
  34 + <tr>
  35 + <td align="middle">4</td>
  36 + <td align="middle"><tt>long</tt></td>
  37 + <td>File version. The following values are known:<br/>
  38 + &#xA0;&#xA0;&#xA0; <tt>0x47</tt>&#xA0; v1.00 through v1.06<br/>
  39 + &#xA0;&#xA0;&#xA0; <tt>0x57</tt>&#xA0; v1.07 or Expansion Set v1.08<br/>
  40 + &#xA0;&#xA0;&#xA0; <tt>0x59</tt>&#xA0; standard game v1.08<br/>
  41 + &#xA0;&#xA0;&#xA0; <tt>0x5C</tt>&#xA0; v1.09 (both the standard game and the Expansion Set.)<br/>
  42 + &#xA0;&#xA0;&#xA0; <tt>0x60</tt>&#xA0; v1.10 and above<br/>
  43 + As it was outlined above, this document only covers version <tt>0x60</tt> of the file format.</td>
  44 + </tr>
  45 + <tr>
  46 + <td align="middle">8</td>
  47 + <td align="middle"><tt>long</tt></td>
  48 + <td>Size of the file, in bytes.</td>
  49 + </tr>
  50 + <tr>
  51 + <td align="middle">12</td>
  52 + <td align="middle"><tt>long</tt></td>
  53 + <td>Checksum of the netire save file. If you attempt to hack the file without storing the
  54 + correct checksum afterwards, your game will fail to load.
  55 + Fortunately, the checksum algorithm is very simple.
  56 + After clearing the checksum field, you add up the values of all the bytes
  57 + in the file, rotating the running total one bit to the left before adding
  58 + each byte. Then store the result in this field.</td>
  59 + </tr>
  60 + <tr>
  61 + <td align="middle">16</td>
  62 + <td align="middle"><tt>long</tt></td>
  63 + <td>Active arms. Determines which weapon set is currently active.</td>
  64 + </tr>
  65 + <tr>
  66 + <td align="middle">20</td>
  67 + <td align="middle">16 <tt>char</tt>s</td>
  68 + <td><a href="Random_Character_Names.html">Character name</a>. The name may be up to 15 characters long;
  69 + the rest of the field must be padded with null-characters. <i>Remember the rules for
  70 + Diablo II character names: 2-15 characters, containing only upper and
  71 + lower case letters (A-Z), with the possible addition of one dash ( - ) or
  72 + underscore ( _ ) as long as it is not the first or last character of the
  73 + name.</i></td>
  74 + </tr>
  75 + <tr>
  76 + <td align="middle">36</td>
  77 + <td align="middle">byte</td>
  78 + <td>
  79 + <div>Character status. This is a bit field:</div>
  80 + <table cellspacing="0" width="80%" align="center" border="1">
  81 + <tbody>
  82 + <tr>
  83 + <th width="10%">7</th>
  84 + <th width="10%">6</th>
  85 + <th width="10%">5</th>
  86 + <th width="10%">4</th>
  87 + <th width="10%">3</th>
  88 + <th width="10%">2</th>
  89 + <th width="10%">1</th>
  90 + <th width="10%">0</th>
  91 + </tr>
  92 + <tr>
  93 + <td align="middle" colspan="2"><i>unknown</i></td>
  94 + <td align="middle">Expansion<br/>Character</td>
  95 + <td align="middle"><i>unknown</i></td>
  96 + <td align="middle">Died</td>
  97 + <td align="middle">Hardcore</td>
  98 + <td align="middle" colspan="2"><i>unknown</i></td>
  99 + </tr>
  100 + </tbody>
  101 + </table>
  102 + <div><i>Note: the &quot;died&quot; bit indicates that your character
  103 + has died at some point in the past. It is never cleared when you resume the game.
  104 + To find out whether your character is currently dead, you need to look
  105 + in the <a href="#item_list">item list</a> below to see if there is some corpse data.
  106 + Obviously, if you have a hardcore character and this bit is set, you won't be able
  107 + to play the game with that charcter anymore.</i></div></td>
  108 + </tr>
  109 + <tr>
  110 + <td align="middle">37</td>
  111 + <td align="middle">byte</td>
  112 + <td>
  113 + Character progression. This number tells (sort of) how many acts
  114 + you have completed from all difficulty levels. It appears to be
  115 + incremented when you kill the final demon in an act &#x2014; i.e., Andarial,
  116 + Duriel, Mephisto, and Diablo / Baal. There's a catch to that last
  117 + one: in an Expansion game, the value is <em>not</em> incremented after
  118 + killing Diablo, but is incremented by 2 after killing Baal. (The
  119 + reason is unknown.) So it skips the values 4, 9, and 14.
  120 + <p>I believe this value is used in determining your character's
  121 + title. The title is one of the following values (depending on the
  122 + character class' gender):</p>
  123 + <table border="0" align="center">
  124 + <tbody>
  125 + <tr>
  126 + <th width="6%">Value</th>
  127 + <th width="20%">Standard</th>
  128 + <th width="20%">Hardcore</th>
  129 + <th width="6%">Value</th>
  130 + <th width="20%">Expansion</th>
  131 + <th width="20%">Hardcode Expansion</th>
  132 + <td width="8%" colspan="5"><!-- @ --></td>
  133 + </tr>
  134 + <tr>
  135 + <td align="middle"><tt>0</tt>-<tt>3</tt></td>
  136 + <td align="middle" colspan="2"><i>(no title)</i></td>
  137 + <td align="middle"><tt>0</tt>-<tt>3</tt></td>
  138 + <td align="middle" colspan="2"><i>(no title)</i></td>
  139 + </tr>
  140 + <tr>
  141 + <td align="middle"><tt>4</tt>-<tt>7</tt></td>
  142 + <td align="middle">Sir / Dame</td>
  143 + <td align="middle">Count / Countess</td>
  144 + <td align="middle"><tt>5</tt>-<tt>8</tt></td>
  145 + <td align="middle">Slayer</td>
  146 + <td align="middle">Destroyer</td>
  147 + </tr>
  148 + <tr>
  149 + <td align="middle"><tt>8</tt>-<tt>11</tt></td>
  150 + <td align="middle">Lord / Lady</td>
  151 + <td align="middle">Duke / Duchess</td>
  152 + <td align="middle"><tt>10</tt>-<tt>13</tt></td>
  153 + <td align="middle">Champion</td>
  154 + <td align="middle">Conqueror</td>
  155 + </tr>
  156 + <tr>
  157 + <td align="middle"><tt>12</tt></td>
  158 + <td align="middle">Baron / Baroness</td>
  159 + <td align="middle">King / Queen</td>
  160 + <td align="middle"><tt>15</tt></td>
  161 + <td align="middle">Patriarch / Matriarch</td>
  162 + <td align="middle">Guardian</td>
  163 + </tr>
  164 + </tbody>
  165 + </table>
  166 + </td>
  167 + </tr>
  168 + <tr>
  169 + <td align="middle">38</td>
  170 + <td align="middle">2 bytes</td>
  171 + <td><i>unknown; probably some kind of padding</i></td>
  172 + </tr>
  173 + <tr>
  174 + <td align="middle">40</td>
  175 + <td align="middle">byte</td>
  176 + <td>Character class. The defined classes are:<br/>
  177 + &#xA0;&#xA0;&#xA0;&#xA0; <tt>0x00</tt>&#xA0; Amazon<br/>
  178 + &#xA0;&#xA0;&#xA0;&#xA0; <tt>0x01</tt>&#xA0; Sorceress<br/>
  179 + &#xA0;&#xA0;&#xA0;&#xA0; <tt>0x02</tt>&#xA0; Necromancer<br/>
  180 + &#xA0;&#xA0;&#xA0;&#xA0; <tt>0x03</tt>&#xA0; Paladin<br/>
  181 + &#xA0;&#xA0;&#xA0;&#xA0; <tt>0x04</tt>&#xA0; Barbarian<br/>
  182 + &#xA0;&#xA0;&#xA0;&#xA0; <tt>0x05</tt>&#xA0; Druid (Expansion character only)<br/>
  183 + &#xA0;&#xA0;&#xA0;&#xA0; <tt>0x06</tt>&#xA0; Assassin (Expansion character only)</td>
  184 + </tr>
  185 + <tr>
  186 + <td align="middle">41</td>
  187 + <td align="middle">2 bytes</td>
  188 + <td><i>unknown; I've only seen the values { 16, 30 } here.</i></td>
  189 + </tr>
  190 + <tr>
  191 + <td align="middle"><a name="header_level">43</a></td>
  192 + <td align="middle">byte</td>
  193 + <td>Character's level. This is the level shown on the character selection screen, but it
  194 + should equal the level given in the <a href="#stats_level">character statistics</a> section.</td>
  195 + </tr>
  196 + <tr>
  197 + <td align="middle">44</td>
  198 + <td align="middle"><tt>long</tt></td>
  199 + <td><i>unknown</i></td>
  200 + </tr>
  201 + <tr>
  202 + <td align="middle">48</td>
  203 + <td align="middle"><tt>long</tt></td>
  204 + <td>Time stamp. This is in the standard <tt>time()</tt> format of the number
  205 + of seconds which have elapsed since midnight, January 1, 1970 (UTC).</td>
  206 + </tr>
  207 + <tr>
  208 + <td align="middle">52</td>
  209 + <td align="middle"><tt>long</tt></td>
  210 + <td><i>unknown</i></td>
  211 + </tr>
  212 + <tr>
  213 + <td align="middle">56</td>
  214 + <td align="middle">16 <tt>long</tt>s</td>
  215 + <td>These are the <a href="Skills.html">skill Ids</a> assigned to the hotkeys for Skill&#xA0;1
  216 + through Skill&#xA0;16. If a skill hotkey is not assigned to a skill, the value is <tt>0xFFFF</tt>.
  217 + <p><!-- @ --></p>
  218 + <div>Hotkey definitions are stored in the <tt><i>character</i>.key</tt>
  219 + file. The structure of that file is not covered by this document.</div></td>
  220 + </tr>
  221 + <tr>
  222 + <td align="middle"><a name="120">120</a></td>
  223 + <td align="middle"><tt>long</tt></td>
  224 + <td>The action assigned to the left mouse button. The value of this field is a <a href="Skills.html">skill Id</a>.</td>
  225 + </tr>
  226 + <tr>
  227 + <td align="middle">124</td>
  228 + <td align="middle"><tt>long</tt></td>
  229 + <td>The action assigned to the right mouse button. The value of this field is also a <b>skill Id</b>.</td>
  230 + </tr>
  231 + <tr>
  232 + <td align="middle">128</td>
  233 + <td align="middle"><tt>long</tt></td>
  234 + <td>In an Expansion character, the action assigned to the alternate left
  235 + mouse button. (The button assignments are swapped when you swap weapons.)</td>
  236 + </tr>
  237 + <tr>
  238 + <td align="middle">132</td>
  239 + <td align="middle"><tt>long</tt></td>
  240 + <td>In an Expansion character, the action assigned to the alternate right mouse button.</td>
  241 + </tr>
  242 + <tr>
  243 + <td align="middle">136</td>
  244 + <td align="middle">32 bytes</td>
  245 + <td><i>unknown</i></td>
  246 + </tr>
  247 + <tr>
  248 + <td align="middle">168</td>
  249 + <td align="middle">3 bytes</td>
  250 + <td>These bytes indicate which difficulty the character is playing.
  251 + The first byte corresponds to Normal, the second Nightmare, and the third
  252 + Hell. If the value is zero, the character is not playing at that
  253 + level. Otherwise, the value looks like this:
  254 + <table cellspacing="0" width="80%" align="center" border="1">
  255 + <tbody>
  256 + <tr>
  257 + <th width="10%">7</th>
  258 + <th width="10%">6</th>
  259 + <th width="10%">5</th>
  260 + <th width="10%">4</th>
  261 + <th width="10%">3</th>
  262 + <th width="10%">2</th>
  263 + <th width="10%">1</th>
  264 + <th width="10%">0</th>
  265 + </tr>
  266 + <tr>
  267 + <td align="middle">Active</td>
  268 + <td align="middle" colspan="4"><i>unknown</i></td>
  269 + <td align="middle" colspan="3">Which Act the<br/>character is in (<tt>0</tt>-<tt>4</tt>)</td>
  270 + </tr>
  271 + </tbody>
  272 + </table>
  273 + </td>
  274 + </tr>
  275 + <tr>
  276 + <td align="middle">171</td>
  277 + <td align="middle"><tt>long</tt></td>
  278 + <td>Map Id. This value looks like a random number, but it corresponds with one of the <tt>long</tt>s
  279 + found in the <tt><i>character</i>.map</tt> file, according to the difficulty being played.</td>
  280 + </tr>
  281 + <tr>
  282 + <td align="middle">175</td>
  283 + <td align="middle"><tt>short</tt></td>
  284 + <td><i>unknown</i></td>
  285 + </tr>
  286 + <tr>
  287 + <td align="middle">177</td>
  288 + <td align="middle"><tt>short</tt></td>
  289 + <td>If your Expansion character has a mercenary who is currently dead, this field is non-zero.</td>
  290 + </tr>
  291 + <tr>
  292 + <td align="middle">179</td>
  293 + <td align="middle"><tt>long</tt></td>
  294 + <td>This looks like a random Id for your mercenary. It is <tt>0</tt> if you have never had a mercenary.
  295 + If your mercenary has died or (in the standard game) been left behind when you move on to the next act,
  296 + this field is still set to the last mercenary you had.</td>
  297 + </tr>
  298 + <tr>
  299 + <td align="middle"><a name="183">183</a></td>
  300 + <td align="middle"><tt>short</tt></td>
  301 + <td>This is a numerical index into the game's language-dependent string table for mercenary names.
  302 + There is a separate list for each type of mercenary (Rogue Scout, Desert Mercenary, Eastern Sorceror,
  303 + and Barbarian). Trevin wrote a <a href="Mercenaries.html">list of mercenary names</a> for the English 1.09 patch.</td>
  304 + </tr>
  305 + <tr>
  306 + <td align="middle">185</td>
  307 + <td align="middle"><tt>short</tt></td>
  308 + <td>This code determines the difficulty level and act where your mercenary was found, as well as the attribute
  309 + of your mercenary (i.e. Cold, Fire, Lightning). Trevin wrote a
  310 + <a href="Mercenaries.html#code">list of the mercenary codes</a> appended to the end of the mercenary name.</td>
  311 + </tr>
  312 + <tr>
  313 + <td align="middle">187</td>
  314 + <td align="middle"><tt>long</tt></td>
  315 + <td>Your mercenary's experience points.</td>
  316 + </tr>
  317 + <tr>
  318 + <td align="middle">191</td>
  319 + <td align="middle">144 bytes</td>
  320 + <td><i>unknown</i></td>
  321 + </tr>
  322 +</tbody>
  323 +</table>
  324 +
  325 +<a name="new_character_small_file"><p>For the newly-created character, this is the only information present in the file (i.e. the file consists of just the header).
  326 +The save file is extended (all other sections added) when you exit the game (even if you haven't done anything in it),
  327 +but the very first save created by the game (i.e. right after you click the OK button on the character-creation screen)
  328 +will be the save with just the header present. Such a save is still a legitimate save, which the game can successfully load.</p></a>
  329 +
  330 +<h2>Quest Completion Data</h2>
  331 +<p>The quest data begins with the following header:</p>
  332 +<table width="100%" border="1">
  333 +<tbody>
  334 + <tr>
  335 + <th width="10%">Byte Position</th>
  336 + <th width="10%">Size</th>
  337 + <th>Contents</th>
  338 + </tr>
  339 + <tr>
  340 + <td align="middle">335</td>
  341 + <td align="middle">4 <tt>char</tt>s</td>
  342 + <td>The string identifier &quot;<tt>Woo!</tt>&quot;.</td>
  343 + </tr>
  344 + <tr>
  345 + <td align="middle">339</td>
  346 + <td align="middle">6 bytes</td>
  347 + <td><i>unknown; there are values { <tt>0x06</tt>, <tt>0x00</tt>, <tt>0x00</tt>, <tt>0x00</tt>, <tt>0x2A</tt>, <tt>0x01</tt> } always present here.</i></td>
  348 + </tr>
  349 +</tbody>
  350 +</table>
  351 +<p>The header is followed by three structures, one for each difficulty level. Note that the byte
  352 +offsets given here are offsets into the structure; the first structure is at offset 345 in the file,
  353 +the second one is at offset 441, and the third one at 537. You have to add the offsets from the table
  354 +to these values to get the actual offset in the file for the corresponding field for the specific difficulty level.</p>
  355 +<p>Although there is some variation in the meaning of the bits per quest, some of the bits appear to have constant meaning.</p>
  356 +<p>Bit 0 indicates the quest is complete. If bit 0 is not set but the rest of the field is non-zero,
  357 +then the quest has been started, but not finished.</p>
  358 +<p>Bit 1 generally means you have completed the requirements for the quest
  359 +(i.e., killed the boss demon), and all that's left is to collect the reward &#x2014;
  360 +for example, &quot;Charsi will imbue an item with magical power.&quot; Not all
  361 +quests have this option. If this bit is set, bit 0 must be cleared.</p>
  362 +<p>Bit 2 is often set when an NPC gives you a quest.</p>
  363 +<p>Bit 12 is set when you have seen the swirling fire animation that closes a quest icon.</p>
  364 +<p>Bit 13 indicates the quest was completed in the current game; when you save
  365 +the game and then reload it, all bit 13's are cleared.</p>
  366 +<table width="100%" border="1">
  367 +<tbody>
  368 + <tr>
  369 + <th width="10%">Byte Position</th>
  370 + <th width="10%">Size</th>
  371 + <th>Contents</th>
  372 + </tr>
  373 + <tr>
  374 + <td align="middle">0</td>
  375 + <td align="middle"><tt>short</tt></td>
  376 + <td>This field contains a 1 if you have been introduced (by Warriv) to Act I.</td>
  377 + </tr>
  378 + <tr>
  379 + <td align="middle">2</td>
  380 + <td align="middle">6 <tt>short</tt>s</td>
  381 + <td>
  382 + <div>These fields contain quest completion data for each quest in Act I.</div>
  383 + <table cellspacing="0" width="100%" align="center" border="1">
  384 + <tbody>
  385 + <tr>
  386 + <th width="10%"><tt>short</tt>&#xA0;#</th>
  387 + <th width="35%">Quest</th>
  388 + <th width="55%">Notes</th>
  389 + </tr>
  390 + <tr>
  391 + <td align="middle">0</td>
  392 + <td>Den of Evil</td>
  393 + <td>Bit 4 is set when you enter the Den.</td>
  394 + </tr>
  395 + <tr>
  396 + <td align="middle">1</td>
  397 + <td>Sisters' Burial Grounds</td>
  398 + <td>Bit 4 is set when you enter the Burial Grounds.</td>
  399 + </tr>
  400 + <tr>
  401 + <td align="middle">2</td>
  402 + <td>Tools of the Trade</td>
  403 + <td>Bit 6 is set when you pick up the Horadric Malus.</td>
  404 + </tr>
  405 + <tr>
  406 + <td align="middle">3</td>
  407 + <td>The Search for Cain</td>
  408 + <td>Bit 4 is set when you enter Tristram.<br/>Bit 10 indicates
  409 + whether you have completed the secret Cow Level (&quot;Moo&quot;). If
  410 + you want to fight the Cow King again, just clear this bit!<br/>If you
  411 + enter Act II without rescuing Deckard Cain, bit 14 will get
  412 + set. You will not be able to rescue Cain yourself; the Rogues
  413 + will have done it instead, and as a consequence, you will be charged
  414 + a fee if you want Cain to identify items for you.</td>
  415 + </tr>
  416 + <tr>
  417 + <td align="middle">4</td>
  418 + <td>The Forgotten Tower</td>
  419 + <td>Bit 2 is set when you read the Moldy Tome.<br/>Bit 6 is set when
  420 + you enter the Forgotten Tower.</td>
  421 + </tr>
  422 + <tr>
  423 + <td align="middle">5</td>
  424 + <td>Sisters to the Slaughter</td>
  425 + <td><!-- @ --></td>
  426 + </tr>
  427 + </tbody>
  428 + </table>
  429 + </td>
  430 + </tr>
  431 + <tr>
  432 + <td align="middle">14</td>
  433 + <td align="middle"><tt>short</tt></td>
  434 + <td><i>uncertain; perhaps this gets set to a non-zero value after you travel from Act I to Act II.</i></td>
  435 + </tr>
  436 + <tr>
  437 + <td align="middle">16</td>
  438 + <td align="middle"><tt>short</tt></td>
  439 + <td>This field contains a 1 if you have been introduced (by Jerhyn) to Act II.</td>
  440 + </tr>
  441 + <tr>
  442 + <td align="middle">18</td>
  443 + <td align="middle">6 <tt>short</tt>s</td>
  444 + <td>
  445 + <div>These fields contain quest completion data for each quest in Act II.</div>
  446 + <table cellspacing="0" width="100%" align="center" border="1">
  447 + <tbody>
  448 + <tr>
  449 + <th width="10%"><tt>short</tt>&#xA0;#</th>
  450 + <th width="35%">Quest</th>
  451 + <th width="55%">Notes</th>
  452 + </tr>
  453 + <tr>
  454 + <td align="middle">0</td>
  455 + <td>Radament's Lair</td>
  456 + <td>Bit 4 is set when you find Radament.</td>
  457 + </tr>
  458 + <tr>
  459 + <td align="middle">1</td>
  460 + <td>The Horadric Staff</td>
  461 + <td>Bit 4 is set when Cain tells you about the Viper Amulet.<br/>
  462 + Bit 5 is set when Cain tells you about the Staff of Kings.<br/>
  463 + Bit 10 is set when Cain tells you about the Horadric Staff.<br/>
  464 + Bit 11 is set when you make the Horadric Staff.</td>
  465 + </tr>
  466 + <tr>
  467 + <td align="middle">2</td>
  468 + <td>Tainted Sun</td>
  469 + <td>Bit 2 is set when the sun goes out.<br/>
  470 + Bit 3 is set when Drognan tells you why.</td>
  471 + </tr>
  472 + <tr>
  473 + <td align="middle">3</td>
  474 + <td>Arcane Sanctuary</td>
  475 + <td rowspan="2"><!-- @ --></td>
  476 + </tr>
  477 + <tr>
  478 + <td align="middle">4</td>
  479 + <td>The Summoner</td>
  480 + </tr>
  481 + <tr>
  482 + <td align="middle">5</td>
  483 + <td>The Seven Tombs</td>
  484 + <td>Bit 3 is set when you talk to Tyrael.<br/>
  485 + Bit 4 is set when you talk to Jerhyn (after killing Duriel).<br/>
  486 + Bit 5 is set when you kill Duriel.<br/>
  487 + Bit 6 is set when Atma congratulates you.<br/>
  488 + Bit 7 is set when Warriv congratulates you.<br/>
  489 + Bit 8 is set by Drognan.<br/>
  490 + Bit 9 is set by Lysander.<br/>
  491 + Bit 10 is set by Cain.<br/>
  492 + Bit 11 is set by Fara.</td>
  493 + </tr>
  494 + </tbody>
  495 + </table>
  496 + </td>
  497 + </tr>
  498 + <tr>
  499 + <td align="middle">30</td>
  500 + <td align="middle"><tt>short</tt></td>
  501 + <td><i>uncertain; perhaps this gets set to a non-zero value after you travel from Act II to Act III.</i></td>
  502 + </tr>
  503 + <tr>
  504 + <td align="middle">32</td>
  505 + <td align="middle"><tt>short</tt></td>
  506 + <td>This field contains a 1 if you have been introduced (by Hratli) to Act III.</td>
  507 + </tr>
  508 + <tr>
  509 + <td align="middle">34</td>
  510 + <td align="middle">6 <tt>short</tt>s</td>
  511 + <td>
  512 + <div>These fields contain quest completion data for each quest in Act III.</div>
  513 + <table cellspacing="0" width="100%" align="center" border="1">
  514 + <tbody>
  515 + <tr>
  516 + <th width="10%"><tt>short</tt>&#xA0;#</th>
  517 + <th width="35%">Quest</th>
  518 + <th width="55%">Notes</th>
  519 + </tr>
  520 + <tr>
  521 + <td align="middle">0</td>
  522 + <td>Lam Esen's Tome</td>
  523 + <td rowspan="2"><!-- @ --></td>
  524 + </tr>
  525 + <tr>
  526 + <td align="middle">1</td>
  527 + <td>Khalim's Will</td>
  528 + </tr>
  529 + <tr>
  530 + <td align="middle">2</td>
  531 + <td>Blade of the Old Religion</td>
  532 + <td>Bit 2 is set when you pick up the Gidbinn.<br/>
  533 + Bit 3 is set when Hratli asks you to find the Gidbinn.</td>
  534 + </tr>
  535 + <tr>
  536 + <td align="middle">3</td>
  537 + <td>The Golden Bird</td>
  538 + <td>Bit 2 is set when Cain tells you about the Jade Figurine.<br/>
  539 + Bit 4 is set when Cain tells you about the Golden Bird.<br/>
  540 + Bit 5 is set when you are given the Potion of Life, and cleared again when you
  541 + drink the Potion. (This prevents you from drinking more than one in a game.)<br/>
  542 + Bit 6 is set when you find the Jade Figurine.</td>
  543 + </tr>
  544 + <tr>
  545 + <td align="middle">4</td>
  546 + <td>The Blackened Temple</td>
  547 + <td rowspan="2"><!-- @ --></td>
  548 + </tr>
  549 + <tr>
  550 + <td align="middle">5</td>
  551 + <td>The Guardian</td>
  552 + </tr>
  553 + </tbody>
  554 + </table>
  555 + </td>
  556 + </tr>
  557 + <tr>
  558 + <td align="middle">46</td>
  559 + <td align="middle"><tt>short</tt></td>
  560 + <td><i>uncertain; perhaps this gets set to a non-zero value after you travel from Act III to Act IV.</i></td>
  561 + </tr>
  562 + <tr>
  563 + <td align="middle">48</td>
  564 + <td align="middle"><tt>short</tt></td>
  565 + <td>This field contains a 1 if you have been introduced to Act IV.</td>
  566 + </tr>
  567 + <tr>
  568 + <td align="middle">50</td>
  569 + <td align="middle">6 <tt>short</tt>s</td>
  570 + <td>
  571 + <div>These fields contain quest completion data for each quest in Act
  572 + IV. Note that there are only three quests here, as opposed to 6 for
  573 + the first three Acts.</div>
  574 + <table cellspacing="0" width="100%" align="center" border="1">
  575 + <tbody>
  576 + <tr>
  577 + <th width="10%"><tt>short</tt>&#xA0;#</th>
  578 + <th width="35%">Quest</th>
  579 + <th width="55%">Notes</th>
  580 + </tr>
  581 + <tr>
  582 + <td align="middle">0</td>
  583 + <td>The Fallen Angel</td>
  584 + <td rowspan="3"><!-- @ --></td>
  585 + </tr>
  586 + <tr>
  587 + <td align="middle">1</td>
  588 + <td>Terror's End</td>
  589 + </tr>
  590 + <tr>
  591 + <td align="middle">2</td>
  592 + <td>Hell's Forge</td>
  593 + </tr>
  594 + <tr>
  595 + <td align="middle">3-5</td>
  596 + <td><i>unused</i></td>
  597 + <td>It looks like quest data for Act IV still has place for 6 quests, despite the fact that this act only has 3.</td>
  598 + </tr>
  599 + </tbody>
  600 + </table>
  601 + </td>
  602 + </tr>
  603 + <tr>
  604 + <td align="middle">62</td>
  605 + <td align="middle"><tt>short</tt></td>
  606 + <td><i>uncertain; perhaps this gets set to a non-zero value after you travel from Act IV to Act V in an Expansion game,
  607 + <b>but this assumption has not been verified yet</b>.</i></td>
  608 + </tr>
  609 + <tr>
  610 + <td align="middle">64</td>
  611 + <td align="middle"><tt>short</tt></td>
  612 + <td><i>unknown; in an Expansion character, this was set to 1 after
  613 + completing Terror's End and talking to Cain in act IV</i>.</td>
  614 + </tr>
  615 + <tr>
  616 + <td align="middle">66</td>
  617 + <td align="middle">2 <tt>short</tt>s</td>
  618 + <td><i>unknown</i></td>
  619 + </tr>
  620 + <tr>
  621 + <td align="middle">70</td>
  622 + <td align="middle">6 <tt>short</tt>s</td>
  623 + <td>
  624 + <div>These fields contain quest completion data for each quest in Act V.</div>
  625 + <table cellspacing="0" width="100%" align="center" border="1">
  626 + <tbody>
  627 + <tr>
  628 + <th width="10%"><tt>short</tt>&#xA0;#</th>
  629 + <th width="35%">Quest</th>
  630 + <th width="55%">Notes</th>
  631 + </tr>
  632 + <tr>
  633 + <td align="middle">0</td>
  634 + <td>Siege on Harrogath</td>
  635 + <td>Bit 3 is set when you find Shenk.<br/>
  636 + Bit 5 is set when Larzuk offers to socket an item for you.</td>
  637 + </tr>
  638 + <tr>
  639 + <td align="middle">1</td>
  640 + <td>Rescue on Mount Arreat</td>
  641 + <td><!-- @ --></td>
  642 + </tr>
  643 + <tr>
  644 + <td align="middle">2</td>
  645 + <td>Prison of Ice</td>
  646 + <td>Bit 7 is set when you read the Scroll of Resistance.<br/>
  647 + Bit 8 is set after you rescue Anya and talk to Malah.</td>
  648 + </tr>
  649 + <tr>
  650 + <td align="middle">3</td>
  651 + <td>Betrayal of Harrogath</td>
  652 + <td>Bit 4 is set when Anya offers to personalize an item for you.</td>
  653 + </tr>
  654 + <tr>
  655 + <td align="middle">4</td>
  656 + <td>Rite of Passage</td>
  657 + <td><!-- @ --></td>
  658 + </tr>
  659 + <tr>
  660 + <td align="middle">5</td>
  661 + <td>Eve of Destruction</td>
  662 + <td>Bit 4 is set when Larzuk congratulates you.<br/>
  663 + Bit 5 is set when Cain congratulates you.<br/>
  664 + Bit 6 is set when Malah congratulates you.<br/>
  665 + Bit 7 is set by Tyrael.<br/>
  666 + Bit 8 is set by Qual-Kehk.<br/>
  667 + Bit 9 is set by Anya.</td>
  668 + </tr>
  669 + </tbody>
  670 + </table>
  671 + </td>
  672 + </tr>
  673 + <tr>
  674 + <td align="middle">82</td>
  675 + <td align="middle">7 <tt>short</tt>s</td>
  676 + <td><i>unknown</i></td>
  677 + </tr>
  678 +</tbody>
  679 +</table>
  680 +
  681 +<h2>Waypoints Data</h2>
  682 +<p>The waypoints data begins with the following header:</p>
  683 +<table width="100%" border="1">
  684 +<tbody>
  685 + <tr>
  686 + <th width="10%">Byte Position</th>
  687 + <th width="10%">Size</th>
  688 + <th>Contents</th>
  689 + </tr>
  690 + <tr>
  691 + <td align="middle">633</td>
  692 + <td align="middle">2 <tt>char</tt>s</td>
  693 + <td>The string identifier &quot;<tt>WS</tt>&quot;.</td>
  694 + </tr>
  695 + <tr>
  696 + <td align="middle">635</td>
  697 + <td align="middle">6 bytes</td>
  698 + <td><i>unknown; there are values { <tt>0x01</tt>, <tt>0x00</tt>, <tt>0x00</tt>, <tt>0x00</tt>, <tt>0x50</tt>, <tt>0x00</tt> } always present here.</i></td>
  699 + </tr>
  700 +</tbody>
  701 +</table>
  702 +<p>The header is followed by three structures, one per each difficulty level.
  703 +Note that the byte offsets given here are offsets into the structure; the first structure is at offset 641 in the file,
  704 +the second one is at offset 665, and the third at 689. You have to add the offsets from the table
  705 +to these values to get the actual offset in the file for the corresponding field for the specific difficulty level.</p>
  706 +<table width="100%" border="1">
  707 +<tbody>
  708 + <tr>
  709 + <th width="10%">Byte Position</th>
  710 + <th width="10%">Size</th>
  711 + <th>Contents</th>
  712 + </tr>
  713 + <tr>
  714 + <td align="middle">0</td>
  715 + <td align="middle">2 bytes</td>
  716 + <td><i>unknown; there are values { <tt>0x02</tt>, <tt>0x01</tt> } always present here.</i></td>
  717 + </tr>
  718 + <tr>
  719 + <td align="middle">2</td>
  720 + <td align="middle">5 bytes</td>
  721 + <td>Waypoints. This is a bitfield, with one bit assigned to each
  722 + waypoint in LSB order &#x2014; so bit 0 in the Rogue Encampment waypoint for Act
  723 + I. The first waypoint in every Act is activated as soon as you enter
  724 + that Act. There are 9 waypoints (bits) in each of Acts I, II, and
  725 + III, and 3 waypoints (bits) in Act IV, so the last waypoint before Diablo
  726 + (River of Flame) is bit 29 (since we start counting from 0). The
  727 + first waypoint for Act V follows at bit 30, and continues to the last
  728 + (ninth) waypoint in Act V at bit 38.
  729 + <p><!-- @ --></p>
  730 + <div>The first waypoint in each of the difficulty levels is always activated,
  731 + even if you have never been to that difficulty level.</div></td>
  732 + </tr>
  733 + <tr>
  734 + <td align="middle">7</td>
  735 + <td align="middle">17 bytes</td>
  736 + <td><i>unknown</i></td>
  737 + </tr>
  738 +</tbody>
  739 +</table>
  740 +
  741 +<p>There is an additional byte value at file offset 713 after the three waypoints structures.
  742 +This byte always has value <tt>0x01</tt> and probably serves as some kind of trailer.</p>
  743 +
  744 +<h2>NPC Introductions</h2>
  745 +<p>Trevin's data on the next section was very sketchy, and hasn't improved since at all.</p>
  746 +<table width="100%" border="1">
  747 +<tbody>
  748 + <tr>
  749 + <th width="10%">Byte Position</th>
  750 + <th width="10%">Size</th>
  751 + <th>Contents</th>
  752 + </tr>
  753 + <tr>
  754 + <td align="middle">714</td>
  755 + <td align="middle">2 <tt>char</tt>s</td>
  756 + <td>The string identifier &quot;<tt>w4</tt>&quot;.</td>
  757 + </tr>
  758 + <tr>
  759 + <td align="middle">716</td>
  760 + <td align="middle">1 byte</td>
  761 + <td><i>unknown</i></td>
  762 + </tr>
  763 + <tr>
  764 + <td align="middle">717</td>
  765 + <td align="middle">1 byte</td>
  766 + <td>
  767 + <div>You have been introduced to:</div>
  768 + <table cellspacing="0" width="80%" align="center" border="1">
  769 + <tbody>
  770 + <tr>
  771 + <th width="10%">7</th>
  772 + <th width="10%">6</th>
  773 + <th width="10%">5</th>
  774 + <th width="10%">4</th>
  775 + <th width="10%">3</th>
  776 + <th width="10%">2</th>
  777 + <th width="10%">1</th>
  778 + <th width="10%">0</th>
  779 + </tr>
  780 + <tr>
  781 + <td align="middle">Warriv</td>
  782 + <td><!-- @ --></td>
  783 + <td align="middle">Charsi</td>
  784 + <td><!-- @ --></td>
  785 + <td align="middle">Kashya</td>
  786 + <td align="middle">Akara</td>
  787 + <td align="middle">Gheed</td>
  788 + <td><!-- @ --></td>
  789 + </tr>
  790 + </tbody>
  791 + </table>
  792 + </td>
  793 + </tr>
  794 + <tr>
  795 + <td align="middle">718</td>
  796 + <td align="middle">1 byte</td>
  797 + <td>
  798 + <table cellspacing="0" width="80%" align="center" border="1">
  799 + <tbody>
  800 + <tr>
  801 + <th width="10%">7</th>
  802 + <th width="10%">6</th>
  803 + <th width="10%">5</th>
  804 + <th width="10%">4</th>
  805 + <th width="10%">3</th>
  806 + <th width="10%">2</th>
  807 + <th width="10%">1</th>
  808 + <th width="10%">0</th>
  809 + </tr>
  810 + <tr>
  811 + <td align="middle">Greiz</td>
  812 + <td><!-- @ --></td>
  813 + <td align="middle">Meshif</td>
  814 + <td align="middle">Geglash</td>
  815 + <td align="middle">Lysander</td>
  816 + <td align="middle">Fara</td>
  817 + <td align="middle">Drognan</td>
  818 + <td><!-- @ --></td>
  819 + </tr>
  820 + </tbody>
  821 + </table>
  822 + </td>
  823 + </tr>
  824 + <tr>
  825 + <td align="middle">719</td>
  826 + <td align="middle">1 byte</td>
  827 + <td>
  828 + <table cellspacing="0" width="80%" align="center" border="1">
  829 + <tbody>
  830 + <tr>
  831 + <th width="10%">7</th>
  832 + <th width="10%">6</th>
  833 + <th width="10%">5</th>
  834 + <th width="10%">4</th>
  835 + <th width="10%">3</th>
  836 + <th width="10%">2</th>
  837 + <th width="10%">1</th>
  838 + <th width="10%">0</th>
  839 + </tr>
  840 + <tr>
  841 + <td align="middle">Alkor</td>
  842 + <td><!-- @ --></td>
  843 + <td align="middle">Asheara</td>
  844 + <td colspan="2"><!-- @ --></td>
  845 + <td align="middle">Cain</td>
  846 + <td><!-- @ --></td>
  847 + <td align="middle">Elzix</td>
  848 + </tr>
  849 + </tbody>
  850 + </table>
  851 + </td>
  852 + </tr>
  853 + <tr>
  854 + <td align="middle">720</td>
  855 + <td align="middle">1 byte</td>
  856 + <td>
  857 + <table cellspacing="0" width="80%" align="center" border="1">
  858 + <tbody>
  859 + <tr>
  860 + <th width="10%">7</th>
  861 + <th width="10%">6</th>
  862 + <th width="10%">5</th>
  863 + <th width="10%">4</th>
  864 + <th width="10%">3</th>
  865 + <th width="10%">2</th>
  866 + <th width="10%">1</th>
  867 + <th width="10%">0</th>
  868 + </tr>
  869 + <tr>
  870 + <td align="middle">Malah</td>
  871 + <td align="middle">Anya</td>
  872 + <td><!-- @ --></td>
  873 + <td align="middle">Natalya</td>
  874 + <td align="middle">Meshif</td>
  875 + <td colspan="2"><!-- @ --></td>
  876 + <td align="middle">Ormus</td>
  877 + </tr>
  878 + </tbody>
  879 + </table>
  880 + </td>
  881 + </tr>
  882 + <tr>
  883 + <td align="middle">721</td>
  884 + <td align="middle">1 byte</td>
  885 + <td>
  886 + <table cellspacing="0" width="80%" align="center" border="1">
  887 + <tbody>
  888 + <tr>
  889 + <th width="10%">7</th>
  890 + <th width="10%">6</th>
  891 + <th width="10%">5</th>
  892 + <th width="10%">4</th>
  893 + <th width="10%">3</th>
  894 + <th width="10%">2</th>
  895 + <th width="10%">1</th>
  896 + <th width="10%">0</th>
  897 + </tr>
  898 + <tr>
  899 + <td colspan="5"><!-- @ --></td>
  900 + <td align="middle">Cain</td>
  901 + <td align="middle">Qual-Kehk</td>
  902 + <td align="middle">Nihlathak</td>
  903 + </tr>
  904 + </tbody>
  905 + </table>
  906 + </td>
  907 + </tr>
  908 + <tr>
  909 + <td align="middle">722</td>
  910 + <td align="middle">3 bytes</td>
  911 + <td><i>unknown</i></td>
  912 + </tr>
  913 + <tr>
  914 + <td align="middle">725</td>
  915 + <td align="middle">8 bytes</td>
  916 + <td>Introductions repeated for Nightmare difficulty.</td>
  917 + </tr>
  918 + <tr>
  919 + <td align="middle">733</td>
  920 + <td align="middle">8 bytes</td>
  921 + <td>Introductions repeated for Hell difficulty.</td>
  922 + </tr>
  923 + <tr>
  924 + <td align="middle">741</td>
  925 + <td align="middle">1 byte</td>
  926 + <td>
  927 + <p>It would appear that bits 1-6 of byte 741 get set after you take the
  928 + caravan to Act II in Normal difficulty. Bit 7 of byte 741 through
  929 + bit 1 of byte 743 get set after you sail to Act III. On entering Act
  930 + IV, bits 2, 5, 6, &amp; 7 of byte 743 and bits 0, 3, &amp; 4 of byte 744
  931 + get set.</p>
  932 + <p>When you return to a previous act and talk to the NPC's, these bits are
  933 + cleared.</p>
  934 + <div>You have yet to be welcomed back by:</div>
  935 + <table cellspacing="0" width="80%" align="center" border="1">
  936 + <tbody>
  937 + <tr>
  938 + <th width="10%">7</th>
  939 + <th width="10%">6</th>
  940 + <th width="10%">5</th>
  941 + <th width="10%">4</th>
  942 + <th width="10%">3</th>
  943 + <th width="10%">2</th>
  944 + <th width="10%">1</th>
  945 + <th width="10%">0</th>
  946 + </tr>
  947 + <tr>
  948 + <td align="middle">Warriv</td>
  949 + <td align="middle">?</td>
  950 + <td align="middle">Charsi</td>
  951 + <td align="middle">Warriv</td>
  952 + <td align="middle">Kashya</td>
  953 + <td align="middle">Akara</td>
  954 + <td align="middle">Gheed</td>
  955 + <td><!-- @ --></td>
  956 + </tr>
  957 + </tbody>
  958 + </table>
  959 + </td>
  960 + </tr>
  961 + <tr>
  962 + <td align="middle">742</td>
  963 + <td align="middle">1 byte</td>
  964 + <td>
  965 + <table cellspacing="0" width="80%" align="center" border="1">
  966 + <tbody>
  967 + <tr>
  968 + <th width="10%">7</th>
  969 + <th width="10%">6</th>
  970 + <th width="10%">5</th>
  971 + <th width="10%">4</th>
  972 + <th width="10%">3</th>
  973 + <th width="10%">2</th>
  974 + <th width="10%">1</th>
  975 + <th width="10%">0</th>
  976 + </tr>
  977 + <tr>
  978 + <td align="middle">Greiz</td>
  979 + <td align="middle">Jerhyn</td>
  980 + <td align="middle">Meshif</td>
  981 + <td align="middle">Geglash</td>
  982 + <td align="middle">?</td>
  983 + <td align="middle">Fara</td>
  984 + <td align="middle">Drognan</td>
  985 + <td align="middle">?</td>
  986 + </tr>
  987 + </tbody>
  988 + </table>
  989 + </td>
  990 + </tr>
  991 + <tr>
  992 + <td align="middle">743</td>
  993 + <td align="middle">1 byte</td>
  994 + <td>
  995 + <table cellspacing="0" width="80%" align="center" border="1">
  996 + <tbody>
  997 + <tr>
  998 + <th width="10%">7</th>
  999 + <th width="10%">6</th>
  1000 + <th width="10%">5</th>
  1001 + <th width="10%">4</th>
  1002 + <th width="10%">3</th>
  1003 + <th width="10%">2</th>
  1004 + <th width="10%">1</th>
  1005 + <th width="10%">0</th>
  1006 + </tr>
  1007 + <tr>
  1008 + <td align="middle">Alkor</td>
  1009 + <td align="middle">Hratli</td>
  1010 + <td align="middle">Asheara</td>
  1011 + <td colspan="2"><!-- @ --></td>
  1012 + <td align="middle">?</td>
  1013 + <td align="middle">?</td>
  1014 + <td align="middle">Elzix</td>
  1015 + </tr>
  1016 + </tbody>
  1017 + </table>
  1018 + </td>
  1019 + </tr>
  1020 + <tr>
  1021 + <td align="middle">744</td>
  1022 + <td align="middle">1 byte</td>
  1023 + <td>
  1024 + <table cellspacing="0" width="80%" align="center" border="1">
  1025 + <tbody>
  1026 + <tr>
  1027 + <th width="10%">7</th>
  1028 + <th width="10%">6</th>
  1029 + <th width="10%">5</th>
  1030 + <th width="10%">4</th>
  1031 + <th width="10%">3</th>
  1032 + <th width="10%">2</th>
  1033 + <th width="10%">1</th>
  1034 + <th width="10%">0</th>
  1035 + </tr>
  1036 + <tr>
  1037 + <td colspan="3"><!-- @ --></td>
  1038 + <td align="middle">?</td>
  1039 + <td align="middle">?</td>
  1040 + <td colspan="2"><!-- @ --></td>
  1041 + <td align="middle">Ormus</td>
  1042 + </tr>
  1043 + </tbody>
  1044 + </table>
  1045 + </td>
  1046 + </tr>
  1047 + <tr>
  1048 + <td align="middle">745</td>
  1049 + <td align="middle">4 bytes</td>
  1050 + <td><i>unknown</i></td>
  1051 + </tr>
  1052 + <tr>
  1053 + <td align="middle">749</td>
  1054 + <td align="middle">8 bytes</td>
  1055 + <td>Greetings repeated for Nightmare difficulty.</td>
  1056 + </tr>
  1057 + <tr>
  1058 + <td align="middle">757</td>
  1059 + <td align="middle">8 bytes</td>
  1060 + <td>Greetings repeated for Hell difficulty.</td>
  1061 + </tr>
  1062 +</tbody>
  1063 +</table>
  1064 +
  1065 +<h2>Character Statistics</h2>
  1066 +<p>The character statistics begin with 2-character identifier:</p>
  1067 +<table width="100%" border="1">
  1068 +<tbody>
  1069 + <tr>
  1070 + <th width="10%">Byte Position</th>
  1071 + <th width="10%">Size</th>
  1072 + <th>Contents</th>
  1073 + </tr>
  1074 + <tr>
  1075 + <td align="middle">765</td>
  1076 + <td align="middle">2 <tt>char</tt>s</td>
  1077 + <td>The string identifier &quot;<tt>gf</tt>&quot;.</td>
  1078 + </tr>
  1079 +</tbody>
  1080 +</table>
  1081 +<p>From this point on, the contents of the file are variable, because character stats are stored in packed format
  1082 +and certain stats may be absent (if the stat is absent in the save file, its value is 0.</p>
  1083 +<p>Starting from patch version 1.10 Diablo II stores stats differently than it used to be in previous game version.
  1084 +Every character stat is stored as a two-value pair. These pairs (and even the values inside them are not
  1085 +byte-aligned. They may start in the middle of one byte, and continue to the second.
  1086 +Here is the basic structure of the pair (note that field sizes are given in bits):</p>
  1087 +<table width="100%" border="1">
  1088 +<thead>
  1089 + <tr>
  1090 + <th align="middle" width="10%">Field Size</th>
  1091 + <th align="middle" width="90%">Description</th>
  1092 + </tr>
  1093 +</thead>
  1094 +<tbody>
  1095 + <tr>
  1096 + <td align="middle">9</td>
  1097 + <td>Stat Id. This field determines the stat whose value is stored in the value-pair and, more importantly,
  1098 + the size of the next field in the pair.</td>
  1099 + </tr>
  1100 + <tr>
  1101 + <td align="middle"><i>variable</i></td>
  1102 + <td>The value that is to be assigned to the corresponding stat. The size of the field, in bits,
  1103 + is determined by the stat itself. Read on to find out where this information can be obtained.</td>
  1104 + </tr>
  1105 +</tbody>
  1106 +</table>
  1107 +<p>The stats list is terminated by the 9-bit value of <tt>0x1FF</tt> (all 9 bits are set),
  1108 +i.e. the entire list is read in a loop, where you read the Id first and, if that Id is <tt>0x1FF</tt>,
  1109 +you exit the loop, otherwise you read the next <i>n</i> bits as a stat value and repeat the loop.</p>
  1110 +<p>The Ids of stats (and sizes of values) are determined by the data-tables normally stored inside
  1111 +the game archive (the MPQ files). The file for this specific purpose is named <tt>ItemStatCost.txt</tt>,
  1112 +which is a kind of CSV file, but with tabulation characters used as separators instead of commas.
  1113 +The game actually uses the <tt>ItemStatCost.bin</tt> one, which is sort of a compiled version
  1114 +of the corresponding text file.</p>
  1115 +<p>Here is an Excel-formatted <a href="ItemStatCost.xlsx">ItemStatCost.xlsx</a> file that contains
  1116 +the data for 1.13d patch with some nice formatting and extra comments. This file actually contains
  1117 +data from two tables, the one needed for the purpose of reading character stats is given on the <b>ItemStatCost</b> sheet.</p>
  1118 +<p>The column <b>ID</b> specifies the Id of the stat, as stored in the 9-bit field of the two-value pair.
  1119 +The row containing that Id describes the stat. There is a textual name of the stat in the <b>Stat</b> column,
  1120 +as well as the size of the value, in bits, that follows the Id in the two-value pair. This size is specified
  1121 +by the <b>CSvBits</b> column. Only values that have value <b>1</b> in the <b>Saved</b> column (first 16 stats)
  1122 +are actually saved in the character stats section of the save file.</p>
  1123 +<p>The stats described by the <b>ItemStatCost</b> table are as follows (in table below Stat Name corresponds
  1124 +to the value in the <b>Stat</b> column from the data table):</p>
  1125 +
  1126 +<table width="100%" border="1">
  1127 +<thead>
  1128 + <tr>
  1129 + <th width="10%">Stat Name</th>
  1130 + <th width="90%">Details</th>
  1131 + </tr>
  1132 +</thead>
  1133 +<tbody>
  1134 + <tr>
  1135 + <td align="middle">strength</td>
  1136 + <td rowspan="4">These stats are self-explanatory. They are always present.</td>
  1137 + </tr>
  1138 + <tr><td align="middle">energy</td></tr>
  1139 + <tr><td align="middle">dexterity</td></tr>
  1140 + <tr><td align="middle">vitality</td></tr>
  1141 + <tr>
  1142 + <td align="middle">statpts</td>
  1143 + <td>The number of Stat Points earned but not distributed.
  1144 + This stat may be absent from the save file if you have distibuted all stat points.</td>
  1145 + </tr>
  1146 + <tr>
  1147 + <td align="middle">newskills</td>
  1148 + <td>The number of Skill Choices earned but not distributed.
  1149 + This stat may be absent from the save file if you have distibuted all skill points.</td>
  1150 + </tr>
  1151 + <tr>
  1152 + <td align="middle">hitpoints</td>
  1153 + <td>Current amount of Life points.
  1154 + <p><!-- @ --></p>
  1155 + <div>These 6 stats are (usually) always present. (There is
  1156 + an exception: if your character is dead, the current Life stat will be
  1157 + gone!) <u>They are also <i>not</i> plain integer values!</u>
  1158 + Instead, each field is a fixed-point binary number, with a 24-bit integer
  1159 + part and an 8-bit fraction part. For example, if the Current Life
  1160 + stat contains the value 0x020AC0, then to get the amount of life
  1161 + remaining you take that value and divide by 256.0 to get 522.75
  1162 + (rounding the number to an integer for display. Note that the
  1163 + current amount of Life, Mana or Stamina may be more than the base amount,
  1164 + because the base does not take into account any blessings bestowed by
  1165 + magical items you are carrying.</div></td>
  1166 + </tr>
  1167 + <tr>
  1168 + <td align="middle">maxhp</td>
  1169 + <td>Base amount of Life points.</td>
  1170 + </tr>
  1171 + <tr>
  1172 + <td align="middle">mana</td>
  1173 + <td>Current amount of Mana points.</td>
  1174 + </tr>
  1175 + <tr>
  1176 + <td align="middle">maxmana</td>
  1177 + <td>Base amount of Mana points.</td>
  1178 + </tr>
  1179 + <tr>
  1180 + <td align="middle">stamina</td>
  1181 + <td>Current amount of Stamina points.</td>
  1182 + </tr>
  1183 + <tr>
  1184 + <td align="middle">maxstamina</td>
  1185 + <td>Base amount of Stamina points.</td>
  1186 + </tr>
  1187 + <tr>
  1188 + <td align="middle"><a name="stats_level">level</a></td>
  1189 + <td>Your character's level. This value must be in the range 1-99
  1190 + (and is therefore always present, even on a new character, with
  1191 + a <a href="#new_character_small_file">minor exception</a>) and should be
  1192 + the same as <a href="#header_level">byte 43</a> in the file header.</td>
  1193 + </tr>
  1194 + <tr>
  1195 + <td align="middle">experience</td>
  1196 + <td>The amount of experience your character has. If you haven't
  1197 + killed a single monster in the game, your experience will be 0, and this
  1198 + field is not stored. Otherwise, this field is always present.</td>
  1199 + </tr>
  1200 + <tr>
  1201 + <td align="middle">gold</td>
  1202 + <td>The amount of gold you are carrying with you (in your inventory or backpack).
  1203 + Just as a helpful reminder, the maximum amount of gold you may carry is directly
  1204 + proportional to your level, at 10,000 gold per level. Thus, a new character can only
  1205 + carry 10,000 gold pieces, but a level 99 character (the maximum) can carry nearly
  1206 + a million in gold (990,000).</td>
  1207 + </tr>
  1208 + <tr>
  1209 + <td align="middle">goldbank</td>
  1210 + <td>The amount of gold you have stowed away (in stash). Just as a helpful
  1211 + reminder, starting from the 1.13c patch onwards, the maximum amount of gold
  1212 + in your stash does not depend on your character's level, and is now a flat
  1213 + cap of 2,500,000 instead.</td>
  1214 + </tr>
  1215 +</tbody>
  1216 +</table>
  1217 +<p>As it was specified above, the stats list is terminated with a stat Id with a special meaning
  1218 +(the Id has value <tt>0x1FF</tt> in this case), and the stat value for this stat Id is not stored
  1219 +(you may view it as a stat whose stat value is 0 bits in size). After that the remaining bits are
  1220 +padded with 0-bits to the nearest byte-boundary so that the next section is byte-aligned.</p>
  1221 +
  1222 +<h2><a name="skills">Character Skills</a></h2>
  1223 +<p>The character skills section begins with the 2-character header,
  1224 +&quot;<tt>if</tt>&quot;. This is followed by 30 bytes, each byte corresponding to
  1225 +one of the character's special skills. To save space, Trevin listed the skills
  1226 +in a <a href="Skills.html">separate table</a>.</p>
  1227 +
  1228 +<h2><a name="item_list">Item List</a></h2>
  1229 +<p>The next major section of the save file is the item list. It begins with the following header:</p>
  1230 +<table width="100%" border="1">
  1231 +<tbody>
  1232 + <tr>
  1233 + <th width="20%">Size</th>
  1234 + <th>Contents</th>
  1235 + </tr>
  1236 + <tr>
  1237 + <td align="middle">2 <tt>char</tt>s</td>
  1238 + <td>The string identifier &quot;<tt>JM</tt>&quot;.</td>
  1239 + </tr>
  1240 + <tr>
  1241 + <td align="middle"><tt>short</tt></td>
  1242 + <td>The number of items your character has. This includes items
  1243 + equipped, tucked in your belt, stored in your inventory, stored in your
  1244 + stash, and hidden in the Horadric Cube. It does <em>not</em>,
  1245 + however, include gems, runes, or jewels which have been inserted into a
  1246 + socketed item. (Those are counted as part of the item.)</td>
  1247 + </tr>
  1248 +</tbody>
  1249 +</table>
  1250 +<p>This header is followed by a list of items. The format of the items is described
  1251 +on the <a href="Item_Format.xhtml">Item Format</a> page.</p>
  1252 +<p>After the list of items, you will find another item list header similar to
  1253 +the one shown above; only this time the item count will be either 0 or 1. The value 0
  1254 +means that your character is currently alive. If the value is 1, then that means
  1255 +your character is dead (if you load this save, a corpse will be lying at your feet in town),
  1256 +in which case 12 bytes of <i>(unknown)</i> data will follow, after which there will be
  1257 +another items list header (the one with the identifier &quot;<tt>JM</tt>&quot; and item count)
  1258 +and item list for items on your corpse. Sadly, the meaning of the 12 bytes is unknown.</p>
  1259 +<p>If you have an Expansion character, then the corpse item list (if there is one) will be
  1260 +followed by the 2-character identifier &quot;<tt>jf</tt>&quot;. If <em>and only
  1261 +if</em> you have a mercenary (alive or dead), this header is followed by an item
  1262 +list header and (possibly empty) item list containing items equipped on the
  1263 +mercenary. This item list is followed by the 2-character trailer &quot;<tt>kf</tt>&quot;.</p>
  1264 +<p>If you have a necromancer, it is possible for you to have an Iron Golem that
  1265 +is preserved when your game is saved and restored. The Iron Golem is based on an
  1266 +item. Following the mercenary item list, there will be a single byte that is <tt>0x00</tt>
  1267 +if there is no golem, or <tt>0x01</tt> if there is. If there is a golem, this byte is
  1268 +followed by a single item.</p>
  1269 +</body>
  1270 +</html>
docs/d2s_save_file_format_1.13d.txt 0 → 100644
  1 +-------------------------------------------------------------------------------
  2 +originally extracted from here:
  3 +http://www.coreyh.org/diablo-2-files/documentation/d2s_save_file_format_1.13d.html
  4 +-------------------------------------------------------------------------------
  5 +
  6 +
  7 + Diablo II Save Game File Format
  8 +
  9 + for Diablo II Expansion Set v1.13d
  10 +
  11 + Updated July 1, 2012
  12 +
  13 +This page was originally written by Trevin Beattie, whose site is no more (his
  14 +latest version of this page is available here though).
  15 +Now this page is maintained by me, Yuri Sakhno (George1).
  16 +
  17 +Introduction
  18 +
  19 +This page describes the format of saved game files for the game Diablo II
  20 +Expansion Set v1.13d. While the information presented here is mostly aplicable
  21 +to earlier versions of the game, there were some drastic changes in version
  22 +1.10 (particularly, in how character stats are saved), so if you intend to read
  23 +files of the versions of the game erlier than that, you would probably be
  24 +better off opening that save in some recent version of the game and then saving
  25 +it again (upgrading the saved game file).
  26 +
  27 +(Note: all values larger than a byte are stored in x86 little-endian order —
  28 +i.e., least significant byte first. A "short" is 2 bytes long, and a "long" is
  29 +4 bytes long. Values starting with "0x" are given in hexadecimal notation;
  30 +otherwise they are decimal.)
  31 +
  32 +File Header
  33 +
  34 +Each save file starts with a file header. Depending on the circumstances, this
  35 +may be the only section present in saved game file.
  36 +
  37 +┌────────┬──────┬─────────────────────────────────────────────────────────────────┐
  38 +│ Byte │ Size │ Contents │
  39 +│Position│ │ │
  40 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  41 +│0 │long │File identifier. This must be the value 0xAA55AA55. │
  42 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  43 +│ │ │File version. The following values are known: │
  44 +│ │ │ 0x47 v1.00 through v1.06 │
  45 +│ │ │ 0x57 v1.07 or Expansion Set v1.08 │
  46 +│ │ │ 0x59 standard game v1.08 │
  47 +│4 │long │ 0x5C v1.09 (both the standard game and the Expansion │
  48 +│ │ │Set.) │
  49 +│ │ │ 0x60 v1.10 and above │
  50 +│ │ │As it was outlined above, this document only covers version │
  51 +│ │ │0x60 of the file format. │
  52 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  53 +│8 │long │Size of the file, in bytes. │
  54 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  55 +│ │ │Checksum of the netire save file. If you attempt to hack the │
  56 +│ │ │file without storing the correct checksum afterwards, your │
  57 +│ │ │game will fail to load. Fortunately, the checksum algorithm is │
  58 +│12 │long │very simple. After clearing the checksum field, you add up the │
  59 +│ │ │values of all the bytes in the file, rotating the running │
  60 +│ │ │total one bit to the left before adding each byte. Then store │
  61 +│ │ │the result in this field. │
  62 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  63 +│16 │long │Active arms. Determines which weapon set is currently active. │
  64 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  65 +│ │ │Character name. The name may be up to 15 characters long; the │
  66 +│ │ │rest of the field must be padded with null-characters. │
  67 +│ │16 │Remember the rules for Diablo II character names: 2-15 │
  68 +│20 │chars │characters, containing only upper and lower case letters │
  69 +│ │ │(A-Z), with the possible addition of one dash ( - ) or │
  70 +│ │ │underscore ( _ ) as long as it is not the first or last │
  71 +│ │ │character of the name. │
  72 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  73 +│ │ │Character status. This is a bit field: │
  74 +│ │ │┌────┬────┬─────────┬───────┬────┬────────┬────┬────┐ │
  75 +│ │ ││ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 │ │
  76 +│ │ │├────┴────┼─────────┼───────┼────┼────────┼────┴────┤ │
  77 +│ │ ││unknown │Expansion│unknown│Died│Hardcore│unknown │ │
  78 +│ │ ││ │Character│ │ │ │ │ │
  79 +│36 │byte │└─────────┴─────────┴───────┴────┴────────┴─────────┘ │
  80 +│ │ │Note: the "died" bit indicates that your character has died at │
  81 +│ │ │some point in the past. It is never cleared when you resume │
  82 +│ │ │the game. To find out whether your character is currently │
  83 +│ │ │dead, you need to look in the item list below to see if there │
  84 +│ │ │is some corpse data. Obviously, if you have a hardcore │
  85 +│ │ │character and this bit is set, you won't be able to play the │
  86 +│ │ │game with that charcter anymore. │
  87 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  88 +│ │ │Character progression. This number tells (sort of) how many │
  89 +│ │ │acts you have completed from all difficulty levels. It appears │
  90 +│ │ │to be incremented when you kill the final demon in an act — │
  91 +│ │ │i.e., Andarial, Duriel, Mephisto, and Diablo / Baal. There's a │
  92 +│ │ │catch to that last one: in an Expansion game, the value is not │
  93 +│ │ │incremented after killing Diablo, but is incremented by 2 │
  94 +│ │ │after killing Baal. (The reason is unknown.) So it skips the │
  95 +│ │ │values 4, 9, and 14. │
  96 +│ │ │ │
  97 +│ │ │I believe this value is used in determining your character's │
  98 +│ │ │title. The title is one of the following values (depending on │
  99 +│37 │byte │the character class' gender): │
  100 +│ │ │ │
  101 +│ │ │Value Standard Hardcore Value Expansion Hardcode │
  102 +│ │ │ Expansion │
  103 +│ │ │0-3 (no title) 0-3 (no title) │
  104 +│ │ │4-7 Sir / Dame Count / 5-8 Slayer Destroyer │
  105 +│ │ │ Countess │
  106 +│ │ │8-11 Lord / Duke / 10-13 Champion Conqueror │
  107 +│ │ │ Lady Duchess │
  108 +│ │ │ Baron / King / Patriarch │
  109 +│ │ │12 Baroness Queen 15 / Guardian │
  110 +│ │ │ Matriarch │
  111 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  112 +│38 │2 │unknown; probably some kind of padding │
  113 +│ │bytes │ │
  114 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  115 +│ │ │Character class. The defined classes are: │
  116 +│ │ │ 0x00 Amazon │
  117 +│ │ │ 0x01 Sorceress │
  118 +│40 │byte │ 0x02 Necromancer │
  119 +│ │ │ 0x03 Paladin │
  120 +│ │ │ 0x04 Barbarian │
  121 +│ │ │ 0x05 Druid (Expansion character only) │
  122 +│ │ │ 0x06 Assassin (Expansion character only) │
  123 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  124 +│41 │2 │unknown; I've only seen the values { 16, 30 } here. │
  125 +│ │bytes │ │
  126 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  127 +│ │ │Character's level. This is the level shown on the character │
  128 +│43 │byte │selection screen, but it should equal the level given in the │
  129 +│ │ │character statistics section. │
  130 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  131 +│44 │long │unknown │
  132 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  133 +│ │ │Time stamp. This is in the standard time() format of the │
  134 +│48 │long │number of seconds which have elapsed since midnight, January │
  135 +│ │ │1, 1970 (UTC). │
  136 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  137 +│52 │long │unknown │
  138 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  139 +│ │ │These are the skill Ids assigned to the hotkeys for Skill 1 │
  140 +│ │ │through Skill 16. If a skill hotkey is not assigned to a │
  141 +│56 │16 │skill, the value is 0xFFFF. │
  142 +│ │longs │ │
  143 +│ │ │Hotkey definitions are stored in the character.key file. The │
  144 +│ │ │structure of that file is not covered by this document. │
  145 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  146 +│120 │long │The action assigned to the left mouse button. The value of │
  147 +│ │ │this field is a skill Id. │
  148 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  149 +│124 │long │The action assigned to the right mouse button. The value of │
  150 +│ │ │this field is also a skill Id. │
  151 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  152 +│ │ │In an Expansion character, the action assigned to the │
  153 +│128 │long │alternate left mouse button. (The button assignments are │
  154 +│ │ │swapped when you swap weapons.) │
  155 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  156 +│132 │long │In an Expansion character, the action assigned to the │
  157 +│ │ │alternate right mouse button. │
  158 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  159 +│136 │32 │unknown │
  160 +│ │bytes │ │
  161 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  162 +│ │ │These bytes indicate which difficulty the character is │
  163 +│ │ │playing. The first byte corresponds to Normal, the second │
  164 +│ │ │Nightmare, and the third Hell. If the value is zero, the │
  165 +│ │ │character is not playing at that level. Otherwise, the value │
  166 +│ │ │looks like this: │
  167 +│168 │3 │┌──────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ │
  168 +│ │bytes ││ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 │ │
  169 +│ │ │├──────┼─────┴─────┴─────┴─────┼─────┴─────┴─────┤ │
  170 +│ │ ││ │ │Which Act the │ │
  171 +│ │ ││Active│unknown │character is in │ │
  172 +│ │ ││ │ │(0-4) │ │
  173 +│ │ │└──────┴───────────────────────┴─────────────────┘ │
  174 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  175 +│ │ │Map Id. This value looks like a random number, but it │
  176 +│171 │long │corresponds with one of the longs found in the character.map │
  177 +│ │ │file, according to the difficulty being played. │
  178 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  179 +│175 │short │unknown │
  180 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  181 +│177 │short │If your Expansion character has a mercenary who is currently │
  182 +│ │ │dead, this field is non-zero. │
  183 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  184 +│ │ │This looks like a random Id for your mercenary. It is 0 if you │
  185 +│ │ │have never had a mercenary. If your mercenary has died or (in │
  186 +│179 │long │the standard game) been left behind when you move on to the │
  187 +│ │ │next act, this field is still set to the last mercenary you │
  188 +│ │ │had. │
  189 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  190 +│ │ │This is a numerical index into the game's language-dependent │
  191 +│ │ │string table for mercenary names. There is a separate list for │
  192 +│183 │short │each type of mercenary (Rogue Scout, Desert Mercenary, Eastern │
  193 +│ │ │Sorceror, and Barbarian). Trevin wrote a list of mercenary │
  194 +│ │ │names for the English 1.09 patch. │
  195 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  196 +│ │ │This code determines the difficulty level and act where your │
  197 +│185 │short │mercenary was found, as well as the attribute of your │
  198 +│ │ │mercenary (i.e. Cold, Fire, Lightning). Trevin wrote a list of │
  199 +│ │ │the mercenary codes appended to the end of the mercenary name. │
  200 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  201 +│187 │long │Your mercenary's experience points. │
  202 +├────────┼──────┼─────────────────────────────────────────────────────────────────┤
  203 +│191 │144 │unknown │
  204 +│ │bytes │ │
  205 +└────────┴──────┴─────────────────────────────────────────────────────────────────┘
  206 +
  207 +For the newly-created character, this is the only information present in the
  208 +file (i.e. the file consists of just the header). The save file is extended
  209 +(all other sections added) when you exit the game (even if you haven't done
  210 +anything in it), but the very first save created by the game (i.e. right after
  211 +you click the OK button on the character-creation screen) will be the save with
  212 +just the header present. Such a save is still a legitimate save, which the game
  213 +can successfully load.
  214 +
  215 +Quest Completion Data
  216 +
  217 +The quest data begins with the following header:
  218 +
  219 +┌────────┬───────┬────────────────────────────────────────────────────────────┐
  220 +│ Byte │ Size │ Contents │
  221 +│Position│ │ │
  222 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  223 +│335 │4 chars│The string identifier "Woo!". │
  224 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  225 +│339 │6 bytes│unknown; there are values { 0x06, 0x00, 0x00, 0x00, 0x2A, │
  226 +│ │ │0x01 } always present here. │
  227 +└────────┴───────┴────────────────────────────────────────────────────────────┘
  228 +
  229 +The header is followed by three structures, one for each difficulty level. Note
  230 +that the byte offsets given here are offsets into the structure; the first
  231 +structure is at offset 345 in the file, the second one is at offset 441, and
  232 +the third one at 537. You have to add the offsets from the table to these
  233 +values to get the actual offset in the file for the corresponding field for the
  234 +specific difficulty level.
  235 +
  236 +Although there is some variation in the meaning of the bits per quest, some of
  237 +the bits appear to have constant meaning.
  238 +
  239 +Bit 0 indicates the quest is complete. If bit 0 is not set but the rest of the
  240 +field is non-zero, then the quest has been started, but not finished.
  241 +
  242 +Bit 1 generally means you have completed the requirements for the quest (i.e.,
  243 +killed the boss demon), and all that's left is to collect the reward — for
  244 +example, "Charsi will imbue an item with magical power." Not all quests have
  245 +this option. If this bit is set, bit 0 must be cleared.
  246 +
  247 +Bit 2 is often set when an NPC gives you a quest.
  248 +
  249 +Bit 12 is set when you have seen the swirling fire animation that closes a
  250 +quest icon.
  251 +
  252 +Bit 13 indicates the quest was completed in the current game; when you save the
  253 +game and then reload it, all bit 13's are cleared.
  254 +
  255 +┌────────┬───────┬────────────────────────────────────────────────────────────┐
  256 +│ Byte │ Size │ Contents │
  257 +│Position│ │ │
  258 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  259 +│0 │short │This field contains a 1 if you have been introduced (by │
  260 +│ │ │Warriv) to Act I. │
  261 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  262 +│ │ │These fields contain quest completion data for each quest in│
  263 +│ │ │Act I. │
  264 +│ │ │┌──────┬───────────────────┬───────────────────────────────┐│
  265 +│ │ ││short │ Quest │ Notes ││
  266 +│ │ ││ # │ │ ││
  267 +│ │ │├──────┼───────────────────┼───────────────────────────────┤│
  268 +│ │ ││0 │Den of Evil │Bit 4 is set when you enter the││
  269 +│ │ ││ │ │Den. ││
  270 +│ │ │├──────┼───────────────────┼───────────────────────────────┤│
  271 +│ │ ││1 │Sisters' Burial │Bit 4 is set when you enter the││
  272 +│ │ ││ │Grounds │Burial Grounds. ││
  273 +│ │ │├──────┼───────────────────┼───────────────────────────────┤│
  274 +│ │ ││2 │Tools of the Trade │Bit 6 is set when you pick up ││
  275 +│ │ ││ │ │the Horadric Malus. ││
  276 +│ │ │├──────┼───────────────────┼───────────────────────────────┤│
  277 +│ │ ││ │ │Bit 4 is set when you enter ││
  278 +│ │ ││ │ │Tristram. ││
  279 +│ │ ││ │ │Bit 10 indicates whether you ││
  280 +│ │ ││ │ │have completed the secret Cow ││
  281 +│2 │6 ││ │ │Level ("Moo"). If you want to ││
  282 +│ │shorts ││ │ │fight the Cow King again, just ││
  283 +│ │ ││ │ │clear this bit! ││
  284 +│ │ ││3 │The Search for Cain│If you enter Act II without ││
  285 +│ │ ││ │ │rescuing Deckard Cain, bit 14 ││
  286 +│ │ ││ │ │will get set. You will not be ││
  287 +│ │ ││ │ │able to rescue Cain yourself; ││
  288 +│ │ ││ │ │the Rogues will have done it ││
  289 +│ │ ││ │ │instead, and as a consequence, ││
  290 +│ │ ││ │ │you will be charged a fee if ││
  291 +│ │ ││ │ │you want Cain to identify items││
  292 +│ │ ││ │ │for you. ││
  293 +│ │ │├──────┼───────────────────┼───────────────────────────────┤│
  294 +│ │ ││ │ │Bit 2 is set when you read the ││
  295 +│ │ ││4 │The Forgotten Tower│Moldy Tome. ││
  296 +│ │ ││ │ │Bit 6 is set when you enter the││
  297 +│ │ ││ │ │Forgotten Tower. ││
  298 +│ │ │├──────┼───────────────────┼───────────────────────────────┤│
  299 +│ │ ││5 │Sisters to the │ ││
  300 +│ │ ││ │Slaughter │ ││
  301 +│ │ │└──────┴───────────────────┴───────────────────────────────┘│
  302 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  303 +│14 │short │uncertain; perhaps this gets set to a non-zero value after │
  304 +│ │ │you travel from Act I to Act II. │
  305 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  306 +│16 │short │This field contains a 1 if you have been introduced (by │
  307 +│ │ │Jerhyn) to Act II. │
  308 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  309 +│ │ │These fields contain quest completion data for each quest in│
  310 +│ │ │Act II. │
  311 +│ │ │┌──────┬───────────────────┬───────────────────────────────┐│
  312 +│ │ ││short │ Quest │ Notes ││
  313 +│ │ ││ # │ │ ││
  314 +│ │ │├──────┼───────────────────┼───────────────────────────────┤│
  315 +│ │ ││0 │Radament's Lair │Bit 4 is set when you find ││
  316 +│ │ ││ │ │Radament. ││
  317 +│ │ │├──────┼───────────────────┼───────────────────────────────┤│
  318 +│ │ ││ │ │Bit 4 is set when Cain tells ││
  319 +│ │ ││ │ │you about the Viper Amulet. ││
  320 +│ │ ││ │ │Bit 5 is set when Cain tells ││
  321 +│ │ ││1 │The Horadric Staff │you about the Staff of Kings. ││
  322 +│ │ ││ │ │Bit 10 is set when Cain tells ││
  323 +│ │ ││ │ │you about the Horadric Staff. ││
  324 +│ │ ││ │ │Bit 11 is set when you make the││
  325 +│ │ ││ │ │Horadric Staff. ││
  326 +│ │ │├──────┼───────────────────┼───────────────────────────────┤│
  327 +│ │ ││ │ │Bit 2 is set when the sun goes ││
  328 +│ │ ││2 │Tainted Sun │out. ││
  329 +│18 │6 ││ │ │Bit 3 is set when Drognan tells││
  330 +│ │shorts ││ │ │you why. ││
  331 +│ │ │├──────┼───────────────────┼───────────────────────────────┤│
  332 +│ │ ││3 │Arcane Sanctuary │ ││
  333 +│ │ │├──────┼───────────────────┤ ││
  334 +│ │ ││4 │The Summoner │ ││
  335 +│ │ │├──────┼───────────────────┼───────────────────────────────┤│
  336 +│ │ ││ │ │Bit 3 is set when you talk to ││
  337 +│ │ ││ │ │Tyrael. ││
  338 +│ │ ││ │ │Bit 4 is set when you talk to ││
  339 +│ │ ││ │ │Jerhyn (after killing Duriel). ││
  340 +│ │ ││ │ │Bit 5 is set when you kill ││
  341 +│ │ ││ │ │Duriel. ││
  342 +│ │ ││5 │The Seven Tombs │Bit 6 is set when Atma ││
  343 +│ │ ││ │ │congratulates you. ││
  344 +│ │ ││ │ │Bit 7 is set when Warriv ││
  345 +│ │ ││ │ │congratulates you. ││
  346 +│ │ ││ │ │Bit 8 is set by Drognan. ││
  347 +│ │ ││ │ │Bit 9 is set by Lysander. ││
  348 +│ │ ││ │ │Bit 10 is set by Cain. ││
  349 +│ │ ││ │ │Bit 11 is set by Fara. ││
  350 +│ │ │└──────┴───────────────────┴───────────────────────────────┘│
  351 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  352 +│30 │short │uncertain; perhaps this gets set to a non-zero value after │
  353 +│ │ │you travel from Act II to Act III. │
  354 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  355 +│32 │short │This field contains a 1 if you have been introduced (by │
  356 +│ │ │Hratli) to Act III. │
  357 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  358 +│ │ │These fields contain quest completion data for each quest in│
  359 +│ │ │Act III. │
  360 +│ │ │┌──────┬───────────────────┬───────────────────────────────┐│
  361 +│ │ ││short │ Quest │ Notes ││
  362 +│ │ ││ # │ │ ││
  363 +│ │ │├──────┼───────────────────┼───────────────────────────────┤│
  364 +│ │ ││0 │Lam Esen's Tome │ ││
  365 +│ │ │├──────┼───────────────────┤ ││
  366 +│ │ ││1 │Khalim's Will │ ││
  367 +│ │ │├──────┼───────────────────┼───────────────────────────────┤│
  368 +│ │ ││ │ │Bit 2 is set when you pick up ││
  369 +│ │ ││2 │Blade of the Old │the Gidbinn. ││
  370 +│ │ ││ │Religion │Bit 3 is set when Hratli asks ││
  371 +│ │ ││ │ │you to find the Gidbinn. ││
  372 +│ │ │├──────┼───────────────────┼───────────────────────────────┤│
  373 +│ │6 ││ │ │Bit 2 is set when Cain tells ││
  374 +│34 │shorts ││ │ │you about the Jade Figurine. ││
  375 +│ │ ││ │ │Bit 4 is set when Cain tells ││
  376 +│ │ ││ │ │you about the Golden Bird. ││
  377 +│ │ ││ │ │Bit 5 is set when you are given││
  378 +│ │ ││3 │The Golden Bird │the Potion of Life, and cleared││
  379 +│ │ ││ │ │again when you drink the ││
  380 +│ │ ││ │ │Potion. (This prevents you from││
  381 +│ │ ││ │ │drinking more than one in a ││
  382 +│ │ ││ │ │game.) ││
  383 +│ │ ││ │ │Bit 6 is set when you find the ││
  384 +│ │ ││ │ │Jade Figurine. ││
  385 +│ │ │├──────┼───────────────────┼───────────────────────────────┤│
  386 +│ │ ││4 │The Blackened │ ││
  387 +│ │ ││ │Temple │ ││
  388 +│ │ │├──────┼───────────────────┤ ││
  389 +│ │ ││5 │The Guardian │ ││
  390 +│ │ │└──────┴───────────────────┴───────────────────────────────┘│
  391 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  392 +│46 │short │uncertain; perhaps this gets set to a non-zero value after │
  393 +│ │ │you travel from Act III to Act IV. │
  394 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  395 +│48 │short │This field contains a 1 if you have been introduced to Act │
  396 +│ │ │IV. │
  397 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  398 +│ │ │These fields contain quest completion data for each quest in│
  399 +│ │ │Act IV. Note that there are only three quests here, as │
  400 +│ │ │opposed to 6 for the first three Acts. │
  401 +│ │ │┌──────┬───────────────────┬───────────────────────────────┐│
  402 +│ │ ││short │ Quest │ Notes ││
  403 +│ │ ││ # │ │ ││
  404 +│ │ │├──────┼───────────────────┼───────────────────────────────┤│
  405 +│ │ ││0 │The Fallen Angel │ ││
  406 +│50 │6 │├──────┼───────────────────┤ ││
  407 +│ │shorts ││1 │Terror's End │ ││
  408 +│ │ │├──────┼───────────────────┤ ││
  409 +│ │ ││2 │Hell's Forge │ ││
  410 +│ │ │├──────┼───────────────────┼───────────────────────────────┤│
  411 +│ │ ││ │ │It looks like quest data for ││
  412 +│ │ ││3-5 │unused │Act IV still has place for 6 ││
  413 +│ │ ││ │ │quests, despite the fact that ││
  414 +│ │ ││ │ │this act only has 3. ││
  415 +│ │ │└──────┴───────────────────┴───────────────────────────────┘│
  416 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  417 +│ │ │uncertain; perhaps this gets set to a non-zero value after │
  418 +│62 │short │you travel from Act IV to Act V in an Expansion game, but │
  419 +│ │ │this assumption has not been verified yet. │
  420 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  421 +│64 │short │unknown; in an Expansion character, this was set to 1 after │
  422 +│ │ │completing Terror's End and talking to Cain in act IV. │
  423 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  424 +│66 │2 │unknown │
  425 +│ │shorts │ │
  426 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  427 +│ │ │These fields contain quest completion data for each quest in│
  428 +│ │ │Act V. │
  429 +│ │ │┌──────┬───────────────────┬───────────────────────────────┐│
  430 +│ │ ││short │ Quest │ Notes ││
  431 +│ │ ││ # │ │ ││
  432 +│ │ │├──────┼───────────────────┼───────────────────────────────┤│
  433 +│ │ ││ │ │Bit 3 is set when you find ││
  434 +│ │ ││0 │Siege on Harrogath │Shenk. ││
  435 +│ │ ││ │ │Bit 5 is set when Larzuk offers││
  436 +│ │ ││ │ │to socket an item for you. ││
  437 +│ │ │├──────┼───────────────────┼───────────────────────────────┤│
  438 +│ │ ││1 │Rescue on Mount │ ││
  439 +│ │ ││ │Arreat │ ││
  440 +│ │ │├──────┼───────────────────┼───────────────────────────────┤│
  441 +│ │ ││ │ │Bit 7 is set when you read the ││
  442 +│ │ ││2 │Prison of Ice │Scroll of Resistance. ││
  443 +│70 │6 ││ │ │Bit 8 is set after you rescue ││
  444 +│ │shorts ││ │ │Anya and talk to Malah. ││
  445 +│ │ │├──────┼───────────────────┼───────────────────────────────┤│
  446 +│ │ ││3 │Betrayal of │Bit 4 is set when Anya offers ││
  447 +│ │ ││ │Harrogath │to personalize an item for you.││
  448 +│ │ │├──────┼───────────────────┼───────────────────────────────┤│
  449 +│ │ ││4 │Rite of Passage │ ││
  450 +│ │ │├──────┼───────────────────┼───────────────────────────────┤│
  451 +│ │ ││ │ │Bit 4 is set when Larzuk ││
  452 +│ │ ││ │ │congratulates you. ││
  453 +│ │ ││ │ │Bit 5 is set when Cain ││
  454 +│ │ ││ │ │congratulates you. ││
  455 +│ │ ││5 │Eve of Destruction │Bit 6 is set when Malah ││
  456 +│ │ ││ │ │congratulates you. ││
  457 +│ │ ││ │ │Bit 7 is set by Tyrael. ││
  458 +│ │ ││ │ │Bit 8 is set by Qual-Kehk. ││
  459 +│ │ ││ │ │Bit 9 is set by Anya. ││
  460 +│ │ │└──────┴───────────────────┴───────────────────────────────┘│
  461 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  462 +│82 │7 │unknown │
  463 +│ │shorts │ │
  464 +└────────┴───────┴────────────────────────────────────────────────────────────┘
  465 +
  466 +Waypoints Data
  467 +
  468 +The waypoints data begins with the following header:
  469 +
  470 +┌────────┬───────┬────────────────────────────────────────────────────────────┐
  471 +│ Byte │ Size │ Contents │
  472 +│Position│ │ │
  473 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  474 +│633 │2 chars│The string identifier "WS". │
  475 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  476 +│635 │6 bytes│unknown; there are values { 0x01, 0x00, 0x00, 0x00, 0x50, │
  477 +│ │ │0x00 } always present here. │
  478 +└────────┴───────┴────────────────────────────────────────────────────────────┘
  479 +
  480 +The header is followed by three structures, one per each difficulty level. Note
  481 +that the byte offsets given here are offsets into the structure; the first
  482 +structure is at offset 641 in the file, the second one is at offset 665, and
  483 +the third at 689. You have to add the offsets from the table to these values to
  484 +get the actual offset in the file for the corresponding field for the specific
  485 +difficulty level.
  486 +
  487 +┌────────┬───────┬────────────────────────────────────────────────────────────┐
  488 +│ Byte │ Size │ Contents │
  489 +│Position│ │ │
  490 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  491 +│0 │2 bytes│unknown; there are values { 0x02, 0x01 } always present │
  492 +│ │ │here. │
  493 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  494 +│ │ │Waypoints. This is a bitfield, with one bit assigned to each│
  495 +│ │ │waypoint in LSB order — so bit 0 in the Rogue Encampment │
  496 +│ │ │waypoint for Act I. The first waypoint in every Act is │
  497 +│ │ │activated as soon as you enter that Act. There are 9 │
  498 +│ │ │waypoints (bits) in each of Acts I, II, and III, and 3 │
  499 +│ │ │waypoints (bits) in Act IV, so the last waypoint before │
  500 +│2 │5 bytes│Diablo (River of Flame) is bit 29 (since we start counting │
  501 +│ │ │from 0). The first waypoint for Act V follows at bit 30, and│
  502 +│ │ │continues to the last (ninth) waypoint in Act V at bit 38. │
  503 +│ │ │ │
  504 +│ │ │The first waypoint in each of the difficulty levels is │
  505 +│ │ │always activated, even if you have never been to that │
  506 +│ │ │difficulty level. │
  507 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  508 +│7 │17 │unknown │
  509 +│ │bytes │ │
  510 +└────────┴───────┴────────────────────────────────────────────────────────────┘
  511 +
  512 +There is an additional byte value at file offset 713 after the three waypoints
  513 +structures. This byte always has value 0x01 and probably serves as some kind of
  514 +trailer.
  515 +
  516 +NPC Introductions
  517 +
  518 +Trevin's data on the next section was very sketchy, and hasn't improved since
  519 +at all.
  520 +
  521 +┌────────┬───────┬────────────────────────────────────────────────────────────┐
  522 +│ Byte │ Size │ Contents │
  523 +│Position│ │ │
  524 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  525 +│714 │2 chars│The string identifier "w4". │
  526 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  527 +│716 │1 byte │unknown │
  528 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  529 +│ │ │You have been introduced to: │
  530 +│ │ │┌──────┬────┬──────┬────┬──────┬─────┬─────┬────┐ │
  531 +│717 │1 byte ││ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 │ │
  532 +│ │ │├──────┼────┼──────┼────┼──────┼─────┼─────┼────┤ │
  533 +│ │ ││Warriv│ │Charsi│ │Kashya│Akara│Gheed│ │ │
  534 +│ │ │└──────┴────┴──────┴────┴──────┴─────┴─────┴────┘ │
  535 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  536 +│ │ │┌─────┬───┬──────┬───────┬────────┬────┬───────┬───┐ │
  537 +│ │ ││ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 │ │
  538 +│718 │1 byte │├─────┼───┼──────┼───────┼────────┼────┼───────┼───┤ │
  539 +│ │ ││Greiz│ │Meshif│Geglash│Lysander│Fara│Drognan│ │ │
  540 +│ │ │└─────┴───┴──────┴───────┴────────┴────┴───────┴───┘ │
  541 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  542 +│ │ │┌─────┬────┬───────┬────┬────┬─────┬────┬─────┐ │
  543 +│ │ ││ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 │ │
  544 +│719 │1 byte │├─────┼────┼───────┼────┴────┼─────┼────┼─────┤ │
  545 +│ │ ││Alkor│ │Asheara│ │Cain │ │Elzix│ │
  546 +│ │ │└─────┴────┴───────┴─────────┴─────┴────┴─────┘ │
  547 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  548 +│ │ │┌─────┬─────┬────┬───────┬──────┬────┬────┬─────┐ │
  549 +│ │ ││ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 │ │
  550 +│720 │1 byte │├─────┼─────┼────┼───────┼──────┼────┴────┼─────┤ │
  551 +│ │ ││Malah│Anya │ │Natalya│Meshif│ │Ormus│ │
  552 +│ │ │└─────┴─────┴────┴───────┴──────┴─────────┴─────┘ │
  553 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  554 +│ │ │┌────┬────┬────┬────┬────┬────┬─────────┬─────────┐ │
  555 +│ │ ││ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 │ │
  556 +│721 │1 byte │├────┴────┴────┴────┴────┼────┼─────────┼─────────┤ │
  557 +│ │ ││ │Cain│Qual-Kehk│Nihlathak│ │
  558 +│ │ │└────────────────────────┴────┴─────────┴─────────┘ │
  559 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  560 +│722 │3 bytes│unknown │
  561 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  562 +│725 │8 bytes│Introductions repeated for Nightmare difficulty. │
  563 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  564 +│733 │8 bytes│Introductions repeated for Hell difficulty. │
  565 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  566 +│ │ │It would appear that bits 1-6 of byte 741 get set after you │
  567 +│ │ │take the caravan to Act II in Normal difficulty. Bit 7 of │
  568 +│ │ │byte 741 through bit 1 of byte 743 get set after you sail to│
  569 +│ │ │Act III. On entering Act IV, bits 2, 5, 6, & 7 of byte 743 │
  570 +│ │ │and bits 0, 3, & 4 of byte 744 get set. │
  571 +│ │ │ │
  572 +│ │ │When you return to a previous act and talk to the NPC's, │
  573 +│741 │1 byte │these bits are cleared. │
  574 +│ │ │ │
  575 +│ │ │You have yet to be welcomed back by: │
  576 +│ │ │┌──────┬───┬──────┬──────┬──────┬─────┬─────┬───┐ │
  577 +│ │ ││ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 │ │
  578 +│ │ │├──────┼───┼──────┼──────┼──────┼─────┼─────┼───┤ │
  579 +│ │ ││Warriv│? │Charsi│Warriv│Kashya│Akara│Gheed│ │ │
  580 +│ │ │└──────┴───┴──────┴──────┴──────┴─────┴─────┴───┘ │
  581 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  582 +│ │ │┌─────┬──────┬──────┬───────┬───┬────┬───────┬───┐ │
  583 +│ │ ││ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 │ │
  584 +│742 │1 byte │├─────┼──────┼──────┼───────┼───┼────┼───────┼───┤ │
  585 +│ │ ││Greiz│Jerhyn│Meshif│Geglash│? │Fara│Drognan│? │ │
  586 +│ │ │└─────┴──────┴──────┴───────┴───┴────┴───────┴───┘ │
  587 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  588 +│ │ │┌─────┬──────┬───────┬────┬────┬────┬────┬─────┐ │
  589 +│ │ ││ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 │ │
  590 +│743 │1 byte │├─────┼──────┼───────┼────┴────┼────┼────┼─────┤ │
  591 +│ │ ││Alkor│Hratli│Asheara│ │? │? │Elzix│ │
  592 +│ │ │└─────┴──────┴───────┴─────────┴────┴────┴─────┘ │
  593 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  594 +│ │ │┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ │
  595 +│ │ ││ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 │ │
  596 +│744 │1 byte │├─────┴─────┴─────┼─────┼─────┼─────┴─────┼─────┤ │
  597 +│ │ ││ │? │? │ │Ormus│ │
  598 +│ │ │└─────────────────┴─────┴─────┴───────────┴─────┘ │
  599 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  600 +│745 │4 bytes│unknown │
  601 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  602 +│749 │8 bytes│Greetings repeated for Nightmare difficulty. │
  603 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  604 +│757 │8 bytes│Greetings repeated for Hell difficulty. │
  605 +└────────┴───────┴────────────────────────────────────────────────────────────┘
  606 +
  607 +Character Statistics
  608 +
  609 +The character statistics begin with 2-character identifier:
  610 +
  611 +┌────────┬───────┬────────────────────────────────────────────────────────────┐
  612 +│ Byte │ Size │ Contents │
  613 +│Position│ │ │
  614 +├────────┼───────┼────────────────────────────────────────────────────────────┤
  615 +│765 │2 chars│The string identifier "gf". │
  616 +└────────┴───────┴────────────────────────────────────────────────────────────┘
  617 +
  618 +From this point on, the contents of the file are variable, because character
  619 +stats are stored in packed format and certain stats may be absent (if the stat
  620 +is absent in the save file, its value is 0.
  621 +
  622 +Starting from patch version 1.10 Diablo II stores stats differently than it
  623 +used to be in previous game version. Every character stat is stored as a
  624 +two-value pair. These pairs (and even the values inside them are not
  625 +byte-aligned. They may start in the middle of one byte, and continue to the
  626 +second. Here is the basic structure of the pair (note that field sizes are
  627 +given in bits):
  628 +
  629 +┌────────┬────────────────────────────────────────────────────────────────────┐
  630 +│ Field │ Description │
  631 +│ Size │ │
  632 +├────────┼────────────────────────────────────────────────────────────────────┤
  633 +│ │Stat Id. This field determines the stat whose value is stored in the│
  634 +│9 │value-pair and, more importantly, the size of the next field in the │
  635 +│ │pair. │
  636 +├────────┼────────────────────────────────────────────────────────────────────┤
  637 +│ │The value that is to be assigned to the corresponding stat. The size│
  638 +│variable│of the field, in bits, is determined by the stat itself. Read on to │
  639 +│ │find out where this information can be obtained. │
  640 +└────────┴────────────────────────────────────────────────────────────────────┘
  641 +
  642 +The stats list is terminated by the 9-bit value of 0x1FF (all 9 bits are set),
  643 +i.e. the entire list is read in a loop, where you read the Id first and, if
  644 +that Id is 0x1FF, you exit the loop, otherwise you read the next n bits as a
  645 +stat value and repeat the loop.
  646 +
  647 +The Ids of stats (and sizes of values) are determined by the data-tables
  648 +normally stored inside the game archive (the MPQ files). The file for this
  649 +specific purpose is named ItemStatCost.txt, which is a kind of CSV file, but
  650 +with tabulation characters used as separators instead of commas. The game
  651 +actually uses the ItemStatCost.bin one, which is sort of a compiled version of
  652 +the corresponding text file.
  653 +
  654 +Here is an Excel-formatted ItemStatCost.xlsx file that contains the data for
  655 +1.13d patch with some nice formatting and extra comments. This file actually
  656 +contains data from two tables, the one needed for the purpose of reading
  657 +character stats is given on the ItemStatCost sheet.
  658 +
  659 +The column ID specifies the Id of the stat, as stored in the 9-bit field of the
  660 +two-value pair. The row containing that Id describes the stat. There is a
  661 +textual name of the stat in the Stat column, as well as the size of the value,
  662 +in bits, that follows the Id in the two-value pair. This size is specified by
  663 +the CSvBits column. Only values that have value 1 in the Saved column (first 16
  664 +stats) are actually saved in the character stats section of the save file.
  665 +
  666 +The stats described by the ItemStatCost table are as follows (in table below
  667 +Stat Name corresponds to the value in the Stat column from the data table):
  668 +
  669 +┌──────────┬───────────────────────────────────────────────────────────────────┐
  670 +│Stat Name │ Details │
  671 +├──────────┼───────────────────────────────────────────────────────────────────┤
  672 +│strength │ │
  673 +├──────────┤ │
  674 +│energy │ │
  675 +├──────────┤These stats are self-explanatory. They are always present. │
  676 +│dexterity │ │
  677 +├──────────┤ │
  678 +│vitality │ │
  679 +├──────────┼───────────────────────────────────────────────────────────────────┤
  680 +│ │The number of Stat Points earned but not distributed. This stat may│
  681 +│statpts │be absent from the save file if you have distibuted all stat │
  682 +│ │points. │
  683 +├──────────┼───────────────────────────────────────────────────────────────────┤
  684 +│ │The number of Skill Choices earned but not distributed. This stat │
  685 +│newskills │may be absent from the save file if you have distibuted all skill │
  686 +│ │points. │
  687 +├──────────┼───────────────────────────────────────────────────────────────────┤
  688 +│ │Current amount of Life points. │
  689 +│ │ │
  690 +│ │These 6 stats are (usually) always present. (There is an exception:│
  691 +│ │if your character is dead, the current Life stat will be gone!) │
  692 +│ │They are also not plain integer values! Instead, each field is a │
  693 +│ │fixed-point binary number, with a 24-bit integer part and an 8-bit │
  694 +│hitpoints │fraction part. For example, if the Current Life stat contains the │
  695 +│ │value 0x020AC0, then to get the amount of life remaining you take │
  696 +│ │that value and divide by 256.0 to get 522.75 (rounding the number │
  697 +│ │to an integer for display. Note that the current amount of Life, │
  698 +│ │Mana or Stamina may be more than the base amount, because the base │
  699 +│ │does not take into account any blessings bestowed by magical items │
  700 +│ │you are carrying. │
  701 +├──────────┼───────────────────────────────────────────────────────────────────┤
  702 +│maxhp │Base amount of Life points. │
  703 +├──────────┼───────────────────────────────────────────────────────────────────┤
  704 +│mana │Current amount of Mana points. │
  705 +├──────────┼───────────────────────────────────────────────────────────────────┤
  706 +│maxmana │Base amount of Mana points. │
  707 +├──────────┼───────────────────────────────────────────────────────────────────┤
  708 +│stamina │Current amount of Stamina points. │
  709 +├──────────┼───────────────────────────────────────────────────────────────────┤
  710 +│maxstamina│Base amount of Stamina points. │
  711 +├──────────┼───────────────────────────────────────────────────────────────────┤
  712 +│ │Your character's level. This value must be in the range 1-99 (and │
  713 +│level │is therefore always present, even on a new character, with a minor │
  714 +│ │exception) and should be the same as byte 43 in the file header. │
  715 +├──────────┼───────────────────────────────────────────────────────────────────┤
  716 +│ │The amount of experience your character has. If you haven't killed │
  717 +│experience│a single monster in the game, your experience will be 0, and this │
  718 +│ │field is not stored. Otherwise, this field is always present. │
  719 +├──────────┼───────────────────────────────────────────────────────────────────┤
  720 +│ │The amount of gold you are carrying with you (in your inventory or │
  721 +│ │backpack). Just as a helpful reminder, the maximum amount of gold │
  722 +│gold │you may carry is directly proportional to your level, at 10,000 │
  723 +│ │gold per level. Thus, a new character can only carry 10,000 gold │
  724 +│ │pieces, but a level 99 character (the maximum) can carry nearly a │
  725 +│ │million in gold (990,000). │
  726 +├──────────┼───────────────────────────────────────────────────────────────────┤
  727 +│ │The amount of gold you have stowed away (in stash). Just as a │
  728 +│goldbank │helpful reminder, starting from the 1.13c patch onwards, the │
  729 +│ │maximum amount of gold in your stash does not depend on your │
  730 +│ │character's level, and is now a flat cap of 2,500,000 instead. │
  731 +└──────────┴───────────────────────────────────────────────────────────────────┘
  732 +
  733 +As it was specified above, the stats list is terminated with a stat Id with a
  734 +special meaning (the Id has value 0x1FF in this case), and the stat value for
  735 +this stat Id is not stored (you may view it as a stat whose stat value is 0
  736 +bits in size). After that the remaining bits are padded with 0-bits to the
  737 +nearest byte-boundary so that the next section is byte-aligned.
  738 +
  739 +Character Skills
  740 +
  741 +The character skills section begins with the 2-character header, "if". This is
  742 +followed by 30 bytes, each byte corresponding to one of the character's special
  743 +skills. To save space, Trevin listed the skills in a separate table.
  744 +
  745 +Item List
  746 +
  747 +The next major section of the save file is the item list. It begins with the
  748 +following header:
  749 +
  750 +┌───────────────┬─────────────────────────────────────────────────────────────┐
  751 +│ Size │ Contents │
  752 +├───────────────┼─────────────────────────────────────────────────────────────┤
  753 +│2 chars │The string identifier "JM". │
  754 +├───────────────┼─────────────────────────────────────────────────────────────┤
  755 +│ │The number of items your character has. This includes items │
  756 +│ │equipped, tucked in your belt, stored in your inventory, │
  757 +│short │stored in your stash, and hidden in the Horadric Cube. It │
  758 +│ │does not, however, include gems, runes, or jewels which have │
  759 +│ │been inserted into a socketed item. (Those are counted as │
  760 +│ │part of the item.) │
  761 +└───────────────┴─────────────────────────────────────────────────────────────┘
  762 +
  763 +This header is followed by a list of items. The format of the items is
  764 +described on the Item Format page.
  765 +
  766 +After the list of items, you will find another item list header similar to the
  767 +one shown above; only this time the item count will be either 0 or 1. The value
  768 +0 means that your character is currently alive. If the value is 1, then that
  769 +means your character is dead (if you load this save, a corpse will be lying at
  770 +your feet in town), in which case 12 bytes of (unknown) data will follow, after
  771 +which there will be another items list header (the one with the identifier "JM"
  772 +and item count) and item list for items on your corpse. Sadly, the meaning of
  773 +the 12 bytes is unknown.
  774 +
  775 +If you have an Expansion character, then the corpse item list (if there is one)
  776 +will be followed by the 2-character identifier "jf". If and only if you have a
  777 +mercenary (alive or dead), this header is followed by an item list header and
  778 +(possibly empty) item list containing items equipped on the mercenary. This
  779 +item list is followed by the 2-character trailer "kf".
  780 +
  781 +If you have a necromancer, it is possible for you to have an Iron Golem that is
  782 +preserved when your game is saved and restored. The Iron Golem is based on an
  783 +item. Following the mercenary item list, there will be a single byte that is
  784 +0x00 if there is no golem, or 0x01 if there is. If there is a golem, this byte
  785 +is followed by a single item.
  786 +
docs/d2s_save_item_format_1.13d.html 0 → 100644
  1 +<html>
  2 +<h1 align="center">Diablo II Item Format</h1>
  3 +<h3 align="center">for Diablo II v1.13d Expansion Set: Lord of Destruction</h3>
  4 +<div align="center">Updated June 23, 2012<br/></div>
  5 +<p>This file was originally written by Trevin Beattie, whose site is no more (his latest version of this file is available
  6 +<a href="https://web.archive.org/web/20161225040510/http://web.archive.org/web/20070829095341/http://www.xmission.com/~trevin/DiabloIIv1.09_Item_Format.shtml">here</a> though).</p>
  7 +<h3>Welcome!</h3>
  8 +<p>Thanks for showing an interest in my Diablo II Item Format page. While
  9 +you're browsing, be sure to check out the preview of my <a href="https://web.archive.org/web/20161225040510/http://www.xmission.com/~trevin/DiabloIIv1.09_Editor.shtml">game
  10 +editor</a> for unix+Motif. I currently have the item editor in
  11 +development!</p>
  12 +<h2>Introduction</h2>
  13 +<p>Having searched the web, I found very few references to the Diablo II
  14 +<tt>.d2s</tt> file format, and most of them covered the old (pre-1.08)
  15 +version. Diablo II v1.09 has significantly changed the file format.
  16 +I have started another page which details <a href="Save_File_Format.xhtml">the
  17 +layout of the major parts of the <tt>.d2s</tt> file.</a> This document
  18 +focuses specifically on the item structure &#x2014; all those pieces of the file
  19 +tagged &quot;<tt>JM</tt>&quot;.</p>
  20 +<p>Rather than describe everything in terms of byte offsets, I'm going to define
  21 +the layout as a series of variable-length bit fields. This is a critical
  22 +part of the item format, because the position of many of the fields can change
  23 +depending on what comes before it. If I say a certain value is a 3-bit
  24 +field starting at bit position 150, for example, this translates to bits 6 and 7
  25 +of the byte 18 and bit 0 of byte 19 in the data structure. You can read an
  26 +arbitrary bit field programatically using the following code (in C):</p>
  27 +<pre>#define read_bits(start,size) \
  28 + ((*((unsigned long *) &amp;data[(start) / 8])
  29 + &gt;&gt; ((start) &amp; 7)) &amp; ((1 &lt;&lt; (size)) - 1))</pre>
  30 +<h2>Item List Header</h2>
  31 +<p>An item list begins with the following simple header:</p>
  32 +<table width="100%" border="1">
  33 +<tbody>
  34 + <tr>
  35 + <th width="10%">Byte Position</th>
  36 + <th width="10%">Size</th>
  37 + <th>Contents</th>
  38 + </tr>
  39 + <tr>
  40 + <td align="middle">0</td>
  41 + <td align="middle">2 <tt>char</tt>s</td>
  42 + <td>Identifier string &quot;<tt>JM</tt>&quot; { 0x4A, 0x4D }</td>
  43 + </tr>
  44 + <tr>
  45 + <td align="middle">2</td>
  46 + <td align="middle">16 bits</td>
  47 + <td>The number of items your character has. This does not include
  48 + gems or jewels which have been glued into socketed items.</td>
  49 + </tr>
  50 +</tbody>
  51 +</table>
  52 +<p>Your item list ends with another 4-byte structure similar to the above,
  53 +except the second field is zero (i.e.,
  54 +{&#xA0;0x4A,&#xA0;0x4D,&#xA0;0x00,&#xA0;0x00&#xA0;}).</p>
  55 +<p>In the Expansion Set, your hireling has his/her own item list. This
  56 +list is separated from yours by the 2-character identifier &quot;<tt>jf</tt>&quot;. This is
  57 +followed by an item list header for the hireling, and then his/her items.
  58 +The second item list is <i>not</i> terminated with the same 4-byte structure as
  59 +the first; instead, it is followed by the 2-character identifier &quot;<tt>kf</tt>&quot;.</p>
  60 +<h2>Item Structure part 1: Simple Items</h2>
  61 +<p>There are still many fields in the item structure which I haven't figured out
  62 +yet, but I'll leave placeholders for them in case I find out what they mean in
  63 +the future. All sizes are in bits unless otherwise specified.</p>
  64 +<table width="100%" border="1">
  65 +<tbody>
  66 + <tr>
  67 + <th width="10%">Bit Position</th>
  68 + <th width="10%">Size</th>
  69 + <th>Contents</th>
  70 + </tr>
  71 + <tr>
  72 + <td align="middle">0</td>
  73 + <td align="middle">2 <tt>char</tt>s</td>
  74 + <td>Identifier string &quot;<tt>JM</tt>&quot; { 0x4A, 0x4D }</td>
  75 + </tr>
  76 + <tr>
  77 + <td align="middle">16</td>
  78 + <td align="middle">4</td>
  79 + <td><i>unknown</i></td>
  80 + </tr>
  81 + <tr>
  82 + <td align="middle">20</td>
  83 + <td align="middle">1</td>
  84 + <td>Item has been identified</td>
  85 + </tr>
  86 + <tr>
  87 + <td align="middle">21</td>
  88 + <td align="middle">6</td>
  89 + <td><i>unknown</i></td>
  90 + </tr>
  91 + <tr>
  92 + <td align="middle"><a name="27">27</a></td>
  93 + <td align="middle">1</td>
  94 + <td>Item is <a href="#sockets">Socketed</a></td>
  95 + </tr>
  96 + <tr>
  97 + <td align="middle">28</td>
  98 + <td align="middle">1</td>
  99 + <td><i>unknown</i></td>
  100 + </tr>
  101 + <tr>
  102 + <td align="middle">29</td>
  103 + <td align="middle">1</td>
  104 + <td>This bit is set on items which you have picked up since the last time
  105 + the game was saved. <i>Why?...</i></td>
  106 + </tr>
  107 + <tr>
  108 + <td align="middle">30</td>
  109 + <td align="middle">2</td>
  110 + <td><i>unknown</i></td>
  111 + </tr>
  112 + <tr>
  113 + <td align="middle">32</td>
  114 + <td align="middle">1</td>
  115 + <td>
  116 + <div>Item is a <a href="#ear">Player Ear</a></div>
  117 + <div><i>Thanks go to Mike of Denmark for identifying this bit.</i></div></td>
  118 + </tr>
  119 + <tr>
  120 + <td align="middle">33</td>
  121 + <td align="middle">1</td>
  122 + <td>"Newbie" item. This bit is set on the weapon and shield your
  123 + character is given when you start the game. Apparently, this gives
  124 + the item the property of having a repair cost of 1gp, as well as a sell
  125 + value of 1gp.</td>
  126 + </tr>
  127 + <tr>
  128 + <td align="middle">34</td>
  129 + <td align="middle">3</td>
  130 + <td><i>unknown</i></td>
  131 + </tr>
  132 + <tr>
  133 + <td align="middle"><a name="37">37</a></td>
  134 + <td align="middle">1</td>
  135 + <td>
  136 + <div>Item is simple (only 111 bits {14 bytes} of item data)</div>
  137 + <div><i>Thanks go to Guillaume Courtin of France for discovering the
  138 + meaning of this bit.</i></div></td>
  139 + </tr>
  140 + <tr>
  141 + <td align="middle">38</td>
  142 + <td align="middle">1</td>
  143 + <td>Item is Ethereal (Cannot be Repaired)</td>
  144 + </tr>
  145 + <tr>
  146 + <td align="middle">39</td>
  147 + <td align="middle">1</td>
  148 + <td><i>unknown; this bit is 1 on the items I've looked at</i></td>
  149 + </tr>
  150 + <tr>
  151 + <td align="middle"><a name="40">40</a></td>
  152 + <td align="middle">1</td>
  153 + <td>Item has been <a href="#personalized">personalized</a> (by Anya in Act V)</td>
  154 + </tr>
  155 + <tr>
  156 + <td align="middle">41</td>
  157 + <td align="middle">1</td>
  158 + <td><i>unknown</i></td>
  159 + </tr>
  160 + <tr>
  161 + <td align="middle"><a name="42">42</a></td>
  162 + <td align="middle">1</td>
  163 + <td>It looks like this bit indicates the item has been given a <a href="#runeword">Rune Word</a>.</td>
  164 + </tr>
  165 + <tr>
  166 + <td align="middle">43</td>
  167 + <td align="middle">15</td>
  168 + <td><i>unknown; some of these bits may be set</i></td>
  169 + </tr>
  170 + <tr>
  171 + <td align="middle">58</td>
  172 + <td align="middle">3</td>
  173 + <td>
  174 + <div><a name="58">Item location.</a> Actually, I have only seen a few
  175 + values for these bits, so I'm not 100% certain of its validity. If
  176 + you see any other value here, let me know what it is and where the item is
  177 + located.</div>
  178 + <table cellspacing="0" width="80%" align="center" border="1">
  179 + <tbody>
  180 + <tr>
  181 + <td align="middle" width="20%">0</td>
  182 + <td width="60%">Item is stored (see <a href="#73">bit field 73</a>)</td>
  183 + </tr>
  184 + <tr>
  185 + <td align="middle">1</td>
  186 + <td>Item is equipped (somewhere on your body)</td>
  187 + </tr>
  188 + <tr>
  189 + <td align="middle">2</td>
  190 + <td>Item is tucked in your belt (or sash)</td>
  191 + </tr>
  192 + <tr>
  193 + <td align="middle">4</td>
  194 + <td>Item is being moved (i.e., has been picked up by the mouse).</td>
  195 + </tr>
  196 + <tr>
  197 + <td align="middle">6</td>
  198 + <td>Item is glued into a socket.</td>
  199 + </tr>
  200 + </tbody>
  201 + </table>
  202 + </td>
  203 + </tr>
  204 + <tr>
  205 + <td align="middle">61</td>
  206 + <td align="middle">4</td>
  207 + <td>
  208 + <div>If the item is equipped, this field tells where it is. Possible
  209 + values are:</div>
  210 + <table cellspacing="0" width="80%" align="center" border="1">
  211 + <tbody>
  212 + <tr>
  213 + <td align="middle" width="20%">1</td>
  214 + <td width="60%">head (helmet)</td>
  215 + </tr>
  216 + <tr>
  217 + <td align="middle">2</td>
  218 + <td>neck (amulet)</td>
  219 + </tr>
  220 + <tr>
  221 + <td align="middle">3</td>
  222 + <td>torso (armor)</td>
  223 + </tr>
  224 + <tr>
  225 + <td align="middle">4</td>
  226 + <td>right hand (weapon)</td>
  227 + </tr>
  228 + <tr>
  229 + <td align="middle">5</td>
  230 + <td>left hand (shield)</td>
  231 + </tr>
  232 + <tr>
  233 + <td align="middle">6</td>
  234 + <td>right finger (ring)</td>
  235 + </tr>
  236 + <tr>
  237 + <td align="middle">7</td>
  238 + <td>left finger (ring)</td>
  239 + </tr>
  240 + <tr>
  241 + <td align="middle">8</td>
  242 + <td>waist (belt)</td>
  243 + </tr>
  244 + <tr>
  245 + <td align="middle">9</td>
  246 + <td>feet (boots)</td>
  247 + </tr>
  248 + <tr>
  249 + <td align="middle">10</td>
  250 + <td>hands (gloves)</td>
  251 + </tr>
  252 + <tr>
  253 + <td align="middle">11</td>
  254 + <td>alternate right hand (Expansion Set only)</td>
  255 + </tr>
  256 + <tr>
  257 + <td align="middle">12</td>
  258 + <td>alternate left hand (Expansion Set only)</td>
  259 + </tr>
  260 + </tbody>
  261 + </table>
  262 + </td>
  263 + </tr>
  264 + <tr>
  265 + <td align="middle">65</td>
  266 + <td align="middle">4</td>
  267 + <td>
  268 + <p>Column number of the left corner of the item, counting from 0.
  269 + Your inventory has ten columns (numbered 0-9), your stash has six, and the
  270 + Horadric Cube has four.</p>
  271 + <p><strong>Note:</strong> Your belt is considered (for the purposes of the
  272 + item format) to have no rows, but either 4, 8, 12, or 16 columns. If
  273 + you prefer, you can divide this field and use the 2 bits at position 67-68
  274 + for the row (but only for belts).</p>
  275 + <p><strong>Note 2:</strong> If the item is equipped, glued to a socket, or
  276 + in transit, then this field appears to contain old data from the last time
  277 + the item was stored. I.e., it may be non-zero, but the value is
  278 + unused.</p></td>
  279 + </tr>
  280 + <tr>
  281 + <td align="middle">69</td>
  282 + <td align="middle">3</td>
  283 + <td>
  284 + <p>Row number of the top of the item, counting from 0. Your
  285 + inventory has four rows (numbered 0-3), your stash has four in normal
  286 + characters or eight in Expansion Set characters, and the Horadric Cube has
  287 + four. (In the belt, this field is always zero.)</p>
  288 + <p><strong>Note:</strong> If the item is equipped, tucked in your belt,
  289 + glued to a socket, or in transit, then this field appears to contain old
  290 + data from the last time the item was stored. I.e., it may be
  291 + non-zero, but the value is unused.</p></td>
  292 + </tr>
  293 + <tr>
  294 + <td align="middle">72</td>
  295 + <td align="middle">1</td>
  296 + <td><i>unknown</i></td>
  297 + </tr>
  298 + <tr>
  299 + <td align="middle">73</td>
  300 + <td align="middle">3</td>
  301 + <td>
  302 + <div><a name="73">Actually</a>, bit 74 seems to always be 0, but since bits
  303 + 73 and 75 are related I just lump them all together. If the item is
  304 + neither equipped nor in your belt, this field tells where it is.
  305 + Possible values are:</div>
  306 + <table cellspacing="0" width="80%" align="center" border="1">
  307 + <tbody>
  308 + <tr>
  309 + <td align="middle" width="20%">0</td>
  310 + <td width="60%">not here <i>(check <a href="#58">bit field 58</a>)</i></td>
  311 + </tr>
  312 + <tr>
  313 + <td align="middle">1</td>
  314 + <td>inventory</td>
  315 + </tr>
  316 + <tr>
  317 + <td align="middle">4</td>
  318 + <td>Horadric Cube</td>
  319 + </tr>
  320 + <tr>
  321 + <td align="middle">5</td>
  322 + <td>stash</td>
  323 + </tr>
  324 + </tbody>
  325 + </table>
  326 + <div><u>If you find an item having any other value in this field, let me
  327 + know what the value is and the item's location!</u></div></td>
  328 + </tr>
  329 + <tr>
  330 + <td align="middle">76</td>
  331 + <td align="middle">4 <tt>char</tt>s<br/>(8 bits ea.)</td>
  332 + <td><a name="76">Item's type.</a> The type is 3 lower-case letters or
  333 + numbers followed by a space; e.g., &quot;<tt>amu&#xA0;</tt>&quot; (Amulet) or &quot;<tt>2hs&#xA0;</tt>&quot;
  334 + (Two-Handed Sword). I have started a list of item identifiers (not
  335 + posted; sorry), but it is by no means complete; I'm sure I don't even have
  336 + half of what's out there!<br/><strong>Warning:</strong> This field is
  337 + <em>not</em> byte-aligned! It starts in the middle of byte 9 and
  338 + runs to the middle of byte 13.</td>
  339 + </tr>
  340 + <tr>
  341 + <td align="middle">108</td>
  342 + <td align="middle">3</td>
  343 + <td>The number of gems (or skulls or jewels) which have been glued to this
  344 + item (if <a href="#27">socketed</a>).
  345 + There will be this many additional item structures for the gems
  346 + immediately following this item, in the order that the gems were inserted.</td>
  347 + </tr>
  348 +</tbody>
  349 +</table>
  350 +<h2><a name="ear">Item Variant: Player Ears</a></h2>
  351 +<div><i>The following information was provided by Mike of Denmark.</i></div>
  352 +<p>If the item is a Player Ear, its structure is slightly different than the
  353 +Simple Items above. The last two fields in the Simple Item structure are
  354 +replaced by the following:</p>
  355 +<table width="100%" border="1">
  356 +<tbody>
  357 + <tr>
  358 + <th width="10%">Bit Position</th>
  359 + <th width="10%">Size</th>
  360 + <th>Contents</th>
  361 + </tr>
  362 + <tr>
  363 + <td align="middle">76</td>
  364 + <td align="middle">3</td>
  365 + <td>Character class of the ear's former owner. The defined classes
  366 + are:<br/>&#xA0;&#xA0;&#xA0;&#xA0; 0&#xA0;
  367 + Amazon<br/>&#xA0;&#xA0;&#xA0;&#xA0; 1&#xA0;
  368 + Sorceress<br/>&#xA0;&#xA0;&#xA0;&#xA0; 2&#xA0;
  369 + Necromancer<br/>&#xA0;&#xA0;&#xA0;&#xA0; 3&#xA0;
  370 + Paladin<br/>&#xA0;&#xA0;&#xA0;&#xA0; 4&#xA0;
  371 + Barbarian<br/>&#xA0;&#xA0;&#xA0;&#xA0; 5&#xA0; Druid (Expansion character
  372 + only)<br/>&#xA0;&#xA0;&#xA0;&#xA0; 6&#xA0; Assassin (Expansion character
  373 + only)</td>
  374 + </tr>
  375 + <tr>
  376 + <td align="middle">79</td>
  377 + <td align="middle">7</td>
  378 + <td>Character level of the ear's former owner.</td>
  379 + </tr>
  380 + <tr>
  381 + <td align="middle">86</td>
  382 + <td align="middle">7</td>
  383 + <td>First character of the former owner's name.</td>
  384 + </tr>
  385 + <tr>
  386 + <td align="middle">93</td>
  387 + <td align="middle">7 &#xD7; <i>N</i>-1</td>
  388 + <td>Second character of the former owner's name; Repeat until you get the
  389 + whole name (15 characters maximum).</td>
  390 + </tr>
  391 + <tr>
  392 + <td align="middle">86 + 7 &#xD7; <i>N</i></td>
  393 + <td align="middle">7</td>
  394 + <td>0&#xA0; (this indicates the end of the name)</td>
  395 + </tr>
  396 +</tbody>
  397 +</table>
  398 +<p>Following the end of the name, the rest of the final byte will be padded with
  399 +0's if necessary, and the Player Ear structure ends there.</p>
  400 +<h2>Item Structure part 2: Extended Items</h2>
  401 +<p>By &quot;extended items&quot; I mean any items which are not <a href="#37">simple.</a>
  402 +Simple items are those which need no further information than that given
  403 +above &#x2014; such as gems, potions, and small quest items &#x2014; and their structure length
  404 +is fixed at 14 bytes. Everything else has an extended structure with a
  405 +possibly variable length set of bit fields. First, I'll describe the part
  406 +of the structure that appears to be the same for all extended items. From
  407 +that point on, there will be no more &quot;bit positions&quot;; only &quot;this field follows
  408 +that field, if it exists&quot;.</p>
  409 +<table width="100%" border="1">
  410 +<tbody>
  411 + <tr>
  412 + <th width="10%">Bit Position</th>
  413 + <th width="10%">Size</th>
  414 + <th>Contents</th>
  415 + </tr>
  416 + <tr>
  417 + <td align="middle">111</td>
  418 + <td align="middle">32</td>
  419 + <td>Unique identifier. Diablo II randomly generates a value for this
  420 + field in order to discourage cheaters from &quot;duping&quot; items.
  421 + Supposedly, if it detects more than one extended item with the same unique
  422 + Id, it will delete the duplicates. (It hasn't done that for me in
  423 + single player mode, though.)</td>
  424 + </tr>
  425 + <tr>
  426 + <td align="middle">143</td>
  427 + <td align="middle">7</td>
  428 + <td>
  429 + <div>This appears to be the item's level; i.e., the level with which the
  430 + item was created (or 'dropped'). The item level is based on the
  431 + level of the monster who dropped it, the level of the area you're in if
  432 + found in a chest, or, in rare cases, your characters level. The item
  433 + level determines what modifiers are allowed on the item.</div>
  434 + <div><i>Note: this is just a theory at this point, but it seems to hold
  435 + for the items I've examined.</i></div></td>
  436 + </tr>
  437 + <tr>
  438 + <td align="middle">150</td>
  439 + <td align="middle">4</td>
  440 + <td>
  441 + <div>Item quality. This field can be one of the following values,
  442 + which determines the quality-specific bit fields that follow:</div>
  443 + <table cellspacing="0" width="80%" align="center" border="1">
  444 + <tbody>
  445 + <tr>
  446 + <td align="middle" width="20%">1</td>
  447 + <td width="60%"><a href="#low_quality">low quality</a></td>
  448 + </tr>
  449 + <tr>
  450 + <td align="middle">2</td>
  451 + <td><a href="#normal_data">normal</a></td>
  452 + </tr>
  453 + <tr>
  454 + <td align="middle">3</td>
  455 + <td><a href="#high_quality">high quality</a></td>
  456 + </tr>
  457 + <tr>
  458 + <td align="middle">4</td>
  459 + <td><a href="#magic_data">magically enhanced</a></td>
  460 + </tr>
  461 + <tr>
  462 + <td align="middle">5</td>
  463 + <td><a href="#set_data">part of a set</a></td>
  464 + </tr>
  465 + <tr>
  466 + <td align="middle">6</td>
  467 + <td><a href="#rare_data">rare</a></td>
  468 + </tr>
  469 + <tr>
  470 + <td align="middle">7</td>
  471 + <td><a href="#unique_data">unique</a></td>
  472 + </tr>
  473 + <tr>
  474 + <td align="middle">8</td>
  475 + <td><a href="#crafted_data">crafted</a></td>
  476 + </tr>
  477 + </tbody>
  478 + </table>
  479 + <div><i>Thanks go to Guillaume Courtin of France for finding the value of
  480 + crafted items.</i></div></td>
  481 + </tr>
  482 +</tbody>
  483 +</table>
  484 +<h2 align="center">WARNING: DATA BELOW THIS POINT MAY CONTAIN ERRORS</h2>
  485 +<h3><a name="ring_data">Ring Data</a></h3>
  486 +<p>After the above data, if the item is a ring, amulet, jewel, or charm, then it
  487 +has a 1 bit followed by three more bits. All other items (that I've seen)
  488 +have just a single 0 bit.</p>
  489 +<table width="100%" border="1">
  490 +<tbody>
  491 + <tr>
  492 + <th width="20%">Size</th>
  493 + <th colspan="2">Contents</th>
  494 + </tr>
  495 + <tr>
  496 + <td align="middle">1</td>
  497 + <td colspan="2">If this bit is set, the item has one of multiple pictures
  498 + associated with it; the next field determines which picture a particular
  499 + item uses. If this bit is 0, the next field is absent. The
  500 + picture field is used for rings, amulets, jewels, and charms.</td>
  501 + </tr>
  502 + <tr>
  503 + <td align="middle">3</td>
  504 + <td>Picture. <i>Optional; only present if the previous bit is 1.</i>
  505 + This field chooses the particular graphic used to display the ring.</td>
  506 + <td width="179"><img height="75" src="/web/20161225040510im_/http://www.coreyh.org/diablo-2-files/documentation/images/Ring_of_the_Leech.jpg" width="179"/></td>
  507 + </tr>
  508 +</tbody>
  509 +</table>
  510 +<p>From this point on, my information is very iffy.</p>
  511 +<h3><a name="unknown_11bit_data"><i>Unknown Field</i></a></h3>
  512 +<table width="100%" border="1">
  513 +<tbody>
  514 + <tr>
  515 + <th width="20%">Size</th>
  516 + <th>Contents</th>
  517 + </tr>
  518 + <tr>
  519 + <td align="middle">1</td>
  520 + <td>This bit apparently is set for certain class-specific Expansion Set
  521 + items. It indicates the presence of the next 11-bit field. If
  522 + this bit is 0, the next field is absent.</td>
  523 + </tr>
  524 + <tr>
  525 + <td align="middle">11</td>
  526 + <td>
  527 + <div><i>Credit for the discovery of this field's meaning goes entirely to
  528 + Guillaume Courtin of France. Thanks!</i></div>
  529 + <div>This field indicates magic properties which are inherent in certain
  530 + class-specific items. A given class-specific item will (almost)
  531 + always start with the same set of properties, even if its quality is
  532 + &quot;normal&quot;. Other quality ratings may add more properties to the
  533 + standard set. It appears that items which will have this field
  534 + are:</div>
  535 + <ul>
  536 + <li>Amazon-only bows, spears, and javelins</li>
  537 + <li>Voodoo heads (Necromancer-only shields)</li>
  538 + <li>Paladin-only shields</li>
  539 + <li>Orbs (Sorceress-Only wands)</li></ul></td>
  540 + </tr>
  541 +</tbody>
  542 +</table>
  543 +<h3><a name="low_quality">Low Quality Item Data</a></h3>
  544 +<p>If the item is one of low quality, it has 3 more bits that give the quality
  545 +details:</p>
  546 +<table width="100%" border="1">
  547 +<tbody>
  548 + <tr>
  549 + <th width="20%">Size</th>
  550 + <th colspan="2">Contents</th>
  551 + </tr>
  552 + <tr>
  553 + <td align="middle">3</td>
  554 + <td>
  555 + <div>Quality:</div>
  556 + <table cellspacing="0" width="80%" align="center" border="1">
  557 + <tbody>
  558 + <tr>
  559 + <td align="middle" width="20%">0</td>
  560 + <td width="60%">Crude</td>
  561 + </tr>
  562 + <tr>
  563 + <td align="middle">1</td>
  564 + <td>Cracked</td>
  565 + </tr>
  566 + <tr>
  567 + <td align="middle">2</td>
  568 + <td>Damaged</td>
  569 + </tr>
  570 + <tr>
  571 + <td align="middle">3</td>
  572 + <td>Low Quality</td>
  573 + </tr>
  574 + </tbody>
  575 + </table>
  576 + <div><i>I haven't recorded any instances of other values, but that doesn't
  577 + mean there won't be any. Also, I'm certain the value has something
  578 + to do with mods on an item's inherent (non-recorded) properties, such as
  579 + weapon damage, but I haven't figured out yet what the correlation is.</i></div></td>
  580 + <td width="173"><img height="121" src="/web/20161225040510im_/http://www.coreyh.org/diablo-2-files/documentation/images/Crude_Heavy_Boots.jpg" width="173"/></td>
  581 + </tr>
  582 +</tbody>
  583 +</table>
  584 +<h3><a name="normal_data">Normal Item Data</a></h3>
  585 +<p>Normal items have no extra quality data.</p>
  586 +<h3><a name="low_quality">High Quality ("Superior") Item Data</a></h3>
  587 +<p>If the item is one of high quality, it has 3 additional bits.</p>
  588 +<table width="100%" border="1">
  589 +<tbody>
  590 + <tr>
  591 + <th width="20%">Size</th>
  592 + <th>Contents</th>
  593 + </tr>
  594 + <tr>
  595 + <td align="middle">3</td>
  596 + <td><i>unknown. I'm certain the value has something to do with mods
  597 + on an item's inherent (non-recorded) properties, such as weapon damage,
  598 + but I haven't figured out yet what the correlation is.</i></td>
  599 + </tr>
  600 +</tbody>
  601 +</table>
  602 +<h3><a name="magic_data">Magically Enhanced Item Data</a></h3>
  603 +<p><img src="/web/20161225040510im_/http://www.coreyh.org/diablo-2-files/documentation/images/Sturdy_Spiked_Shield_of_Spikes.jpg" align="right"/>
  604 +Magically enhanced items have two 11-bit fields representing the item's prefix
  605 +and suffix. Either one (but not both) may be omitted. The prefix and
  606 +suffix each are used in choosing the <a href="#enhancements">magical
  607 +enhancements</a> for an item (although the enhancements are modifiable), and can
  608 +also increase the minimum level required to use them item and affect the item's
  609 +color.</p><img src="/web/20161225040510im_/http://www.coreyh.org/diablo-2-files/documentation/images/Mesh_Belt_of_the_Mammoth.jpg" align="left"/>
  610 +<br clear="both"/>
  611 +<table width="100%" border="1">
  612 +<tbody>
  613 + <tr>
  614 + <th width="20%">Size</th>
  615 + <th>Contents</th>
  616 + </tr>
  617 + <tr>
  618 + <td align="middle">11</td>
  619 + <td>Item prefix (i.e., &quot;Gold&quot; or &quot;Tangerine&quot;). I've started a <a href="Magic_Names.html#prefix">list
  620 + of prefix identifiers</a>, but it is very sparse at this time. If
  621 + this field is 0, the item has no prefix.</td>
  622 + </tr>
  623 + <tr>
  624 + <td align="middle">11</td>
  625 + <td>Item suffix (i.e., &quot;of Greed&quot; or &quot;of Life&quot;). I've started a <a href="Magic_Names.html#suffix">list
  626 + of suffix identifiers</a>, but it is very sparse at this time. If
  627 + this field is 0, the item has no suffix.</td>
  628 + </tr>
  629 +</tbody>
  630 +</table>
  631 +<h3><a name="set_data">Set Item Data</a></h3>
  632 +<p></p>Set items have a 12-bit field containing the ID of the set.
  633 +<em>(Not the set member, but the whole set.)</em> The set member is
  634 +identified by cross-referencing the <a href="#76">item
  635 +type</a> with the set Id. Also note that set items have <a href="#set_extended_data">an
  636 +extra field</a> following the <a href="#specific">item-specific data</a>.
  637 +<p><!-- @ --></p>
  638 +<table width="100%" border="1">
  639 +<tbody>
  640 + <tr>
  641 + <th width="20%">Size</th>
  642 + <th colspan="2">Contents</th>
  643 + </tr>
  644 + <tr>
  645 + <td align="middle">12</td>
  646 + <td>
  647 + <div>Set identifier; i.e., all items which are part of the set will have
  648 + the same value in this field. Since I've only identified a few set
  649 + items, I'll give their ID's here:</div>
  650 + <table cellspacing="0" width="80%" align="center" border="1">
  651 + <tbody>
  652 + <tr>
  653 + <td align="middle" width="20%">2</td>
  654 + <td width="60%"><span color="#004000">Cleglaw's Brace</span></td>
  655 + </tr>
  656 + <tr>
  657 + <td align="middle">3</td>
  658 + <td><span color="#004000">Iratha's Finery</span></td>
  659 + </tr>
  660 + <tr>
  661 + <td align="middle">4</td>
  662 + <td><span color="#004000">Isenhart's Armory</span></td>
  663 + </tr>
  664 + <tr>
  665 + <td align="middle">6</td>
  666 + <td><span color="#004000">Milabrega's Regalia</span></td>
  667 + </tr>
  668 + <tr>
  669 + <td align="middle">7</td>
  670 + <td><span color="#004000">Cathan's Traps</span></td>
  671 + </tr>
  672 + <tr>
  673 + <td align="middle">11</td>
  674 + <td><span color="#004000">Berserker's Arsenal</span></td>
  675 + </tr>
  676 + <tr>
  677 + <td align="middle">12</td>
  678 + <td><span color="#004000">Death's Disguise</span></td>
  679 + </tr>
  680 + <tr>
  681 + <td align="middle">13</td>
  682 + <td><span color="#004000">Angelic Raiment</span></td>
  683 + </tr>
  684 + </tbody>
  685 + </table></td>
  686 + <td width="245"><img height="250" src="/web/20161225040510im_/http://www.coreyh.org/diablo-2-files/documentation/images/Deaths_Hand_Leather_Gloves.jpg" width="245"/></td>
  687 + </tr>
  688 +</tbody>
  689 +</table>
  690 +<h3><a name="rare_data">Rare Item Data</a></h3>
  691 +<p><img height="294" src="/web/20161225040510im_/http://www.coreyh.org/diablo-2-files/documentation/images/Loath_Song_Battle_Axe.jpg" width="253" align="right"/> This is by far the worst beast to decode. Rare items have a
  692 +variable number of bits before we get to the item contents, and this number can
  693 +vary anywhere from 55 to 88!</p>
  694 +<p><img height="156" src="/web/20161225040510im_/http://www.coreyh.org/diablo-2-files/documentation/images/Eagle_Mark_Amulet.jpg" width="331" align="left"/> <i>Update 3/14/2002:</i> <strong>EUREKA!!</strong> I've
  695 +finally figured out the variable fields!; See the table below.<br clear="both"/></p>
  696 +<table width="100%" border="1">
  697 +<tbody>
  698 + <tr>
  699 + <th width="20%">Size</th>
  700 + <th>Contents</th>
  701 + </tr>
  702 + <tr>
  703 + <td align="middle">8</td>
  704 + <td>This is the Id for the <a href="Magic_Names.html#rare_first_name">first
  705 + word of the item's name</a> (i.e., &quot;Stone&quot; or &quot;Doom&quot;).</td>
  706 + </tr>
  707 + <tr>
  708 + <td align="middle">8</td>
  709 + <td>This is the ID for the <a href="Magic_Names.html#rare_second_name">second
  710 + word of the item's name</a> (i.e., &quot;Finger&quot; or &quot;Shroud&quot;).</td>
  711 + </tr>
  712 + <tr>
  713 + <td align="middle">1</td>
  714 + <td>If this field is 1, the next 11-bit field is present. If 0, the
  715 + next field is absent.</td>
  716 + </tr>
  717 + <tr>
  718 + <td align="middle">11</td>
  719 + <td>First <a href="Magic_Names.html#prefix">magic
  720 + prefix</a> <i>(optional)</i>. Although this &quot;prefix&quot; isn't actually
  721 + shown in the item name, it is used in determining the magical properties,
  722 + required level, coloring, and other attributes of the rare item.</td>
  723 + </tr>
  724 + <tr>
  725 + <td align="middle">1</td>
  726 + <td>If this field is 1, the next 11-bit field is present. If 0, the
  727 + next field is absent.</td>
  728 + </tr>
  729 + <tr>
  730 + <td align="middle">11</td>
  731 + <td>First <a href="Magic_Names.html#suffix">magic
  732 + suffix</a> <i>(optional)</i>. Although this &quot;suffix&quot; isn't actually
  733 + shown in the item name, it is used in determining the magical properties,
  734 + required level, coloring, and other attributes of the rare item.</td>
  735 + </tr>
  736 + <tr>
  737 + <td align="middle">1</td>
  738 + <td>If this field is 1, the next 11-bit field is present. If 0, the
  739 + next field is absent.</td>
  740 + </tr>
  741 + <tr>
  742 + <td align="middle">11</td>
  743 + <td>Second magic prefix <i>(optional)</i></td>
  744 + </tr>
  745 + <tr>
  746 + <td align="middle">1</td>
  747 + <td>If this field is 1, the next 11-bit field is present. If 0, the
  748 + next field is absent.</td>
  749 + </tr>
  750 + <tr>
  751 + <td align="middle">11</td>
  752 + <td>Second magic suffix <i>(optional)</i></td>
  753 + </tr>
  754 + <tr>
  755 + <td align="middle">1</td>
  756 + <td>If this field is 1, the next 11-bit field is present. If 0, the
  757 + next field is absent.</td>
  758 + </tr>
  759 + <tr>
  760 + <td align="middle">11</td>
  761 + <td>Third magic prefix <i>(optional)</i></td>
  762 + </tr>
  763 + <tr>
  764 + <td align="middle">1</td>
  765 + <td>If this field is 1, the next 11-bit field is present. If 0, the next field is absent.</td>
  766 + </tr>
  767 + <tr>
  768 + <td align="middle">11</td>
  769 + <td>Third magic suffix <i>(optional)</i></td>
  770 + </tr>
  771 +</tbody>
  772 +</table>
  773 +<h3><a name="unique_data">Unique Item Data</a></h3>
  774 +<p>Unique items have an additional 12 bit field, which in <em>most</em> cases is
  775 +the unique item ID. The few exceptions are certain quest items (e.g., the
  776 +Horadric Malus).</p>
  777 +<table width="100%" border="1">
  778 +<tbody>
  779 + <tr>
  780 + <th width="20%">Size</th>
  781 + <th colspan="2">Contents</th>
  782 + </tr>
  783 + <tr>
  784 + <td align="middle">12</td>
  785 + <td>
  786 + <div>Item identifier. Since I've only identified a few unique items,
  787 + I'll give their ID's here:</div>
  788 + <table cellspacing="0" width="80%" align="center" border="1">
  789 + <tbody>
  790 + <tr>
  791 + <td align="middle" width="20%">13</td>
  792 + <td width="60%"><span color="#8b6914">Ume's Lament</span> Grim Wand</td>
  793 + </tr>
  794 + <tr>
  795 + <td align="middle">31</td>
  796 + <td><span color="#8b6914">Hellplague</span> Long Sword</td>
  797 + </tr>
  798 + <tr>
  799 + <td align="middle">75</td>
  800 + <td><span color="#8b6914">Wormskull</span> Bone Helm</td>
  801 + </tr>
  802 + <tr>
  803 + <td align="middle">77</td>
  804 + <td><span color="#8b6914">Undead Crown</span> Crown <i>(no, that is not a typo!)</i></td>
  805 + </tr>
  806 + <tr>
  807 + <td align="middle">91</td>
  808 + <td><span color="#8b6914">Goldskin</span> Full Plate Mail</td>
  809 + </tr>
  810 + <tr>
  811 + <td align="middle">120</td>
  812 + <td><span color="#8b6914">Nagelring</span> Ring <i>(not a typo either; I checked)</i></td>
  813 + </tr>
  814 + <tr>
  815 + <td align="middle">123</td>
  816 + <td>Amulet <span color="#8b6914">of the Viper</span></td>
  817 + </tr>
  818 + <tr>
  819 + <td align="middle">125</td>
  820 + <td><span color="#8b6914">Horadric</span> Staff</td>
  821 + </tr>
  822 + <tr>
  823 + <td align="middle">126</td>
  824 + <td><span color="#8b6914">Hell Forge</span> Hammer</td>
  825 + </tr>
  826 + <tr>
  827 + <td align="middle">4095<br/>(0xFFF)</td>
  828 + <td><span color="#8b6914"><i>(other; probably a quest
  829 + item)</i></span></td>
  830 + </tr>
  831 + </tbody>
  832 + </table>
  833 + </td>
  834 + <td width="332"><img height="310" src="/web/20161225040510im_/http://www.coreyh.org/diablo-2-files/documentation/images/Hellplague.jpg" width="332"/></td>
  835 + </tr>
  836 +</tbody>
  837 +</table>
  838 +<h3><a name="crafted_data">Crafted Item Data</a></h3>
  839 +<p>Crafted items appear to be coded exactly like rare items, having a rare name
  840 +(two parts) and six optional prefixes / suffixes.</p>
  841 +<table width="100%" border="1">
  842 +<tbody>
  843 + <tr>
  844 + <th width="20%">Size</th>
  845 + <th>Contents</th>
  846 + </tr>
  847 + <tr>
  848 + <td align="middle">8</td>
  849 + <td>This is the Id for the <a href="Magic_Names.html#rare_first_name">first
  850 + word of the item's name</a> (i.e., &quot;Stone&quot; or &quot;Doom&quot;).</td>
  851 + </tr>
  852 + <tr>
  853 + <td align="middle">8</td>
  854 + <td>This is the Id for the <a href="Magic_Names.html#rare_second_name">second
  855 + word of the item's name</a> (i.e., &quot;Finger&quot; or &quot;Shroud&quot;).</td>
  856 + </tr>
  857 + <tr>
  858 + <td align="middle">1</td>
  859 + <td>If this field is 1, the next 11-bit field is present. If 0, the
  860 + next field is absent.</td>
  861 + </tr>
  862 + <tr>
  863 + <td align="middle">11</td>
  864 + <td>First <a href="Magic_Names.html#prefix">magic
  865 + prefix</a> <i>(optional)</i>. Although this &quot;prefix&quot; isn't actually
  866 + shown in the item name, it is used in determining the magical properties,
  867 + required level, coloring, and other attributes of the crafted item.</td>
  868 + </tr>
  869 + <tr>
  870 + <td align="middle">1</td>
  871 + <td>If this field is 1, the next 11-bit field is present. If 0, the
  872 + next field is absent.</td>
  873 + </tr>
  874 + <tr>
  875 + <td align="middle">11</td>
  876 + <td>First <a href="Magic_Names.html#suffix">magic
  877 + suffix</a> <i>(optional)</i>. Although this &quot;suffix&quot; isn't actually
  878 + shown in the item name, it is used in determining the magical properties,
  879 + required level, coloring, and other attributes of the crafted item.</td>
  880 + </tr>
  881 + <tr>
  882 + <td align="middle">1</td>
  883 + <td>If this field is 1, the next 11-bit field is present. If 0, the
  884 + next field is absent.</td>
  885 + </tr>
  886 + <tr>
  887 + <td align="middle">11</td>
  888 + <td>Second magic prefix <i>(optional)</i></td>
  889 + </tr>
  890 + <tr>
  891 + <td align="middle">1</td>
  892 + <td>If this field is 1, the next 11-bit field is present. If 0, the
  893 + next field is absent.</td>
  894 + </tr>
  895 + <tr>
  896 + <td align="middle">11</td>
  897 + <td>Second magic suffix <i>(optional)</i></td>
  898 + </tr>
  899 + <tr>
  900 + <td align="middle">1</td>
  901 + <td>If this field is 1, the next 11-bit field is present. If 0, the
  902 + next field is absent.</td>
  903 + </tr>
  904 + <tr>
  905 + <td align="middle">11</td>
  906 + <td>Third magic prefix <i>(optional)</i></td>
  907 + </tr>
  908 + <tr>
  909 + <td align="middle">1</td>
  910 + <td>If this field is 1, the next 11-bit field is present. If 0, the
  911 + next field is absent.</td>
  912 + </tr>
  913 + <tr>
  914 + <td align="middle">11</td>
  915 + <td>Third magic suffix <i>(optional)</i></td>
  916 + </tr>
  917 +</tbody>
  918 +</table>
  919 +<h3><a name="runeword">Rune Word</a></h3>
  920 +<p>If the item has a rune word (indicated by <a href="#42">bit
  921 +42</a> being set), there is an additional field at this point.</p>
  922 +<table width="100%" border="1">
  923 +<tbody>
  924 + <tr>
  925 + <th width="20%">Size</th>
  926 + <th>Contents</th>
  927 + </tr>
  928 + <tr>
  929 + <td align="middle">12</td>
  930 + <td>This <em>appears</em> to be an index to the rune word, although I
  931 + can't say what the index is based on. The first rune word,
  932 + &quot;Ancient's Pledge&quot;, has a value of 27. The next rune word, &quot;Black&quot;,
  933 + has a value of 32. etc.</td>
  934 + </tr>
  935 + <tr>
  936 + <td align="middle">4</td>
  937 + <td><i>Unknown; the value is 5 on all items I've looked at.</i></td>
  938 + </tr>
  939 +</tbody>
  940 +</table>
  941 +<h3><a name="personalized">Personalization</a></h3>
  942 +<p>The following segment is present if and only if the item is personalized
  943 +(i.e., <a href="#40">bit
  944 +40</a> is set). Only armor and weapons (except for quest items) can be
  945 +personalized.</p>
  946 +<table width="100%" border="1">
  947 +<tbody>
  948 + <tr>
  949 + <th width="20%">Size</th>
  950 + <th>Contents</th>
  951 + </tr>
  952 + <tr>
  953 + <td align="middle">7</td>
  954 + <td>First character of the owner's name (just plain ASCII!)</td>
  955 + </tr>
  956 + <tr>
  957 + <td align="middle">7</td>
  958 + <td>Second character of the owner's name</td>
  959 + </tr>
  960 + <tr>
  961 + <td align="middle">7 &#xD7; <i>N</i>-2</td>
  962 + <td>Repeat until you get the whole name (15 characters maximum)</td>
  963 + </tr>
  964 + <tr>
  965 + <td align="middle">7</td>
  966 + <td>0&#xA0; (this indicates the end of the name)</td>
  967 + </tr>
  968 +</tbody>
  969 +</table>
  970 +<h3><a name="unknown_11bit_data"><i>Unknown Field</i></a></h3>
  971 +<p>All items have this field between the personalization (if it exists) and the
  972 +item-specific data:</p>
  973 +<table width="100%" border="1">
  974 +<tbody>
  975 + <tr>
  976 + <th width="20%">Size</th>
  977 + <th>Contents</th>
  978 + </tr>
  979 + <tr>
  980 + <td align="middle">1</td>
  981 + <td><i>unknown; this usually is 0, but is 1 on a Tome of Identify.
  982 + (It's still 0 on a Tome of Townportal.)</i></td>
  983 + </tr>
  984 +</tbody>
  985 +</table>
  986 +<h2><a name="specific">Item Structure part 3: Item-Specific Data</a></h2>
  987 +<p>The presence of the following fields depends on the item type. Fields
  988 +which are present will be stored in the order shown. Unfortunately there
  989 +is no means of telling which fields are present from the item data itself; you
  990 +need to look up the <a href="#76">item
  991 +type</a> in a table to figure out whether it is a weapon, armor, or stack, and
  992 +read the fields accordingly.</p>
  993 +<h3>Armor: Defense Rating</h3>
  994 +<table width="100%" border="1">
  995 +<tbody>
  996 + <tr>
  997 + <th width="20%">Size</th>
  998 + <th>Contents</th>
  999 + </tr>
  1000 + <tr>
  1001 + <td align="middle">10</td>
  1002 + <td>Defense value +10. i.e., a defense rating of 23 would be
  1003 + stored in this field as 33; thus the maximum defense value you can store
  1004 + is 1013 (although I haven't tried it). Note that this is the base
  1005 + defense rating, before applying any magical enhancements (i.e., the number
  1006 + shown in white).</td>
  1007 + </tr>
  1008 +</tbody>
  1009 +</table>
  1010 +<h3>Armor and Weapons: Durability</h3>
  1011 +<p>Even though stacked weapons don't show any durability rating in the game,
  1012 +they still have two 8-bit fields in the same spot. This includes bombs
  1013 +(exploding and gas potions). The values in such cases are very small, so
  1014 +I'm not sure what they mean.</p>
  1015 +<table width="100%" border="1">
  1016 +<tbody>
  1017 + <tr>
  1018 + <th width="20%">Size</th>
  1019 + <th>Contents</th>
  1020 + </tr>
  1021 + <tr>
  1022 + <td align="middle">8</td>
  1023 + <td>Maximum Durability. Note that this is the base durability,
  1024 + before applying any magical enhancements (i.e., the number shown in
  1025 + white).<br/><i>Note: </i>I've found an indestructable item, and it appears
  1026 + that in such a case the maximum durability field is zero!</td>
  1027 + </tr>
  1028 + <tr>
  1029 + <td align="middle">8</td>
  1030 + <td>Current Durability. This may be greater than the maximum
  1031 + durability if the item is magically enhanced.<br/><i>Note: </i>I've found
  1032 + an indestructable item, and it appears that in such a case the current
  1033 + durability field is missing!</td>
  1034 + </tr>
  1035 +</tbody>
  1036 +</table>
  1037 +<h3><a name="sockets">Armor and (non-stacked) Weapons: Sockets</a></h3>
  1038 +<p>The following field is present if and only if the item is socketed (i.e., <a href="#27">bit
  1039 +27</a> is set).</p>
  1040 +<table width="100%" border="1">
  1041 +<tbody>
  1042 + <tr>
  1043 + <th width="20%">Size</th>
  1044 + <th colspan="2">Contents</th>
  1045 + </tr>
  1046 + <tr>
  1047 + <td align="middle">4</td>
  1048 + <td>Number of sockets<br/><i>Note that even though this field is 4 bits
  1049 + wide, each item type has a built-in upper limit to the total number of
  1050 + sockets. This limit is built into the game. The most I've ever
  1051 + seen is 6 for, e.g., a gothic axe.</i></td>
  1052 + <td width="179"><img height="137" src="/web/20161225040510im_/http://www.coreyh.org/diablo-2-files/documentation/images/Socketed_Mask.jpg" width="179"/></td>
  1053 + </tr>
  1054 +</tbody>
  1055 +</table>
  1056 +<h3>Tomes:</h3>
  1057 +<p>Tomes have an extra 5 bits inserted at this point. I have no idea what
  1058 +purpose they serve. It looks like the value is 0 on all of my tomes.</p>
  1059 +<table width="100%" border="1">
  1060 +<tbody>
  1061 + <tr>
  1062 + <th width="20%">Size</th>
  1063 + <th>Contents</th>
  1064 + </tr>
  1065 + <tr>
  1066 + <td align="middle">5</td>
  1067 + <td><i>unknown</i></td>
  1068 + </tr>
  1069 +</tbody>
  1070 +</table>
  1071 +<h3>Stacked Weapons, Quivers, Keys, and Tomes: Quantity</h3>
  1072 +<table width="100%" border="1">
  1073 +<tbody>
  1074 + <tr>
  1075 + <th width="20%">Size</th>
  1076 + <th>Contents</th>
  1077 + </tr>
  1078 + <tr>
  1079 + <td align="middle">9</td>
  1080 + <td>Quantity</td>
  1081 + </tr>
  1082 +</tbody>
  1083 +</table>
  1084 +<h2><a name="enhancements">Item Structure part 3: Magical Enhancements</a></h2>
  1085 +<h3>Item Structure part 2<sup>bis</sup>: <a name="set_extended_data">Set Item Data
  1086 +Revisited</a></h3>
  1087 +<p>Items which are part of a set have an additional 5 bits following the
  1088 +item-specific data.</p>
  1089 +<table width="100%" border="1">
  1090 +<tbody>
  1091 + <tr>
  1092 + <th width="20%">Size</th>
  1093 + <th>Contents</th>
  1094 + </tr>
  1095 + <tr>
  1096 + <td align="middle">5</td>
  1097 + <td>This appears to be an indicator of how many lists of magic properties
  1098 + follows. The first list are the properties the item has if you do
  1099 + not have any other members of the set. Following lists are applied
  1100 + once you equip other items in the set. The value is 1 if there are
  1101 + two (total) property lists, or 3 if there are three property lists.</td>
  1102 + </tr>
  1103 +</tbody>
  1104 +</table>
  1105 +<p>Following the item-specific data are a variable number of variable length bit
  1106 +fields describing any magical enhancements placed on the item. Each
  1107 +property begins with a 9-bit identifier. An identifier of <tt>0x1FF</tt>
  1108 +(all 1's) indicates the end of the property list ... except in the event the
  1109 +item belongs to a set, in which case there will be another one or two groups of
  1110 +magical properties following, depending on whether the set item data (above) is
  1111 +1 or 3, respectively. Also, if an item has been given a <a href="#42">Rune
  1112 +Word</a>, it appears that the Rune Word's properties begin with a <tt>0x1FF</tt>
  1113 +identifier (presumably to set them apart from the item's normal properties...
  1114 +but I need to examine more items to be certain.)</p>
  1115 +<p>Because the number of bits (and fields) after the 9-bit identifier varies, I
  1116 +do not give a field width here. Instead, check my <a href="Magic_Properties.html">table
  1117 +of magic properties</a> for field sizes. I'm sure it's not complete, but
  1118 +it does have most of the common properties.</p>
  1119 +<p>Following the last 9-bit value of 0x1FF, the rest of the final byte will be
  1120 +padded with 0's if necessary, and the item structure ends there. For
  1121 +example, if the item had 341 bits of data, the last (43<sup>rd</sup>) byte will
  1122 +be 0x1F. If the item had 248 bits of data, the last (31<sup>st</sup>) byte
  1123 +will be 0xFF.</p>
  1124 +</body>
  1125 +</html>