Skip to content

Commit

Permalink
v0.1.6-alpha
Browse files Browse the repository at this point in the history
- Fix the bug causing program termination on the game title screen:
  - Add checks for out-of-bounds indexes pointing to arrays with item data,
  - Add checks for invalid player stats,
  - Add a function `CheckPlayerStats()` which checks for if the player stats read from game memory are valid. If they are, that means, the game has been loaded properly,
  - Don't start the tracking for equipment, time and location, until the `CheckPlayerStats()` return `TRUE`. This prevents populating files with garbage data,
  - Remove the bug from the `Known Issues` section in `README.md` file.

- Change variable types from `UINT8` to `UINT8` for STR, INT, and AGL in `PrintPlayerStats2()` function
  • Loading branch information
tomasz-rozanski committed Oct 27, 2019
1 parent 0e364f0 commit fc521e5
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 43 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
*.app

# Visual Studio Stuff
*.sln

# Files built by Visual Studio
*_i.c
Expand Down
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ To build *VSTrack* use **Visual Studio 2019** or **Build Tools for Visual Studio
## Known Issues
[known-issues]: #known-issues

- If the *VSTrack* is running before the game loaded, it will stop as soon as the game cinematic starts to play.
- **The workaround**: start *VSTrack* a few seconds after starting the "New Game" mode, or right after loading the game from a save file.
Everything's fine. Really.


## Acknowledgements
Expand Down
111 changes: 110 additions & 1 deletion includes/vst_equipment.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* 6 cuboid
* 7 rhombohedron
* Shape angle (bits 3-7):
* ncrement by 360°/32,
* increment by 360°/32,
* center is casting position,
* direction is upward, incrementing backward
*/
Expand Down Expand Up @@ -354,6 +354,14 @@ WriteBladeInfo(DWORD processID)
BytesRead = ReadGameMemory(
processID, OFFSET_EQUIPPED_WEAPON_BLADE, BytesToRead, &BladeInfo);

// Check for out-of-bound indexes
if (BladeInfo.NamesListPosition > 511 || //
BladeInfo.ListPosition > 90 || //
BladeInfo.Category > 10)
{
return;
}

FILE *fpBladeInfoExt = fopen("game_stats/blade-full.txt", "w");

// Check if weapon is eqipped
Expand Down Expand Up @@ -443,6 +451,15 @@ WriteBladeInfoShort(DWORD processID)
BytesRead = ReadGameMemory(
processID, OFFSET_EQUIPPED_WEAPON_BLADE, BytesToRead, &BladeInfo);

// Check for out-of-bound indexes
if (BladeInfo.NamesListPosition > 511 || //
BladeInfo.ListPosition > 90 || //
BladeInfo.Material > 7 || //
BladeInfo.Category > 10)
{
return;
}

FILE *fpBladeInfoShort = fopen("game_stats/blade-short.txt", "w");

// Check if weapon is eqipped
Expand Down Expand Up @@ -505,6 +522,19 @@ WriteWeaponInfo(DWORD processID)
BytesRead = ReadGameMemory(
processID, OFFSET_EQUIPPED_WEAPON_GEM_SLOT3, BytesToRead, &Gem3Info);

// Check for out-of-bound indexes
if (BladeInfo.NamesListPosition > 511 || //
BladeInfo.ListPosition > 90 || //
BladeInfo.Category > 10 || //
BladeInfo.Material > 7 || //
GripInfo.ListPosition > 31 || //
Gem1Info.ListPosition > 62 || //
Gem2Info.ListPosition > 62 || //
Gem3Info.ListPosition > 62)
{
return;
}

FILE *fpWeaponInfo = fopen("game_stats/weapon-full.txt", "w");

// Check if weapon is eqipped
Expand Down Expand Up @@ -683,6 +713,16 @@ WriteShieldInfo(DWORD processID)
BytesRead = ReadGameMemory(
processID, OFFSET_EQUIPPED_SHIELD_GEM_SLOT3, BytesToRead, &Gem3Info);

