Server Help Forum Index Server Help
Community forums for Subgame, ASSS, and bots
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   StatisticsStatistics   RegisterRegister 
 ProfileProfile   Login to check your private messagesLogin to check your private messages   LoginLogin (SSL) 

Server Help | ASSS Wiki (0) | Shanky.com
Reversing subgame2 ran into a problem

 
Post new topic   Reply to topic Printable version
 View previous topic  I want to run a hockey or powerball game Post :: Post wiki problem  View next topic  
Author Message
fatrolls
Novice


Age:36
Gender:Gender:Male
Joined: Jul 25 2013
Posts: 35
Offline

PostPosted: Wed Apr 16, 2014 11:24 pm    Post subject: Reversing subgame2 ran into a problem Reply to topic Reply with quote

I'm trying to port subgame2 into Linux but I ran into a problem.

I know the maximum allowed players in subgame2 is either 1024 or 1025 or maybe that's maximum in just one arena I don't know for sure.

But when I was re-factoring some structures I ran into a interesting problem for some reason the structure starts to overlap what I called ArenaPlayerCount which is at 0xFF0C of the struct_ARENA I called it.

Now the playerPointersForSomething starts at 0xFB20

FF0C - FB20 = 3EC of space which is 1004 bytes of space.

Lets say the struct_PLAYER is a total of 0x35D (861 bytes).

So yeah about only 1 player can fit in there, so.. I figured it had to be a array of addresses which point to that struct_PLAYER which makes sense.

But since the addresses take 4 bytes each that means 1004/4=251

Which means only 251 players can be stored in the arena?

I also thought maybe ArenaPlayerCount is like a base address.

And every player pointer is only 1 byte long which would append to the base address but seems like that's impossible since the addresses are always in randomized or just unpredictable locations.

Thought maybe the playerPointersForSomething itself isn't a array but just a pointer to another location which holds all the players but I couldn't find it. Then again it can't be since the playerPointersForSomething points to the first player.

Also the struct_ARENA can't be larger I found the structure limit here
newArena = operator new(0x1D40Eu);
So each arena structure is exactly 119,822 bytes.


I remember when I used to play Trench Wars during World War 3 there was over 380 players in one arena so I don't believe the limit is 251 players per arena, I'm just doing something wrong.

Here is a fully decompiled function to show the bug, I already posted on many other reversing forums thinking they'll show me some basics on how to do this but meh no replies so far thinking I may get some insight here.

Code: Show/Hide

int __thiscall GetNextFrequencyToJoin(struct_ARENA *arena)
{
  struct_ARENA *arenaa; // ebx@1
  signed int TotalPlaying; // ebp@1
  struct_PLAYER **eachPlayer; // edx@2
  int ArenaPlayerCount; // esi@2
  int Frequency; // eax@3
  signed int CurrentFrequency; // esi@10
  int *NumPlayersPerFreqArrayy; // edi@10
  int NumPlayersThisFreq; // ecx@12
  signed int TotalPlayingg; // [sp+10h] [bp-324h]@1
  int NumPlayersPerFreqArray[200]; // [sp+14h] [bp-320h]@1

  arenaa = arena;
  memset(NumPlayersPerFreqArray, 0, sizeof(NumPlayersPerFreqArray));
  TotalPlaying = 0;
  TotalPlayingg = 0;
  if ( arena->ArenaPlayerCount > 0 )
  {
    eachPlayer = arena->playerPointersForSomething;// Obviously Player Pointers but why only 251? If possible 1025 players
    ArenaPlayerCount = arena->ArenaPlayerCount;
    do
    {
      Frequency = (*eachPlayer)->Frequency;
      if ( Frequency >= 0 && (*eachPlayer)->Ship != 8 )
      {
        if ( Frequency < 200 )
          ++NumPlayersPerFreqArray[Frequency];
        ++TotalPlaying;
      }
      ++eachPlayer;
      --ArenaPlayerCount;
    }
    while ( ArenaPlayerCount );
    TotalPlayingg = TotalPlaying;
  }
  CurrentFrequency = 0;
  NumPlayersPerFreqArrayy = NumPlayersPerFreqArray;
  while ( 1 )
  {
    if ( CurrentFrequency >= arenaa->ArenaSettings.MaxFrequency )
      return rand() % arenaa->ArenaSettings.MaxFrequency;
    NumPlayersThisFreq = *NumPlayersPerFreqArrayy;
    if ( !*NumPlayersPerFreqArrayy )
      break;
    if ( NumPlayersThisFreq < arenaa->ArenaSettings.MaxPerTeam
      && NumPlayersThisFreq <= TotalPlayingg / arenaa->ServersideArenaSettings.TeamDesiredTeams )
      break;
    ++CurrentFrequency;
    ++NumPlayersPerFreqArrayy;
    if ( CurrentFrequency >= 200 )
      return rand() % arenaa->ArenaSettings.MaxFrequency;
  }
  return CurrentFrequency;
}


Here is a Naked version just so you can see the address offsets for the structure.
Code: Show/Hide

