From eacc61480f2ece544003556bb4827186a28e35f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20R=C3=B3=C5=BCa=C5=84ski?= Date: Wed, 7 Apr 2021 02:48:54 +0200 Subject: [PATCH] 0.4.0-alpha - New major feature: Enemy tracking: * display name, HP, and MP of every hostile character in the current room, * text file for this one is `game_data/map/enemy_data.txt`, - Add controller input tracking, with button holding timers (debug build only), - Add current game mode tracking (debug build only). Currently recognized modes are: * Normal, * Battle, * Cut-scene, * Menu Screen, * Quick Menu, * First Person View, * Activate Panel, * Open Container, * Draw Weapon, * Use Locked Door, * End of Turn - Update supported `BizHawk` version to `2.6.1` --- .gitignore | 3 + README.md | 5 +- includes/vst_actors.h | 345 +++++++++++++++++++++++++++++++++++++++ includes/vst_emulation.h | 80 ++++++++- includes/vst_equipment.h | 2 +- includes/vst_gazette.h | 10 +- includes/vst_init.h | 9 + includes/vst_input.h | 15 +- includes/vst_location.h | 4 +- includes/vst_player.h | 12 +- includes/vst_time.h | 6 +- includes/vst_translate.h | 44 ++++- includes/vst_types.h | 65 ++++++++ main.c | 33 ++-- makefile | 6 + 15 files changed, 598 insertions(+), 41 deletions(-) create mode 100644 includes/vst_actors.h create mode 100644 makefile diff --git a/.gitignore b/.gitignore index 4bee27d..b5d4651 100644 --- a/.gitignore +++ b/.gitignore @@ -107,3 +107,6 @@ sub.bat # Misc changes.md TODO.md +.vimrc +ed.bat + diff --git a/README.md b/README.md index 92682a5..3f1d0a1 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ At this moment, you can track the following: * Player stats (HP, MP, RISK, STR, INT, AGL, range, walking/running speed) * Player status effects * Player location (area name, room name) +* Enemy tracking (name, HP, MP) * In-game timer (with 1 second precision) * Kill List and Weapon Usage list * Map and Chest completion (**real-time!**) @@ -37,7 +38,7 @@ Currently, *VSTrack* can work with [ePSXe][epsxe-emulator] and [BizHawk][bizhawk To use *VSTrack* you'll need: * One of the supported emulators: * **ePSXe** version *1.9.25* or *2.0.5* - * **BizHawk** version *2.4.2* + * **BizHawk** version *2.6.1* * Copy of the game: * **Vagrant Story** NTSC-US version *(SLUS-01040)* 1 @@ -52,7 +53,7 @@ No installation is required. Just copy the executable into preffered folder, and When you'll see the start menu, press key `1-3` to choose emulator version you're using to play the game, or `0` to exit. If your selection was correct, you should see some basic game information in the console window. -Alternatively, you can pass preferred emulator number as a command-line parameter, so if you want to use *VSTrack* with `BizHawk 2.4.2`, type: +Alternatively, you can pass preferred emulator number as a command-line parameter, so if you want to use *VSTrack* with `BizHawk 2.6.1`, type: ```bash vstrack.exe 3 ``` diff --git a/includes/vst_actors.h b/includes/vst_actors.h new file mode 100644 index 0000000..af816e1 --- /dev/null +++ b/includes/vst_actors.h @@ -0,0 +1,345 @@ +#ifndef _VST_ACTORS_H +#define _VST_ACTORS_H + +#define OFFSET_ACTOR_DATA_POINTERS 0x800F1928 +#define OFFSET_ACTOR_DATA_FIRST_NODE 0x8011f9f0 +#define MAX_ACTORS_NUMBER 15 +#define ACTORS_NAMES_LIST_LENGTH 108 + +char *ActorsNamesList[ACTORS_NAMES_LIST_LENGTH] = { // + "Air Elemental", // + "Arch Dragon", // + "Ashley Riot", // + "Asura", // + "Bandit", // + "Basilisk", // + "Bat", // + "Bejart", // + "Blood Lizard", // + "Callo Merlose", // + "City Gaurd", // + "Crimson Blade", // + "Damascus Crab", // + "Damascus Golem", // + "Dao", // + "Dark Crusader", // + "Dark Dragon", // + "Dark Elemental", // + "Dark Skeleton", // + "Dark Eye", // + "Dead Crimson Blade", // + "Death", // + "Djinn", // + "Dragon", // + "Dragon Zombie", // + "Duane", // + "Duke Bardorba", // + "Dullahan", // + "Dummy", // + "Earth Dragon", // + "Earth Elemental", // + "Fire Elemental", // + "Flame Dragon", // + "Gargoyle", // + "Ghast", // + "Ghost", // + "Ghoul", // + "Giant Crab", // + "Goblin", // + "Goblin Leader", // + "Golem", // + "Goodwin", // + "Gremlin", // + "Grissom", // + "Guildenstern", // + "Harpy", // + "Hellhound", // + "Ichthious", // + "Ifrit", // + "Imp", // + "Iron Crab", // + "Iron Golem", // + "John Hardin", // + "Joshua Bardorba", // + "Kali", // + "Last Crusader", // + "Lich", // + "Lich Lord", // + "Lizardman", // + "Lord Joshua", // + "Mandel", // + "Marco Riot", // + "Marid", // + "Matrix Ashley", // + "Matrix Merlose", // + "Mimic", // + "Minotaur", // + "Minotaur Lord", // + "Minotaur Zombie", // + "Mullenkamp Soldier", // change 'ü' to 'u'? + "Mummy", // + "Neesa", // + "Nightmare", // + "Nightstalker", // + "Ogre", // + "Ogre Lord", // + "Ogre Zombie", // + "Orc", // + "Orc Leader", // + "Poison Slime", // + "Quicksilver", // + "Ravana", // + "Rosencrantz", // + "Sackheim", // + "Samantha", // + "Sarjik", // + "Shadow", // + "Shrieker", // + "Silver Wolf", // + "Skeleton", // + "Skeleton Knight", // + "Sky Dragon", // + "Slime", // + "Snow Dragon", // + "Stirge", // + "Sydney Losstarot", // probably not used in this form (look below) + "Sydney", // + "Tia Riot", // + "Tieger", // + "Water Elemental", // + "Wraith", // + "Wyvern", // + "Wyvern Knight", // + "Wyvern Queen", // + "Zombie", // + "Zombie Fighter", // + "Zombie Knight", // + "Zombie Mage" +}; + +void +ReadActorPointer(u32 *ActorPointer, usize ActorNumber) +{ + usize BytesToRead = sizeof(u32); + + ReadGameMemory(processID, + OFFSET_ACTOR_DATA_POINTERS + (ActorNumber * sizeof(u32)), BytesToRead, + ActorPointer); +} + +void +ReadActorData(actor_data *ActorData, u32 ActorPointer) +{ + usize BytesToRead = sizeof(actor_data); + + ReadGameMemory(processID, (usize) ActorPointer, BytesToRead, ActorData); +} + +void +ReadNextActorPointer(u32 *ActorPointerCur, u32 *ActorPointerNext) +{ + actor_data ActorDataTemp; + ReadActorData(&ActorDataTemp, *ActorPointerCur); + *ActorPointerNext = ActorDataTemp.NextActorPtr; +} + +BOOL +IsActorNameValid(char *ActorName) +{ + for (int i = 0; i < ACTORS_NAMES_LIST_LENGTH; i++) + { + + if (strcmp(ActorName, ActorsNamesList[i]) == 0) + { + return TRUE; + } + } + return FALSE; +} + +void +PrintActorsDataOld() +{ + sprintf(szBuffer, "\nACTIVE ACTORS:\n"); + WriteToBackBuffer(); + + actor_data ActorData; + u32 ActorPointer = 0; + u32 ActiveActorMarker = 0; + + // ReadActiveActorMarker(OFFSET_ACTIVE_ACTOR_MARKER, &ActiveActorMarker); + // sprintf(szBuffer, "ActiveActorMarker: 0x%x\n", ActiveActorMarker); + // WriteToBackBuffer(); + + for (int i = 2; i < MAX_ACTORS_NUMBER; i++) + { + ReadActorPointer(&ActorPointer, i); + if (ActorPointer) + { + ReadActorData(&ActorData, ActorPointer); + + // u32 NameOffset = ActorPointer + (u32) offsetof(actor_data, Name); + ReadActorName(ActorData.NamePointer); + + if (IsActorNameValid(ActorName)) + { + u16 HPCur = ActorData.HPCur; + u16 HPMax = ActorData.HPMax; + u16 MPCur = ActorData.MPCur; + u16 MPMax = ActorData.MPMax; + + if (GameStatus == GAME_STATUS_CUTSCENE && HPMax == 100 && + MPMax == 100) // cutscene + { + return; + } + + if (HPCur == 0) + { + continue; + } + + sprintf(szBuffer, "%s -- ", ActorName); + WriteToBackBuffer(); + + sprintf(szBuffer, "HP %d/%d ", HPCur, HPMax); + WriteToBackBuffer(); + + if (MPMax > 0) + { + sprintf(szBuffer, "MP %d/%d ", MPCur, MPMax); + } + + sprintf(szBuffer, "ADDR 0x%x ", ActorPointer); + WriteToBackBuffer(); + + sprintf(szBuffer, "\n"); + WriteToBackBuffer(); + } + } + } +} + +void +PrintActorsData() +{ + sprintf(szBuffer, "\nACTIVE ACTORS:\n"); + WriteToBackBuffer(); + + actor_data ActorData; + u32 ActorPointerCur = OFFSET_ACTOR_DATA_POINTERS; + u32 ActorPointerNext = 0x000000; + + // sprintf(szBuffer, "ADDR 0x%x\n", ActorPointerCur); + // WriteToBackBuffer(); + + ReadNextActorPointer(&ActorPointerCur, &ActorPointerNext); + while (ActorPointerNext) + { + ReadActorData(&ActorData, ActorPointerNext); + + ReadActorName(ActorData.NamePointer); + + u16 HPCur = ActorData.HPCur; + u16 HPMax = ActorData.HPMax; + u16 MPCur = ActorData.MPCur; + u16 MPMax = ActorData.MPMax; + + if (GameStatus == GAME_STATUS_CUTSCENE && HPMax == 100 && + MPMax == 100) // cutscene + { + return; + } + + sprintf(szBuffer, "0x%x -- ", ActorPointerNext); + WriteToBackBuffer(); + + sprintf(szBuffer, "%s -- ", ActorName); + WriteToBackBuffer(); + + if (HPCur == 0) + { + sprintf(szBuffer, "Dead "); + WriteToBackBuffer(); + } + else + { + sprintf(szBuffer, "HP %d/%d ", HPCur, HPMax); + WriteToBackBuffer(); + + if (MPMax > 0) + { + sprintf(szBuffer, "MP %d/%d ", MPCur, MPMax); + WriteToBackBuffer(); + } + } + sprintf(szBuffer, "\n"); + WriteToBackBuffer(); + + ActorPointerCur = ActorPointerNext; + ReadNextActorPointer(&ActorPointerCur, &ActorPointerNext); + } +} + +void +WriteActorsData() +{ + FILE *fpActorsData = fopen("game_data/map/enemy_data.txt", "w"); + + fprintf(fpActorsData, "Active Enemies\n"); + + actor_data ActorData; + // Use this one if you want to include player data: + // u32 ActorPointerCur = OFFSET_ACTOR_DATA_POINTERS; + u32 ActorPointerCur = OFFSET_ACTOR_DATA_FIRST_NODE; + u32 ActorPointerNext = 0x000000; + + // sprintf(fpActorsData, "ADDR 0x%x\n", ActorPointerCur); + // WriteToBackBuffer(); + + ReadNextActorPointer(&ActorPointerCur, &ActorPointerNext); + while (ActorPointerNext) + { + ReadActorData(&ActorData, ActorPointerNext); + + ReadActorName(ActorData.NamePointer); + + u16 HPCur = ActorData.HPCur; + u16 HPMax = ActorData.HPMax; + u16 MPCur = ActorData.MPCur; + u16 MPMax = ActorData.MPMax; + + if (GameStatus == GAME_STATUS_CUTSCENE && HPMax == 100 && + MPMax == 100) // cutscene + { + return; + } + + // fprintf(fpActorsData, "0x%x -- ", ActorPointerNext); + + fprintf(fpActorsData, "%s -- ", ActorName); + + if (HPCur == 0) + { + fprintf(fpActorsData, "Dead "); + } + else + { + fprintf(fpActorsData, "HP %d/%d ", HPCur, HPMax); + + if (MPMax > 0) + { + fprintf(fpActorsData, "MP %d/%d ", MPCur, MPMax); + } + } + fprintf(fpActorsData, "\n"); + + ActorPointerCur = ActorPointerNext; + ReadNextActorPointer(&ActorPointerCur, &ActorPointerNext); + } + + fclose(fpActorsData); +} + +#endif + diff --git a/includes/vst_emulation.h b/includes/vst_emulation.h index 7ea27d0..fd9c09c 100644 --- a/includes/vst_emulation.h +++ b/includes/vst_emulation.h @@ -6,11 +6,81 @@ // EMU_OFFSET = PSX_OFFSET + EMU_BASE_ADDRESS - PSX_TO_EMU // PSX_OFFSET = PSX_TO_EMU + EMU_OFFSET - EMU_BASE_ADDRESS -#define PSX_TO_EPSXE_1925 0x7F974960 -#define PSX_TO_EPSXE_2050 0x7F57DFE0 +#define PSX_TO_EPSXE_1925 0x7f974960 +#define PSX_TO_EPSXE_2050 0x7f57dfe0 -#define PSX_TO_BIZHAWK_2320 0x7FEE2780 -#define PSX_TO_BIZHAWK_2410 0x7FCF2070 -#define PSX_TO_BIZHAWK_2420 0x7FCF2070 +#define PSX_TO_BIZHAWK_2320 0x7fee2780 +#define PSX_TO_BIZHAWK_2410 0x7fcf2070 +#define PSX_TO_BIZHAWK_2420 0x7fcf2070 +#define PSX_TO_BIZHAWK_2520 0x7fcef080 +#define PSX_TO_BIZHAWK_2610 0x7fcef080 + +// GameStatus flag: +// 1=Normal, +// 2=TargetSphere +// 3=CutScene +// 4=? +// 5=MenuScreen +// 6=QuickMenu +// 7=FirstPersonView +// 8=TrapPanel/HealPanel +// 9=TreasureChest/Container +// A=DrawingWeapon +// B=OperateLockedDoor +// C=? + +#define OFFSET_GAME_STATUS 0x800f196c + +#define GAME_STATUS_NORMAL 0x0001 +#define GAME_STATUS_BATTLE 0x0002 +#define GAME_STATUS_CUTSCENE 0x0003 +#define GAME_STATUS_MENU_SCREEN 0x0005 +#define GAME_STATUS_QUICK_MENU 0x0006 +#define GAME_STATUS_FP_VIEW 0x0007 +#define GAME_STATUS_ACTIVATE_PANEL 0x0008 +#define GAME_STATUS_OPEN_CONTAINER 0x0009 +#define GAME_STATUS_DRAW_WEAPON 0x000a +#define GAME_STATUS_USE_OPEN_DOOR 0x000b +#define GAME_STATUS_END_OF_TURN 0x000c + +char *GameStatusNameList[17] = { + "Normal", // 1 + "Battle", // 2 + "Cut-scene", // 3 + "???", // 4 + "Menu Screen", // 5 + "Quick Menu", // 6 + "First Person View", // 7 + "Activate Panel", // 8 + "Open Container", // 9 + "Draw Weapon", // 10 + "Use Locked Door", // 11 + "End of Turn", // 12 + "???", // 13 + "???", // 14 + "???", // 15 + "???", // 16 + "???" // 17 +}; + +void +ReadGameStatus(u16 *GameStatus) +{ + + usize BytesToRead = sizeof(u16); + + ReadGameMemory(processID, OFFSET_GAME_STATUS, BytesToRead, GameStatus); +} + +void +PrintGameStatus(u16 *GameStatus) +{ + sprintf(szBuffer, "\nGAME STATUS:\n"); + WriteToBackBuffer(); + + sprintf(szBuffer, "#%d -- %s\n", *GameStatus, + GameStatusNameList[*GameStatus - 1]); + WriteToBackBuffer(); +} #endif diff --git a/includes/vst_equipment.h b/includes/vst_equipment.h index ac6118f..c7b0ada 100644 --- a/includes/vst_equipment.h +++ b/includes/vst_equipment.h @@ -750,7 +750,7 @@ PrintBladeLeveling(u8 BladeNumber) default: { sprintf_s( - szBuffer, _countof(szBuffer), "\n\nNo leveling weapon equipped\n\n"); + szBuffer, _countof(szBuffer), "\nNo leveling weapon equipped\n\n"); WriteToBackBuffer(); } } diff --git a/includes/vst_gazette.h b/includes/vst_gazette.h index 5982cb5..172353d 100644 --- a/includes/vst_gazette.h +++ b/includes/vst_gazette.h @@ -184,7 +184,7 @@ ReadKillList() void PrintKillList() { - sprintf_s(szBuffer, _countof(szBuffer), "\n== KILL LIST ==\n\n"); + sprintf_s(szBuffer, _countof(szBuffer), "\nKILL LIST:\n"); WriteToBackBuffer(); sprintf_s(szBuffer, _countof(szBuffer), "Human: %5i\n", KillListCur.Human); WriteToBackBuffer(); @@ -239,7 +239,7 @@ ReadWeaponUsage() void PrintWeaponUsage() { - sprintf_s(szBuffer, _countof(szBuffer), "\n== WEAPON USAGE ==\n\n"); + sprintf_s(szBuffer, _countof(szBuffer), "\nWEAPON USAGE:\n"); WriteToBackBuffer(); sprintf_s(szBuffer, _countof(szBuffer), "Dagger: %5i\n", WeaponUsageCur.Dagger); @@ -558,7 +558,7 @@ void PrintChestCount(u8 *ChestCount) { u16 ChestCountScore = (*ChestCount * 100) / CHEST_COUNT_MAX; - sprintf_s(szBuffer, _countof(szBuffer), "\n\n== CHEST COUNT ==\n\n"); + sprintf_s(szBuffer, _countof(szBuffer), "\nCHEST COUNT:\n"); WriteToBackBuffer(); sprintf_s(szBuffer, _countof(szBuffer), "%i/%i ( %i%% )\n", *ChestCount, @@ -585,7 +585,7 @@ void PrintMapCount(u16 *MapCount) { u16 MapCountScore = (*MapCount * 100) / MAP_COUNT_MAX; - sprintf_s(szBuffer, _countof(szBuffer), "\n\n== ROOM COUNT ==\n\n"); + sprintf_s(szBuffer, _countof(szBuffer), "\nROOM COUNT:\n"); WriteToBackBuffer(); sprintf_s(szBuffer, _countof(szBuffer), "%i/%i ( %i%% )\n", *MapCount, @@ -608,4 +608,4 @@ WriteMapCount(u16 *MapCount) fclose(fpMapCount); } -#endif \ No newline at end of file +#endif diff --git a/includes/vst_init.h b/includes/vst_init.h index 6e15e16..d36c8c3 100644 --- a/includes/vst_init.h +++ b/includes/vst_init.h @@ -14,6 +14,8 @@ char szExeName[MAX_PATH]; // In-game data +u16 GameStatus; + // Time game_time GameTimeCur = { -1 }; game_time GameTimePrev = { -1 }; @@ -116,4 +118,11 @@ BOOL GameOver = FALSE; // set to TRUE when the last boss is dead // Input u16 ControllerInputCur; u16 ControllerInputPrev; + +buttons_timers ButtonsTimers; + +// Actors in the room +#define ACTOR_NAME_LENGTH 20 +char ActorName[ACTOR_NAME_LENGTH]; + #endif diff --git a/includes/vst_input.h b/includes/vst_input.h index fa8d2ea..f53ef50 100644 --- a/includes/vst_input.h +++ b/includes/vst_input.h @@ -3,6 +3,7 @@ // Controller input #define OFFSET_CONTROLLER_INPUT 0x8005E1C0 +#define OFFSET_BUTTONS_TIMERS 0x80055C90 #define MASK_CONTROLLER_INPUT_L2 0x0001 #define MASK_CONTROLLER_INPUT_R2 0x0002 @@ -68,12 +69,20 @@ ReadControllerInput(u16 *ControllerInput) processID, OFFSET_CONTROLLER_INPUT, BytesToRead, ControllerInput); } +void +ReadButtonsTimers(buttons_timers *ButtonsTimers) +{ + usize BytesToRead = sizeof(buttons_timers); + + ReadGameMemory(processID, OFFSET_BUTTONS_TIMERS, BytesToRead, ButtonsTimers); +} + void PrintControllerInput(u16 *ControllerInput) { u16 Input = *ControllerInput; - sprintf(szBuffer, "\n-- Controller Input --\n\n"); + sprintf(szBuffer, "\nCONTROLLER INPUT:\n"); WriteToBackBuffer(); if (!Input) // if the register is empty, skip to the end @@ -87,7 +96,8 @@ PrintControllerInput(u16 *ControllerInput) { if (ControllerInputMasks[i] & Input) { - sprintf(szBuffer, "%s ", ControllerInputNames[i]); + sprintf(szBuffer, "%s(%d) ", ControllerInputNames[i], + ButtonsTimers.Timers[i]); WriteToBackBuffer(); } } @@ -95,6 +105,7 @@ PrintControllerInput(u16 *ControllerInput) WriteToBackBuffer(); } } + void WriteControllerInput(u16 *ControllerInput) { diff --git a/includes/vst_location.h b/includes/vst_location.h index 00fee1d..b810d36 100644 --- a/includes/vst_location.h +++ b/includes/vst_location.h @@ -566,7 +566,7 @@ PrintLocation() u8 ZoneNumber = LocationCur.ZoneNumber; u8 MapNumber = LocationCur.MapNumber; - sprintf(szBuffer, "\n\n== LOCATION ==\n\n"); + sprintf(szBuffer, "\n\nLOCATION:\n"); WriteToBackBuffer(); sprintf_s(szBuffer, _countof(szBuffer), "%s, %s ( Zone %i, Map %i )\n", @@ -584,4 +584,4 @@ IsThisTheLastBossMap() return FALSE; } -#endif \ No newline at end of file +#endif diff --git a/includes/vst_player.h b/includes/vst_player.h index 8788a0e..a6151f1 100644 --- a/includes/vst_player.h +++ b/includes/vst_player.h @@ -14,7 +14,7 @@ #define OFFSET_PLAYER_PTR_00_SHP_HDR 0x8011FA34 // ptr00ShpHdr #define OFFSET_PLAYER_PTR_WEAPON_WEP_HDR 0x8011FA38 // ptrWeaponWEPHdr #define OFFSET_PLAYER_PTR_00_SHP_DATA 0x8011FA3C // ptr00ShpData -#define OFFSET_PLAYER_CHARACTER_NAME \ +#define OFFSET_PLAYER_CHARACTER_NAME \ 0x8011FA40 // CharacterName $18str "Ashley Riot" // Main stats @@ -29,7 +29,7 @@ #define OFFSET_PLAYER_INT_ORIGINAL 0x8011FA68 // OriginalINT #define OFFSET_PLAYER_AGL_EQUIPPED 0x8011FA6A // EquippedAGL #define OFFSET_PLAYER_AGL_ORIGINAL 0x8011FA6C // OriginalAGL -#define OFFSET_PLAYER_WALKING_SPEED_WITH_BOX \ +#define OFFSET_PLAYER_WALKING_SPEED_WITH_BOX \ 0x8011FA71 // WalkingSpeedWhenCarryingBoxes #define OFFSET_PLAYER_RUNNING_SPEED 0x8011FA73 // RunningSpeed #define OFFSET_PLAYER_RANGE 0x8011FA78 // range @@ -111,8 +111,8 @@ u32 StatusEffectMasks[32] = { // void ReadPlayerStats(player_stats *PlayerStats) { - usize Offset = - (usize)(OFFSET_PLAYER_HP_CURRENT - PSX_TO_EMU + processBaseAddress); + // usize Offset = + // (usize)(OFFSET_PLAYER_HP_CURRENT - PSX_TO_EMU + processBaseAddress); usize BytesToRead = sizeof(player_stats); @@ -204,7 +204,7 @@ PrintPlayerStats(player_stats *PlayerStats) AGL_Buff = '-'; } - sprintf(szBuffer, "\n\n== PLAYER STATS ==\n\n"); + sprintf(szBuffer, "\n\nPLAYER STATS:\n"); WriteToBackBuffer(); sprintf(szBuffer, @@ -238,7 +238,7 @@ PrintPlayerEffects(status_effects *PlayerEffects) { status_effects Effects = *PlayerEffects; - sprintf(szBuffer, "\n-- Status Effects --\n\n"); + sprintf(szBuffer, "\nSTATUS EFFECTS:\n"); WriteToBackBuffer(); u32 StatusEffectMask = Effects.EffectID; diff --git a/includes/vst_time.h b/includes/vst_time.h index 337f713..509ac75 100644 --- a/includes/vst_time.h +++ b/includes/vst_time.h @@ -12,7 +12,7 @@ PrintGameTimeShort(game_time *GameTime) u8 Minutes = GameTime->Minutes; u8 Hours = GameTime->Hours; - sprintf_s(szBuffer, _countof(szBuffer), "\n\n== GAME TIME ==\n\n"); + sprintf_s(szBuffer, _countof(szBuffer), "\nGAME TIME:\n"); WriteToBackBuffer(); sprintf_s(szBuffer, _countof(szBuffer), "%02i:%02i:%02i\n", Hours, Minutes, @@ -27,7 +27,7 @@ PrintGameTimeRecord(game_time *RecordTime) u8 Minutes = RecordTime->Minutes; u8 Hours = RecordTime->Hours; - fprintf(stdout, "\n== RECORD TIME ==\n\n"); + fprintf(stdout, "\nRECORD TIME:\n"); fprintf(stdout, "%02i:%02i:%02i\n", Hours, Minutes, Seconds); } @@ -101,4 +101,4 @@ IsItLater(game_time *TimeOld, game_time *TimeNew) return New > Old; } -#endif \ No newline at end of file +#endif diff --git a/includes/vst_translate.h b/includes/vst_translate.h index 2bc7c81..e88cb79 100644 --- a/includes/vst_translate.h +++ b/includes/vst_translate.h @@ -22,7 +22,7 @@ char TranslationTableChars[125] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'Â', 'Ä', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Î', 'Ò', 'Ó', 'Ô', 'Ö', 'Ù', 'Ú', 'Û', 'Ü', 'ß', 'æ', 'à', 'á', 'â', 'ä', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ò', 'ó', 'ô', 'ö', 'ù', - 'ú', 'û', 'ü', ' ', '!', '"', '%', '\'', '(', ')', '{', '}', '[', ']', ';', + 'ú', 'û', 'u', ' ', '!', '"', '%', '\'', '(', ')', '{', '}', '[', ']', ';', ':', ',', '.', '/', '\\', '<', '>', '?', '-', '+', '\n' }; void @@ -69,6 +69,44 @@ ReadWeaponName() } } +void +ReadActorName(u32 NameOffset) +{ + ActorName[0] = '\0'; + + char ActorNameHex[ACTOR_NAME_LENGTH]; + usize BytesToRead = (usize) ACTOR_NAME_LENGTH; + + usize BytesRead = + ReadGameMemory(processID, NameOffset, BytesToRead, ActorNameHex); + + for (int i = 0, k = 0; i < ACTOR_NAME_LENGTH; ++i) + { + u8 *HexCode = (u8 *) &ActorNameHex[i]; + if (*HexCode == 0xE7 || *HexCode == 0x00) + { + ActorName[k] = '\0'; + break; + } + + if (*HexCode == 0xFA && *(HexCode + 1) == 0x06) + { + ActorName[k++] = ' '; + i++; + continue; + } + + for (int j = 0, size = _countof(TranslationTableHex); j < size; ++j) + { + if (TranslationTableHex[j] == (char) *HexCode) + { + ActorName[k++] = TranslationTableChars[j]; + break; + } + } + } +} + void ReadWeaponNumber() { @@ -95,8 +133,8 @@ void PrintWeaponName() { sprintf_s( - szBuffer, _countof(szBuffer), "\n\nWeapon name: %s\n\n", nameWeaponCur); + szBuffer, _countof(szBuffer), "\nWEAPON NAME:\n%s\n", nameWeaponCur); WriteToBackBuffer(); } -#endif \ No newline at end of file +#endif diff --git a/includes/vst_types.h b/includes/vst_types.h index 07b0d19..34c2859 100644 --- a/includes/vst_types.h +++ b/includes/vst_types.h @@ -275,4 +275,69 @@ typedef struct u8 Map; } map_flag_check; +/* +#pragma pack(push, 1) +typedef struct +{ + u32 L2; + u32 R2; + u32 L1; + u32 R1; + u32 Triangle; + u32 Circle; + u32 Cross; + u32 Square; + u32 Select; + u32 L3; + u32 R3; + u32 Start; + u32 Up; + u32 Right; + u32 Down; + u32 Left; +} buttons_timers; +#pragma pack(pop) +*/ + +#pragma pack(push, 1) +typedef struct +{ + u32 Timers[16]; +} buttons_timers; +#pragma pack(pop) + +#pragma pack(push, 1) +typedef struct +{ + u32 NextActorPtr; // 0 + u8 _padding1[40]; // 4 + u16 PosX; // 44 (0x2c) + u16 PosY; // 46 (0x2e) + u8 _padding2[12]; // 48 (0x30) + u32 NamePointer; // 60 (0x3c) + u8 _padding3[16]; // 64 (0x40) + char Name[20]; // 80 (0x50) + u8 _padding4[4]; // 100 (0x64) + u16 HPCur; // 104 (0x68) + u16 HPMax; // 106 (0x6a) + u16 MPCur; // 108 (0x6c) + u16 MPMax; // 110 (0x6e) + u16 Risk; // 112 (0x70) + u16 STRCur; // 114 (0x72) + u16 STRMax; // 116 (0x74) + u16 INTCur; // 118 (0x76) + u16 INTMax; // 120 (0x78) + u16 AGLCur; // 122 (0x7a) + u16 AGLMax; // 124 (0x7c) + u8 _padding5[14]; // 126 (0x7e) + char WeaponName[18]; // 140 (0x8c) +} actor_data; +#pragma pack(pop) + +typedef struct +{ + u32 ActorPointer; + BOOL IsDead; +} actor_status; + #endif diff --git a/main.c b/main.c index 422bb2d..12eeb28 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -16,6 +17,7 @@ #include "includes/vst_time.h" #include "includes/vst_player.h" #include "includes/vst_input.h" +#include "includes/vst_actors.h" #include "includes/vst_location.h" #include "includes/vst_gazette.h" #include "includes/vst_debug.h" @@ -37,7 +39,7 @@ main(int argc, char *argv[]) fprintf(stdout, "1. ePSXe 1.9.25\n"); fprintf(stdout, "2. ePSXe 2.0.50\n"); - fprintf(stdout, "3. BizHawk 2.4.2\n\n"); + fprintf(stdout, "3. BizHawk 2.6.1\n\n"); fprintf(stdout, "0. Exit\n\n"); scanf_s("%2s", ver_s, (unsigned) _countof(ver_s)); @@ -75,7 +77,7 @@ main(int argc, char *argv[]) } case 3: { - PSX_TO_EMU = PSX_TO_BIZHAWK_2420; + PSX_TO_EMU = PSX_TO_BIZHAWK_2610; sprintf_s(szExeName, MAX_PATH, "EmuHawk.exe"); sprintf_s(szModuleName, MAX_PATH, "octoshock.dll"); break; @@ -167,6 +169,11 @@ main(int argc, char *argv[]) GameTimePrev = GameTimeCur; ReadGameTime(&GameTimeCur); + // GAME STATUS + ReadGameStatus(&GameStatus); +#ifdef DEBUG + PrintGameStatus(&GameStatus); +#endif // Check if the time progressed if (GameTimeChanged(&GameTimePrev, &GameTimeCur)) { @@ -232,8 +239,11 @@ main(int argc, char *argv[]) WriteLocation(); } #ifdef DEBUG - PrintLocation(); + // PrintLocation(); + PrintActorsData(); #endif + // ACTORS IN THE ROOM + WriteActorsData(); // STATS statsPlayerPrev = statsPlayerCur; @@ -243,7 +253,7 @@ main(int argc, char *argv[]) WritePlayerStats(&statsPlayerCur); } #ifdef DEBUG - PrintPlayerStats(&statsPlayerCur); + // PrintPlayerStats(&statsPlayerCur); #endif effectsPlayerPrev = effectsPlayerCur; @@ -256,13 +266,13 @@ main(int argc, char *argv[]) #ifdef DEBUG PrintPlayerEffects(&effectsPlayerCur); #endif - + ReadButtonsTimers(&ButtonsTimers); ControllerInputPrev = ControllerInputCur; ReadControllerInput(&ControllerInputCur); - if (ControllerInputChanged()) - { - WriteControllerInput(&ControllerInputCur); - } + // if (ControllerInputChanged()) + // { + // WriteControllerInput(&ControllerInputCur); + // } #ifdef DEBUG PrintControllerInput(&ControllerInputCur); #endif @@ -321,7 +331,7 @@ main(int argc, char *argv[]) #ifdef DEBUG sprintf_s( - szBuffer, _countof(szBuffer), "Weapon number: %zi\n", WeaponNumber); + szBuffer, _countof(szBuffer), "WEAPON NUMBER: %zi\n", WeaponNumber); WriteToBackBuffer(); #endif @@ -391,10 +401,9 @@ main(int argc, char *argv[]) } else { - sprintf_s(szBuffer, _countof(szBuffer), "============================\n" - "== VSTracker v0.3.3-alpha ==\n" + "== VSTracker v0.4.0-alpha ==\n" "============================\n"); WriteToBackBuffer(); diff --git a/makefile b/makefile new file mode 100644 index 0000000..9cfd643 --- /dev/null +++ b/makefile @@ -0,0 +1,6 @@ +main.obj: main.c + cl /c /nologo /DDEBUG /Zi main.c +vst.exe: main.obj + @cl main.c /Fe: vst /DDEBUG /nologo /Zi /link user32.lib psapi.lib Wtsapi32.lib Advapi32.lib + @echo Bulding and linking... +