diff --git a/Source/pfile.cpp b/Source/pfile.cpp index 4ae97d14d..b1f5ebf61 100644 --- a/Source/pfile.cpp +++ b/Source/pfile.cpp @@ -2,10 +2,13 @@ #include "../types.h" -int pfile_cpp_init_value; -char hero_names[MAX_CHARACTERS][PLR_NAME_LEN]; +#define PASSWORD_SINGLE "xrgyrkj1" +#define PASSWORD_MULTI "szqnlsk1" + +static int pfile_cpp_init_value; +static char hero_names[MAX_CHARACTERS][PLR_NAME_LEN]; BOOL gbValidSaveFile; // idb -int save_prev_tc; // weak +static int save_prev_tc; // weak const int pfile_inf = 0x7F800000; // weak @@ -35,37 +38,30 @@ void __cdecl pfile_init_save_directory() void __fastcall pfile_check_available_space(char *pszDir) { - char *v1; // edi - char *v2; // eax - char v3; // cl - BOOL v4; // esi - DWORD TotalNumberOfClusters; // [esp+8h] [ebp-10h] - DWORD NumberOfFreeClusters; // [esp+Ch] [ebp-Ch] - DWORD BytesPerSector; // [esp+10h] [ebp-8h] - DWORD SectorsPerCluster; // [esp+14h] [ebp-4h] - - v1 = pszDir; - v2 = pszDir; - while ( 1 ) - { - v3 = *v2; - if ( !*v2 ) - break; - ++v2; - if ( v3 == '\\' ) - { - *v2 = '\0'; - break; - } + char *s; + BOOL hasSpace; + DWORD TotalNumberOfClusters; + DWORD NumberOfFreeClusters; + DWORD BytesPerSector; + DWORD SectorsPerCluster; + + s = pszDir; + while ( *s ) { + if ( *s++ != '\\' ) + continue; + *s = '\0'; + break; } - v4 = GetDiskFreeSpace(v1, &SectorsPerCluster, &BytesPerSector, &NumberOfFreeClusters, &TotalNumberOfClusters); - if ( !v4 ) - goto LABEL_12; - if ( (signed __int64)(BytesPerSector * (unsigned __int64)SectorsPerCluster * NumberOfFreeClusters) < 0xA00000 ) - v4 = 0; - if ( !v4 ) -LABEL_12: - DiskFreeDlg(v1); + + hasSpace = GetDiskFreeSpace(pszDir, &SectorsPerCluster, &BytesPerSector, &NumberOfFreeClusters, &TotalNumberOfClusters); + if ( hasSpace ) { + // 10MB is the amount hardcoded in the error dialog + if ( (__int64)SectorsPerCluster * BytesPerSector * NumberOfFreeClusters < (__int64)(10 << 20) ) + hasSpace = FALSE; + } + + if ( !hasSpace ) + DiskFreeDlg(pszDir); } void __cdecl pfile_write_hero() @@ -87,45 +83,34 @@ void __cdecl pfile_write_hero() } // 679660: using guessed type char gbMaxPlayers; -int __fastcall pfile_get_save_num_from_name(char *name) +unsigned int __fastcall pfile_get_save_num_from_name(const char *name) { - char *v1; // ebx - unsigned int v2; // esi + unsigned int i; - v1 = name; - v2 = 0; - do - { - if ( !_strcmpi(hero_names[v2], v1) ) + for ( i=0; i < MAX_CHARACTERS; i++ ) { + if ( !_strcmpi(hero_names[i], name) ) break; - ++v2; } - while ( v2 < MAX_CHARACTERS ); - return v2; + + return i; } -void __fastcall pfile_encode_hero(PkPlayerStruct *pPack) +void __fastcall pfile_encode_hero(const PkPlayerStruct *pPack) { - int v1; // ebx - void *v2; // edi - char password[16]; // [esp+Ch] [ebp-14h] - void *v4; // [esp+1Ch] [ebp-4h] + char *packed; + DWORD packed_len; + char password[16] = PASSWORD_SINGLE; - strcpy(password, "xrgyrkj1"); - *(_DWORD *)&password[9] = 0; - *(_WORD *)&password[13] = 0; - v4 = pPack; - password[15] = 0; - if ( (unsigned char)gbMaxPlayers > 1u ) - strcpy(password, "szqnlsk1"); - v1 = codec_get_encoded_len(1266); - v2 = DiabloAllocPtr(v1); - memcpy(v2, v4, 0x4F2u); - codec_encode(v2, 1266, v1, password); - mpqapi_write_file("hero", (char *)v2, v1); - mem_free_dbg(v2); + if ( gbMaxPlayers > 1 ) + strcpy(password, PASSWORD_MULTI); + + packed_len = codec_get_encoded_len(sizeof(*pPack)); + packed = (char*)DiabloAllocPtr(packed_len); + memcpy(packed, pPack, sizeof(*pPack)); + codec_encode(packed, sizeof(*pPack), packed_len, password); + mpqapi_write_file("hero", packed, packed_len); + mem_free_dbg(packed); } -// 679660: using guessed type char gbMaxPlayers; bool __fastcall pfile_open_archive(bool a1, int save_num) { @@ -149,40 +134,36 @@ bool __fastcall pfile_open_archive(bool a1, int save_num) } // 679660: using guessed type char gbMaxPlayers; -void __fastcall pfile_get_save_path(char *pszBuf, int dwBufSize, int save_num) +void __fastcall pfile_get_save_path(char *pszBuf, DWORD dwBufSize, unsigned int save_num) { - char *v3; // esi - const char *v4; // ebx - DWORD v5; // edi - char *v6; // eax - char v7[260]; // [esp+8h] [ebp-104h] + DWORD plen; + char *s; + char path[MAX_PATH]; + const char *fmt = "\\multi_%d.sv"; - v3 = pszBuf; - v4 = "\\multi_%d.sv"; - if ( (unsigned char)gbMaxPlayers <= 1u ) - v4 = "\\single_%d.sv"; - v5 = GetModuleFileName(ghInst, pszBuf, 0x104u); - v6 = strrchr(v3, '\\'); - if ( v6 ) - *v6 = 0; - if ( !v5 ) + if ( gbMaxPlayers <= 1 ) + fmt = "\\single_%d.sv"; + + // BUGFIX: ignores dwBufSize and uses MAX_PATH instead + plen = GetModuleFileName(ghInst, pszBuf, MAX_PATH); + s = strrchr(pszBuf, '\\'); + if ( s ) + *s = '\0'; + + if ( !plen ) TermMsg("Unable to get save directory"); - sprintf(v7, v4, save_num); - strcat(v3, v7); - _strlwr(v3); + + sprintf(path, fmt, save_num); + strcat(pszBuf, path); + _strlwr(pszBuf); } -// 679660: using guessed type char gbMaxPlayers; -void __fastcall pfile_flush(bool is_single_player, int save_num) +void __fastcall pfile_flush(BOOL is_single_player, unsigned int save_num) { - int v2; // esi - bool v3; // di - char FileName[260]; // [esp+8h] [ebp-104h] + char FileName[MAX_PATH]; - v2 = save_num; - v3 = is_single_player; - pfile_get_save_path(FileName, 260, save_num); - mpqapi_flush_and_close(FileName, v3, v2); + pfile_get_save_path(FileName, sizeof(FileName), save_num); + mpqapi_flush_and_close(FileName, is_single_player, save_num); } bool __fastcall pfile_create_player_description(char *dst, int len) @@ -254,38 +235,34 @@ void __cdecl pfile_flush_W() pfile_flush(1, v0); } -void __fastcall game_2_ui_player(PlayerStruct *p, _uiheroinfo *heroinfo, BOOL bHasSaveFile) +void __fastcall game_2_ui_player(const PlayerStruct *p, _uiheroinfo *heroinfo, BOOL bHasSaveFile) { - _uiheroinfo *v3; // esi - PlayerStruct *v4; // edi - char v5; // al + memset(heroinfo, 0, sizeof(*heroinfo)); + strncpy(heroinfo->name, p->_pName, sizeof(heroinfo->name) - 1); + heroinfo->name[sizeof(heroinfo->name) - 1] = '\0'; + heroinfo->level = p->_pLevel; + heroinfo->heroclass = game_2_ui_class(p); + heroinfo->strength = p->_pStrength; + heroinfo->magic = p->_pMagic; + heroinfo->dexterity = p->_pDexterity; + heroinfo->vitality = p->_pVitality; + heroinfo->gold = p->_pGold; + heroinfo->hassaved = bHasSaveFile; + heroinfo->herorank = (unsigned char)p->pDiabloKillLevel; + heroinfo->spawned = 0; +} - v3 = heroinfo; - v4 = p; - memset(heroinfo, 0, 0x2Cu); - strncpy(v3->name, v4->_pName, 0xFu); - v3->name[15] = 0; - v3->level = v4->_pLevel; - v3->heroclass = game_2_ui_class(v4); - v3->strength = v4->_pStrength; - v3->magic = v4->_pMagic; - v3->dexterity = v4->_pDexterity; - v3->vitality = v4->_pVitality; - v3->gold = v4->_pGold; - v3->hassaved = bHasSaveFile; - v5 = v4->pDiabloKillLevel; - v3->spawned = 0; - v3->herorank = v5; -} - -char __fastcall game_2_ui_class(PlayerStruct *p) -{ - char result; // al - - result = p->_pClass; - if ( result ) - result = (result != 1) + 1; - return result; +unsigned char __fastcall game_2_ui_class(const PlayerStruct *p) +{ + unsigned char uiclass; + if ( p->_pClass == PC_WARRIOR ) + uiclass = UI_WARRIOR; + else if ( p->_pClass == PC_ROGUE ) + uiclass = UI_ROGUE; + else + uiclass = UI_SORCERER; + + return uiclass; } BOOL __stdcall pfile_ui_set_hero_infos(BOOL (__stdcall *ui_add_hero_info)(_uiheroinfo *)) diff --git a/Source/pfile.h b/Source/pfile.h index 532fc9bc3..1badd5be4 100644 --- a/Source/pfile.h +++ b/Source/pfile.h @@ -2,25 +2,22 @@ #ifndef __PFILE_H__ #define __PFILE_H__ -extern int pfile_cpp_init_value; -extern char hero_names[MAX_CHARACTERS][PLR_NAME_LEN]; extern BOOL gbValidSaveFile; // idb -extern int save_prev_tc; // weak void __cdecl pfile_cpp_init(); void __cdecl pfile_init_save_directory(); void __fastcall pfile_check_available_space(char *pszDir); void __cdecl pfile_write_hero(); -int __fastcall pfile_get_save_num_from_name(char *name); -void __fastcall pfile_encode_hero(PkPlayerStruct *pPack); +unsigned int __fastcall pfile_get_save_num_from_name(const char *name); +void __fastcall pfile_encode_hero(const PkPlayerStruct *pPack); bool __fastcall pfile_open_archive(bool a1, int save_num); -void __fastcall pfile_get_save_path(char *pszBuf, int dwBufSize, int save_num); -void __fastcall pfile_flush(bool is_single_player, int save_num); +void __fastcall pfile_get_save_path(char *pszBuf, DWORD dwBufSize, unsigned int save_num); +void __fastcall pfile_flush(BOOL is_single_player, unsigned int save_num); bool __fastcall pfile_create_player_description(char *dst, int len); int __fastcall pfile_create_save_file(char *name_1, char *name_2); void __cdecl pfile_flush_W(); -void __fastcall game_2_ui_player(PlayerStruct *p, _uiheroinfo *heroinfo, BOOL bHasSaveFile); -char __fastcall game_2_ui_class(PlayerStruct *p); +void __fastcall game_2_ui_player(const PlayerStruct *p, _uiheroinfo *heroinfo, BOOL bHasSaveFile); +unsigned char __fastcall game_2_ui_class(const PlayerStruct *p); BOOL __stdcall pfile_ui_set_hero_infos(BOOL (__stdcall *ui_add_hero_info)(_uiheroinfo *)); char *__fastcall GetSaveDirectory(char *dst, int dst_size, int save_num); bool __fastcall pfile_read_hero(void *archive, PkPlayerStruct *pPack);