// Check for out-of-bound indexes
if (ShieldInfo.ListPosition > 80 || //
ShieldInfo.Material > 7 || //
Gem1Info.ListPosition > 62 || //
Gem2Info.ListPosition > 62 || //
Gem3Info.ListPosition > 62)
{
return;
}

FILE *fpShieldInfoExt = fopen("game_stats/shield-full.txt", "w");

// Check if shield is eqipped. If not, write the warning and skip the rest.
Expand Down Expand Up @@ -826,6 +866,13 @@ WriteShieldInfoShort(DWORD processID)
BytesRead = ReadGameMemory(
processID, OFFSET_EQUIPPED_SHIELD, BytesToRead, &ShieldInfo);

// Check for out-of-bound indexes
if (ShieldInfo.ListPosition > 80 || //
ShieldInfo.Material > 7)
{
return;
}

FILE *fpShieldInfoShort = fopen("game_stats/shield-short.txt", "w");

// Check if shield is eqipped. If not, write the warning and skip the rest.
Expand Down Expand Up @@ -881,6 +928,13 @@ WriteGloveInfo(DWORD processID, int which_glove)

BytesRead = ReadGameMemory(processID, offset, BytesToRead, &GloveInfo);

// Check for out-of-bound indexes
if (GloveInfo.ListPosition > 80 || //
GloveInfo.Material > 7)
{
return;
}

FILE *fpGloveInfoExt = fopen(FileName, "w");

// Check if a glove is eqipped. If not, write the warning and skip the rest.
Expand Down Expand Up @@ -965,6 +1019,13 @@ WriteGloveInfoShort(DWORD processID, int which_glove)

BytesRead = ReadGameMemory(processID, offset, BytesToRead, &GloveInfo);

// Check for out-of-bound indexes
if (GloveInfo.ListPosition > 80 || //
GloveInfo.Material > 7)
{
return;
}

FILE *fpGloveInfoShort = fopen(FileName, "w");

// Check if a glove is eqipped. If not, write the warning and skip the rest.
Expand Down Expand Up @@ -1015,6 +1076,13 @@ WriteHeadArmorInfo(DWORD processID)
BytesRead =
ReadGameMemory(processID, OFFSET_EQUIPPED_HEAD, BytesToRead, &HeadInfo);

// Check for out-of-bound indexes
if (HeadInfo.ListPosition > 80 || //
HeadInfo.Material > 7)
{
return;
}

FILE *fpHeadInfoExt = fopen("game_stats/armor-head-full.txt", "w");

// Check if a head armor is eqipped.
Expand Down Expand Up @@ -1092,6 +1160,13 @@ WriteHeadArmorInfoShort(DWORD processID)
BytesRead =
ReadGameMemory(processID, OFFSET_EQUIPPED_HEAD, BytesToRead, &HeadInfo);

// Check for out-of-bound indexes
if (HeadInfo.ListPosition > 80 || //
HeadInfo.Material > 7)
{
return;
}

FILE *fpHeadInfoShort = fopen("game_stats/armor-head-short.txt", "w");

// Check if a head armor is eqipped.
Expand Down Expand Up @@ -1141,6 +1216,13 @@ WriteBodyArmorInfo(DWORD processID)
BytesRead =
ReadGameMemory(processID, OFFSET_EQUIPPED_BODY, BytesToRead, &BodyInfo);

// Check for out-of-bound indexes
if (BodyInfo.ListPosition > 80 || //
BodyInfo.Material > 7)
{
return;
}

FILE *fpBodyInfoExt = fopen("game_stats/armor-body-full.txt", "w");

// Check if a body armor is eqipped. If not, write the warning and skip the
Expand Down Expand Up @@ -1219,6 +1301,13 @@ WriteBodyArmorInfoShort(DWORD processID)
BytesRead =
ReadGameMemory(processID, OFFSET_EQUIPPED_BODY, BytesToRead, &BodyInfo);

// Check for out-of-bound indexes
if (BodyInfo.ListPosition > 80 || //
BodyInfo.Material > 7)
{
return;
}

FILE *fpBodyInfoShort = fopen("game_stats/armor-body-short.txt", "w");

