port LevelStats

This commit is contained in:
rr- 2021-02-09 20:58:31 +01:00
parent 5361d69f33
commit 4c1350e446
6 changed files with 266 additions and 127 deletions

View file

@ -26,21 +26,15 @@
#define CurrentLevel VAR_U_(0x00453C4C, __int32)
#define Lara VAR_U_(0x0045ED80, LARA_INFO)
#define LaraItem VAR_U_(0x0045EE6C, ITEM_INFO*)
#define LevelNames ARRAY_(0x00453648, const char*, [22])
#define LevelTitles ARRAY_(0x00453DF8, const char*, [22])
#define SecretCounts ARRAY_(0x00453CB0, __int8, [16])
#define LevelNames ARRAY_(0x00453648, const char*, [NUMBER_OF_LEVELS])
#define LevelTitles ARRAY_(0x00453DF8, const char*, [NUMBER_OF_LEVELS])
#define SecretTotals ARRAY_(0x00453CB0, __int8, [MAX_SECRETS])
#define IsResetFlag VAR_U_(0x00459F50, int)
#define Word45BB14 VAR_U_(0x0045BB14, __int16)
#define Byte45BB17 VAR_U_(0x0045BB17, __int8)
#define Word45BB08 VAR_U_(0x0045BB08, __int16)
#define InputStatus VAR_U_(0x0045EEF4, int)
#define Kills VAR_U_(0x0045BB0E, int)
#define TimeTaken VAR_U_(0x0045BB0A, int)
#define PickupsTaken VAR_U_(0x0045BB16, int)
#define SecretsTaken VAR_U_(0x0045BB12, int)
#define HiRes VAR_U_(0x00459F64, int)
#define Effects VAR_U_(0x0045EE70, FX_INFO*)
#define NextFxFree VAR_U_(0x0045EE74, int16_t)
#define NextFxActive VAR_U_(0x0045EE7A, int16_t)
#define SaveGame ARRAY_(0x0045B9C0, SAVEGAME_INFO, [2])
#endif

View file

