Clean, self-contained extraction of the BattleTech-specific work from the
reverse-engineering workspace -- engine + game + content + build, with nothing
from Red Planet or the raw archive dumps. Builds green (Win32) and runs the
single-player drive->animate->target->fire->damage->destroy loop out of the box.
Layout:
engine/ MUNGA + MUNGA_L4 shared 2007 engine, carrying our BT render/loader
work (bgfload/L4D3D/L4VIDEO: BSL bit-slice decode, LOD/ground/shadow
models) + image codec; the minimal rp/ headers the audio HAL needs
game/ reconstructed BT logic + surviving-original BT source + fwd shims
+ WinMain launcher
content/ full runtime tree (BTL4.RES, VIDEO/, GAUGE/, AUDIO/, eggs, BTDPL.INI)
docs/ format specs + reconstruction ledgers
reference/ raw Ghidra pseudocode (recon source-of-truth) + decomp exporter
tools/ MP console emulator + map/resource scanners
One top-level CMake builds munga_engine lib + bt410_l4 game lib + btl4.exe.
All paths relativized (186 fwd shims + ~437 CMake abs paths -> repo-relative);
DXSDK is the one external, overridable via -DDXSDK. Verified: builds to a
byte-identical 2.27MB exe and runs combat (TARGET DESTROYED, 0 crashes) against
the bundled content.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
334 lines
11 KiB
C
334 lines
11 KiB
C
// Recovered decompilation of functions attributed to bt_l4/btl4mssn.cpp
|
|
// (from BTL4OPT.EXE via embedded assert paths). Pseudocode — reconstruct against the header.
|
|
|
|
/* ---- @ 004d2c30 ---- */
|
|
|
|
void __cdecl FUN_004d2c30(int param_1,int param_2)
|
|
|
|
{
|
|
char *pcVar1;
|
|
uint *puVar2;
|
|
int *piVar3;
|
|
char *pcVar4;
|
|
int iVar5;
|
|
undefined3 extraout_var;
|
|
undefined4 *puVar6;
|
|
uint uVar7;
|
|
undefined3 extraout_var_00;
|
|
undefined3 extraout_var_01;
|
|
char *pcVar8;
|
|
bool bVar9;
|
|
int local_a4 [5];
|
|
int local_90 [5];
|
|
undefined4 local_7c;
|
|
int local_78;
|
|
float local_74;
|
|
int *local_70;
|
|
int *local_6c;
|
|
int *local_68;
|
|
int *local_64;
|
|
int *local_60;
|
|
int *local_5c;
|
|
undefined4 *local_58;
|
|
uint *local_54;
|
|
uint *local_50;
|
|
uint *local_4c;
|
|
char *local_48;
|
|
char *local_44;
|
|
int *local_40;
|
|
char *local_3c;
|
|
float local_38;
|
|
int local_34;
|
|
char *local_30;
|
|
int *local_2c;
|
|
int *local_28;
|
|
char *local_24;
|
|
char *local_20;
|
|
int *local_1c;
|
|
char *local_18;
|
|
char *local_14;
|
|
char *local_10;
|
|
char *local_c;
|
|
int *local_8;
|
|
|
|
local_8 = *(int **)(*(int *)(*(int *)(DAT_004efc94 + 0x2c) + 0x14) + 0x1064);
|
|
local_8[3] = local_8[3] + 1;
|
|
*(undefined4 *)(param_1 + 0x2c) = 0;
|
|
local_c = (char *)0x0;
|
|
FUN_00404088(param_2,(char *)local_8[2],s_vehicle_0051e5b5,&local_c);
|
|
if (local_c == (char *)0x0) {
|
|
FUN_004dbb24(&DAT_00524e20,s_Error__vehicle_not_specified__0051e5bd,(char *)0x0);
|
|
FUN_004036a0(1);
|
|
}
|
|
pcVar4 = FUN_00402300(local_c);
|
|
*(char **)(param_1 + 0x2c) = pcVar4;
|
|
*(undefined4 *)(param_1 + 0x28) = 0;
|
|
local_10 = (char *)0x0;
|
|
FUN_00404088(param_2,(char *)local_8[2],s_dropzone_0051e5dc,&local_10);
|
|
if (local_10 == (char *)0x0) {
|
|
FUN_004dbb24(&DAT_00524e20,s_Error__dropzone_not_specified__0051e5e5,(char *)0x0);
|
|
FUN_004036a0(1);
|
|
}
|
|
pcVar4 = FUN_00402300(local_10);
|
|
*(char **)(param_1 + 0x28) = pcVar4;
|
|
*(undefined4 *)(param_1 + 0x3c) = 0;
|
|
FUN_004040d8(param_2,(char *)local_8[2],s_loadzones_0051e605,(int *)(param_1 + 0x3c));
|
|
*(undefined4 *)(param_1 + 0x20) = 0;
|
|
local_14 = (char *)0x0;
|
|
FUN_00404088(param_2,(char *)local_8[2],s_color_0051e60f,&local_14);
|
|
if (local_14 == (char *)0x0) {
|
|
FUN_004dbb24(&DAT_00524e20,s_Error__color_not_specified__0051e615,(char *)0x0);
|
|
FUN_004036a0(1);
|
|
}
|
|
pcVar4 = FUN_00402300(local_14);
|
|
*(char **)(param_1 + 0x20) = pcVar4;
|
|
local_18 = (char *)0x0;
|
|
FUN_00404088(param_2,(char *)local_8[2],s_patch_0051e632,&local_18);
|
|
if (local_18 == (char *)0x0) {
|
|
FUN_004dbb24(&DAT_00524e20,s_Error__patch_not_specified__0051e638,(char *)0x0);
|
|
FUN_004036a0(1);
|
|
}
|
|
FUN_00402a98((int *)&local_1c,(int *)(param_1 + 0xf8),local_18);
|
|
piVar3 = local_1c + 3;
|
|
*piVar3 = *piVar3 + -1;
|
|
if (*piVar3 == 0) {
|
|
FUN_004024d8(local_1c,3);
|
|
}
|
|
*(undefined4 *)(param_1 + 0x24) = 0;
|
|
local_20 = (char *)0x0;
|
|
FUN_00404088(param_2,(char *)local_8[2],s_badge_0051e655,&local_20);
|
|
if (local_20 == (char *)0x0) {
|
|
FUN_004dbb24(&DAT_00524e20,s_Error__badge_not_specified__0051e65b,(char *)0x0);
|
|
FUN_004036a0(1);
|
|
}
|
|
pcVar4 = FUN_00402300(local_20);
|
|
*(char **)(param_1 + 0x24) = pcVar4;
|
|
iVar5 = FUN_00404088(param_2,(char *)local_8[2],s_badge_0051e678,&local_24);
|
|
if (iVar5 == 0) {
|
|
FUN_00402a98((int *)&local_2c,(int *)(param_1 + 0xec),s_DEFAULT_0051e67e);
|
|
piVar3 = local_2c + 3;
|
|
*piVar3 = *piVar3 + -1;
|
|
if (*piVar3 == 0) {
|
|
FUN_004024d8(local_2c,3);
|
|
}
|
|
}
|
|
else {
|
|
FUN_00402a98((int *)&local_28,(int *)(param_1 + 0xec),local_24);
|
|
piVar3 = local_28 + 3;
|
|
*piVar3 = *piVar3 + -1;
|
|
if (*piVar3 == 0) {
|
|
FUN_004024d8(local_28,3);
|
|
}
|
|
}
|
|
local_30 = s_Unspecified_0051e686;
|
|
iVar5 = FUN_00404088(param_2,(char *)local_8[2],s_experience_0051e692,&local_30);
|
|
if (iVar5 == 0) {
|
|
pcVar4 = *(char **)(param_1 + 0x2c);
|
|
pcVar8 = s_camera_0051e69d;
|
|
do {
|
|
bVar9 = *pcVar4 == *pcVar8;
|
|
if (!bVar9) break;
|
|
if (*pcVar4 == '\0') goto LAB_004d2f3e;
|
|
pcVar1 = pcVar4 + 1;
|
|
bVar9 = *pcVar1 == pcVar8[1];
|
|
if (!bVar9) break;
|
|
pcVar4 = pcVar4 + 2;
|
|
pcVar8 = pcVar8 + 2;
|
|
bVar9 = *pcVar1 == '\0';
|
|
} while (!bVar9);
|
|
if (!bVar9) {
|
|
FUN_004dbb24((int *)&DAT_00524e68,(char *)local_8[2],(char *)0x0);
|
|
FUN_004dbb24((int *)&DAT_00524e68,s_page_missing_expereince__0051e6a4,(char *)0x0);
|
|
FUN_004d9c38((int *)&DAT_00524e68);
|
|
FUN_0040385c(s_Exiting_0051e6be,s_d__tesla_bt_bt_l4_BTL4MSSN_CPP_0051e6c6,0xf0);
|
|
goto LAB_004d3052;
|
|
}
|
|
}
|
|
LAB_004d2f3e:
|
|
pcVar8 = s_Unspecified_0051e6e5;
|
|
pcVar4 = local_30;
|
|
do {
|
|
if (*pcVar8 != *pcVar4) goto LAB_004d2f68;
|
|
bVar9 = true;
|
|
if (*pcVar8 == '\0') break;
|
|
pcVar1 = pcVar8 + 1;
|
|
if (*pcVar1 != pcVar4[1]) goto LAB_004d2f68;
|
|
pcVar8 = pcVar8 + 2;
|
|
pcVar4 = pcVar4 + 2;
|
|
bVar9 = *pcVar1 == '\0';
|
|
} while (!bVar9);
|
|
if (!bVar9) {
|
|
LAB_004d2f68:
|
|
iVar5 = FUN_004d4b58(local_30,s_novice_0051e6f1);
|
|
if (iVar5 == 0) {
|
|
*(undefined4 *)(param_1 + 0xe4) = 0;
|
|
}
|
|
else {
|
|
iVar5 = FUN_004d4b58(local_30,s_standard_0051e6f8);
|
|
if (iVar5 == 0) {
|
|
*(undefined4 *)(param_1 + 0xe4) = 1;
|
|
}
|
|
else {
|
|
iVar5 = FUN_004d4b58(local_30,s_veteran_0051e701);
|
|
if (iVar5 == 0) {
|
|
*(undefined4 *)(param_1 + 0xe4) = 2;
|
|
}
|
|
else {
|
|
iVar5 = FUN_004d4b58(local_30,s_expert_0051e709);
|
|
pcVar4 = local_30;
|
|
if (iVar5 == 0) {
|
|
*(undefined4 *)(param_1 + 0xe4) = 3;
|
|
}
|
|
else {
|
|
FUN_004dbb24((int *)&DAT_00524e68,(char *)local_8[2],(char *)0x0);
|
|
FUN_004dbb24((int *)&DAT_00524e68,s_has_an_unknown_experience_field_o_0051e710,
|
|
(char *)0x0);
|
|
FUN_004dbb24((int *)&DAT_00524e68,pcVar4,(char *)0x0);
|
|
FUN_004d9c38((int *)&DAT_00524e68);
|
|
FUN_0040385c(s_Exiting_0051e735,s_d__tesla_bt_bt_l4_BTL4MSSN_CPP_0051e73d,0x108);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
LAB_004d3052:
|
|
local_34 = 0;
|
|
bVar9 = FUN_004040d8(param_2,(char *)local_8[2],s_advancedDamage_0051e75c,&local_34);
|
|
if (CONCAT31(extraout_var,bVar9) != 0) {
|
|
if (local_34 == 0) {
|
|
*(undefined4 *)(param_1 + 0xf0) = 0;
|
|
}
|
|
else {
|
|
*(undefined4 *)(param_1 + 0xf0) = 1;
|
|
}
|
|
}
|
|
iVar5 = FUN_00404088(param_2,(char *)local_8[2],&DAT_0051e76b,&local_3c);
|
|
if (iVar5 == 0) {
|
|
FUN_004dbb24((int *)&DAT_00524e68,s_Each_Player_page_must_have_a_rol_0051e7fd,(char *)0x0);
|
|
FUN_004d9c38((int *)&DAT_00524e68);
|
|
FUN_0040385c(s_Exiting_0051e827,s_d__tesla_bt_bt_l4_BTL4MSSN_CPP_0051e82f,0x1c3);
|
|
}
|
|
else {
|
|
FUN_00402a98((int *)&local_40,(int *)(param_1 + 0xe8),local_3c);
|
|
piVar3 = local_40 + 3;
|
|
*piVar3 = *piVar3 + -1;
|
|
if (*piVar3 == 0) {
|
|
FUN_004024d8(local_40,3);
|
|
}
|
|
iVar5 = FUN_00404088(param_2,local_3c,s_model_0051e770,&local_44);
|
|
if (iVar5 == 0) {
|
|
FUN_004dbb24((int *)&DAT_00524e68,local_3c,(char *)0x0);
|
|
FUN_004dbb24((int *)&DAT_00524e68,s_page_or_model_field_missing___0051e7b7,(char *)0x0);
|
|
FUN_004d9c38((int *)&DAT_00524e68);
|
|
FUN_0040385c(s_Exiting_0051e7d6,s_d__tesla_bt_bt_l4_BTL4MSSN_CPP_0051e7de,0x1bd);
|
|
}
|
|
else {
|
|
FUN_004323c7(local_90,param_1 + 0x50);
|
|
puVar6 = (undefined4 *)(**(code **)(local_90[0] + 0x54))(local_90,param_1 + 0xe8);
|
|
FUN_00432405(local_90,2);
|
|
if (puVar6 == (undefined4 *)0x0) {
|
|
puVar6 = (undefined4 *)FUN_00402298(0x2c);
|
|
if (puVar6 == (undefined4 *)0x0) {
|
|
puVar6 = (undefined4 *)0x0;
|
|
}
|
|
else {
|
|
local_48 = local_44;
|
|
local_50 = (uint *)FUN_00402298(0x10);
|
|
if (local_50 == (uint *)0x0) {
|
|
local_4c = (uint *)0x0;
|
|
}
|
|
else {
|
|
local_4c = FUN_00402460(local_50,local_48);
|
|
}
|
|
local_4c[3] = local_4c[3] + 1;
|
|
puVar6 = FUN_00429a9c(puVar6,(int *)(param_1 + 0xe8),(int *)&local_4c);
|
|
}
|
|
local_54 = local_4c;
|
|
puVar2 = local_4c + 3;
|
|
*puVar2 = *puVar2 - 1;
|
|
if (*puVar2 == 0) {
|
|
FUN_004024d8((int *)local_4c,3);
|
|
}
|
|
local_5c = puVar6 + 9;
|
|
local_60 = (int *)*local_5c;
|
|
local_60[3] = local_60[3] + 1;
|
|
local_58 = puVar6;
|
|
FUN_004323c7(local_a4,param_1 + 0x50);
|
|
iVar5 = (**(code **)(local_a4[0] + 0x54))(local_a4,&local_60);
|
|
FUN_00432405(local_a4,2);
|
|
uVar7 = (uint)(iVar5 == 0);
|
|
local_64 = local_60;
|
|
piVar3 = local_60 + 3;
|
|
*piVar3 = *piVar3 + -1;
|
|
if (*piVar3 == 0) {
|
|
FUN_004024d8(local_60,3);
|
|
}
|
|
if (uVar7 != 0) {
|
|
local_68 = local_58 + 9;
|
|
local_6c = (int *)*local_68;
|
|
local_6c[3] = local_6c[3] + 1;
|
|
(**(code **)(*(int *)(param_1 + 0x50) + 8))(param_1 + 0x50,local_58,&local_6c);
|
|
local_70 = local_6c;
|
|
piVar3 = local_6c + 3;
|
|
*piVar3 = *piVar3 + -1;
|
|
if (*piVar3 == 0) {
|
|
FUN_004024d8(local_6c,3);
|
|
}
|
|
}
|
|
}
|
|
iVar5 = FUN_00404118(param_2,local_3c,s_dmgInflctdMdfr_0051e776,&local_38);
|
|
if (iVar5 != 0) {
|
|
puVar6[3] = local_38;
|
|
}
|
|
iVar5 = FUN_00404118(param_2,local_3c,s_dmgRcvdMdfr_0051e785,&local_38);
|
|
if (iVar5 != 0) {
|
|
local_74 = local_38;
|
|
puVar6[4] = local_38;
|
|
}
|
|
iVar5 = FUN_00404118(param_2,local_3c,s_dmgBias_0051e791,&local_38);
|
|
if (iVar5 != 0) {
|
|
puVar6[6] = local_38;
|
|
}
|
|
iVar5 = FUN_00404118(param_2,local_3c,s_friendlyFire_0051e799,&local_38);
|
|
if (iVar5 != 0) {
|
|
puVar6[5] = local_38;
|
|
}
|
|
bVar9 = FUN_004040d8(param_2,local_3c,s_return_0051e7a6,&local_78);
|
|
if (CONCAT31(extraout_var_00,bVar9) != 0) {
|
|
puVar6[10] = local_78;
|
|
}
|
|
iVar5 = FUN_00404118(param_2,local_3c,s_killBonus_0051e7ad,&local_38);
|
|
if (iVar5 != 0) {
|
|
puVar6[7] = local_38;
|
|
}
|
|
}
|
|
}
|
|
bVar9 = FUN_004040d8(param_2,(char *)local_8[2],s_bitmapindex_0051e84e,(int *)(param_1 + 0x4c));
|
|
if (CONCAT31(extraout_var_01,bVar9) == 0) {
|
|
FUN_004dbb24(&DAT_00524e20,s_No_Bitmap_for_player_0051e85a,(char *)0x0);
|
|
FUN_004dbb24(&DAT_00524e20,(char *)local_8[2],(char *)0x0);
|
|
FUN_004d9c38(&DAT_00524e20);
|
|
}
|
|
else {
|
|
local_7c = *(undefined4 *)(param_1 + 0x4c);
|
|
iVar5 = (**(code **)(*(int *)(param_1 + 0x68) + 0xc))(param_1 + 0x68,&local_7c);
|
|
if (((iVar5 != 0) && (*(int *)(DAT_004efc94 + 0x4c) != 0)) &&
|
|
(piVar3 = *(int **)(*(int *)(DAT_004efc94 + 0x4c) + 0x1c530), piVar3 != (int *)0x0)) {
|
|
(**(code **)(*piVar3 + 0x28))
|
|
(piVar3,1,0,0xff,0,0,0,0,iVar5,0,0,*(int *)(iVar5 + 0xc) + -1,
|
|
*(int *)(iVar5 + 0x10) + -1);
|
|
(**(code **)(*piVar3 + 8))(piVar3,1);
|
|
(**(code **)(*piVar3 + 0xc))(piVar3);
|
|
}
|
|
}
|
|
piVar3 = local_8 + 3;
|
|
*piVar3 = *piVar3 + -1;
|
|
if (*piVar3 == 0) {
|
|
FUN_004024d8(local_8,3);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
|