You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

810 lines
20 KiB

//HEADER_GOES_HERE
#include "../types.h"
#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
const int pfile_inf = 0x7F800000; // weak
struct pfile_cpp_init
{
pfile_cpp_init()
{
pfile_cpp_init_value = pfile_inf;
}
} _pfile_cpp_init;
// 47F1C0: using guessed type int pfile_inf;
void __cdecl pfile_init_save_directory()
{
DWORD len;
char Buffer[MAX_PATH];
len = GetWindowsDirectory(Buffer, sizeof(Buffer));
if ( len ) {
pfile_check_available_space(Buffer);
len = GetModuleFileName(ghInst, Buffer, sizeof(Buffer));
}
if ( !len )
TermMsg("Unable to initialize save directory");
else
pfile_check_available_space(Buffer);
}
void __fastcall pfile_check_available_space(char *pszDir)
{
char *s;
BOOL hasSpace;
DWORD TotalNumberOfClusters;
DWORD NumberOfFreeClusters;
DWORD BytesPerSector;
DWORD SectorsPerCluster;
s = pszDir;
while ( *s ) {
if ( *s++ != '\\' )
continue;
*s = '\0';
break;
}
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()
{
unsigned int save_num;
PkPlayerStruct pkplr;
save_num = pfile_get_save_num_from_name(plr[myplr]._pName);
if (pfile_open_archive(TRUE, save_num)) {
PackPlayer(&pkplr, myplr, gbMaxPlayers == 1);
pfile_encode_hero(&pkplr);
pfile_flush(gbMaxPlayers == 1, save_num);
}
}
unsigned int __fastcall pfile_get_save_num_from_name(const char *name)
{
unsigned int i;
for ( i=0; i < MAX_CHARACTERS; i++ ) {
if ( !_strcmpi(hero_names[i], name) )
break;
}
return i;
}
void __fastcall pfile_encode_hero(const PkPlayerStruct *pPack)
{
char *packed;
DWORD packed_len;
char password[16] = PASSWORD_SINGLE;
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);
}
BOOL __fastcall pfile_open_archive(BOOL a1, unsigned int save_num)
{
char FileName[MAX_PATH];
pfile_get_save_path(FileName, sizeof(FileName), save_num);
if ( mpqapi_open_archive(FileName, FALSE, save_num) )
return TRUE;
if ( a1 && gbMaxPlayers > 1 )
mpqapi_update_multi_creation_time(save_num);
return FALSE;
}
void __fastcall pfile_get_save_path(char *pszBuf, DWORD dwBufSize, unsigned int save_num)
{
DWORD plen;
char *s;
char path[MAX_PATH];
const char *fmt = "\\multi_%d.sv";
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(path, fmt, save_num);
strcat(pszBuf, path);
_strlwr(pszBuf);
}
void __fastcall pfile_flush(BOOL is_single_player, unsigned int save_num)
{
char FileName[MAX_PATH];
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)
{
int v2; // edi
char *v3; // ebx
int v4; // eax
char src[128]; // [esp+Ch] [ebp-ACh]
_uiheroinfo hero_info; // [esp+8Ch] [ebp-2Ch]
myplr = 0;
v2 = len;
v3 = dst;
pfile_read_player_from_save();
game_2_ui_player(plr, &hero_info, gbValidSaveFile);
UiSetupPlayerInfo(chr_name_str, &hero_info, 'DRTL');
if ( !v3 || !v2 )
goto LABEL_5;
v4 = UiCreatePlayerDescription(&hero_info, 'DRTL', src);
if ( v4 )
{
SStrCopy(v3, src, v2);
LABEL_5:
v4 = 1;
}
return v4;
}
int __fastcall pfile_create_save_file(char *name_1, char *name_2)
{
char *v2; // edi
char *v3; // ebp
int v4; // esi
int v5; // eax
char *v7; // [esp+20h] [ebp-30h]
_uiheroinfo heroinfo; // [esp+24h] [ebp-2Ch]
v2 = name_2;
v3 = name_1;
if ( pfile_get_save_num_from_name(name_2) != MAX_CHARACTERS )
return 0;
v4 = 0;
v7 = plr[0]._pName;
while ( _strcmpi(v3, v7) )
{
v7 += 21720;
++v4;
if ( v7 == plr[4]._pName )
return 0;
}
v5 = pfile_get_save_num_from_name(v3);
if ( v5 == MAX_CHARACTERS )
return 0;
SStrCopy(hero_names[v5], v2, 32);
SStrCopy(plr[v4]._pName, v2, 32);
if ( !_strcmpi(chr_name_str, v3) )
SStrCopy(chr_name_str, v2, 16);
game_2_ui_player(plr, &heroinfo, gbValidSaveFile);
UiSetupPlayerInfo(chr_name_str, &heroinfo, 'DRTL');
pfile_write_hero();
return 1;
}
void __cdecl pfile_flush_W()
{
pfile_flush(TRUE, pfile_get_save_num_from_name(plr[myplr]._pName));
}
void __fastcall game_2_ui_player(const PlayerStruct *p, _uiheroinfo *heroinfo, BOOL bHasSaveFile)
{
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;
}
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 *))
{
char *v1; // esi
//int v2; // eax
int v3; // eax
DWORD v4; // eax
unsigned int v5; // esi
void *v7; // eax
void *v8; // edi
//int v9; // eax
bool v10; // al
PkPlayerStruct pkplr; // [esp+Ch] [ebp-7BCh]
struct _OFSTRUCT ReOpenBuff; // [esp+500h] [ebp-2C8h]
char FileName[260]; // [esp+588h] [ebp-240h]
char NewFileName[260]; // [esp+68Ch] [ebp-13Ch]
_uiheroinfo hero_info; // [esp+790h] [ebp-38h]
int unused; // [esp+7BCh] [ebp-Ch]
LPCSTR lpSrcStr; // [esp+7C0h] [ebp-8h]
int save_num; // [esp+7C4h] [ebp-4h]
memset(hero_names, 0, sizeof(hero_names));
if ( (unsigned char)gbMaxPlayers > 1u )
{
lpSrcStr = 0;
save_num = 0;
do
{
if ( (unsigned int)save_num >= MAX_CHARACTERS )
break;
GetSaveDirectory(FileName, 260, (int)lpSrcStr);
v1 = strrchr(FileName, '\\') + 1;
if ( v1 != (char *)1 && OpenFile(FileName, &ReOpenBuff, 0x4000u) != -1 )
{
if ( !SRegLoadString("Diablo\\Converted", (const char *)v1, 0, NewFileName, 260) )
{
while ( 1 )
{
v3 = save_num++;
pfile_get_save_path(NewFileName, 260, v3);
if ( OpenFile(NewFileName, &ReOpenBuff, 0x4000u) == -1 )
break;
if ( (unsigned int)save_num >= MAX_CHARACTERS )
goto LABEL_13;
}
if ( CopyFile(FileName, NewFileName, 1) )
{
SRegSaveString("Diablo\\Converted", v1, 0, NewFileName);
v4 = GetFileAttributes(NewFileName);
if ( v4 != -1 )
{
_LOBYTE(v4) = v4 & 0xF9;
SetFileAttributes(NewFileName, v4);
}
}
}
}
LABEL_13:
++lpSrcStr;
}
while ( (unsigned int)lpSrcStr < MAX_CHARACTERS );
}
unused = 1;
v5 = 0;
do
{
v7 = pfile_open_save_archive(&unused, v5);
v8 = v7;
if ( v7 )
{
if ( pfile_read_hero(v7, &pkplr) )
{
strcpy(hero_names[v5], pkplr.pName);
UnPackPlayer(&pkplr, 0, 0);
v10 = pfile_archive_contains_game(v8);
game_2_ui_player(plr, &hero_info, v10);
ui_add_hero_info(&hero_info);
}
pfile_SFileCloseArchive(v8);
}
++v5;
}
while ( v5 < MAX_CHARACTERS );
return 1;
}
// 679660: using guessed type char gbMaxPlayers;
char *__fastcall GetSaveDirectory(char *dst, int dst_size, unsigned int save_num)
{
DWORD dirLen;
char FileName[MAX_PATH];
const char *savename;
// BUGFIX: ignores dst_size and uses MAX_PATH instead
if ( gbMaxPlayers > 1 ) {
savename = "\\dlinfo_%d.drv";
dirLen = GetWindowsDirectory(dst, MAX_PATH);
} else {
char *s;
savename = "\\single_%d.sv";
dirLen = GetModuleFileName(ghInst, dst, MAX_PATH);
s = strrchr(dst, '\\');
if ( s )
*s = '\0';
}
if ( !dirLen )
TermMsg("Unable to get save directory");
sprintf(FileName, savename, save_num);
strcat(dst, FileName);
return _strlwr(dst);
}
BOOL __fastcall pfile_read_hero(void *archive, PkPlayerStruct *pPack)
{
HANDLE file;
if ( !SFileOpenFileEx(archive, "hero", 0, &file) )
return FALSE;
else {
DWORD dwlen;
BOOL ret = FALSE;
char password[16] = PASSWORD_SINGLE;
DWORD nSize = 16;
if ( gbMaxPlayers > 1 )
strcpy(password, PASSWORD_MULTI);
dwlen = SFileGetFileSize(file, NULL);
if ( dwlen ) {
DWORD read;
unsigned char *buf = DiabloAllocPtr(dwlen);
if ( SFileReadFile(file, buf, dwlen, &read, NULL) ) {
BOOL decoded = TRUE;
read = codec_decode(buf, dwlen, password);
if ( !read && gbMaxPlayers > 1 ) {
GetComputerName(password, &nSize);
if ( SFileSetFilePointer(file, 0, NULL, 0) || !SFileReadFile(file, buf, dwlen, &read, NULL) )
decoded = FALSE;
else
read = codec_decode(buf, dwlen, password);
}
if ( decoded && read == sizeof(*pPack) ) {
memcpy(pPack, buf, sizeof(*pPack));
ret = TRUE;
}
}
if ( buf )
mem_free_dbg(buf);
}
SFileCloseFile(file);
return ret;
}
}
HANDLE __fastcall pfile_open_save_archive(int *unused, unsigned int save_num)
{
char SrcStr[MAX_PATH];
HANDLE archive;
pfile_get_save_path(SrcStr, sizeof(SrcStr), save_num);
if ( SFileOpenArchive(SrcStr, 0x7000, 0, &archive) )
return archive;
return NULL;
}
void __fastcall pfile_SFileCloseArchive(HANDLE hsArchive)
{
SFileCloseArchive(hsArchive);
}
BOOL __fastcall pfile_archive_contains_game(HANDLE hsArchive)
{
HANDLE file;
if ( gbMaxPlayers != 1 )
return FALSE;
if ( !SFileOpenFileEx(hsArchive, "game", 0, &file) )
return FALSE;
SFileCloseFile(file);
return TRUE;
}
BOOL __stdcall pfile_ui_set_class_stats(int player_class_nr, _uidefaultstats *class_stats)
{
int v2; // eax
v2 = (char)pfile_get_player_class(player_class_nr);
class_stats->strength = StrengthTbl[v2];
class_stats->magic = MagicTbl[v2];
class_stats->dexterity = DexterityTbl[v2];
class_stats->vitality = VitalityTbl[v2];
return 1;
}
char __fastcall pfile_get_player_class(unsigned int player_class_nr)
{
char pc_class;
if ( player_class_nr == UI_WARRIOR )
pc_class = PC_WARRIOR;
else if ( player_class_nr == UI_ROGUE )
pc_class = PC_ROGUE;
else
pc_class = PC_SORCERER;
return pc_class;
}
BOOL __stdcall pfile_ui_save_create(_uiheroinfo *heroinfo)
{
unsigned int v1; // edi
//int v3; // eax
char v5; // al
PkPlayerStruct pkplr; // [esp+8h] [ebp-4F4h]
v1 = pfile_get_save_num_from_name(heroinfo->name);
if ( v1 == MAX_CHARACTERS )
{
v1 = 0;
do
{
if ( !*hero_names[v1] )
break;
++v1;
}
while ( v1 < MAX_CHARACTERS );
if ( v1 == MAX_CHARACTERS )
return 0;
}
//_LOBYTE(v3) = pfile_open_archive(0, v1);
if ( !pfile_open_archive(0, v1) )
return 0;
mpqapi_remove_hash_entries(pfile_get_file_name);
strncpy(hero_names[v1], heroinfo->name, 0x20u);
hero_names[v1][31] = 0;
v5 = pfile_get_player_class((unsigned char)heroinfo->heroclass);
CreatePlayer(0, v5);
strncpy(plr[0]._pName, heroinfo->name, 0x20u);
plr[0]._pName[31] = 0;
PackPlayer(&pkplr, 0, 1);
pfile_encode_hero(&pkplr);
game_2_ui_player(plr, heroinfo, 0);
pfile_flush(1, v1);
return 1;
}
BOOL __stdcall pfile_get_file_name(DWORD lvl, char *dst)
{
const char *fmt;
if ( gbMaxPlayers > 1 ) {
if ( lvl )
return FALSE;
fmt = "hero";
} else {
if ( lvl < 17 )
fmt = "perml%02d";
else if ( lvl < 34 ) {
lvl -= 17;
fmt = "perms%02d";
} else if ( lvl == 34 )
fmt = "game";
else if ( lvl == 35 )
fmt = "hero";
else
return FALSE;
}
sprintf(dst, fmt, lvl);
return TRUE;
}
BOOL __stdcall pfile_delete_save(_uiheroinfo *hero_info)
{
unsigned int v1; // eax
char FileName[260]; // [esp+0h] [ebp-104h]
v1 = pfile_get_save_num_from_name(hero_info->name);
if ( v1 < MAX_CHARACTERS )
{
hero_names[v1][0] = 0;
pfile_get_save_path(FileName, 260, v1);
DeleteFile(FileName);
}
return 1;
}
void __cdecl pfile_read_player_from_save()
{
int dwChar; // edi
void *v1; // esi
//int v2; // eax
PkPlayerStruct pkplr; // [esp+8h] [ebp-4F4h]
dwChar = pfile_get_save_num_from_name(chr_name_str);
v1 = pfile_open_save_archive(0, dwChar);
if ( !v1 )
TermMsg("Unable to open archive");
//_LOBYTE(v2) = pfile_read_hero(v1, &pkplr);
if ( !pfile_read_hero(v1, &pkplr) )
TermMsg("Unable to load character");
UnPackPlayer(&pkplr, myplr, 0);
gbValidSaveFile = pfile_archive_contains_game(v1);
pfile_SFileCloseArchive(v1);
}
void __fastcall GetTempLevelNames(char *szTemp)
{
char *v1; // esi
v1 = szTemp;
pfile_get_save_num_from_name(plr[myplr]._pName);
if ( setlevel )
sprintf(v1, "temps%02d", (unsigned char)setlvlnum);
else
sprintf(v1, "templ%02d", currlevel);
}
// 5CCB10: using guessed type char setlvlnum;
// 5CF31D: using guessed type char setlevel;
void __fastcall GetPermLevelNames(char *szPerm)
{
char *v1; // esi
int v2; // ebx
//int v3; // eax
//int v4; // eax
int v5; // edi
v1 = szPerm;
v2 = pfile_get_save_num_from_name(plr[myplr]._pName);
GetTempLevelNames(v1);
//_LOBYTE(v3) = pfile_open_archive(0, v2);
if ( !pfile_open_archive(0, v2) )
TermMsg("Unable to read to save file archive");
//_LOBYTE(v4) = mpqapi_has_file(v1);
v5 = mpqapi_has_file(v1);
pfile_flush(1, v2);
if ( !v5 )
{
if ( setlevel )
sprintf(v1, "perms%02d", (unsigned char)setlvlnum);
else
sprintf(v1, "perml%02d", currlevel);
}
}
// 5CCB10: using guessed type char setlvlnum;
// 5CF31D: using guessed type char setlevel;
void __fastcall pfile_get_game_name(char *dst)
{
char *v1; // esi
v1 = dst;
pfile_get_save_num_from_name(plr[myplr]._pName);
strcpy(v1, "game");
}
void __cdecl pfile_remove_temp_files()
{
int v0; // eax
int v1; // esi
//int v2; // eax
if ( (unsigned char)gbMaxPlayers <= 1u )
{
v0 = pfile_get_save_num_from_name(plr[myplr]._pName);
v1 = v0;
//_LOBYTE(v2) = pfile_open_archive(0, v0);
if ( !pfile_open_archive(0, v0) )
TermMsg("Unable to write to save file archive");
mpqapi_remove_hash_entries(GetTempSaveNames);
pfile_flush(1, v1);
}
}
// 679660: using guessed type char gbMaxPlayers;
BOOL __stdcall GetTempSaveNames(DWORD dwIndex, char *szTemp)
{
const char *fmt;
if ( dwIndex < 17 )
fmt = "templ%02d";
else if ( dwIndex < 34 ) {
dwIndex -= 17;
fmt = "temps%02d";
} else
return FALSE;
sprintf(szTemp, fmt, dwIndex);
return TRUE;
}
void __cdecl pfile_rename_temp_to_perm()
{
int v0; // eax
int v1; // edi
//int v2; // eax
int v3; // esi
//int v4; // eax
//int v5; // eax
//int v6; // eax
char v7[260]; // [esp+8h] [ebp-208h]
char v8[260]; // [esp+10Ch] [ebp-104h]
v0 = pfile_get_save_num_from_name(plr[myplr]._pName);
v1 = v0;
//_LOBYTE(v2) = pfile_open_archive(0, v0);
if ( !pfile_open_archive(0, v0) )
TermMsg("Unable to write to save file archive");
v3 = 0;
while ( 1 )
{
//_LOBYTE(v6) = GetTempSaveNames(v3, v7);
if ( !GetTempSaveNames(v3, v7) )
break;
GetPermSaveNames(v3++, v8);
//_LOBYTE(v4) = mpqapi_has_file(v7);
if ( mpqapi_has_file(v7) )
{
//_LOBYTE(v5) = mpqapi_has_file(v8);
if ( mpqapi_has_file(v8) )
mpqapi_remove_hash_entry(v8);
mpqapi_rename(v7, v8);
}
}
GetPermSaveNames(v3, v8);
pfile_flush(1, v1);
}
BOOL __stdcall GetPermSaveNames(DWORD dwIndex, char *szPerm)
{
const char *fmt;
if ( dwIndex < 17 )
fmt = "perml%02d";
else if ( dwIndex < 34 ) {
dwIndex -= 17;
fmt = "perms%02d";
} else
return FALSE;
sprintf(szPerm, fmt, dwIndex);
return TRUE;
}
void __fastcall pfile_write_save_file(char *pszName, void *pbData, int dwLen, int qwLen)
{
void *v4; // ebx
int v5; // eax
//int v6; // eax
char file_name[260]; // [esp+Ch] [ebp-118h]
char password[16]; // [esp+110h] [ebp-14h]
int v9; // [esp+120h] [ebp-4h]
v4 = pbData;
pfile_strcpy(file_name, pszName);
v5 = pfile_get_save_num_from_name(plr[myplr]._pName);
strcpy(password, "xrgyrkj1");
v9 = v5;
*(_DWORD *)&password[9] = 0;
*(_WORD *)&password[13] = 0;
password[15] = 0;
if ( (unsigned char)gbMaxPlayers > 1u )
strcpy(password, "szqnlsk1");
codec_encode(v4, dwLen, qwLen, password);
//_LOBYTE(v6) = pfile_open_archive(0, v9);
if ( !pfile_open_archive(0, v9) )
TermMsg("Unable to write to save file archive");
mpqapi_write_file(file_name, (char *)v4, qwLen);
pfile_flush(1, v9);
}
// 679660: using guessed type char gbMaxPlayers;
void __fastcall pfile_strcpy(char *dst, const char *src)
{
strcpy(dst, src);
}
char *__fastcall pfile_read(char *pszName, int *pdwLen)
{
int *v2; // ebx
int v3; // eax
void *v4; // edi
//int v5; // eax
int v6; // eax
void *v7; // eax
//int v8; // eax
char *v9; // esi
int v10; // eax
//int v11; // eax
char v13[260]; // [esp+Ch] [ebp-124h]
char password[16]; // [esp+110h] [ebp-20h]
void *src_dst; // [esp+120h] [ebp-10h]
int nread; // [esp+124h] [ebp-Ch]
DWORD nSize; // [esp+128h] [ebp-8h]
void *file; // [esp+12Ch] [ebp-4h]
v2 = pdwLen;
pfile_strcpy(v13, pszName);
v3 = pfile_get_save_num_from_name(plr[myplr]._pName);
v4 = pfile_open_save_archive(0, v3);
if ( !v4 )
TermMsg("Unable to open save file archive");
//_LOBYTE(v5) = SFileOpenFileEx(v4, v13, 0, &file);
if ( !SFileOpenFileEx(v4, v13, 0, &file) )
TermMsg("Unable to open save file");
v6 = SFileGetFileSize((int *)file, 0);
*v2 = v6;
if ( !v6 )
TermMsg("Invalid save file");
v7 = DiabloAllocPtr(*v2);
src_dst = v7;
//_LOBYTE(v8) = SFileReadFile(file, (char *)v7, *v2, (unsigned long *)&nread, 0);
if ( !SFileReadFile(file, (char *)v7, *v2, (unsigned long *)&nread, 0) )
TermMsg("Unable to read save file");
SFileCloseFile(file);
pfile_SFileCloseArchive(v4);
strcpy(password, "xrgyrkj1");
nSize = 16;
*(_DWORD *)&password[9] = 0;
*(_WORD *)&password[13] = 0;
password[15] = 0;
if ( (unsigned char)gbMaxPlayers > 1u )
strcpy(password, "szqnlsk1");
v9 = (char *)src_dst;
v10 = codec_decode(src_dst, *v2, password);
*v2 = v10;
if ( !v10 )
{
if ( (unsigned char)gbMaxPlayers > 1u )
{
GetComputerName(password, &nSize);
if ( SFileSetFilePointer(file, 0, 0, 0) )
TermMsg("Unable to read save file");
//_LOBYTE(v11) = SFileReadFile(file, v9, *v2, (unsigned long *)&nread, 0);
if ( !SFileReadFile(file, v9, *v2, (unsigned long *)&nread, 0) )
TermMsg("Unable to read save file");
*v2 = codec_decode(v9, *v2, password);
}
if ( !*v2 )
TermMsg("Invalid save file");
}
return v9;
}
// 679660: using guessed type char gbMaxPlayers;
void __fastcall pfile_update(BOOL force_save)
{
// BUGFIX: these tick values should be treated as unsigned to handle overflows correctly
static int save_prev_tc;
if (gbMaxPlayers != 1) {
int tick = GetTickCount();
if(force_save || tick - save_prev_tc > 60000) {
save_prev_tc = tick;
pfile_write_hero();
}
}
}