@ -13,11 +13,11 @@ void __cdecl init_game_malloc() {
GameAllocMemUsed = 0;
}
void __cdecl game_free(int freeSize) {
void __cdecl game_free(int free_size) {
TRACE("");
GameAllocMemPointer -= freeSize;
GameAllocMemFree += freeSize;
GameAllocMemUsed -= freeSize;
GameAllocMemPointer -= free_size;
GameAllocMemFree += free_size;
GameAllocMemUsed -= free_size;
}
void __cdecl DB_Log(char *a1, ...) {
@ -195,83 +195,94 @@ int LoadRooms(FILE *fp) {
return 1;
}
void __cdecl LevelStats(int levelID) {
void __cdecl LevelStats(int level_id) {
TRACE("");
if (TR1MConfig.keep_health_between_levels) {
TR1MData.stored_lara_health = LaraItem ? LaraItem->hit_points : LARA_HITPOINTS;
TR1MData.stored_lara_health = LaraItem
? LaraItem->hit_points
: LARA_HITPOINTS;
}
static char buf[100];
static char string[100];
TEXTSTRING *txt;
TempVideoAdjust(HiRes, 1.0);
T_InitPrint();
sprintf(buf, "%s", LevelTitles[levelID]);
unsigned int *txt = T_Print(0, -50, 0, buf);
// heading
sprintf(string, "%s", LevelTitles[level_id]); // TODO: translation
txt = T_Print(0, -50, 0, string);
T_CentreH(txt, 1);
T_CentreV(txt, 1);
int timeTakenInSeconds = TimeTaken / 0x1Eu;
if (timeTakenInSeconds / 3600) {
// time taken
int seconds = SaveGame[0].timer / 30;
int hours = seconds / 3600;
int minutes = (seconds / 60) % 60;
seconds %= 60;
if (hours) {
sprintf(
buf,
string,
"%s %d:%d%d:%d%d",
"TIME TAKEN",
timeTakenInSeconds / 3600,
((timeTakenInSeconds / 60) % 60) / 10,
((timeTakenInSeconds / 60) % 60) % 10,
(timeTakenInSeconds % 60) / 10,
(timeTakenInSeconds % 60) % 10
"TIME TAKEN", // TODO: translation
hours,
minutes / 10,
minutes % 10,
seconds / 10,
seconds % 10
);
} else {
sprintf(
buf,
string,
"%s %d:%d%d",
"TIME TAKEN",
(timeTakenInSeconds / 60) % 60,
(timeTakenInSeconds % 60) / 10,
(timeTakenInSeconds % 60) % 10
"TIME TAKEN", // TODO: translation
minutes,
seconds / 10,
seconds % 10
);
}
txt = T_Print(0, 70, 0, buf);
txt = T_Print(0, 70, 0, string);
T_CentreH(txt, 1);
T_CentreV(txt, 1);
int secretsTaken = 0;
int secretsTotal = 16;
// secrets
int secrets_taken = 0;
int secrets_total = MAX_SECRETS;
do {
if (SecretsTaken & 1) {
++secretsTaken;
if (SaveGame[0].secrets & 1) {
++secrets_taken;
}
SecretsTaken >>= 1;
--secretsTotal;
SaveGame[0].secrets >>= 1;
--secrets_total;
}
while (secretsTotal);
while (secrets_total);
sprintf(
buf,
string,
"%s %d %s %d",
"SECRETS",
secretsTaken,
"OF",
SecretCounts[levelID]
"SECRETS", // TODO: translation
secrets_taken,
"OF", // TODO: translation
SecretTotals[level_id] // TODO: calculate this automatically
);
txt = T_Print(0, 40, 0, buf);
txt = T_Print(0, 40, 0, string);
T_CentreH(txt, 1);
T_CentreV(txt, 1);
sprintf(buf, "%s %d", "PICKUPS", PickupsTaken);
txt = T_Print(0, 10, 0, buf);
// pickups
sprintf(string, "%s %d", "PICKUPS", SaveGame[0].pickups); // TODO: translation
txt = T_Print(0, 10, 0, string);
T_CentreH(txt, 1);
T_CentreV(txt, 1);
sprintf(buf, "%s %d", "KILLS", Kills);
txt = T_Print(0, -20, 0, buf);
// kills
sprintf(string, "%s %d", "KILLS", SaveGame[0].kills); // TODO: translation
txt = T_Print(0, -20, 0, string);
T_CentreH(txt, 1);
T_CentreV(txt, 1);
while (InputStatus & 0x100000) {
// wait till action key
while (InputStatus & IN_SELECT) {
S_UpdateInput();
}
S_InitialisePolyList();
@ -280,7 +291,7 @@ void __cdecl LevelStats(int levelID) {
T_DrawText();
S_OutputPolyList();
S_DumpScreen();
while (!(InputStatus & 0x100000)) {
while (!(InputStatus & IN_SELECT)) {
if (IsResetFlag) {
break;
}
@ -292,39 +303,39 @@ void __cdecl LevelStats(int levelID) {
S_DumpScreen();
}
if (levelID == 15) {
Byte45BB17 = 1;
int tmp = 1;
do
sub_434520(tmp++);
while ( tmp <= 15 );
Word45BB14 = 1;
// go to next level
if (level_id == LEVEL10C) {
SaveGame[0].bonus_flag = 1;
for (int level = LEVEL1; level <= LEVEL10C; level++) {
ModifyStartInfo(level);
}
SaveGame[0].current_level = 1;
} else {
CreateStartInfo(levelID + 1);
sub_434520(levelID + 1);
Word45BB14 = levelID + 1;
CreateStartInfo(level_id + 1);
ModifyStartInfo(level_id + 1);
SaveGame[0].current_level = level_id + 1;
}
Word45BB08 &= 0xFFFEu;
sub_41CD10();
SaveGame[0].start[CURRENT].available = 0;
S_FadeToBlack();
TempVideoRemove();
}
int __cdecl S_LoadLevel(int levelID) {
TRACE("%d", levelID);
int ret = LoadLevel(LevelNames[levelID], levelID);
int __cdecl S_LoadLevel(int level_id) {
TRACE("%d", level_id);
int ret = LoadLevel(LevelNames[level_id], level_id);
if (TR1MConfig.keep_health_between_levels) {
// check if we're in main menu by seeing if there is Lara item in the
// currently loaded level.
int laraFound = 0;
int lara_found = 0;
for (int i = 0; i < LevelItemCount; i++) {
if (Items[i].object_id == ID_LARA) {
laraFound = 1;
lara_found = 1;
}
}
if (!laraFound) {
if (!lara_found) {
TR1MData.stored_lara_health = LARA_HITPOINTS;
}
}
@ -368,13 +379,13 @@ int __cdecl S_DrawHealthBar(int percent) {
int __cdecl LoadItems(FILE *handle)
{
int itemCount = 0;
_fread(&itemCount, 4u, 1u, handle);
int item_count = 0;
_fread(&item_count, 4u, 1u, handle);
TRACE("Item count: %d", itemCount);
TRACE("Item count: %d", item_count);
if (itemCount) {
if (itemCount > 256) {
if (item_count) {
if (item_count > 256) {
strcpy(StringToShow, "LoadItems(): Too Many Items being Loaded!!");
return 0;
}
@ -388,21 +399,21 @@ int __cdecl LoadItems(FILE *handle)
return 0;
}
LevelItemCount = itemCount;
LevelItemCount = item_count;
InitialiseItemArray(256);
for (int i = 0; i < itemCount; ++i) {
ITEM_INFO *currentItem = &Items[i];
_fread(&currentItem->object_id, 2u, 1u, handle);
_fread(&currentItem->room_number, 2u, 1u, handle);
_fread(&currentItem->pos.x, 4u, 1u, handle);
_fread(&currentItem->pos.y, 4u, 1u, handle);
_fread(&currentItem->pos.z, 4u, 1u, handle);
_fread(&currentItem->pos.rot_y, 2u, 1u, handle);
_fread(&currentItem->shade1, 2u, 1u, handle);
_fread(&currentItem->flags, 2u, 1u, handle);
for (int i = 0; i < item_count; ++i) {
ITEM_INFO *current_item = &Items[i];
_fread(&current_item->object_id, 2u, 1u, handle);
_fread(&current_item->room_number, 2u, 1u, handle);
_fread(&current_item->pos.x, 4u, 1u, handle);
_fread(&current_item->pos.y, 4u, 1u, handle);
_fread(&current_item->pos.z, 4u, 1u, handle);
_fread(&current_item->pos.rot_y, 2u, 1u, handle);
_fread(&current_item->shade1, 2u, 1u, handle);
_fread(&current_item->flags, 2u, 1u, handle);
int object_id = currentItem->object_id;
int object_id = current_item->object_id;
if (object_id < 0 || object_id >= ID_NUMBER_OBJECTS) {
sprintf(
StringToShow,
@ -417,10 +428,10 @@ int __cdecl LoadItems(FILE *handle)
object_id == ID_LARGE_MEDIPACK_ITEM ||
object_id == ID_SMALL_MEDIPACK_ITEM
)) {
currentItem->pos.x = -1;
currentItem->pos.y = -1;
currentItem->pos.z = -1;
currentItem->room_number = 0;
current_item->pos.x = -1;
current_item->pos.y = -1;
current_item->pos.z = -1;
current_item->room_number = 0;
}
InitialiseItem(i);

View file

@ -4,39 +4,39 @@
#include <stdio.h>
#include "util.h"
#define game_malloc ((void __cdecl*(*)(int, int))0x0041E2F0)
#define ins_line ((int __cdecl(*)(int, int, int, int, int, char))0x00402710)
#define _fread ((size_t __cdecl(*)(void *, size_t, size_t, FILE *))0x00442C20)
#define InitialiseItemArray ((void __cdecl(*)(int itemCount))0x00421B10)
#define S_ExitSystem ((void __cdecl(*)(const char *))0x0041E260)
#define InitialiseItem ((void __cdecl(*)(__int16))0x00421CC0)
#define InitialiseLaraInventory ((void __cdecl(*)(int levelID))0x00428170)
#define InitialiseLOT ((void __cdecl(*)())0x0042A780)
#define LoadLevel ((int __cdecl(*)(const char *path, int levelID))0x0041AFB0)
#define T_DrawText ((void __cdecl(*)())0x00439B00)
#define S_DumpScreen ((__int32 __cdecl(*)())0x0042FC70)
#define S_InitialisePolyList ((void __cdecl(*)())0x0042FC60)
#define S_UpdateInput ((void __cdecl(*)())0x0041E550)
#define S_CopyBufferToScreen ((void __cdecl(*)())0x00416A60)
#define S_OutputPolyList ((void __cdecl(*)())0x0042FD10)
#define sub_41CD10 ((void __cdecl(*)())0x0041CD10)
#define sub_434520 ((void __cdecl(*)(int))0x00434520)
#define CreateStartInfo ((void __cdecl(*)(int levelID))0x004345E0)
#define TempVideoRemove ((void __cdecl(*)())0x004167D0)
#define T_InitPrint ((void __cdecl(*)())0x00439750)
#define T_Print ((int* __cdecl(*)(__int16, __int16, __int16, const char *))0x00439780)
#define T_CentreH ((unsigned int* __cdecl(*)(unsigned int*, __int16))0x004399A0)
#define T_CentreV ((unsigned int* __cdecl(*)(unsigned int*, __int16))0x004399C0)
#define TempVideoAdjust ((void __cdecl(*)(int hi_res, double sizer))0x00416550)
#define game_malloc ((void __cdecl*(*)(uint32_t length, int type))0x0041E2F0)
#define ins_line ((int __cdecl(*)(int, int, int, int, int, char))0x00402710)
#define _fread ((size_t __cdecl(*)(void *, size_t, size_t, FILE *))0x00442C20)
#define InitialiseItemArray ((void __cdecl(*)(int item_count))0x00421B10)
#define S_ExitSystem ((void __cdecl(*)(const char *message))0x0041E260)
#define InitialiseItem ((void __cdecl(*)(int16_t item_num))0x00421CC0)
#define InitialiseLaraInventory ((void __cdecl(*)(int level_id))0x00428170)
#define InitialiseLOT ((void __cdecl(*)())0x0042A780)
#define LoadLevel ((int __cdecl(*)(const char *path, int level_id))0x0041AFB0)
#define T_DrawText ((void __cdecl(*)())0x00439B00)
#define S_DumpScreen ((__int32 __cdecl(*)())0x0042FC70)
#define S_InitialisePolyList ((void __cdecl(*)())0x0042FC60)
#define S_UpdateInput ((void __cdecl(*)())0x0041E550)
#define S_CopyBufferToScreen ((void __cdecl(*)())0x00416A60)
#define S_OutputPolyList ((void __cdecl(*)())0x0042FD10)
#define S_FadeToBlack ((void __cdecl(*)())0x0041CD10)
#define CreateStartInfo ((void __cdecl(*)(int level_id))0x004345E0)
#define ModifyStartInfo ((void __cdecl(*)(int level_id))0x00434520)
#define TempVideoRemove ((void __cdecl(*)())0x004167D0)
#define T_InitPrint ((void __cdecl(*)())0x00439750)
#define T_Print ((TEXTSTRING *__cdecl(*)(int16_t xpos, int16_t ypos, int16_t zpos, const char *string))0x00439780)
#define T_CentreH ((void __cdecl(*)(TEXTSTRING *text_string, int16_t enable))0x004399A0)
#define T_CentreV ((void __cdecl(*)(TEXTSTRING *text_string, int16_t enable))0x004399C0)
#define TempVideoAdjust ((void __cdecl(*)(int hires, double sizer))0x00416550)
void __cdecl init_game_malloc();
void __cdecl game_free(int freeSize);
void __cdecl game_free(int free_size);
void __cdecl DB_Log(char *a1, ...);
const char* __cdecl GetFullPath(const char *filename);
int __cdecl FindCdDrive();
int __cdecl LoadRooms(FILE *fp);
void __cdecl LevelStats(int levelID);
int __cdecl S_LoadLevel(int levelID);
void __cdecl LevelStats(int level_id);
int __cdecl S_LoadLevel(int level_id);
int __cdecl S_DrawHealthBar(int percent);
int __cdecl LoadItems(FILE *handle);
void __cdecl InitialiseLara();

View file

@ -5,11 +5,15 @@
#include <stdint.h>
typedef uint16_t PHD_ANGLE;
typedef uint32_t SG_COL;
typedef void UNKNOWN_STRUCT;
#define LARA_HITPOINTS 1000
#define LARA_AIR 1800
#define NO_ITEM -1
#define MAX_SECRETS 16
#define MAX_SAVEGAME_BUFFER (10*1024)
#define SAVEGAME_VERSION 0x1
#define LARA_HITPOINTS 1000
#define LARA_AIR 1800
#define NO_ITEM -1
#define NUM_EFFECTS 100
@ -103,6 +107,66 @@ typedef enum {
GBUF_FloorData = 17,
} GAMEALLOC_BUFFER;
typedef enum {
GYM = 0,
LEVEL1 = 1, // Peru 1: Caves
LEVEL2 = 2, // Peru 2: City of Vilcabamba
LEVEL3A = 3, // Peru 3: The Lost Valley
LEVEL3B = 4, // Peru 4: Tomb of Qualopec
LEVEL4 = 5, // Greece 1: St Francis Folly
LEVEL5 = 6, // Greece 2: Colosseum
LEVEL6 = 7, // Greece 3: Place Midas
LEVEL7A = 8, // Greece 4: Cistern
LEVEL7B = 9, // Greece 5: Tomb of Tihocan
LEVEL8A = 10, // Egypt 1: City of Khamoon
LEVEL8B = 11, // Egypt 2: Obelisk of Khamoon
LEVEL8C = 12, // Egypt 3: Sanctuary of Scion
LEVEL10A = 13, // Lost island 1: Natla's Mines
LEVEL10B = 14, // Lost island 2: Atlantis
LEVEL10C = 15, // Lost island 3: The great pyramid
CUTSCENE1 = 16,
CUTSCENE2 = 17,
CUTSCENE3 = 18,
CUTSCENE4 = 19,
TITLE = 20,
CURRENT = 21,
// UB_LEVEL1 = 22, // TRUB - Egypt
// UB_LEVEL2 = 23, // TRUB - Temple of Cat
// UB_LEVEL3 = 24,
// UB_LEVEL4 = 25,
NUMBER_OF_LEVELS = 22,
} GAME_LEVELS;
#define IN_FORWARD (1<<0)
#define IN_BACK (1<<1)
#define IN_LEFT (1<<2)
#define IN_RIGHT (1<<3)
#define IN_JUMP (1<<4)
#define IN_DRAW (1<<5)
#define IN_ACTION (1<<6)
#define IN_SLOW (1<<7)
#define IN_OPTION (1<<8)
#define IN_LOOK (1<<9)
#define IN_STEPL (1<<10)
#define IN_STEPR (1<<11)
#define IN_ROLL (1<<12)
#define IN_PAUSE (1<<13)
#define IN_A (1<<14) // A to F are Debug thingys..
#define IN_B (1<<15)
#define IN_C (1<<16)
#define IN_MENUBACK (1<<17)
#define IN_UP (1<<18)
#define IN_DOWN (1<<19)
#define IN_SELECT (1<<20)
#define IN_DESELECT (1<<21)
#define IN_SAVE (1<<22)
#define IN_LOAD (1<<23)
#define IN_ACTION_AUTO (1<<24)
#define IN_CHEAT (1<<25)
#define IN_D (1<<26)
#define IN_E (1<<27)
#define IN_F (1<<28)
#pragma pack(push, 1)
typedef struct {
@ -327,6 +391,75 @@ typedef struct {
/* 0024 end */
} FX_INFO;
typedef struct {
/* 0000 */ uint16_t pistol_ammo;
/* 0002 */ uint16_t magnum_ammo;
/* 0004 */ uint16_t uzi_ammo;
/* 0006 */ uint16_t shotgun_ammo;
/* 0008 */ uint8_t num_medis;
/* 0009 */ uint8_t num_big_medis;
/* 000A */ uint8_t num_scions;
/* 000B */ int8_t gun_status;
/* 000C */ int8_t gun_type;
/* 000D */ uint16_t available : 1;
/* */ uint16_t got_pistols : 1;
/* */ uint16_t got_magnums : 1;
/* */ uint16_t got_uzis : 1;
/* */ uint16_t got_shotgun : 1;
/* 000F end */
} START_INFO;
typedef struct {
/* 0000 */ START_INFO start[NUMBER_OF_LEVELS];
/* 014A */ uint32_t timer;
/* 014E */ uint32_t kills;
/* 0152 */ uint16_t secrets;
/* 0154 */ uint16_t current_level;
/* 0156 */ uint8_t pickups;
/* 0157 */ uint8_t bonus_flag;
/* 0158 */ uint8_t num_pickup1;
/* 0159 */ uint8_t num_pickup2;
/* 015A */ uint8_t num_puzzle1;
/* 015B */ uint8_t num_puzzle2;
/* 015C */ uint8_t num_puzzle3;
/* 015D */ uint8_t num_puzzle4;
/* 015E */ uint8_t num_key1;
/* 015F */ uint8_t num_key2;
/* 0160 */ uint8_t num_key3;
/* 0161 */ uint8_t num_key4;
/* 0162 */ uint8_t num_leadbar;
/* 0163 */ uint8_t challenge_failed;
/* 0164 */ char buffer[MAX_SAVEGAME_BUFFER];
/* 2964 end */
} SAVEGAME_INFO;
typedef struct {
/* 0000 */ uint32_t flags;
/* 0004 */ uint16_t textflags;
/* 0006 */ uint16_t bgndflags;
/* 0008 */ uint16_t outlflags;
/* 000A */ int16_t xpos;
/* 000C */ int16_t ypos;
/* 000E */ int16_t zpos;
/* 0010 */ int16_t letter_spacing;
/* 0012 */ int16_t word_spacing;
/* 0014 */ int16_t flash_rate;
/* 0016 */ int16_t flash_count;
/* 0018 */ int16_t bgnd_colour;
/* 001A */ SG_COL *bgnd_gour;
/* 001E */ int16_t outl_colour;
/* 0020 */ SG_COL *outl_gour;
/* 0024 */ int16_t bgnd_size_x;
/* 0026 */ int16_t bgnd_size_y;
/* 0028 */ int16_t bgnd_off_x;
/* 002A */ int16_t bgnd_off_y;
/* 002C */ int16_t bgnd_off_z;
/* 002E */ int32_t scale_h;
/* 0032 */ int32_t scale_v;
/* 0034 */ char *string;
/* 0038 end */
} TEXTSTRING;
#pragma pop
#endif

View file

@ -10,12 +10,12 @@ void tr1m_inject_func(void *from, void *to) {
VirtualProtect(from, sizeof(JMP), PAGE_EXECUTE_READWRITE, &tmp);
HANDLE hCurrentProcess = GetCurrentProcess();
JMP buf;
buf.opCode = 0xE9;
buf.opcode = 0xE9;
buf.offset = (DWORD)(to) - ((DWORD)(from) + sizeof(JMP));
WriteProcessMemory(hCurrentProcess, from, &buf, sizeof(JMP), &tmp);
CloseHandle(hCurrentProcess);
// arsunt style - doesn't work because of GLRage calling VirtualProtect
//((JMP*)(from))->opCode = 0xE9;
//((JMP*)(from))->opcode = 0xE9;
//((JMP*)(from))->offset = (DWORD)(to) - ((DWORD)(from) + sizeof(JMP));
}

View file

@ -6,11 +6,12 @@
#define FEATURE_DISABLE_MEDPACKS
#include <stdio.h>
#include <stdint.h>
#pragma pack(push, 1)
typedef struct {
__int8 opCode; // must be 0xE9;
__int32 offset; // jump offset
int8_t opcode; // must be 0xE9
uint32_t offset;
} JMP;
#pragma pack(pop)