DESKTOP-AB9OQPJ\RED-10 %!s(int64=3) %!d(string=hai) anos
pai
achega
c8da647562

+ 0 - 1
jni/CFTTGraphicsDevice.h

@@ -75,7 +75,6 @@ class CFTTGraphicsDevice {
 public:
   //CFTTGraphicsDevice();
   virtual ~CFTTGraphicsDevice();
-
   virtual int create() = 0;
   virtual void destroy() = 0;
   virtual void createVolatileResources() = 0;

+ 4 - 0
jni/CGfxCharacter.cpp

@@ -210,6 +210,10 @@ const char *aStorsoSPng_0 = "%storso_%s.png";
 const char *aDataModelsPlay = "data/models/player/textures/";
 static const char *off_3230BC[12] = {0};
 static uint32 dword_3A4ED4[4] = {FTTHash("gloves"), 0, 0, 0};
+
+TSATAnim_TSX* GetAnim(uint a1){
+  return CGfxCharacter::s_pAnimLib->GetAnim(rand(),true);
+}
 //-------------------------------------------------------------------------------------------------
 //0017D450
 CGfxCharacter::CGfxCharacter(int i1, int i2, int i3, TPlayerInfo *tPlayerInfo4, CPlayer *cPlayer5, int i6, int i7) {

+ 1 - 1
jni/CGfxCharacter.h

@@ -143,7 +143,7 @@ struct TCharAnimSpec {
   int v_3;
   int v_4;
 };
-
+TSATAnim_TSX* GetAnim(uint a1);
 // TSATFrameSample 0x498
 
 class CGfxCharacter {

+ 555 - 47
jni/CGfxCrowd.cpp

@@ -1,99 +1,607 @@
 #include "CGfxCrowd.h"
-#include "memctrl.h"
 
+#include "CCrowdNewShader.h"
+#include "CFTTGraphicsDevice.h"
+#include "CFTTMaterialManager.h"
+#include "CFTTTextureManager.h"
+#include "CGaussianNewShader.h"
+#include "CGfxCharacter.h"
+#include "CGfxEnvironmentMap.h"
+#include "CGfxKits.h"
+#include "CGfxPlayer.h"
+#include "CGraphicsTexLoadOptions.h"
+#include "CModelManager.h"
+#include "CPBRLighting.h"
+#include "CPlayerShader.h"
+#include "FTTALG.h"
+#include "GFXSCENE.h"
+#include "Matrix.h"
+#include "TGame.h"
+#include "XSYS.h"
+#include "memctrl.h"
 CGfxCrowd *CGfxCrowd::ms_pInstance = nullptr;
+uchar byte_2FEFF4[15] = {5, 4, 0, 0xC, 1, 5, 4, 0, 0xC, 1, 3, 2, 0, 3, 3};
+uchar byte_2FF003[180] = {
+    3,    3,   0xE,  0xE, 0x10, 0,   0, 0, 0,   0, 0, 0, 2, 3,   6,
+    0x11, 0,   0,    0,   0,    0,   0, 0, 0,   0, 0, 0, 0, 0,   0,
+    0,    0,   0,    0,   0,    0,   0, 1, 5,   4, 7, 8, 9, 0xA, 0xC,
+    0xD,  0xE, 0xF,  3,   0,    0,   0, 0, 0,   0, 0, 0, 0, 0,   0,
+    3,    3,   0xE,  0xE, 0x10, 0,   0, 0, 0,   0, 0, 0, 2, 3,   6,
+    0x11, 0,   0,    0,   0,    0,   0, 0, 0,   0, 0, 0, 0, 0,   0,
+    0,    0,   0,    0,   0,    0,   0, 1, 5,   4, 7, 8, 9, 0xA, 0xC,
+    0xD,  0xE, 0xF,  3,   0,    0,   0, 0, 0,   0, 0, 0, 0, 0,   0,
+    3,    3,   0x10, 0,   0,    0,   0, 0, 0,   0, 0, 0, 2, 3,   0,
+    0,    0,   0,    0,   0,    0,   0, 0, 0,   0, 0, 0, 0, 0,   0,
+    0,    0,   0,    0,   0,    0,   3, 4, 0xA, 0, 0, 0, 0, 0,   0,
+    0,    0,   0,    3,   4,    0xA, 0, 0, 0,   0, 0, 0, 0, 0,   0};
+
+
+uchar byte_2FDF94[] = {0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 3, 4, 4, 4, 4};
+
+struct Unknow_4630E0
+{
+  uchar byte_4630E0[8];
+  uchar byte_4630E8[0x10];
+} t_4630e0;
+// 00185e1a ^_-
+// void GetFaceData(TFTTModel *pModel0, ushort *&pUS1, int &i2, int i3) {
+//   int iR1 = 0;
+//   i2 = 0;
+//   //.text:00185E2E                 B               loc_185E58
+//   for (int iR6 = 0; iR6 < pModel0->us_10; iR6++) {  // loc_185E30
+//     bool b = i3 == -1;
+//     // text:00185E32                 IT NE
+//     if (i3 != -1)
+//       b = i3 == iR6;
+//     //.text:00185E36                 BNE             loc_185E54
+//     if (b) {
+//       uint iR7 = pModel0->u_28.list_C[iR6].field_4;
+//       //.text:00185E40                 CBZ             R7, loc_185E4C
+//       if (iR7) {
+//         iR1 += iR7 - 2;
+//         i2 = iR1;
+//       }
+//       // loc_185E4C
+//       iR1 += pModel0->u_28.list_C[iR6].field_6;
+//       i2 = iR1;
+//     }
+//     // loc_185E54
+//   }
+//   //.text:00185E5E                 BCC             loc_185E30
+
+//   pUS1 = new ushort[iR1 * 3];
+//   int offsetR9 = 0;
+//   int posR7 = 0;
+//   // LOGE("pppp");
+//   //.text:00185E86                 B               loc_185F9A
+//   for (int iR6 = 0; iR6 < pModel0->us_10; iR6++) {  // loc_185E88
+//     bool b = i3 == -1;
+//     //.text:00185E8A                 IT NE
+//     if (i3 != -1)
+//       b = i3 == iR6;
+//     int sizeR12;
+//     //.text:00185E8E                 BNE             loc_185EDE
+//     if (b) {  //.text:00185E90
+//       memcpy(&pUS1[3 * offsetR9],
+//              (char *)&pModel0->u_24.pmodel_union_struct_2[posR7],
+//              6 * pModel0->u_28.list_C[iR6].field_6);
+//       sizeR12 = pModel0->u_28.list_C[iR6].field_6;
+//       int lenR3 = pModel0->u_28.list_C[iR6].field_4;
+//       offsetR9 += sizeR12;
+//       int sLR, eR0;
+//       //.text:00185ED0                 CBZ             R3, loc_185EF0
+//       if (lenR3) {  //.text:00185ED2
+
+//         sLR = pModel0->u_28.list_C[iR6].field_2;
+//         eR0 = pModel0->u_28.list_C[iR6].field_0;
+//         //.text:00185EDC                 B               loc_185EF6
+//       } else {  // loc_185EF0
+//         eR0 = 0;
+//         sLR = 0;
+//       }
+//       // loc_185EF6
+//       //.text:00185EFC                 BCS             loc_185F92
+//       for (int iR2 = 2; iR2 < lenR3; iR2++) {
+//         int iR3 = 3 * offsetR9;
+//         pUS1[iR3] = eR0;
+//         //.text:00185F0C                 BNE             loc_185F26
+//         if (iR2 << 31) {  // loc_185F26
+//           pUS1[iR3 + 1] = (&pModel0->u_28.list_C[iR6].field_0)[iR2];
+//           pUS1[iR3 + 2] = sLR;
+//         } else {  //.text:00185F0E
+//           pUS1[iR3 + 1] = sLR;
+//           pUS1[iR3 + 2] = (&pModel0->u_28.list_C[iR6].field_0)[iR2];
+//         }
+//         // loc_185F3E
+
+//         //.text:00185F62                 BEQ             loc_185F72
+//         if (pUS1[3 * offsetR9] == pUS1[3 * offsetR9 + 1]
+//             //.text:00185F70                 BNE             loc_185F8C
+//             || pUS1[3 * offsetR9 + 1] == pUS1[3 * offsetR9 + 2] || pUS1[3 *
+//             offsetR9] == pUS1[3 * offsetR9 + 2]) {
+//           --i2;
+
+//         } else {  // loc_185F8C
+//           ++offsetR9;
+//         }
+
+//         eR0 = sLR;
+//         sLR = (&pModel0->u_28.list_C[iR6].field_0)[iR2];
+//       }
+
+//     } else {  // oc_185EDE
+//       sizeR12 = pModel0->u_28.list_C[iR6].field_6;
+//     }
+//     posR7 += sizeR12;
+//   }  //.text:00185FA0                 BCC.W           loc_185E88
+// }
 //-------------------------------------------------------------------------------------------------
-//0019691C
+// 0019691C 经过单元测试功能正常 (前5关)
 CGfxCrowd::CGfxCrowd() {
-  LOGI("CGfxCrowd::CGfxCrowd entry");
+  // pRender2Tex_9C = nullptr;
+  // pRender2Tex_A0 = nullptr;
+  // pRender2Tex_A4 = nullptr;
+
+  // b_CBB4 = false;
+
+  // // 001969D0
+  // CFTTTexParam var_28(1);
+  // dCrowdNewShaderID_CBBC[0] =
+  // CCrowdNewShader::s_tInstance.CreateMat(ECrowdNewShader_Quads_1,
+  //                                                                    ECrowdNewShader_Alphatest_0,
+  //                                                                    var_28,
+  //                                                                    ECrowdNewShader_CullMode_1);
+
+  // // 001969E4
+  // dCrowdNewShaderID_CBBC[1] =
+  // CCrowdNewShader::s_tInstance.CreateMat(ECrowdNewShader_Quads_1,
+  //                                                                    ECrowdNewShader_Alphatest_1,
+  //                                                                    var_28,
+  //                                                                    ECrowdNewShader_CullMode_1);
+
+  // // 001969F8
+  // dCrowdNewShaderID_CBBC[2] =
+  // CCrowdNewShader::s_tInstance.CreateMat(ECrowdNewShader_Quads_0,
+  //                                                                    ECrowdNewShader_Alphatest_0,
+  //                                                                    var_28,
+  //                                                                    ECrowdNewShader_CullMode_1);
 }
 //-------------------------------------------------------------------------------------------------
-//00196A10
+// 00196A10
 CGfxCrowd::~CGfxCrowd() {
+  Shut();
+  for (int r5 = 0; r5 != 3; r5++) {  // loc_196A48
+    // loc_196A3C
+    FTT_pMtlL->ReleaseMaterial(dCrowdNewShaderID_CBBC[r5]);
+  }
+
+  // 00196A4C
 }
 //-------------------------------------------------------------------------------------------------
-//001968CC ^_^
-void CGfxCrowd::Initialise() {
-}
+// 001968CC ^_^
+void CGfxCrowd::Initialise() { ms_pInstance = new CGfxCrowd; }
 //-------------------------------------------------------------------------------------------------
-//001968EC
+// 001968EC
 void CGfxCrowd::Shutdown() {
+  if (CGfxCrowd::ms_pInstance != nullptr) {
+    delete CGfxCrowd::ms_pInstance;
+  }
+  CGfxCrowd::ms_pInstance = nullptr;
 }
 //-------------------------------------------------------------------------------------------------
-//0019690C
-CGfxCrowd *CGfxCrowd::Get() {
-  return nullptr;
-}
+// 0019690C
+CGfxCrowd *CGfxCrowd::Get() { return CGfxCrowd::ms_pInstance; }
 //-------------------------------------------------------------------------------------------------
-//00196AF8
-void CGfxCrowd::Shut() {
-}
+// 00196AF8
+void CGfxCrowd::Shut() { LOGX("CGfxCrowd::Shut 00196AF8"); }
 //-------------------------------------------------------------------------------------------------
-//
-void CGfxCrowd::Init() {
-}
+// 00196E72 ^_^
+void CGfxCrowd::Init() { f_CBB8 = 0; }
 //-------------------------------------------------------------------------------------------------
-//00197140
+// 00197140
 void CGfxCrowd::AddStand(CFTTModel *, CFTTMatrix32) {
+  LOGX("CGfxCrowd::AddStand 00197140");
 }
 //-------------------------------------------------------------------------------------------------
-//00199D4C
+// 00199D4C
 void CGfxCrowd::GetCapacity(CFTTModel *, CFTTMatrix32) {
+  LOGX("CGfxCrowd::GetCapacity 00199D4C");
 }
 //-------------------------------------------------------------------------------------------------
-//00199E08
-void CGfxCrowd::AssessDesirability(TGfxCrowdSeat &) {
+// 00199E08 ^_^ 经过单元测试,功能正常(前5关)
+void CGfxCrowd::AssessDesirability(TGfxCrowdSeat &tSeat) {
+  tSeat.f_18 =
+      powf(XSYS_RandomNoSyncF(17.5f), 1.5f) + (20.0f - (tSeat.f_4 + tSeat.f_4));
 }
 //-------------------------------------------------------------------------------------------------
-//00199E3C
-void CGfxCrowd::AssessDesirability(TGfxCrowdSeat &, bool) {
+// 00199E3C 经过单元测试,功能正常(前5关)
+void CGfxCrowd::AssessDesirability(TGfxCrowdSeat &tSeat1, bool b2) {
+  float fr6 = powf(XSYS_RandomNoSyncF(20.0f), 1.5f);
+  float fs16 = -1.0f;
+  // 00199E62
+  if (b2) {
+    // 00199E6A
+    fs16 = 1.0;
+  }
+
+  // 00199E70
+  float fs6 = XMATH_ClampFloat(tSeat1.f_8, -60.0f, 60.0f);
+  float fs0 = fr6 + (20.0f - (tSeat1.f_4 + tSeat1.f_4));
+  float fs8 = 10.0f + (fabs(tSeat1.f_0) * -0.5f);
+
+  /*
+    以下写法与原始汇编一致,但是可读性差,我改成逻辑一致,可读性更强的代码
+    float32x2_t f32_1{fs8, 0.0f};
+    float32x2_t f32_2{0.0f, 0.0f};
+    float32x2_t ff32 = vmax_f32(f32_1, f32_2);
+    float dfs8 = ff32[0];
+    -----
+    我改成直接调用 fmaxf API
+  */
+
+  tSeat1.f_18 =
+      (fs0 + (fs16 * fs6)) + fmaxf(10.0f + (fabs(tSeat1.f_0) * -0.5f), 0.0f);
 }
 //-------------------------------------------------------------------------------------------------
-//00199ED0
-void CGfxCrowd::Distribute(uint) {
-}
+// 00199ED0
+void CGfxCrowd::Distribute(uint) { LOGX("CGfxCrowd::Distribute 00199ED0"); }
 //-------------------------------------------------------------------------------------------------
-//0019CBA0
-void CGfxCrowd::UpdateCrowdTextures(uint) {
+// 0019CBA0
+void CGfxCrowd::UpdateCrowdTextures(uint r1_u) {
+  // sp30=this
+  // sp2c=r1_u
+  switch (r1_u) {
+      // sp28=m_st_D0
+      // r11=m_st_D0
+    case 0: {
+      // loc_19CBE6
+      // sp28=m_st_D0
+
+      CrowdTextureCreationData *r1_pdata = new CrowdTextureCreationData;
+      r1_pdata->mpFTTAtlasGenerator_194C = 0;
+      r1_pdata->miCFTTMaterialIndex_0 = -1;
+      r1_pdata->name_texture_5C = 0;
+      r1_pdata->name_texture_60 = 0;
+      r1_pdata->name_texture_64 = 0;
+      r1_pdata->pmembers_34 = 0;
+      r1_pdata->field_38[0] = 0;
+      r1_pdata->field_38[1] = 0;
+      r1_pdata->field_40 = 0;
+      r1_pdata->field_44 = 0;
+      tPtrTextureData_D0 = r1_pdata;
+      g_pGraphicsDevice->setDither(false);
+      // 0019CC38
+      // check 返回值 空函数
+      tPtrTextureData_D0.pType_0->miCFTTMaterialIndex_0 =
+          CGaussianNewShader::s_tInstance.CreateMat(
+              EGaussianNewShader_Channel_1, EGaussianNewShader_Blend_1);
+      CFTTTexLoadOptions options_sp78 =
+          g_tGlobalTexLoadOptions.mTexLoadOptions_4;
+      // r9=spd0
+      TBuildKitTeamTextures team_textures_spd0[2];
+      for (int r1_i = 0; r1_i < 2; r1_i++) {
+        // loc_19CC72
+        team_textures_spd0[r1_i].pCTeam_0 = 0;
+        team_textures_spd0[r1_i].filed_4 = -1;
+      }
+      CGfxKits::LoadKitTeamTextures(
+          &tGame.CTeam_2C60[0], &team_textures_spd0[0],
+          g_tGlobalTexLoadOptions.mTexLoadOptions_4, 0);
+      CGfxKits::LoadKitTeamTextures(
+          &tGame.CTeam_2C60[1], &team_textures_spd0[1],
+          g_tGlobalTexLoadOptions.mTexLoadOptions_4, 0);
+      CGfxKits::BeginBuildKit(0);
+      // check 传参
+      CGfxKits::GetTexture(tPtrTextureData_D0.pType_0->field_4,
+                           team_textures_spd0, 0, EKitTextureType_0, NULL);
+      CGfxKits::GetTexture(tPtrTextureData_D0.pType_0->field_8,
+                           team_textures_spd0, 1, EKitTextureType_0, NULL);
+      // 0019CCDE
+      CGfxKits::GetTexture(tPtrTextureData_D0.pType_0->field_C,
+                           &team_textures_spd0[1], 0, EKitTextureType_0, NULL);
+      CGfxKits::GetTexture(tPtrTextureData_D0.pType_0->field_10,
+                           &team_textures_spd0[1], 1, EKitTextureType_0, NULL);
+      CGfxKits::EndBuildKit();
+      // 0019CD02
+      CGfxKits::FreeKitTeamTextures(team_textures_spd0);
+      CGfxKits::FreeKitTeamTextures(&team_textures_spd0[1]);
+      // 0019CD0E
+      tPtrTextureData_D0.pType_0->model_2C = CModelManager::LoadModel(
+          "data/models/crowd/crowd1.FTM", "data/models/crowd/",
+          EModelLoadFlags_2, true);
+      // 0019CD20
+      tPtrTextureData_D0.pType_0->model_30 = CModelManager::LoadModel(
+          "data/models/crowd/crowd2.FTM", "data/models/crowd/",
+          EModelLoadFlags_2, true);
+      // 0019CD34
+      tPtrTextureData_D0.pType_0->texture_48 = FTT_pTex->LoadTexture(
+          "data/models/Player/Textures/kit_dyn_n.p", options_sp78);
+      // 0019CD50
+      tPtrTextureData_D0.pType_0->texture_4C = FTT_pTex->LoadTexture(
+          "data/models/Player/Textures/kit_dyn_a.p", options_sp78);
+      // 0019CD5E
+      tPtrTextureData_D0.pType_0->texture_50 = FTT_pTex->LoadTexture(
+          "data/models/Player/Textures/atlas_n.png", options_sp78);
+      // 0019CD6C
+      tPtrTextureData_D0.pType_0->texture_58 = FTT_pTex->LoadTexture(
+          "data/models/Player/Textures/atlas_s.png", options_sp78);
+      // 0019CD7A
+      options_sp78.eMinFilter_18 = EFTTTex_MinFilter_0;
+      CFTTTexture *r4_name_texture = CFTTTexture::LoadName(
+          "data/models/Crowd/jeans.png", options_sp78, true);
+      if (tPtrTextureData_D0.pType_0->name_texture_5C) {  // 0019CD98
+        delete tPtrTextureData_D0.pType_0->name_texture_5C;
+      }
+      // loc_19CD9E
+      tPtrTextureData_D0.pType_0->name_texture_5C = r4_name_texture;
+      r4_name_texture = CFTTTexture::LoadName("data/models/Crowd/steward.png",
+                                              options_sp78, true);
+      if (tPtrTextureData_D0.pType_0->name_texture_60) {  // 0019CDB6
+        delete tPtrTextureData_D0.pType_0->name_texture_60;
+      }
+      // loc_19CDBC
+      tPtrTextureData_D0.pType_0->name_texture_60 = r4_name_texture;
+
+      r4_name_texture = CFTTTexture::LoadName("data/models/Crowd/jacket.png",
+                                              options_sp78, true);
+      if (tPtrTextureData_D0.pType_0->name_texture_64) {  // 0019CDD4
+        delete tPtrTextureData_D0.pType_0->name_texture_64;
+      }
+      // loc_19CDDA
+      tPtrTextureData_D0.pType_0->name_texture_64 = r4_name_texture;
+      GFXSCENE_Apply(NULL);
+      CFTTVector32 vrctor32_sp50;
+      vrctor32_sp50.float_0 = 0;
+      vrctor32_sp50.float_4 = 0.300000012f;
+      vrctor32_sp50.float_8 = -1.0f;
+      GFXSCENE_vLightDir = Normalize(vrctor32_sp50);
+      // 0019CDFA
+      // GFXSCENE_vLightDir=vrctor32_sp120;
+      CPBRLighting::Get()->Reinitialise(true);
+      CGfxEnvironmentMap::Get()->SetForced(EEnvMapOverride_1);
+      // loc_19CE38
+      // check new size 0x15E08  以及头部数据
+      TCrowdMember *r5_pmember = new TCrowdMember[0x20];
+      // 0019CE48 这里的符号不对
+      // FTTUPtr<TCrowdMember []>::operator=(TCrowdMember*)
+      tPtrTextureData_D0.pType_0->pmembers_34 = r5_pmember;
+      CPlayerShader::s_tInstance.SetCinematic(EPlayerShader_Cinematic_1);
+      CFTTVector32x4 vector32x4_sp120;
+      vector32x4_sp120.my[0] = 1.0f;
+      vector32x4_sp120.my[1] = 1.0f;
+      vector32x4_sp120.my[0] = 0;
+      vector32x4_sp120.my[0] = 0;
+
+      CPlayerShader::s_tInstance.SetCinematicLightingCloth(vector32x4_sp120);
+      vector32x4_sp120.my[0] = 1.0f;
+      vector32x4_sp120.my[1] = 1.0f;
+      vector32x4_sp120.my[0] = 0;
+      vector32x4_sp120.my[0] = 0;
+      CPlayerShader::s_tInstance.SetCinematicLightingSkin(vector32x4_sp120);
+
+      break;
+    }
+    case 1: {
+      // 0019CE84
+      for (int r4_i = 0; r4_i != 0x20; r4_i++) {
+        // loc_19CE9E
+        float s0_f = XSYS_RandomNoSyncF(0.0799999982f);
+        tPtrTextureData_D0.pType_0->pmembers_34.pType_0[r4_i]
+            .m_cVec32_ADC.float_4 = 0;
+        tPtrTextureData_D0.pType_0->pmembers_34.pType_0[r4_i]
+            .m_cVec32_ADC.float_8 = 0;
+
+        tPtrTextureData_D0.pType_0->pmembers_34.pType_0[r4_i]
+            .m_cVec32_ADC.float_0 =
+            (-6.975 + r4_i * 0.449999988f) + (s0_f - 0.0399999991f);
+      }
+      // 0019CEDA
+      CGfxPlayer::SetupBatchConstants();
+      CPlayerShader::s_tInstance.SetShadowMap(EPlayerShader_ShadowMap_0);
+      CPlayerShader::s_tInstance.SetBlendMode(EPlayerShader_BlendMode_0);
+      CPlayerShader::s_tInstance.SetModel(EPlayerShader_Model_0);
+      CPlayerShader::s_tInstance.SetQuality(EPlayerShader_Quality_2);
+      break;
+    }
+    case 2:
+    case 4: {  // loc_19CFB4
+               // sp4c=tPtrTextureData_D0
+      CFTTRenderToTexture r5_ptexture =
+          g_pGraphicsDevice->createRenderToTexture(
+              EFTTTexFormat_2, 0x400, 0x400, 0x1, 0x18, EFTTRTTZBufMode_1,
+              false, EFTTTextureType_0, 1);
+      ECrowdMemberType r4_member_type = ECrowdMemberType_0;
+      if (r1_u != 2) r4_member_type = ECrowdMemberType_1;
+      // 0019CFE0
+      if (tPtrTextureData_D0.pType_0[(uint)r4_member_type]
+              .texture_38)  // 0019CFF4
+        delete tPtrTextureData_D0.pType_0[(uint)r4_member_type].texture_38;
+      // loc_19CFFA
+      tPtrTextureData_D0.pType_0[(uint)r4_member_type].texture_38 = r5_ptexture;
+      // loc_19D022
+      for (uint r6_u = 0; r6_u != 0x20; r6_u++) {
+        // loc_19D002
+        if (r6_u <= 5) {  // 0019D00C
+          tPtrTextureData_D0.pType_0->pmembers_34.pType_0[r6_u].Setup(
+              r4_member_type, r6_u);
+        } else {
+          // loc_19D012
+          tPtrTextureData_D0.pType_0->pmembers_34.pType_0[r6_u].Setup(
+              ECrowdMemberType_2, r6_u - 6);
+        }
+        // loc_19D018
+      }
+      // 0019D026
+      FTTALG::Shuffle(tPtrTextureData_D0.pType_0->pmembers_34.pType_0,
+                      &tPtrTextureData_D0.pType_0->pmembers_34.pType_0[0x20]);
+      // 0019D032
+      // loc_19D084
+      for (int r4_i = 0; r4_i != 0x20; r4_i++) {
+        // loc_19D04C
+        float s0_f = XSYS_RandomNoSyncF(0.0399999991f);
+        tPtrTextureData_D0.pType_0->pmembers_34.pType_0[r4_i]
+            .m_cVec32_ADC.float_4 = 0;
+        tPtrTextureData_D0.pType_0->pmembers_34.pType_0[r4_i]
+            .m_cVec32_ADC.float_8 = 0;
+
+        tPtrTextureData_D0.pType_0->pmembers_34.pType_0[r4_i]
+            .m_cVec32_ADC.float_0 =
+            (-6.975 + r4_i * 0.449999988f) + (s0_f - 0.0199999996f);
+      }
+      // 0019D088
+      // sp38=unk_2FEFF4
+      // sp34=unk_2FF003
+      // r1=0
+      int r1_i = 0;
+      // loc_19D128
+      for (int r2_i = 0; r2_i != 0x20; r2_i++) {
+        // loc_19D0A2
+        // sp44=r2_i
+        // sp48=r1
+        int r1_i = (int)tPtrTextureData_D0.pType_0->pmembers_34.pType_0[r2_i]
+                       .m_eCrowdMemberType_0 *
+                   3;
+        uchar *r4_pb = &byte_2FEFF4[r1_i];
+        int i_sp40 = XSYS_RandomNoSync(byte_2FEFF4[r1_i]);
+        // sp3c=r4_pb[4]
+        int r10_i = XSYS_RandomNoSync(r4_pb[1]);
+        int r5_i = XSYS_RandomNoSync(r4_pb[2]);
+        int r0_i = XSYS_RandomNoSync(r4_pb[3]);
+        uchar *r6_pb =
+            &byte_2FF003[tPtrTextureData_D0.pType_0->pmembers_34.pType_0[r2_i]
+                             .m_eCrowdMemberType_0 *
+                         15];
+        //
+        int r0_i1 = XSYS_RandomNoSync(r4_pb[4]);
+        tPtrTextureData_D0.pType_0->buff_68[r2_i * 5] =
+            *[r6_pb + (uchar) i_sp40];
+        tPtrTextureData_D0.pType_0->buff_68[r2_i * 5 + 1] =
+            *[r6_pb + (uchar)r10_i + 0xC];
+        tPtrTextureData_D0.pType_0->buff_68[r2_i * 5 + 2] =
+            *[r6_pb + (uchar)r5_i + 0x18];
+        tPtrTextureData_D0.pType_0->buff_68[r2_i * 5 + 3] =
+            *[r6_pb + (uchar)r0_i + 0x24];
+        tPtrTextureData_D0.pType_0->buff_68[r2_i * 5 + 4] =
+            *[r6_pb + (uchar)r0_i1 + 0x30];
+      }
+      // 0019D12C
+      // sp48=byte_2FDF94
+      // sp44=byte_4630E0
+      // loc_19D1DC
+      for (int r9_i = 0; r9_i != 0x20; r9_i++) {
+        // 0019D146
+        // loc_19D1D0
+        //这个循环数据结构不清晰暂时不处理
+        for (int r5_i = 0; r5_i != 0x20; r5_i++) {
+          // loc_19D14A
+          //check 寻址
+          tPtrTextureData_D0.pType_0->field_10c[r5_i].b_0 =
+              tPtrTextureData_D0.pType_0->buff_68[r9_i * 5 + byte_2FDF94[r5_i]];
+          char r0_b=GetAnim( tPtrTextureData_D0.pType_0->field_10c[r5_i].b_0)->filed_4;
+          int r0_i;
+          if(r5_i==t_4630e0.byte_4630E0[byte_2FDF94[r5_i]*2]){
+            //0019D17A
+            //check UXTH
+           r0_i=  XSYS_RandomNoSync(r0_b);
+          }else{//loc_19D182
+
+          }
+          //loc_19D1CA
+          tPtrTextureData_D0.pType_0->field_10c[r5_i].us_2=r0_i;
+        }
+        //0019D1D4
+      }
+      break;
+    }
+    case 3:
+    case 5: {
+      // loc_19D20E
+      //check 赋值
+     CFTTClearSettings clear_setting_sp120= g_tBlankCanvasClearSettings;
+     clear_setting_sp120.field_18=0xFFFFFF;
+     int r0_i=0;
+     if(r1_u!=3){
+       r0_i=1;
+     }
+     //sp40=tPtrTextureData_D0.pType_0[r0_i].texture_38
+     tPtrTextureData_D0.pType_0[r0_i].texture_38->BeginRenderToTexture(clear_setting_sp120);
+     //0019D24A
+
+    }
+
+    default:
+      break;
+  }
 }
 //-------------------------------------------------------------------------------------------------
-//0019F7E4
+// 0019F7E4 ^_^
 void CGfxCrowd::Render() {
+  // LOGI("CGfxCrowd::Render 0019F7E4");
+  // if (aVec_8C[0].GetObj() == nullptr || pRender2Tex_9C == nullptr) {  //
+  // 0019F7EC
+  //   return;
+  // }
+
+  // // 0019F7F4
+  // g_pGraphicsDevice->setDepthTest(EFTTDepthTest_8, false);
+  // RenderSteward();
+  // RenderStatic();
+  // RenderDynamic();
+  // g_pGraphicsDevice->setDepthTest(EFTTDepthTest_8, true);
+
+  // // 0019F82A
+  // for (uint r5 = 0; r5 < vec_64.use_count_C; r5++) {  // loc_19F838
+  //   // loc_19F82C
+  //   vec_64.GetObj()[r5].GetObj()->Render();
+  // }
+
+  // // 0019F83E
+  // for (uint r5 = 0; r5 < vec_78.use_count_C; r5++) {  // loc_19F838
+  //   // loc_19F82C
+  //   vec_78.GetObj()[r5].GetObj()->Render();
+  // }
 }
 //-------------------------------------------------------------------------------------------------
-//0019F85C
+// 0019F85C
 void CGfxCrowd::RenderSteward() {
+  LOGX("CGfxCrowd::RenderSteward 0019F85C %p", this);
 }
 //-------------------------------------------------------------------------------------------------
-//0019F990
+// 0019F990
 void CGfxCrowd::RenderStatic() {
+  LOGX("CGfxCrowd::RenderStatic 0019F990 %p", this);
 }
 //-------------------------------------------------------------------------------------------------
-//0019FCC8
+// 0019FCC8
 void CGfxCrowd::RenderDynamic() {
+  LOGX("CGfxCrowd::RenderDynamic 0019FCC8 %p", this);
 }
 //-------------------------------------------------------------------------------------------------
-//001A101C
-void CGfxCrowd::Process() {
-}
+// 001A101C
+void CGfxCrowd::Process() { LOGI("CGfxCrowd::Process 001A101C"); }
 //-------------------------------------------------------------------------------------------------
-//001A12C8
-void CGfxCrowd::GetCrowdState(float &, float &, float &) {
+// 001A12C8 ^_^
+void CGfxCrowd::GetCrowdState(float &f1, float &f2, float &f3) {
+  // f1 = tCrowd_C0EC[0].f_0;
+  // f2 = tCrowd_C0EC[4].f_0;
+  // f3 = tCrowd_C0EC[8].f_0;
 }
 //-------------------------------------------------------------------------------------------------
-//001A12E6
-void CGfxCrowd::GetCapacity() {
-}
+// 001A12E6 ^_^
+int CGfxCrowd::GetCapacity() { return vec_0.use_count_C; }
 //-------------------------------------------------------------------------------------------------
-//001A12EA
-void CGfxCrowd::GetTextureCreationData() {
+// 001A12EA ^_^
+CrowdTextureCreationData *CGfxCrowd::GetTextureCreationData() {
+  return tPtrTextureData_D0.pType_0;
 }
 //-------------------------------------------------------------------------------------------------
-//001A12F0
-void CGfxCrowd::GetCrowdValue(ECrowdMemberType) {
+// 001A12F0 ^_^
+float CGfxCrowd::GetCrowdValue(ECrowdMemberType eType1) {
+  return f_CBC8[eType1];
 }
 //-------------------------------------------------------------------------------------------------
-//001A12FC
-void CGfxCrowd::SetCrowdValue(ECrowdMemberType, float) {
+// 001A12FC ^_^
+void CGfxCrowd::SetCrowdValue(ECrowdMemberType eType1, float f2) {
+  f_CBC8[eType1] = f2;
 }
 //-------------------------------------------------------------------------------------------------

+ 95 - 67
jni/CGfxCrowd.h

@@ -3,6 +3,16 @@
 #define _CGFXCROWD_H_
 
 #include "CFTTModel.h"
+#include "FTTVector.h"
+#include "CStaticAABBTree.h"
+#include "FTTUPtr.h"
+#include "CrowdTextureCreationData.h"
+#include "TDrawCall.h"
+#include "CGfxCrowdCardGroup.h"
+#include "CGfxCrowdFlagRender.h"
+#include "TGfxCrowdState.h"
+#include "CFTTRenderToTexture.h"
+#include "TCrowd.h"
 
 /*
 0019691C CGfxCrowd::CGfxCrowd()
@@ -32,81 +42,99 @@
 0xCBD4
 */
 
-struct TGfxCrowdSeat {
+struct TGfxCrowdSection {
   int un_0;
 };
 
-enum ECrowdMemberType {
-  ECrowdMemberType_0,
-  ECrowdMemberType_1,
-  ECrowdMemberType_2,
-  ECrowdMemberType_3,
-  ECrowdMemberType_4,
-  ECrowdMemberType_5,
+struct TGfxCardSection {
+  int un_0;
 };
 
-struct StructCGfxCrowd_D0 {
-  int m_field_0;
-  int m_field_4;
-  int m_field_8;
-  int m_field_C;
-  int m_field_10;
-  int m_field_14;
-  int m_field_18;
-  int m_field_1C;
-  int m_field_20;
-  int m_field_24;
-  int m_field_28;
-  CFTTModel *m_field_2C;
-  CFTTModel *m_field_30;
-  int m_field_34;
-  int m_field_38;
-  int m_field_3C;
-  int m_field_40;
-  int m_field_44;
-  int m_field_48;
-  int m_field_4C;
-  int m_field_50;
-  int m_field_54;
-  int m_field_58;
-  int m_field_5C;
-  int m_field_60;
-  int m_field_64;
-  int m_field_68;
-  int m_field_6C;
-  int m_field_70;
-  char dat[0xCA90];
+struct TGfxCrowdDynamic {
+  int un_0;
 };
+
+/*
+Crowd 相关类, 重点检查 Anderson
+
+CGfxCrowd.cpp
+CGfxCrowdCardGroup.cpp
+CGfxCrowdFlagPhysics.cpp
+CGfxCrowdFlagRender.cpp
+CrowdSortB.cpp
+CrowdSortD.cpp
+CrowdTextureCreationData.cpp
+TCrowdMember.cpp
+TGfxCrowdState.cpp
+*/
+
 class CGfxCrowd {
 public:
-  CGfxCrowd();                                     // 0019691C
-  ~CGfxCrowd();                                    // 00196A10
-  static void Initialise();                        // 001968CC
-  static void Shutdown();                          // 001968EC
-  static CGfxCrowd *Get();                         // 0019690C
-  static void Shut();                              // 00196AF8
-  void Init();                                     // 00196E72
-  void AddStand(CFTTModel *, CFTTMatrix32);        // 00197140
-  void GetCapacity(CFTTModel *, CFTTMatrix32);     // 00199D4C
-  void AssessDesirability(TGfxCrowdSeat &);        // 00199E08
-  void AssessDesirability(TGfxCrowdSeat &, bool);  // 00199E3C
-  void Distribute(uint);                           // 00199ED0
-  static void UpdateCrowdTextures(uint);           // 0019CBA0
-  void Render();                                   // 0019F7E4
-  void RenderSteward();                            // 0019F85C
-  void RenderStatic();                             // 0019F990
-  void RenderDynamic();                            // 0019FCC8
-  void Process();                                  // 001A101C
-  void GetCrowdState(float &, float &, float &);   // 001A12C8
-  void GetCapacity();                              // 001A12E6
-  void GetTextureCreationData();                   // 001A12EA
-  void GetCrowdValue(ECrowdMemberType);            // 001A12F0
-  void SetCrowdValue(ECrowdMemberType, float);     // 001A12FC
-
-  char dat[0xD0];
-  StructCGfxCrowd_D0 *m_st_D0;
-
-  // uchar dat[0xCBD4];
+  CGfxCrowd();                                         // 0019691C
+  ~CGfxCrowd();                                        // 00196A10
+  static void Initialise();                            // 001968CC
+  static void Shutdown();                              // 001968EC
+  static CGfxCrowd *Get();                             // 0019690C
+  static void Shut();                                  // 00196AF8
+  void Init();                                         // 00196E72
+  void AddStand(CFTTModel *, CFTTMatrix32);            // 00197140
+  void GetCapacity(CFTTModel *, CFTTMatrix32);         // 00199D4C
+  void AssessDesirability(TGfxCrowdSeat &);            // 00199E08
+  void AssessDesirability(TGfxCrowdSeat &, bool);      // 00199E3C
+  void Distribute(uint);                               // 00199ED0
+  void UpdateCrowdTextures(uint);               // 0019CBA0
+  void Render();                                       // 0019F7E4
+  void RenderSteward();                                // 0019F85C
+  void RenderStatic();                                 // 0019F990
+  void RenderDynamic();                                // 0019FCC8
+  void Process();                                      // 001A101C
+  void GetCrowdState(float &, float &, float &);       // 001A12C8
+  int GetCapacity();                                   // 001A12E6
+  CrowdTextureCreationData *GetTextureCreationData();  // 001A12EA
+  float GetCrowdValue(ECrowdMemberType);               // 001A12F0
+  void SetCrowdValue(ECrowdMemberType, float);         // 001A12FC
+
+  FTTVector<TGfxCrowdSeat> vec_0;
+  FTTVector<TGfxCrowdSeat> vec_14;
+  FTTVector<TGfxCrowdDynamic> vec_28;
+  FTTVector<TGfxCardSection> vec_3C;
+  FTTVector<FTTUPtr<CGfxCrowdFlagPhysics>> vec_50;
+  FTTVector<FTTUPtr<CGfxCrowdFlagRender>> vec_64;
+  FTTVector<FTTUPtr<CGfxCrowdCardGroup>> vec_78;
+  FTTUPtr<CFTTRenderHelper> aVec_8C[2];
+  FTTUPtr<CFTTRenderHelper> tUPtr_94;
+  FTTUPtr<CFTTRenderHelper> tUPtr_98;
+
+  CFTTRenderToTexture *pRender2Tex_9C;
+  CFTTRenderToTexture *pRender2Tex_A0;
+  CFTTRenderToTexture *pRender2Tex_A4;
+
+  FTTVector<uint> vec_A8;
+  FTTVector<TDrawCall> vec_BC;
+
+  FTTUPtr<CrowdTextureCreationData> tPtrTextureData_D0;
+
+  int field_D4;
+  int field_D8;
+
+  uchar field_DC[0xBFF8];  //????????????????????????????????????????????????????? 未知
+
+  int field_C0D4;
+
+  FTTVector<TGfxCrowdSection> vec_C0D8;
+
+  TGfxCrowdState tCrowd_C0EC[9];
+  TGfxCrowdState tCrowd_C1A0[32][4];
+
+  FTTVector<CStaticAABBTree<ushort, 16u>> vec_CBA0;
+
+  bool b_CBB4;
+  bool b_CBB5;
+  bool b_CBB6;
+  bool b_CBB7;
+  float f_CBB8;
+  uint dCrowdNewShaderID_CBBC[3];  // 00196A3C 此处可以确定是一个数组
+  float f_CBC8[3];                 // 001A12FC
 
   static CGfxCrowd *ms_pInstance;
 };

+ 15 - 8
jni/CStaticAABBTree.h

@@ -1,8 +1,9 @@
-//CStaticAABBTree - [2020-04-13 11:57:47]
+// CStaticAABBTree - [2020-04-13 11:57:47]
 #ifndef _CSTATICAABBTREE_H_
 #define _CSTATICAABBTREE_H_
 
-#include "common.h"
+#include "TAABB.h"
+#include "FTTVector.h"
 
 /*
 0019C900 CStaticAABBTree<ushort,16u>::Init(TAABB *,ushort *,uint)
@@ -14,34 +15,40 @@
 */
 
 template <typename T, int len>
+class TStaticAABBNode {
+public:
+  int un_0;
+};
+
+template <typename T, int len>
 class CStaticAABBTree {
 public:
-  //001A4D36
+  // 001A4D36
   ~CStaticAABBTree(){
 
   };
 
-  //0019C900
+  // 0019C900
   void Init(TAABB *, ushort *, uint){
 
   };
 
-  //001A1006
+  // 001A1006
   void Test(FTTVector<uint> &, CFTTFrustum32 const &){
 
   };
 
-  //001A7A48
+  // 001A7A48
   void swap(CStaticAABBTree<T, len> &, CStaticAABBTree<ushort, 16u> &){
 
   };
 
-  //001A7A76
+  // 001A7A76
   void Build(TStaticAABBNode<T, len> *, TAABB *, ushort *, TAABB *, ushort *, float *, uint){
 
   };
 
-  //001A8390
+  // 001A8390
   void Test(TStaticAABBNode<T, len> *, FTTVector<uint> &, CFTTFrustum32 const &, bool){
 
   };

+ 7 - 7
jni/CStoryCore.cpp

@@ -154,7 +154,7 @@ void CStoryCore::RandomiseSunPos() {}
 //单元测试等级: 目测游戏表现
 //单元测试内容: 前10关
 //单元测试结果:正常
-//已测试分支 0 1 17 18
+//已测试分支 0 1 2 10 12 13 14 17 18
 void CStoryCore::ProcessText(wchar_t *r0_wp, int r1_i, wchar_t const *r2_wp,
                              int r3_i) {
   wchar_t const *r8_pw = r2_wp;
@@ -175,7 +175,7 @@ void CStoryCore::ProcessText(wchar_t *r0_wp, int r1_i, wchar_t const *r2_wp,
     // loc_1E2576
     LOGE("ProcessText_1");//ok
     if (r7_pw) {
-      // 001E258A
+      // 001E258A OK
       LOGE("ProcessText_2");
       wchar_t wp_sp10[0x40];
       memset(wp_sp10, 0, sizeof(wp_sp10));
@@ -279,8 +279,8 @@ void CStoryCore::ProcessText(wchar_t *r0_wp, int r1_i, wchar_t const *r2_wp,
           // loc_1E26A8
           break;
         }
-        case 'p': {  // loc_1E2662
-        LOGE("ProcessText_10");
+        case 'p': {  // loc_1E2662 OK
+        LOGE("ProcessText_10");  
           xstrlcpy(wp_sp10, MP_cMyProfile.GetPlayerName(), 0x40);
           if (xstrlen(wp_sp10) == 0) {
             // 001E267E
@@ -305,9 +305,9 @@ void CStoryCore::ProcessText(wchar_t *r0_wp, int r1_i, wchar_t const *r2_wp,
           // loc_1E26A8
         }
       }
-      LOGE("ProcessText_12");
+      LOGE("ProcessText_12");//OK
       int r9_i = xstrlen(wp_sp10);
-      if (r9_i >= 1) {  // 001E26B4
+      if (r9_i >= 1) {  // 001E26B4  OK
         // r8_pw=r7_substr+2;
         LOGE("ProcessText_13");
         memcpy(r5_wp, r8_pw, (r7_pw - r8_pw)*2);
@@ -320,7 +320,7 @@ void CStoryCore::ProcessText(wchar_t *r0_wp, int r1_i, wchar_t const *r2_wp,
             ((uint)(r7_pw[1] - 'n') <= 6 && (1 << (r7_pw[1] - 'n')) & 0x47)) {
           // loc_1E26FC
           // check
-          LOGE("ProcessText_14");
+          LOGE("ProcessText_14");//OK
           if (r8_pw[0] == 0x2019 || r8_pw[0] == '\'') {
             // 001E270C
             if ((wp_sp10[r9_i - 1] | 0x20) == 's') {

+ 32 - 13
jni/CrowdTextureCreationData.h

@@ -4,8 +4,9 @@
 
 #include "FTTUPtr.h"
 #include "FTTAtlasGenerator.h"
+#include "CFTTModel.h"
 #include "TCrowdMember.h"
-
+class TCrowdMember;
 /*
 001A4C50 CrowdTextureCreationData::~CrowdTextureCreationData()
 */
@@ -15,27 +16,45 @@ public:
   virtual ~UnKmowClass(){};
 };
 
+struct CrowdTextureCreationData_10C
+{
+  uchar b_0;
+  uchar b_1;
+  ushort us_2;
+  
+}
 class CrowdTextureCreationData {
 public:
   ~CrowdTextureCreationData();  // 001A4C50
 
   int miCFTTMaterialIndex_0;
-  char buff_4[0x30];
-  FTTUPtr<TCrowdMember> field_34;
-  FTTUPtr<UnKmowClass> field_38[2];
+  int field_4;
+  int field_8;
+  int field_C;
+  int field_10;
+  char buff_14[0x18];
+  CFTTModel* model_2C;
+  CFTTModel* model_30; 
+  FTTUPtr<TCrowdMember> pmembers_34;
+  CFTTRenderToTexture* texture_38;
+  FTTUPtr<UnKmowClass> field_3C;
   UnKmowClass* field_40;
   UnKmowClass* field_44;
-  int* field_48;
-  int* field_4C;
-  int* field_50;
-
+  int texture_48;
+  int texture_4C;
+  int texture_50;
   int* field_54;
-  int* field_58;
-  UnKmowClass* field_5C;
-  UnKmowClass* field_60;
-  UnKmowClass* field_64;
-  char buff_68[0x18e4];
+  int texture_58;
+  CFTTTexture* name_texture_5C;
+  CFTTTexture* name_texture_60;
+  CFTTTexture* name_texture_64;
+  char buff_68[0xa4];
+  
+  CrowdTextureCreationData_10C field_10c[0x20];
+  char buff_18c[0x17c0];
+
   FTTUPtr<FTTAtlasGenerator> mpFTTAtlasGenerator_194C;
+  char buf_1950[0x1420];
 };
 
 #endif  //_CROWDTEXTURECREATIONDATA_H_

+ 4 - 0
jni/FTTALG.h

@@ -85,6 +85,10 @@ FTTVector<FTTPair<CFTTBMMMatrixCache::Key,CFTTBMMMatrixCache::StartCount> >::Ite
 */
 
 namespace FTTALG {
+  template <typename T>
+  void  Shuffle(T*,T*){
+
+  }
 template <typename TCompare,
           typename TKey,
           typename TVecIterator>

+ 107 - 109
jni/GM.cpp

@@ -1,163 +1,161 @@
 #include "GM.h"
+
+#include "CBall.h"
 #include "GU.h"
-#include "XMATH.h"
 #include "TGame.h"
-#include "CBall.h"
+#include "XMATH.h"
 
 #define Add2Ptr(PTR, INC, CAST) ((CAST)((uint64)(PTR) + (INC)))
-#define PI                      3.14159274f
-#define NEGPI                   -3.14159274f
+#define PI 3.14159274f
+#define NEGPI -3.14159274f
 
 //-------------------------------------------------------------------------------------------------
-//0015B0A4
-void GM_CheckGoalSide() {
-}
+// 0015B0A4
+void GM_CheckGoalSide() {}
 //-------------------------------------------------------------------------------------------------
-//0015B340
-void GM_CalcPlayerDist() {
-}
+// 0015B340
+void GM_CalcPlayerDist() {}
 //-------------------------------------------------------------------------------------------------
-//0015B7C8
-void GM_IsOnPitch(TPoint) {
-}
+// 0015B7C8
+void GM_IsOnPitch(TPoint) {}
 //-------------------------------------------------------------------------------------------------
-//0015B7F8
+// 0015B7F8
 void GM_SwapInt(int &i0, int &i1) {
   int tmp_r2 = i1;
   i1 = i0;
   i0 = tmp_r2;
 }
 //-------------------------------------------------------------------------------------------------
-//0015B804
-int GM_CalcGoalDist(TPoint, int) {
-  return 0;
-}
+// 0015B804
+int GM_CalcGoalDist(TPoint, int) { return 0; }
 //-------------------------------------------------------------------------------------------------
-//0016E0BC
-void GM_GetRotPowerTrajectory(TPoint3D pt0, int *i1, int *i2, int *i3) {
-}
+// 0016E0BC
+void GM_GetRotPowerTrajectory(TPoint3D pt0, int *i1, int *i2, int *i3) {}
 //-------------------------------------------------------------------------------------------------
-//0016E108
-void GM_GetVecFromRotPowerTrajectory(TPoint3D *, int, int, int) {
-}
+// 0016E108
+void GM_GetVecFromRotPowerTrajectory(TPoint3D *, int, int, int) {}
 //-------------------------------------------------------------------------------------------------
-//00171E50
-void GM_DeflectBallFromDribbler(CPlayer *player, int *i1) {
-}
+// 00171E50
+void GM_DeflectBallFromDribbler(CPlayer *player, int *i1) {}
 //-------------------------------------------------------------------------------------------------
-//00178C7C
-int GM_CheckInterception(CPlayer *, int, int, int) {
-  return 0;
-}
+// 00178C7C
+int GM_CheckInterception(CPlayer *, int, int, int) { return 0; }
 //-------------------------------------------------------------------------------------------------
-//00178D3C
-void GM_CheckInterceptionPos(CPlayer *, int, int, TPoint *) {
-}
+// 00178D3C
+void GM_CheckInterceptionPos(CPlayer *, int, int, TPoint *) {}
 //-------------------------------------------------------------------------------------------------
-//00179170
-void GM_CheckInterceptionX(CPlayer *, int) {
-}
+// 00179170
+void GM_CheckInterceptionX(CPlayer *, int) {}
 //-------------------------------------------------------------------------------------------------
-//0017918C
-void GM_CalcPlayerBallInterceptions() {
-}
+// 0017918C
+void GM_CalcPlayerBallInterceptions() {}
 //-------------------------------------------------------------------------------------------------
-//00179A44
-int GM_GetPlayerNearestPoint(int i0, TPoint pt1, int i2, int *i3) {
-  return 0;
-}
+// 00179A44
+int GM_GetPlayerNearestPoint(int i0, TPoint pt1, int i2, int *i3) { return 0; }
 //-------------------------------------------------------------------------------------------------
-//00179AD0
-int GM_GetPlayerNearestPoint(int i0, TPoint pt1, int *i2) {
-  return 0;
-}
+// 00179AD0
+int GM_GetPlayerNearestPoint(int i0, TPoint pt1, int *i2) { return 0; }
 //-------------------------------------------------------------------------------------------------
-//00179B60
-void GM_GetPlayerNearestPointF(int, TPoint, int, int, int) {
-}
+// 00179B60
+void GM_GetPlayerNearestPointF(int, TPoint, int, int, int) {}
 //-------------------------------------------------------------------------------------------------
-//00179BE0
-void GM_GetPlayerNearestPointFX(int, TPoint, bool *, int, int, int, int) {
-}
+// 00179BE0
+void GM_GetPlayerNearestPointFX(int, TPoint, bool *, int, int, int, int) {}
 //-------------------------------------------------------------------------------------------------
-//00179C80
-void GM_GetPlayerNearestPointRange(int, TPoint, bool *, int, int) {
-}
+// 00179C80
+void GM_GetPlayerNearestPointRange(int, TPoint, bool *, int, int) {}
 //-------------------------------------------------------------------------------------------------
-//00179F90
-void GM_GetLineIntersectWeighted(TPoint, TPoint, TPoint, int, int, int *, int *) {
-}
+// 00179F90
+void GM_GetLineIntersectWeighted(TPoint, TPoint, TPoint, int, int, int *,
+                                 int *) {}
 //-------------------------------------------------------------------------------------------------
-//0017A04C
-void GM_GetPlayerFutureNearestLineWeighted(int, int, bool *, TPoint3D, TPoint3D, int, int, int *, int *) {
-}
+// 0017A04C
+void GM_GetPlayerFutureNearestLineWeighted(int, int, bool *, TPoint3D, TPoint3D,
+                                           int, int, int *, int *) {}
 //-------------------------------------------------------------------------------------------------
-//0017A24C
-int GM_GetPlayerFutureNearestLine(int, CPlayer *, TPoint, TPoint, int *, int *) {
+// 0017A24C
+int GM_GetPlayerFutureNearestLine(int, CPlayer *, TPoint, TPoint, int *,
+                                  int *) {
   return 0;
 }
 //-------------------------------------------------------------------------------------------------
-//0017A340
-void GM_GetPlayerTotalSpace(int, int) {
-}
+// 0017A340
+void GM_GetPlayerTotalSpace(int, int) {}
 //-------------------------------------------------------------------------------------------------
-//0017A510
-void GM_GetPointSpace(int, TPoint) {
-}
+// 0017A510
+void GM_GetPointSpace(int, TPoint) {}
 //-------------------------------------------------------------------------------------------------
-//0017A558
-void GM_GetPlayerSpaceRot(CPlayer *, int, int, int) {
-}
+// 0017A558
+void GM_GetPlayerSpaceRot(CPlayer *, int, int, int) {}
 //-------------------------------------------------------------------------------------------------
-//0017A744
-void GM_DistanceSq(TPoint const *, TPoint const *) {
-}
+// 0017A744
+void GM_DistanceSq(TPoint const *, TPoint const *) {}
 //-------------------------------------------------------------------------------------------------
-//0017A76A
-void GM_Distance(TPoint const *, TPoint const *) {
-}
+// 0017A76A
+void GM_Distance(TPoint const *, TPoint const *) {}
 //-------------------------------------------------------------------------------------------------
-//0017A796
-uint GM_Distance3D(TPoint3D *pt0, TPoint3D *pt1) {
-  return 0;
-}
+// 0017A796
+uint GM_Distance3D(TPoint3D *pt0, TPoint3D *pt1) { return 0; }
 //-------------------------------------------------------------------------------------------------
-//0017A7DA
-void GM_PlayerLimitDistancePos(CPlayer *Player, TPoint pt1, unsigned int ui2) {
-}
+// 0017A7DA
+void GM_PlayerLimitDistancePos(CPlayer *Player, TPoint pt1, unsigned int ui2) {}
 //-------------------------------------------------------------------------------------------------
-//0017A810
-void GM_PlayerLimitDistance(CPlayer *, int) {
-}
+// 0017A810
+void GM_PlayerLimitDistance(CPlayer *, int) {}
 //-------------------------------------------------------------------------------------------------
-//0017A858
-void GM_PlayerLimitDistancePosPol(CPlayer *, TPoint, int, int) {
-}
+// 0017A858
+void GM_PlayerLimitDistancePosPol(CPlayer *, TPoint, int, int) {}
 //-------------------------------------------------------------------------------------------------
-//0017A898
-void GM_SetBestPointSpace(int, TPoint *, int, int) {
-}
+// 0017A898
+void GM_SetBestPointSpace(int, TPoint *, int, int) {}
 //-------------------------------------------------------------------------------------------------
-//0017A9EC
-void GM_PointIsBetweenPoints(TPoint, TPoint, TPoint, int) {
-}
+// 0017A9EC
+void GM_PointIsBetweenPoints(TPoint, TPoint, TPoint, int) {}
 //-------------------------------------------------------------------------------------------------
-//0017AA3A
-void GM_TendAngle(int, int) {
-}
+// 0017AA3A
+void GM_TendAngle(int, int) {}
 //-------------------------------------------------------------------------------------------------
-//0017AA88
-float GM_BlendAngleF(float f0, float f1, float f2) {
-  return 0.0f;
-}
+// 0017AA88
+float GM_BlendAngleF(float f0, float f1, float f2) { return 0.0f; }
 //-------------------------------------------------------------------------------------------------
-//0017AB34 ^_^
+// 0017AB34 ^_^
 float GM_BlendAngleAroundF(float f0, float f1, float f2, float f3) {
   return 0.0f;
 }
 //-------------------------------------------------------------------------------------------------
-//0017ABC8
+// 0017ABC8 ^_-
 int GM_BlendAngle(int i0, int i1, int i2) {
-  return 0;
+  i0 = i0 & 0x3fff;
+  i1 = i1 & 0x3fff;
+  if (i0 == i1) {
+    // 0017ABD2
+    return i0;
+  }
+  int r3_i = i0 - i1;
+  int r12_i = 0x100 - i2;
+  if (r3_i < 0) {
+    // 0017ABDE
+    r3_i = -r3_i;
+  }
+  if (r3_i > 0x2000) {
+    // /0017ABE6
+    if ((uint)i0<=0x1fff) {
+      // 0017ABEE
+      i1 *= i2;
+      i0 |= 0x4000;
+    } else {
+      // loc_17ABF6
+      i1 |= 0x4000;
+      i1 *= i2;
+    }
+  } else {
+    // loc_17ABFA
+    i1 *= i2;
+  }
+  // loc_17ABFC
+  i0 = r12_i * i0 + i1;
+
+  i0 = i0 / 256 & 0x3fff;
+  return i0;
 }
 //-------------------------------------------------------------------------------------------------

+ 21 - 0
jni/TCrowd.h

@@ -0,0 +1,21 @@
+// TCrowd - [2022-05-14 22:51:23]
+#ifndef _TCROWD_H_
+#define _TCROWD_H_
+
+struct TGfxCrowdSeat {
+  float f_0;   // 00199E1A 由此判断是float
+  float f_4;   // 00199E66 由此判断是float
+  float f_8;   // 00199E64 由此判断是float
+  float f_C;   // 类型尚不确定,先定义成float
+  float f_10;  // 类型尚不确定,先定义成float
+  float f_14;  // 类型尚不确定,先定义成float
+  float f_18;  // 00199E32 由此判断是float
+};
+
+enum ECrowdMemberType {
+  ECrowdMemberType_0,
+  ECrowdMemberType_1,
+  ECrowdMemberType_2
+};
+
+#endif  //_TCROWD_H_

+ 1 - 0
jni/TCrowdMember.h

@@ -5,6 +5,7 @@
 #include "TUV.h"
 #include "CGfxCrowd.h"
 #include "SAT.h"
+#include "TCrowd.h"
 class CFTTModel;
 class TAABB;
 

+ 2 - 2
jni/TGfxCrowdState.h

@@ -3,10 +3,10 @@
 #define _TGFXCROWDSTATE_H_
 #include "common.h"
 #include "CGfxCrowd.h"
-
+#include "TCrowd.h"
 class TGfxCrowdState {
 public:
-  //  TGfxCrowdState(){} // 自定义构造函数
+    TGfxCrowdState(){} // 自定义构造函数
   TGfxCrowdState(float, ECrowdMemberType, uchar, bool);  // 0019CA8C
   void Process();                                        // 001A1144
   void ProcessState();                                   // 001A1308

+ 0 - 1
jni/sub.cpp

@@ -201,7 +201,6 @@ void sub_16D8B2(int *r0_pi, fpoint3<PointType_18> &r1_pfpoint3) {
 //单元测试等级: 目测游戏表现
 //单元测试内容: 前10关未调用
 //单元测试结果:
-//已测试分支
 void sub_16C7DC(fpoint3<PointType_18> &r0_pfpoint3,fpoint3<PointType_18> &r1_pfpoint3,fpoint3<PointType_18> &r2_pfpoint3) {
   //LOGE("sub_16C7DC");
   int r12_i = r2_pfpoint3.x_0;