// Check if a body armor is eqipped. If not, write the warning and skip the
Expand Down Expand Up @@ -1269,6 +1358,13 @@ WriteLegsArmorInfo(DWORD processID)
BytesRead =
ReadGameMemory(processID, OFFSET_EQUIPPED_LEGS, BytesToRead, &LegsInfo);

// Check for out-of-bound indexes
if (LegsInfo.ListPosition > 80 || //
LegsInfo.Material > 7)
{
return;
}

FILE *fpLegsInfoExt = fopen("game_stats/armor-legs-full.txt", "w");

// Check if a leg armor is eqipped.
Expand Down Expand Up @@ -1346,6 +1442,13 @@ WriteLegsArmorInfoShort(DWORD processID)
BytesRead =
ReadGameMemory(processID, OFFSET_EQUIPPED_LEGS, BytesToRead, &LegsInfo);

// Check for out-of-bound indexes
if (LegsInfo.ListPosition > 80 || //
LegsInfo.Material > 7)
{
return;
}

FILE *fpLegsInfoShort = fopen("game_stats/armor-legs-short.txt", "w");

// Check if a leg armor is eqipped.
Expand Down Expand Up @@ -1395,6 +1498,12 @@ WriteNecklaceInfo(DWORD processID)
BytesRead =
ReadGameMemory(processID, OFFSET_EQUIPPED_NECK, BytesToRead, &NeckInfo);

// Check for out-of-bound indexes
if (NeckInfo.NamesListPosition > 31)
{
return;
}

FILE *fpNeckInfoExt = fopen("game_stats/accessory.txt", "w");

// Check if a necklace is eqipped.
Expand Down
43 changes: 37 additions & 6 deletions includes/vst_player.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,12 +241,12 @@ PrintPlayerStats2(void)
BytesRead = ReadGameMemory(processID, OFFSET_PLAYER_STATUS_EFFECTS,
sizeof(status_effect), &StatusEffects);

UINT8 STR_Original = PlayerStats.STR_Original;
UINT8 STR_Equipped = PlayerStats.STR_Equipped;
UINT8 INT_Original = PlayerStats.INT_Original;
UINT8 INT_Equipped = PlayerStats.INT_Equipped;
UINT8 AGL_Original = PlayerStats.AGL_Original;
UINT8 AGL_Equipped = PlayerStats.AGL_Equipped;
UINT16 STR_Original = PlayerStats.STR_Original;
UINT16 STR_Equipped = PlayerStats.STR_Equipped;
UINT16 INT_Original = PlayerStats.INT_Original;
UINT16 INT_Equipped = PlayerStats.INT_Equipped;
UINT16 AGL_Original = PlayerStats.AGL_Original;
UINT16 AGL_Equipped = PlayerStats.AGL_Equipped;

char STR_Buff = ' ';
char INT_Buff = ' ';
Expand Down Expand Up @@ -336,6 +336,37 @@ PrintPlayerStats2(void)
}
}

BOOL
CheckPlayerStats(void)
{
player_stats PlayerStats;

DWORD BytesRead;

BytesRead = ReadGameMemory(
processID, OFFSET_PLAYER_HP_CURRENT, sizeof(player_stats), &PlayerStats);

UINT16 HP_Current = PlayerStats.HP_Current;
UINT16 HP_Maximum = PlayerStats.HP_Maximum;
UINT16 MP_Current = PlayerStats.MP_Current;
UINT16 MP_Maximum = PlayerStats.MP_Maximum;
UINT16 Risk = PlayerStats.Risk;
UINT16 STR_Original = PlayerStats.STR_Original;
UINT16 INT_Original = PlayerStats.INT_Original;
UINT16 AGL_Original = PlayerStats.AGL_Original;

// Check for invalid data
if (HP_Current == 0 || HP_Current > 999 || HP_Maximum > 999 ||
MP_Current == 0 || MP_Current > 999 || MP_Maximum > 999 ||
STR_Original > 999 || INT_Original > 999 || AGL_Original > 999 ||
Risk > 100)
{
return FALSE;
}

return TRUE;
}

