/* * UNPUBLISHED -- Rights reserved under the copyright laws of the * United States. Use of a copyright notice is precautionary only and * does not imply publication or disclosure. * * THIS DOCUMENTATION CONTAINS CONFIDENTIAL AND PROPRIETARY INFORMATION * OF BLIZZARD ENTERTAINMENT. ANY DUPLICATION, MODIFICATION, * DISTRIBUTION, OR DISCLOSURE IS STRICTLY PROHIBITED WITHOUT THE PRIOR * EXPRESS WRITTEN PERMISSION OF BLIZZARD ENTERTAINMENT. */ #include "../types.h" char gbSomebodyWonGameKludge; // weak char pkdata_6761C0[4100]; char szPlayerDescript[128]; short sgwPackPlrOffsetTbl[4]; PkPlayerStruct pkplr[4]; char sgbPlayerTurnBitTbl[4]; char sgbPlayerLeftGameTbl[4]; int multi_cpp_init_value; // weak int sgbSentThisCycle; // idb int dword_678628; // weak char gbActivePlayers; // weak char gbGameDestroyed; // weak char sgbSendDeltaTbl[4]; _gamedata sgGameInitInfo; char byte_678640; // weak int sglTimeoutStart; // weak int sgdwPlayerLeftReasonTbl[4]; char pkdata_678658[4100]; unsigned int sgdwGameLoops; // idb char gbMaxPlayers; // weak char sgbTimeout; // weak char szPlayerName[128]; char gbDeltaSender; // weak int sgbNetInited; // weak int player_state[4]; int multi_inf = 0x7F800000; // weak event_type event_types[3] = { EVENT_TYPE_PLAYER_LEAVE_GAME, EVENT_TYPE_PLAYER_CREATE_GAME, EVENT_TYPE_PLAYER_MESSAGE }; //----- (0043FAC9) -------------------------------------------------------- struct multi_cpp_init { multi_cpp_init() { multi_cpp_init_value = multi_inf; } } _multi_cpp_init; // 47F154: using guessed type int multi_inf; // 678620: using guessed type int multi_cpp_init_value; //----- (0043FAD4) -------------------------------------------------------- void __fastcall multi_msg_add(unsigned char *a1, unsigned char a2) { if ( a1 ) { if ( a2 ) tmsg_add(a1, a2); } } //----- (0043FAE2) -------------------------------------------------------- void __fastcall NetSendLoPri(unsigned char *pbMsg, unsigned char bLen) { unsigned char *v2; // esi unsigned char v3; // bl int v4; // edx v2 = pbMsg; v3 = bLen; if ( pbMsg ) { if ( bLen ) { multi_copy_packet(pkdata_678658, pbMsg, bLen); _LOBYTE(v4) = v3; multi_send_packet(v2, v4); } } } //----- (0043FB0B) -------------------------------------------------------- void __fastcall multi_copy_packet(void *a1, void *packet, int size) { int v3; // eax int v4; // ebx char *v5; // esi v3 = *(_DWORD *)a1; v4 = *(_DWORD *)a1 + (unsigned char)size; if ( (unsigned int)(v4 + 2) <= 0x1000 ) { *(_DWORD *)a1 = v4 + 1; *((_BYTE *)a1 + v3 + 4) = size; v5 = (char *)a1 + v3 + 5; memcpy(v5, packet, (unsigned char)size); v5[(unsigned char)size] = 0; } } //----- (0043FB4D) -------------------------------------------------------- void __fastcall multi_send_packet(void *packet, int dwSize) { void *v2; // esi unsigned char v3; // bl TPkt pkt; // [esp+8h] [ebp-200h] v2 = packet; v3 = dwSize; NetRecvPlrData(&pkt); pkt.hdr.wLen = v3 + 19; memcpy(pkt.body, v2, v3); if ( !SNetSendMessage(myplr, &pkt.hdr, (unsigned short)pkt.hdr.wLen) ) nthread_terminate_game("SNetSendMessage0"); } //----- (0043FBB5) -------------------------------------------------------- void __fastcall NetRecvPlrData(TPkt *pkt) { pkt->hdr.wCheck = 'ip'; pkt->hdr.px = plr[myplr].WorldX; pkt->hdr.py = plr[myplr].WorldY; pkt->hdr.targx = plr[myplr]._ptargx; pkt->hdr.targy = plr[myplr]._ptargy; pkt->hdr.php = plr[myplr]._pHitPoints; pkt->hdr.pmhp = plr[myplr]._pMaxHP; pkt->hdr.bstr = plr[myplr]._pBaseStr; pkt->hdr.bmag = plr[myplr]._pBaseMag; pkt->hdr.bdex = plr[myplr]._pBaseDex; } //----- (0043FC6F) -------------------------------------------------------- void __fastcall NetSendHiPri(unsigned char *pbMsg, unsigned char bLen) { unsigned char *v2; // edi unsigned char v3; // bl int v4; // edx unsigned char *v5; // eax TSyncHeader *v6; // eax int v7; // eax int v8; // eax TPkt pkt; // [esp+Ch] [ebp-204h] int size; // [esp+20Ch] [ebp-4h] v2 = pbMsg; v3 = bLen; if ( pbMsg && bLen ) { multi_copy_packet(pkdata_6761C0, pbMsg, bLen); _LOBYTE(v4) = v3; multi_send_packet(v2, v4); } if ( !dword_678628 ) { dword_678628 = 1; NetRecvPlrData(&pkt); size = gdwNormalMsgSize - 19; v5 = multi_recv_packet(pkdata_6761C0, pkt.body, &size); v6 = (TSyncHeader *)multi_recv_packet(pkdata_678658, v5, &size); v7 = sync_all_monsters(v6, size); size = v7; v8 = gdwNormalMsgSize - v7; pkt.hdr.wLen = v8; if ( !SNetSendMessage(-2, &pkt.hdr, v8) ) nthread_terminate_game("SNetSendMessage"); } } // 678628: using guessed type int dword_678628; // 679760: using guessed type int gdwNormalMsgSize; //----- (0043FD27) -------------------------------------------------------- unsigned char *__fastcall multi_recv_packet(void *packet, unsigned char *a2, int *a3) { char *v3; // esi unsigned char *result; // eax char *v5; // ebx size_t v6; // edi char *v7; // ebx unsigned char *v8; // [esp+4h] [ebp-4h] v3 = (char *)packet; result = a2; v8 = a2; if ( *(_DWORD *)packet ) { v5 = (char *)packet + 4; while ( *v5 ) { v6 = (unsigned char)*v5; if ( v6 > *a3 ) break; v7 = v5 + 1; memcpy(v8, v7, v6); v8 += v6; v5 = &v7[v6]; *a3 -= v6; } memcpy(v3 + 4, v5, (size_t)&v3[*(_DWORD *)v3 - (_DWORD)v5 + 5]); *(_DWORD *)v3 += v3 - v5 + 4; result = v8; } return result; } //----- (0043FD90) -------------------------------------------------------- void __fastcall multi_send_msg_packet(int a1, unsigned char *a2, unsigned char len) { //const void *v3; // edx signed int v4; // ebx unsigned int v5; // edi TPkt pkt; // [esp+Ch] [ebp-204h] int v8; // [esp+20Ch] [ebp-4h] v8 = a1; NetRecvPlrData(&pkt); pkt.hdr.wLen = len + 19; memcpy(pkt.body, a2, len); v4 = 1; v5 = 0; while ( 1 ) { if ( v4 & v8 ) { if ( !SNetSendMessage(v5, &pkt.hdr, len + 19) && SErrGetLastError() != STORM_ERROR_INVALID_PLAYER ) break; } ++v5; v4 *= 2; if ( v5 >= 4 ) return; } nthread_terminate_game("SNetSendMessage"); } //----- (0043FE0E) -------------------------------------------------------- void __cdecl multi_msg_countdown() { int v0; // esi v0 = 0; do { if ( player_state[v0] & 0x20000 ) { if ( gdwMsgLenTbl[v0] == 4 ) multi_parse_turn(v0, *(_DWORD *)glpMsgTbl[v0]); } ++v0; } while ( v0 < 4 ); } //----- (0043FE3D) -------------------------------------------------------- void __fastcall multi_parse_turn(int pnum, int turn) { int v2; // esi unsigned int v3; // esi v2 = turn; if ( turn < 0 ) multi_handle_turn_upper_bit(pnum); v3 = v2 & 0x7FFFFFFF; if ( sgbSentThisCycle < gdwTurnsInTransit + v3 ) { if ( v3 >= 0x7FFFFFFF ) v3 = (unsigned short)v3; sgbSentThisCycle = v3 + gdwTurnsInTransit; sgdwGameLoops = 4 * v3 * (unsigned char)byte_679704; } } // 679704: using guessed type char byte_679704; // 679738: using guessed type int gdwTurnsInTransit; //----- (0043FE85) -------------------------------------------------------- void __fastcall multi_handle_turn_upper_bit(int pnum) { signed int v1; // eax v1 = 0; do { if ( player_state[v1] & 0x10000 && v1 != pnum ) break; ++v1; } while ( v1 < 4 ); if ( myplr == v1 ) { sgbSendDeltaTbl[pnum] = 1; } else if ( myplr == pnum ) { gbDeltaSender = v1; } } // 6796E4: using guessed type char gbDeltaSender; //----- (0043FEB7) -------------------------------------------------------- void __fastcall multi_player_left(int pnum, int reason) { sgbPlayerLeftGameTbl[pnum] = 1; sgdwPlayerLeftReasonTbl[pnum] = reason; multi_clear_left_tbl(); } //----- (0043FECA) -------------------------------------------------------- void __cdecl multi_clear_left_tbl() { int v0; // esi v0 = 0; do { if ( sgbPlayerLeftGameTbl[v0] ) { if ( gbBufferMsgs == 1 ) msg_send_drop_pkt(v0, sgdwPlayerLeftReasonTbl[v0]); else multi_player_left_msg(v0, 1); sgbPlayerLeftGameTbl[v0] = 0; sgdwPlayerLeftReasonTbl[v0] = 0; } ++v0; } while ( v0 < 4 ); } // 676194: using guessed type char gbBufferMsgs; //----- (0043FF0E) -------------------------------------------------------- void __fastcall multi_player_left_msg(int pnum, int left) { int v2; // edi int v3; // ebx int v4; // esi char *v5; // eax int v6; // edi v2 = pnum; v3 = left; v4 = pnum; if ( plr[pnum].plractive ) { RemovePlrFromMap(pnum); RemovePortalMissile(v2); DeactivatePortal(v2); RemovePlrPortal(v2); RemovePlrMissiles(v2); if ( v3 ) { v5 = "Player '%s' just left the game"; v6 = sgdwPlayerLeftReasonTbl[v2] - 0x40000004; if ( v6 ) { if ( v6 == 2 ) v5 = "Player '%s' dropped due to timeout"; } else { v5 = "Player '%s' killed Diablo and left the game!"; gbSomebodyWonGameKludge = 1; } EventPlrMsg(v5, plr[v4]._pName); } plr[v4].plractive = 0; plr[v4]._pName[0] = 0; --gbActivePlayers; } } // 6761B8: using guessed type char gbSomebodyWonGameKludge; // 67862C: using guessed type char gbActivePlayers; //----- (0043FF9D) -------------------------------------------------------- void __cdecl multi_net_ping() { sgbTimeout = 1; sglTimeoutStart = GetTickCount(); } // 678644: using guessed type int sglTimeoutStart; // 679661: using guessed type char sgbTimeout; //----- (0043FFB0) -------------------------------------------------------- int __cdecl multi_handle_delta() { int v0; // esi int recieved; // [esp+4h] [ebp-4h] if ( gbGameDestroyed ) { gbRunGame = 0; return 0; } v0 = 0; do { if ( sgbSendDeltaTbl[v0] ) { sgbSendDeltaTbl[v0] = 0; DeltaExportData(v0); } ++v0; } while ( v0 < 4 ); sgbSentThisCycle = nthread_send_and_recv_turn(sgbSentThisCycle, 1); if ( !nthread_recv_turns(&recieved) ) { multi_begin_timeout(); return 0; } sgbTimeout = 0; if ( recieved ) { if ( dword_678628 ) { dword_678628 = 0; if ( !multi_check_pkt_valid(pkdata_6761C0) ) NetSendHiPri(0, 0); } else { NetSendHiPri(0, 0); dword_678628 = 0; } } multi_mon_seeds(); return 1; } // 525650: using guessed type int gbRunGame; // 678628: using guessed type int dword_678628; // 67862D: using guessed type char gbGameDestroyed; // 679661: using guessed type char sgbTimeout; //----- (00440058) -------------------------------------------------------- // Microsoft VisualC 2-11/net runtime int __fastcall multi_check_pkt_valid(char *a1) { return *(_DWORD *)a1 == 0; } //----- (00440060) -------------------------------------------------------- void __cdecl multi_mon_seeds() { unsigned int v0; // eax int v1; // edx int *v2; // ecx int v3; // esi v0 = _rotr(++sgdwGameLoops, 8); v1 = 0; v2 = &monster[0]._mAISeed; do { v3 = v1++ + v0; *v2 = v3; v2 += 57; } while ( (signed int)v2 < (signed int)&monster[200]._mAISeed ); } //----- (00440093) -------------------------------------------------------- void __cdecl multi_begin_timeout() { unsigned char bGroupPlayers; // bl signed int v1; // eax signed int nLowestActive; // esi signed int nLowestPlayer; // edi signed int v4; // eax int v5; // edx unsigned char v6; // [esp+Fh] [ebp-1h] bGroupPlayers = 0; #ifdef _DEBUG if ( sgbTimeout && !debug_mode_key_i ) #else if ( sgbTimeout ) #endif { v1 = GetTickCount() - sglTimeoutStart; if ( v1 <= 20000 ) { if ( v1 >= 10000 ) { v6 = 0; nLowestActive = -1; nLowestPlayer = -1; v4 = 0; do { v5 = player_state[v4]; if ( v5 & 0x10000 ) { if ( nLowestPlayer == -1 ) nLowestPlayer = v4; if ( v5 & 0x40000 ) { ++bGroupPlayers; if ( nLowestActive == -1 ) nLowestActive = v4; } else { ++v6; } } ++v4; } while ( v4 < 4 ); if ( bGroupPlayers >= v6 && (bGroupPlayers != v6 || nLowestPlayer == nLowestActive) ) { if ( nLowestActive == myplr ) multi_check_drop_player(); } else { gbGameDestroyed = 1; } } } else { gbRunGame = 0; } } } // 525650: using guessed type int gbRunGame; // 67862D: using guessed type char gbGameDestroyed; // 678644: using guessed type int sglTimeoutStart; // 679661: using guessed type char sgbTimeout; //----- (00440128) -------------------------------------------------------- void __cdecl multi_check_drop_player() { int v0; // esi int v1; // eax v0 = 0; do { v1 = player_state[v0]; if ( !(v1 & 0x40000) ) { if ( v1 & 0x10000 ) SNetDropPlayer(v0, 0x40000006); } ++v0; } while ( v0 < 4 ); } //----- (00440153) -------------------------------------------------------- void __cdecl multi_process_network_packets() { //int v0; // eax TPktHdr *v1; // ecx TPktHdr *v2; // edi int v3; // eax bool v4; // zf unsigned char *v5; // esi int v6; // ebx int v7; // eax int v8; // ecx int v9; // eax int v10; // eax int v11; // esi int v12; // eax int v13; // ecx int v14; // eax //int v15; // eax TPktHdr *pkt; // [esp+0h] [ebp-Ch] int len; // [esp+4h] [ebp-8h] char arglist[4]; // [esp+8h] [ebp-4h] multi_clear_left_tbl(); multi_process_tmsgs(); //_LOBYTE(v0) = SNetReceiveMessage((int *)arglist, (char **)&pkt, &len); if ( SNetReceiveMessage((int *)arglist, (char **)&pkt, &len) ) { do { ++dword_676198; multi_clear_left_tbl(); v1 = pkt; v2 = pkt; if ( (unsigned int)len >= 0x13 && *(_DWORD *)arglist < 4u && pkt->wCheck == 'ip' && (unsigned short)pkt->wLen == len ) { v3 = *(_DWORD *)arglist; v4 = *(_DWORD *)arglist == myplr; plr[v3]._pownerx = (unsigned char)pkt->px; v5 = &v1->py; plr[v3]._pownery = (unsigned char)v1->py; if ( !v4 ) { v4 = gbBufferMsgs == 1; plr[v3]._pHitPoints = v1->php; plr[v3]._pMaxHP = v1->pmhp; plr[v3]._pBaseStr = (unsigned char)v1->bstr; plr[v3]._pBaseMag = (unsigned char)v1->bmag; plr[v3]._pBaseDex = (unsigned char)v1->bdex; if ( !v4 && plr[v3].plractive && plr[v3]._pHitPoints ) { if ( currlevel != plr[v3].plrlevel || plr[v3]._pLvlChanging ) { plr[v3].WorldX = (unsigned char)v1->px; plr[v3].WorldY = (unsigned char)*v5; plr[v3]._px = (unsigned char)v1->px; plr[v3]._py = (unsigned char)*v5; plr[v3]._ptargx = (unsigned char)v1->targx; plr[v3]._ptargy = (unsigned char)v1->targy; } else { v6 = abs(plr[v3].WorldX - (unsigned char)v1->px); v7 = abs(plr[*(_DWORD *)arglist].WorldY - (unsigned char)*v5); if ( (v6 > 3 || v7 > 3) && !dPlayer[(unsigned char)v2->px][(unsigned char)*v5] ) { FixPlrWalkTags(*(int *)arglist); v8 = *(_DWORD *)arglist; v9 = *(_DWORD *)arglist; plr[v9]._poldx = plr[*(_DWORD *)arglist].WorldX; plr[v9]._poldy = plr[v9].WorldY; FixPlrWalkTags(v8); v10 = *(_DWORD *)arglist; plr[v10].WorldX = (unsigned char)v2->px; plr[v10].WorldY = (unsigned char)*v5; plr[v10]._px = (unsigned char)v2->px; plr[v10]._py = (unsigned char)*v5; dPlayer[plr[v10].WorldX][plr[v10].WorldY] = arglist[0] + 1; } v11 = abs(plr[*(_DWORD *)arglist]._px - plr[*(_DWORD *)arglist].WorldX); v12 = abs(plr[*(_DWORD *)arglist]._py - plr[*(_DWORD *)arglist].WorldY); v13 = *(_DWORD *)arglist; if ( v11 > 1 || v12 > 1 ) { v14 = *(_DWORD *)arglist; plr[v14]._px = plr[*(_DWORD *)arglist].WorldX; plr[v14]._py = plr[v13].WorldY; } MakePlrPath(v13, (unsigned char)v2->targx, (unsigned char)v2->targy, 1u); } } } multi_handle_all_packets(*(int *)arglist, (TPkt *)&v2[1], len - 19); } //_LOBYTE(v15) = SNetReceiveMessage((int *)arglist, (char **)&pkt, &len); } while ( SNetReceiveMessage((int *)arglist, (char **)&pkt, &len) ); } if ( SErrGetLastError() != STORM_ERROR_NO_MESSAGES_WAITING ) nthread_terminate_game("SNetReceiveMsg"); } // 676194: using guessed type char gbBufferMsgs; // 676198: using guessed type int dword_676198; //----- (0044041D) -------------------------------------------------------- void __fastcall multi_handle_all_packets(int players, TPkt *packet, int a3) { TCmd *v3; // esi int i; // edi int v5; // eax v3 = (TCmd *)packet; for ( i = players; a3; a3 -= v5 ) { v5 = ParseCmd(i, v3); if ( !v5 ) break; v3 += v5; } } //----- (00440444) -------------------------------------------------------- void __cdecl multi_process_tmsgs() { int v0; // eax TPkt pkt; // [esp+0h] [ebp-200h] while ( 1 ) { v0 = tmsg_get(&pkt.hdr.px, 512); if ( !v0 ) break; multi_handle_all_packets(myplr, &pkt, v0); } } //----- (00440477) -------------------------------------------------------- void __fastcall multi_send_zero_packet(int pnum, char a2, void *pbSrc, int dwLen) { unsigned int v4; // edi short v5; // si unsigned short dwBody; // ax TPkt pkt; // [esp+Ch] [ebp-208h] int pnuma; // [esp+20Ch] [ebp-8h] int v10; // [esp+210h] [ebp-4h] v4 = dwLen; _LOBYTE(v10) = a2; pnuma = pnum; v5 = 0; while ( v4 ) { pkt.hdr.wCheck = 'ip'; pkt.body[0] = v10; dwBody = gdwLargestMsgSize - 24; pkt.hdr.px = 0; pkt.hdr.py = 0; pkt.hdr.targx = 0; pkt.hdr.targy = 0; pkt.hdr.php = 0; pkt.hdr.pmhp = 0; pkt.hdr.bstr = 0; pkt.hdr.bmag = 0; pkt.hdr.bdex = 0; *(_WORD *)&pkt.body[1] = v5; if ( v4 < gdwLargestMsgSize - 24 ) dwBody = v4; *(_WORD *)&pkt.body[3] = dwBody; memcpy(&pkt.body[5], pbSrc, dwBody); pkt.hdr.wLen = *(_WORD *)&pkt.body[3] + 24; if ( !SNetSendMessage(pnuma, &pkt.hdr, *(unsigned short *)&pkt.body[3] + 24) ) { nthread_terminate_game("SNetSendMessage2"); return; } pbSrc = (char *)pbSrc + *(unsigned short *)&pkt.body[3]; v4 -= *(unsigned short *)&pkt.body[3]; v5 += *(_WORD *)&pkt.body[3]; } } // 67975C: using guessed type int gdwLargestMsgSize; //----- (0044055D) -------------------------------------------------------- void __cdecl NetClose() { if ( sgbNetInited ) { sgbNetInited = 0; nthread_cleanup(); dthread_cleanup(); tmsg_cleanup(); multi_event_handler(0); SNetLeaveGame(3); msgcmd_cmd_cleanup(); if ( (unsigned char)gbMaxPlayers > 1u ) Sleep(2000); } } // 679660: using guessed type char gbMaxPlayers; // 6796E8: using guessed type int sgbNetInited; //----- (004405A4) -------------------------------------------------------- char __fastcall multi_event_handler(int a1) { int v1; // edi void *(__stdcall *v2)(int, void (__stdcall *)(_SNETEVENT *)); // ebx unsigned int v3; // esi int v4; // eax char *v5; // eax v1 = a1; v2 = SNetRegisterEventHandler; if ( !a1 ) v2 = SNetUnregisterEventHandler; v3 = 0; do { v4 = (int)v2(event_types[v3], multi_handle_events); if ( !v4 && v1 ) { v5 = GetLastErr(); TermMsg("SNetRegisterEventHandler:\n%s", v5); } ++v3; } while ( v3 < 3 ); return v4; } //----- (004405EC) -------------------------------------------------------- void __stdcall multi_handle_events(_SNETEVENT *pEvt) { int v1; // ecx int *v2; // eax int *v3; // eax switch ( pEvt->eventid ) { case EVENT_TYPE_PLAYER_CREATE_GAME: v3 = (int *)pEvt->data; sgGameInitInfo.dwSeed = *v3; _LOBYTE(sgGameInitInfo.bDiff) = *((_BYTE *)v3 + 4); sgbPlayerTurnBitTbl[pEvt->playerid] = 1; break; case EVENT_TYPE_PLAYER_LEAVE_GAME: v1 = 0; sgbPlayerLeftGameTbl[pEvt->playerid] = 1; sgbPlayerTurnBitTbl[pEvt->playerid] = 0; v2 = (int *)pEvt->data; if ( v2 && pEvt->databytes >= 4u ) v1 = *v2; sgdwPlayerLeftReasonTbl[pEvt->playerid] = v1; if ( v1 == 0x40000004 ) gbSomebodyWonGameKludge = 1; sgbSendDeltaTbl[pEvt->playerid] = 0; dthread_remove_player(pEvt->playerid); if ( (unsigned char)gbDeltaSender == pEvt->playerid ) gbDeltaSender = 4; break; case EVENT_TYPE_PLAYER_MESSAGE: ErrorPlrMsg((char *)pEvt->data); break; } } // 6761B8: using guessed type char gbSomebodyWonGameKludge; // 6796E4: using guessed type char gbDeltaSender; //----- (00440694) -------------------------------------------------------- int __fastcall NetInit(int bSinglePlayer, int *pfExitProgram) { int v2; // ebx int v4; // eax //int v5; // ecx TCmdPlrInfoHdr *v6; // edx bool v7; // zf //int v9; // eax //int v10; // eax _SNETPROGRAMDATA ProgramData; // [esp+8h] [ebp-A8h] _SNETUIDATA UiData; // [esp+44h] [ebp-6Ch] _SNETPLAYERDATA a2; // [esp+94h] [ebp-1Ch] int v14; // [esp+A4h] [ebp-Ch] unsigned int len; // [esp+A8h] [ebp-8h] int *a4; // [esp+ACh] [ebp-4h] a4 = pfExitProgram; v14 = bSinglePlayer; v2 = 0; while ( 1 ) { *a4 = 0; SetRndSeed(0); sgGameInitInfo.dwSeed = time(0); _LOBYTE(sgGameInitInfo.bDiff) = gnDifficulty; memset(&ProgramData, 0, 0x3Cu); ProgramData.size = 60; ProgramData.programname = "Diablo Retail"; ProgramData.programdescription = gszVersionNumber; ProgramData.programid = 'DRTL'; ProgramData.versionid = 42; ProgramData.maxplayers = 4; ProgramData.multi_seed = (int)&sgGameInitInfo; ProgramData.initdata = (void *)8; ProgramData.reserved2 = (void *)15; ProgramData.languageid = 1033; memset(&a2, 0, 0x10u); a2.size = 16; memset(&UiData, 0, 0x50u); UiData.size = 80; UiData.parentwindow = SDrawGetFrameWindow(0); UiData.artcallback = UiArtCallback; UiData.createcallback = UiCreateGameCallback; UiData.drawdesccallback = UiDrawDescCallback; UiData.messageboxcallback = UiMessageBoxCallback; UiData.soundcallback = UiSoundCallback; UiData.authcallback = UiAuthCallback; UiData.getdatacallback = UiGetDataCallback; UiData.categorycallback = UiCategoryCallback; UiData.selecthero = (void (__cdecl *)())mainmenu_select_hero_dialog; UiData.createhero = (void (__cdecl *)())mainmenu_create_hero; UiData.profiledraw = UiProfileDraw; UiData.profilecallback = UiProfileCallback; UiData.profilegetstring = UiProfileGetString(); memset(sgbPlayerTurnBitTbl, 0, 4u); gbGameDestroyed = 0; memset(sgbPlayerLeftGameTbl, 0, 4u); memset(sgdwPlayerLeftReasonTbl, 0, 0x10u); memset(sgbSendDeltaTbl, 0, 4u); memset(plr, 0, 0x15360u); memset(sgwPackPlrOffsetTbl, 0, 8u); SNetSetBasePlayer(0); if ( v14 ) v4 = multi_init_single(&ProgramData, &a2, &UiData); else v4 = multi_init_multi(&ProgramData, &a2, &UiData, a4); if ( !v4 ) return 0; sgbNetInited = 1; sgbTimeout = 0; delta_init(); InitPlrMsg(); multi_clear_pkt(pkdata_6761C0); multi_clear_pkt(pkdata_678658); dword_678628 = 0; sync_clear_pkt(); nthread_start(sgbPlayerTurnBitTbl[myplr]); dthread_start(); MI_Dummy(0); /* v5 */ sgdwGameLoops = 0; sgbSentThisCycle = 0; gbDeltaSender = myplr; gbSomebodyWonGameKludge = 0; nthread_send_and_recv_turn(0, 0); SetupLocalCoords(); _LOBYTE(v6) = CMD_SEND_PLRINFO; multi_send_pinfo(-2, v6); gbActivePlayers = 1; v7 = sgbPlayerTurnBitTbl[myplr] == 0; plr[myplr].plractive = 1; if ( v7 || msg_wait_resync() ) break; NetClose(); byte_678640 = 0; } gnDifficulty = _LOBYTE(sgGameInitInfo.bDiff); SetRndSeed(sgGameInitInfo.dwSeed); do { glSeedTbl[v2] = GetRndSeed(); gnLevelTypeTbl[v2] = InitNewSeed(v2); ++v2; } while ( v2 < 17 ); //_LOBYTE(v9) = SNetGetGameInfo(GAMEINFO_NAME, szPlayerName, 128, len); if ( !SNetGetGameInfo(GAMEINFO_NAME, szPlayerName, 128, &len) ) nthread_terminate_game("SNetGetGameInfo1"); //_LOBYTE(v10) = SNetGetGameInfo(GAMEINFO_PASSWORD, szPlayerDescript, 128, len); if ( !SNetGetGameInfo(GAMEINFO_PASSWORD, szPlayerDescript, 128, &len) ) nthread_terminate_game("SNetGetGameInfo2"); return 1; } // 6761B8: using guessed type char gbSomebodyWonGameKludge; // 678628: using guessed type int dword_678628; // 67862C: using guessed type char gbActivePlayers; // 67862D: using guessed type char gbGameDestroyed; // 678640: using guessed type char byte_678640; // 679661: using guessed type char sgbTimeout; // 6796E4: using guessed type char gbDeltaSender; // 6796E8: using guessed type int sgbNetInited; //----- (00440992) -------------------------------------------------------- void __fastcall multi_clear_pkt(char *a1) { *(_DWORD *)a1 = 0; a1[4] = 0; } //----- (0044099A) -------------------------------------------------------- void __fastcall multi_send_pinfo(int pnum, TCmdPlrInfoHdr *cmd) { char v2; // bl int v3; // esi int v4; // edx PkPlayerStruct pkplr; // [esp+8h] [ebp-4F4h] v2 = (char)cmd; v3 = pnum; PackPlayer(&pkplr, myplr, 1); _LOBYTE(v4) = v2; dthread_send_delta(v3, v4, &pkplr, 1266); } //----- (004409D5) -------------------------------------------------------- int __fastcall InitNewSeed(int newseed) { int result; // eax result = 0; if ( newseed ) { result = 1; if ( newseed < 1 || newseed > 4 ) { if ( newseed < 5 || newseed > 8 ) { if ( newseed < 9 || newseed > 12 ) result = 4; else result = 3; } else { result = 2; } } } return result; } //----- (00440A05) -------------------------------------------------------- void __cdecl SetupLocalCoords() { int x; // ecx int y; // edx if ( !leveldebug || (unsigned char)gbMaxPlayers > 1u ) { currlevel = 0; leveltype = 0; setlevel = 0; } x = 75; y = 68; #ifdef _DEBUG if ( debug_mode_key_inverted_v || debug_mode_key_d ) { x = 49; y = 23; } #endif x += plrxoff[myplr]; y += plryoff[myplr]; plr[myplr].WorldX = x; plr[myplr].WorldY = y; plr[myplr]._px = x; plr[myplr]._py = y; plr[myplr]._ptargx = x; plr[myplr]._ptargy = y; plr[myplr].plrlevel = currlevel; plr[myplr]._pLvlChanging = 1; plr[myplr].pLvlLoad = 0; plr[myplr]._pmode = PM_NEWLVL; plr[myplr].destAction = -1; } // 52572C: using guessed type int leveldebug; // 5BB1ED: using guessed type char leveltype; // 5CF31D: using guessed type char setlevel; // 679660: using guessed type char gbMaxPlayers; //----- (00440A9B) -------------------------------------------------------- int __fastcall multi_init_single(_SNETPROGRAMDATA *client_info, _SNETPLAYERDATA *user_info, _SNETUIDATA *ui_info) { //int v3; // eax int result; // eax //int v5; // eax char *v6; // eax //_LOBYTE(v3) = SNetInitializeProvider(0, client_info, user_info, ui_info, &fileinfo); if ( SNetInitializeProvider(0, client_info, user_info, ui_info, &fileinfo) ) { ui_info = 0; //_LOBYTE(v5) = SNetCreateGame("local", "local", "local", 0, (char *)&sgGameInitInfo.dwSeed, 8, 1, "local", "local", (int *)&ui_info); if ( !SNetCreateGame("local", "local", "local", 0, (char *)&sgGameInitInfo.dwSeed, 8, 1, "local", "local", (int *)&ui_info) ) { v6 = GetLastErr(); TermMsg("SNetCreateGame1:\n%s", v6); } myplr = 0; gbMaxPlayers = 1; result = 1; } else { SErrGetLastError(); result = 0; } return result; } // 679660: using guessed type char gbMaxPlayers; //----- (00440B09) -------------------------------------------------------- int __fastcall multi_init_multi(_SNETPROGRAMDATA *client_info, _SNETPLAYERDATA *user_info, _SNETUIDATA *ui_info, int *a4) { _SNETPLAYERDATA *v4; // ebx signed int i; // edi int a6; // [esp+Ch] [ebp-Ch] int a2; // [esp+10h] [ebp-8h] int type; // [esp+14h] [ebp-4h] v4 = user_info; a2 = (int)client_info; for ( i = 1; ; i = 0 ) { type = 0; if ( byte_678640 ) { if ( !UiSelectProvider(0, (_SNETPROGRAMDATA *)a2, v4, ui_info, &fileinfo, &type) && (!i || SErrGetLastError() != STORM_ERROR_REQUIRES_UPGRADE || !multi_upgrade(a4)) ) { return 0; } if ( type == 'BNET' ) plr[0].pBattleNet = 1; } multi_event_handler(1); if ( UiSelectGame(1, (_SNETPROGRAMDATA *)a2, v4, ui_info, &fileinfo, &a6) ) break; byte_678640 = 1; } if ( (unsigned int)a6 >= 4 ) return 0; myplr = a6; gbMaxPlayers = 4; pfile_read_player_from_save(); if ( type == 'BNET' ) plr[myplr].pBattleNet = 1; return 1; } // 678640: using guessed type char byte_678640; // 679660: using guessed type char gbMaxPlayers; //----- (00440BDB) -------------------------------------------------------- int __fastcall multi_upgrade(int *a1) { int *v1; // esi int result; // eax int status; // [esp+4h] [ebp-4h] v1 = a1; SNetPerformUpgrade((unsigned long *)&status); result = 1; if ( status && status != 1 ) { if ( status == 2 ) { *v1 = 1; } else if ( status == -1 ) { DrawDlg("Network upgrade failed"); } result = 0; } return result; } //----- (00440C17) -------------------------------------------------------- void __fastcall multi_player_joins(int pnum, TCmdPlrInfoHdr *cmd, int a3) { int v3; // ebx TCmdPlrInfoHdr *v4; // edi short *v5; // esi int v6; // esi bool v7; // zf char *v8; // eax int v9; // ST08_4 int v10; // edx int v11; // eax int v12; // ecx int v13; // eax v3 = pnum; v4 = cmd; if ( myplr != pnum ) { v5 = &sgwPackPlrOffsetTbl[pnum]; if ( *v5 == cmd->wOffset || (*v5 = 0, !cmd->wOffset) ) { if ( !a3 && !*v5 ) { _LOBYTE(cmd) = CMD_ACK_PLRINFO; multi_send_pinfo(pnum, cmd); } memcpy((char *)&pkplr[v3] + (unsigned short)v4->wOffset, &v4[1], (unsigned short)v4->wBytes); *v5 += v4->wBytes; if ( *v5 == 1266 ) { *v5 = 0; multi_player_left_msg(v3, 0); v6 = v3; plr[v3]._pGFXLoad = 0; UnPackPlayer(&pkplr[v3], v3, 1); if ( a3 ) { ++gbActivePlayers; v7 = sgbPlayerTurnBitTbl[v3] == 0; plr[v6].plractive = 1; v8 = "Player '%s' (level %d) just joined the game"; if ( v7 ) v8 = "Player '%s' (level %d) is already in the game"; EventPlrMsg(v8, plr[v6]._pName, plr[v6]._pLevel); LoadPlrGFX(v3, 1); SyncInitPlr(v3); if ( plr[v6].plrlevel == currlevel ) { if ( (signed int)(plr[v6]._pHitPoints & 0xFFFFFFC0) <= 0 ) { plr[v6]._pgfxnum = 0; LoadPlrGFX(v3, 128); v9 = plr[v6]._pDWidth; v10 = plr[v6]._pDAnim[0]; plr[v6]._pmode = 8; NewPlrAnim(v3, v10, plr[v6]._pDFrames, 1, v9); v11 = plr[v6]._pAnimLen; v12 = v11 - 1; plr[v6]._pVar8 = 2 * v11; v13 = plr[v6].WorldX; plr[v6]._pAnimFrame = v12; dFlags[v13][plr[v6].WorldY] |= 4u; } else { StartStand(v3, 0); } } } } } } } // 67862C: using guessed type char gbActivePlayers;