int __thiscall GetNextFrequencyToJoin(int arena)
{
  struct_ARENA *arenaa; // ebx@1
  signed int TotalPlaying; // ebp@1
  int eachPlayer; // edx@2
  int ArenaPlayerCount; // esi@2
  int Frequency; // eax@3
  signed int CurrentFrequency; // esi@10
  int *NumPlayersPerFreqArrayy; // edi@10
  int NumPlayersThisFreq; // ecx@12
  signed int TotalPlayingg; // [sp+10h] [bp-324h]@1
  int NumPlayersPerFreqArray[200]; // [sp+14h] [bp-320h]@1

  arenaa = arena;
  memset(NumPlayersPerFreqArray, 0, sizeof(NumPlayersPerFreqArray));
  TotalPlaying = 0;
  TotalPlayingg = 0;
  if ( *(arena + 65292) > 0 )
  {
    eachPlayer = arena + 64288;                 // Obviously Player Pointers but why only 251? If possible 1025 players
    ArenaPlayerCount = *(arena + 65292);
    do
    {
      Frequency = *(*eachPlayer + 279);
      if ( Frequency >= 0 && *(*eachPlayer + 275) != 8 )
      {
        if ( Frequency < 200 )
          ++NumPlayersPerFreqArray[Frequency];
        ++TotalPlaying;
      }
      eachPlayer += 4;
      --ArenaPlayerCount;
    }
    while ( ArenaPlayerCount );
    TotalPlayingg = TotalPlaying;
  }
  CurrentFrequency = 0;
  NumPlayersPerFreqArrayy = NumPlayersPerFreqArray;
  while ( 1 )
  {
    if ( CurrentFrequency >= *(arenaa + 109378) )
      return rand() % *(arenaa + 109378);
    NumPlayersThisFreq = *NumPlayersPerFreqArrayy;
    if ( !*NumPlayersPerFreqArrayy )
      break;
    if ( NumPlayersThisFreq < *(arenaa + 109567) && NumPlayersThisFreq <= TotalPlayingg / *(arenaa + 109706) )
      break;
    ++CurrentFrequency;
    ++NumPlayersPerFreqArrayy;
    if ( CurrentFrequency >= 200 )
      return rand() % *(arenaa + 109378);
  }
  return CurrentFrequency;
}


Super raw
Code: Show/Hide

function GetNextFrequencyToJoin {
    esp = esp - 0x324;
    ebx = ecx;
    ecx = 0xc8;
    asm{ rep stosd   };
    ebp = 0x0;
    if (*(ebx + 0xff0c) > 0x0) {
            edx = ebx + 0xfb20;
            esi = 0x0;
            do {
                    if ((*(*edx + 0x117) >= 0x0) && (*(ecx + 0x113) != 0x8)) {
                            if (eax < 0xc8) {
                                    *(esp + eax * 0x4 + 0x14) = *(esp + eax * 0x4 + 0x14) + 0x1;
                            }
                            ebp = &var_1;
                    }
                    edx = edx + 0x4;
                    esi = esi - 0x1;
            } while (esi != 0x0);
    }
    ebp = *(ebx + 0x1ab42);
    esi = 0x0;
    edi = esp + 0x14;

loc_4045a3:
    if (esi >= ebp) goto loc_4045d4;
    goto loc_4045a7;

loc_4045d4:
    eax = sub_41ceb0();
    asm{ cdq         };
    temp_2 = MAKEWORD(edx:eax);
    temp_3 = *(ebx + 0x1ab42);
    eax = temp_2 / temp_3;
    return temp_2 % temp_3;

loc_4045a7:
    if (*edi == 0x0) goto loc_4045ed;
    goto loc_4045ad;

loc_4045ed:
    eax = esi;
    return eax;

loc_4045ad:
    if (ecx >= *(int8_t *)(ebx + 0x1abff)) goto loc_4045c8;
    goto loc_4045b9;

loc_4045c8:
    esi = esi + 0x1;
    edi = edi + 0x4;
    if (esi < 0xc8) goto loc_4045a3;
    goto loc_4045d4;

loc_4045b9:
    asm{ cdq         };
    temp_0 = MAKEWORD(edx:*(esp + 0x10));
    temp_1 = *(ebx + 0x1ac8a);
    edx = temp_0 % temp_1;
    if (ecx <= temp_0 / temp_1) goto loc_4045ed;
    goto loc_4045c8;
}
Back to top
View users profile Send private message Add User to Ignore List
L.C.
Server Help Squatter


Age:33
Gender:Gender:Male
Joined: Jan 03 2003
Posts: 574
Location: Missouri, US
Offline

PostPosted: Sat May 28, 2016 1:59 am    Post subject: Reply to topic Reply with quote

Quote:
I remember when I used to play Trench Wars during World War 3 there was over 380 players in one arena so I don't believe the limit is 251 players per arena, I'm just doing something wrong.
When Continuum 0.36 or 0.37 was released, the only zone running the compatible Subgame had 700-1000 players in a single arena. I remember it very clearly, and it handled it well/okay too. I've never been able to replicate the results to that degree with bots though.
Back to top
View users profile Send private message Add User to Ignore List Send email Visit posters website AIM Address Yahoo Messenger MSN Messenger
Display posts from previous:   
Post new topic   Reply to topic    Server Help Forum Index -> General Questions All times are GMT - 5 Hours
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You can attach files in this forum
You can download files in this forum
View online users | View Statistics | View Ignored List


Software by php BB © php BB Group
Server Load: 670 page(s) served in previous 5 minutes.

phpBB Created this page in 0.536285 seconds : 27 queries executed (83.0%): GZIP compression disabled