DWORD
ReadLastBossHealth(UINT16 *BossHP)
{
Expand Down
2 changes: 1 addition & 1 deletion includes/vst_translate.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ GetWeaponName(DWORD processID, char *WeaponName)
processID, OFFSET_EQUIPPED_WEAPON_BLADE, BytesToRead, &BladeInfo);

// Check if weapon is eqipped
if (BladeInfo.ListPosition == 0)
if (BladeInfo.ListPosition == 0 || BladeInfo.ListPosition > 511)
{
return;
}
Expand Down
75 changes: 42 additions & 33 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,52 +128,61 @@ wmain(int argc, wchar_t *argv[])
SetCursorPosition(hStdout, 0, 0);
SetCursorPosition(hBackBuffer, 0, 0);

sprintf(szBuffer, "============================\n"
"== VSTracker v0.1.4-alpha ==\n"
"============================\n");
WriteToBackBuffer();
// Write player stats into the file

ReadPlayTime(&PlayTimeCurrent);
PrintPlayTimeShort2(&PlayTimeCurrent);
WritePlayTimeToFile(&PlayTimeCurrent, _T("game_stats//play-time.txt"));
if (CheckPlayerStats())
{
ReadPlayTime(&PlayTimeCurrent);
PrintPlayTimeShort2(&PlayTimeCurrent);
WritePlayTimeToFile(&PlayTimeCurrent, _T("game_stats//play-time.txt"));

// Check player's location
ReadLocation(&Location);
GetAreaAndRoomName(&Location, szAreaName, szRoomName);
PrintLocation2(&Location, szAreaName, szRoomName);
WriteLocationIntoFile(&Location, szAreaName, szRoomName);
// Check player's location
ReadLocation(&Location);
GetAreaAndRoomName(&Location, szAreaName, szRoomName);
PrintLocation2(&Location, szAreaName, szRoomName);
WriteLocationIntoFile(&Location, szAreaName, szRoomName);

// Write player stats into the file
WritePlayerStats();
PrintPlayerStats2();
PrintPlayerStats2();
WritePlayerStats();

GetWeaponName(processID, GlobalWeaponName);
GetWeaponName(processID, GlobalWeaponName);

// Write equipment stats into files
WriteWeaponInfo(processID);
// Write equipment stats into files
WriteWeaponInfo(processID);

WriteBladeInfo(processID);
WriteBladeInfoShort(processID);
WriteBladeInfo(processID);
WriteBladeInfoShort(processID);

WriteShieldInfo(processID);
WriteShieldInfoShort(processID);
WriteShieldInfo(processID);
WriteShieldInfoShort(processID);

WriteGloveInfo(processID, RIGHT_GLOVE);
WriteGloveInfoShort(processID, RIGHT_GLOVE);
WriteGloveInfo(processID, RIGHT_GLOVE);
WriteGloveInfoShort(processID, RIGHT_GLOVE);

WriteGloveInfo(processID, LEFT_GLOVE);
WriteGloveInfoShort(processID, LEFT_GLOVE);
WriteGloveInfo(processID, LEFT_GLOVE);
WriteGloveInfoShort(processID, LEFT_GLOVE);

WriteHeadArmorInfo(processID);
WriteHeadArmorInfoShort(processID);
WriteHeadArmorInfo(processID);
WriteHeadArmorInfoShort(processID);

WriteBodyArmorInfo(processID);
WriteBodyArmorInfoShort(processID);
WriteBodyArmorInfo(processID);
WriteBodyArmorInfoShort(processID);

WriteLegsArmorInfo(processID);
WriteLegsArmorInfoShort(processID);
WriteLegsArmorInfo(processID);
WriteLegsArmorInfoShort(processID);

WriteNecklaceInfo(processID);
WriteNecklaceInfo(processID);
}
else
{
sprintf(szBuffer, "============================\n"
"== VSTracker v0.1.6-alpha ==\n"
"============================\n");
WriteToBackBuffer();

sprintf(szBuffer, "\nWaiting for the game to load ...\n");
WriteToBackBuffer();
}

// Handle last boss
if (IsThisTheLastBossRoom(&Location))
Expand Down

0 comments on commit fc521e5

Please sign in to comment.