diff --git a/d2char.c b/d2char.c index 4135c4e..5e90cb6 100644 --- a/d2char.c +++ b/d2char.c @@ -1,7 +1,8 @@ +#include + #include "d2char.h" -#include "d2skills.h" #include "d2mercs.h" -#include +#include "d2skills.h" uint32_t calcChecksum(D2CharHeader* c, void* charData) { uint32_t origChecksum = c->checksum; @@ -61,9 +62,6 @@ const char* getCharacterTitle(D2CharHeader* c) { if(isHardcore(c)) { // Expansion Hardcore switch(tier) { - case 0: - return D2S_CHARPROGRESS_TIER0_NAME; - break; case 1: return D2S_CHARPROGRESS_EXPANSION_TIER1_NAME_HARDCORE; break; @@ -77,9 +75,6 @@ const char* getCharacterTitle(D2CharHeader* c) { } else { // Expansion Softcore switch(tier) { - case 0: - return D2S_CHARPROGRESS_TIER0_NAME; - break; case 1: return D2S_CHARPROGRESS_EXPANSION_TIER1_NAME; break; @@ -96,9 +91,6 @@ const char* getCharacterTitle(D2CharHeader* c) { if(isHardcore(c)) { // Classic Hardcore switch(tier) { - case 0: - return D2S_CHARPROGRESS_TIER0_NAME; - break; case 1: return isFemale(c) ? D2S_CHARPROGRESS_CLASSIC_TIER1_NAME_HARDCORE_F : D2S_CHARPROGRESS_CLASSIC_TIER1_NAME_HARDCORE_M; break; @@ -112,9 +104,6 @@ const char* getCharacterTitle(D2CharHeader* c) { } else { // Classic Softcore switch(tier) { - case 0: - return D2S_CHARPROGRESS_TIER0_NAME; - break; case 1: return isFemale(c) ? D2S_CHARPROGRESS_CLASSIC_TIER1_NAME_F : D2S_CHARPROGRESS_CLASSIC_TIER1_NAME_M; break; @@ -127,10 +116,18 @@ const char* getCharacterTitle(D2CharHeader* c) { } } } + return D2S_CHARPROGRESS_TIER0_NAME; } size_t getLastPlayed(D2CharHeader* c, char* buf, size_t bufLen) { - struct tm* time = localtime(&(c->lastPlayed)); + // In amd64, since long is 64 bits long, time_t is also 64 bits long + // thus needing conversion from the save file type, which is a uint32_t + #ifdef __x86_64__ + uint64_t convTimestamp = c->lastPlayed; + #else + uint32_t convTimestamp = c->lastPlayed; + #endif + struct tm* time = localtime((time_t*)&convTimestamp); size_t ret = strftime(buf, bufLen, "%c", time); if(!ret) { fprintf(stderr,"libd2char error: Provided buffer for time string was too small\n"); @@ -152,7 +149,7 @@ int getCurrentDifficulty(D2CharHeader* c) { } const char* getMercName(D2CharHeader* c) { - return getMercNameTableEntry(c->mercenaryType, c->mercenaryNameID); + return _getMercName(c->mercenaryType, c->mercenaryNameID); } const char* getMercType(D2CharHeader* c) { diff --git a/d2char.h b/d2char.h index b1f789e..b253ed2 100644 --- a/d2char.h +++ b/d2char.h @@ -3,6 +3,10 @@ #include #include +#include +#include + +#include "d2quest.h" #include "d2strings.h" #define D2S_HEADER_LENGTH 765 @@ -13,7 +17,6 @@ #define D2S_HOTKEYS_LENGTH 64 #define D2S_CHAR_APPEARANCE_LENGTH 32 #define D2S_DIFFICULTY_LENGTH 3 -#define D2S_QUESTS_LENGTH 298 #define D2S_WAYPOINTS_LENGTH 81 #define D2S_NPCDATA_LENGTH 51 @@ -49,10 +52,10 @@ enum D2S_CHARCLASS { enum D2S_ACT { D2S_ACT1 = 0, - D2S_ACT2 = 1, - D2S_ACT3 = 2, - D2S_ACT4 = 3, - D2S_ACT5 = 4 + D2S_ACT2, + D2S_ACT3, + D2S_ACT4, + D2S_ACT5 }; typedef struct __attribute__((packed)){ @@ -71,7 +74,7 @@ typedef struct __attribute__((packed)){ uint32_t unknown3; // TODO uint32_t lastPlayed; uint32_t unknown4; // TODO - uint8_t hotkeys[D2S_HOTKEYS_LENGTH]; // Not implemented. Too bad! + uint8_t hotkeys[D2S_HOTKEYS_LENGTH]; // Not implemented. (Yet) uint32_t leftAbility; uint32_t rightAbility; uint32_t leftAbilityAlt; // Left ability when alternative weapon set (II) is selected @@ -86,7 +89,7 @@ typedef struct __attribute__((packed)){ uint16_t mercenaryType; uint32_t mercenaryExp; uint8_t unknown6[144]; // TODO - uint8_t questData[D2S_QUESTS_LENGTH]; + D2QuestData questData; uint8_t waypointData[D2S_WAYPOINTS_LENGTH]; uint8_t NPCIntroductions[D2S_NPCDATA_LENGTH]; // Not implemented. (Yet) } D2CharHeader; diff --git a/d2mercs.c b/d2mercs.c index 9d95c9f..a1af155 100644 --- a/d2mercs.c +++ b/d2mercs.c @@ -15,6 +15,6 @@ int _getMercType(int mercID) { } const char* _getMercName(int mercID, int mercNameID) { - int offset = getMercType(mercID); + int offset = _getMercType(mercID); return mercNames[mercNameID + offset]; } \ No newline at end of file diff --git a/d2quest.c b/d2quest.c new file mode 100644 index 0000000..383585f --- /dev/null +++ b/d2quest.c @@ -0,0 +1,148 @@ +#include "d2char.h" +#include "d2quest.h" + +void getQuestData_DenOfEvil(D2QuestData* d, int difficulty, void* dest) { + uint16_t questData = d->quests[difficulty].actData[D2S_ACT1].questCheckpoints[0]; + +} + +void getQuestData_SisterBurialGrounds(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_SearchForCain(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_ForgottenTower(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_ToolsOfTheTrade(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_SistersToTheSlaughter(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_RadamentLair(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_HoradricStaff(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_TaintedSun(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_ArcaneSanctuary(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_Summoner(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_SevenTombs(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_GoldenBird(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_BladeOfTheOldReligion(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_KhalimWill(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_LamEsenTome(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_BlackenedTemple(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_Guardian(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_FallenAngel(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_Hellforge(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_TerrorEnd(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_SiegeOnHarrogath(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_RescueOnMountArreat(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_PrisonOfIce(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_BetrayalOfHarrogath(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_RiteOfPassage(D2QuestData* d, int difficulty, void* dest) { + +} + +void getQuestData_EveOfDestruction(D2QuestData* d, int difficulty, void* dest) { + +} + +void(*questFunc[])(D2QuestData*,int,void*) = { + &getQuestData_DenOfEvil, + &getQuestData_SisterBurialGrounds, + &getQuestData_SearchForCain, + &getQuestData_ForgottenTower, + &getQuestData_ToolsOfTheTrade, + &getQuestData_SistersToTheSlaughter, + &getQuestData_RadamentLair, + &getQuestData_HoradricStaff, + &getQuestData_TaintedSun, + &getQuestData_ArcaneSanctuary, + &getQuestData_Summoner, + &getQuestData_SevenTombs, + &getQuestData_GoldenBird, + &getQuestData_BladeOfTheOldReligion, + &getQuestData_KhalimWill, + &getQuestData_LamEsenTome, + &getQuestData_BlackenedTemple, + &getQuestData_Guardian, + &getQuestData_FallenAngel, + &getQuestData_Hellforge, + &getQuestData_TerrorEnd, + &getQuestData_SiegeOnHarrogath, + &getQuestData_RescueOnMountArreat, + &getQuestData_PrisonOfIce, + &getQuestData_BetrayalOfHarrogath, + &getQuestData_RiteOfPassage, + &getQuestData_EveOfDestruction +}; + +int getQuestStatus(D2QuestData* d, unsigned int quest, unsigned int difficulty, void* dest) { + if(quest >= D2S_QUEST_DEN_OF_EVIL && quest <= D2S_QUEST_EVE_OF_DESTRUCTION) { + questFunc[quest](d,difficulty,dest); + } + return D2S_QUEST_UNKNOWN; +} \ No newline at end of file diff --git a/d2quest.h b/d2quest.h new file mode 100644 index 0000000..d48ba73 --- /dev/null +++ b/d2quest.h @@ -0,0 +1,176 @@ +#ifndef D2QUEST_H +#define D2QUEST_H + +#include + +#define D2S_QUESTDATA_HEADER_LENGTH 4 + +enum D2S_QUEST { + D2S_QUEST_UNKNOWN = -1, + D2S_QUEST_DEN_OF_EVIL = 0, + D2S_QUEST_SISTER_BURIAL_GROUNDS, + D2S_QUEST_SEARCH_FOR_CAIN, + D2S_QUEST_FORGOTTEN_TOWER, + D2S_QUEST_TOOLS_OF_THE_TRADE, + D2S_QUEST_SISTERS_TO_THE_SLAUGHTER, + D2S_QUEST_RADAMENT_LAIR, + D2S_QUEST_HORADRIC_STAFF, + D2S_QUEST_TAINTED_SUN, + D2S_QUEST_ARCANE_SANCTUARY, + D2S_QUEST_SUMMONER, + D2S_QUEST_SEVEN_TOMBS, + D2S_QUEST_GOLDEN_BIRD, + D2S_QUEST_BLADE_OF_THE_OLD_RELIGION, + D2S_QUEST_KHALIM_WILL, + D2S_QUEST_LAM_ESEN_TOME, + D2S_QUEST_BLACKENED_TEMPLE, + D2S_QUEST_GUARDIAN, + D2S_QUEST_FALLEN_ANGEL, + D2S_QUEST_HELLFORGE, + D2S_QUEST_TERROR_END, + D2S_QUEST_SIEGE_ON_HARROGATH, + D2S_QUEST_RESCUE_ON_MOUNT_ARREAT, + D2S_QUEST_PRISON_OF_ICE, + D2S_QUEST_BETRAYAL_OF_HARROGATH, + D2S_QUEST_RITE_OF_PASSAGE, + D2S_QUEST_EVE_OF_DESTRUCTION +}; + +typedef struct { + int enteredDen; +} D2S_QUEST_DEN_OF_EVIL_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_SISTER_BURIAL_GROUNDS_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_SEARCH_FOR_CAIN_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_FORGOTTEN_TOWER_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_TOOLS_OF_THE_TRADE_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_SISTERS_TO_THE_SLAUGHTER_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_RADAMENT_LAIR_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_HORADRIC_STAFF_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_TAINTED_SUN_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_ARCANE_SANCTUARY_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_SUMMONER_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_SEVEN_TOMBS_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_GOLDEN_BIRD_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_BLADE_OF_THE_OLD_RELIGION_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_KHALIM_WILL_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_LAM_ESEN_TOME_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_BLACKENED_TEMPLE_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_GUARDIAN_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_FALLEN_ANGEL_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_HELLFORGE_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_TERROR_END_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_SIEGE_ON_HARROGATH_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_RESCUE_ON_MOUNT_ARREAT_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_PRISON_OF_ICE_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_BETRAYAL_OF_HARROGATH_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_RITE_OF_PASSAGE_struct; + +typedef struct { + int enteredDen; +} D2S_QUEST_EVE_OF_DESTRUCTION_struct; + +typedef struct __attribute__((packed)) { + uint16_t actStarted; + uint16_t questCheckpoints[6]; + uint16_t actEnded; +} D2ActData; + +typedef struct __attribute__((packed)) { + uint16_t actStarted; + uint16_t unknown1[2]; + uint16_t questCheckpoints[6]; + uint16_t unknown2[7]; +} D2XActData; + +typedef struct __attribute__((packed)) { + D2ActData actData[4]; + D2XActData expansionAct; +} D2Quests; + +typedef struct __attribute__((packed)) { + const char* header[D2S_QUESTDATA_HEADER_LENGTH]; + uint32_t unknown1; + uint16_t size; // in bytes + D2Quests quests[3]; // 1 set for each difficulty +} D2QuestData; + +// Returns quest status for the specified quest and act. dest must be a struct of the specified +// quest. Passing anything else may cause the program to crash if it doesn't fit into memory :) +int getQuestStatus(D2QuestData* d, unsigned int quest, unsigned int difficulty, void* dest); + +#endif \ No newline at end of file diff --git a/d2skills.h b/d2skills.h index 09e158c..15a91e0 100644 --- a/d2skills.h +++ b/d2skills.h @@ -2,6 +2,7 @@ #define D2SKILLS_H #include + #include "d2strings.h" const char* const skills[] = {