From 03f0367ef6411bb344ff79bc1ebb486d3ed20300 Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Sat, 27 Apr 2024 09:19:33 +0200 Subject: [PATCH] port Inv_Display --- docs/progress.svg | 76 ++--- docs/progress.txt | 100 +++--- src/decomp/decomp.c | 11 +- src/game/inventory.c | 668 ++++++++++++++++++++++++++++++++++++++++- src/game/inventory.h | 5 +- src/global/const.h | 1 + src/global/funcs.h | 31 +- src/global/types.h | 84 +++++- src/global/vars.h | 44 +-- src/inject_exec.c | 1 + src/specific/s_input.c | 2 +- 11 files changed, 881 insertions(+), 142 deletions(-) diff --git a/docs/progress.svg b/docs/progress.svg index 78e38084..a127e13e 100644 --- a/docs/progress.svg +++ b/docs/progress.svg @@ -69,10 +69,10 @@ Tomb2.exe progress according to the physical function order: -36.70% (447) · 60.84% (741) · 0.41% (5) · 2.05% (25) +36.78% (448) · 60.76% (740) · 0.41% (5) · 2.05% (25) - - + + @@ -403,7 +403,7 @@ void __cdecl Overlay_AddDisplayPickup(int16_t obj_num); void __cdecl Overlay_DisplayModeInfo(char* string); void __cdecl Overlay_DrawModeInfo(void); -int32_t __cdecl Inv_Display(int32_t inventory_mode); +int32_t __cdecl Inv_Display(int32_t inventory_mode); void __cdecl Inv_Construct(void); void __cdecl Inv_SelectMeshes(INVENTORY_ITEM *inv_item); int32_t __cdecl Inv_AnimateInventoryItem(INVENTORY_ITEM *inv_item); @@ -423,21 +423,21 @@ int32_t __cdecl Inv_RemoveItem(int32_t item_num); int32_t __cdecl Inv_GetItemOption(int32_t item_num); void __cdecl RemoveInventoryText(void); -void __cdecl Inv_RingInit(RING_INFO *ring, int16_t type, INVENTORY_ITEM **list, int16_t qty, int16_t current, IMOTION_INFO *imo); -void __cdecl Inv_RingGetView(RING_INFO *ring, PHD_3DPOS *viewer); -void __cdecl Inv_RingLight(RING_INFO *ring); -void __cdecl Inv_RingCalcAdders(RING_INFO *ring, int16_t rotation_duration); -void __cdecl Inv_RingDoMotions(RING_INFO *ring); -void __cdecl Inv_RingRotateLeft(RING_INFO *ring); -void __cdecl Inv_RingRotateRight(RING_INFO *ring); -void __cdecl Inv_RingMotionInit(RING_INFO *ring, int16_t frames, int16_t status, int16_t status_target); -void __cdecl Inv_RingMotionSetup(RING_INFO *ring, int16_t status, int16_t status_target, int16_t frames); -void __cdecl Inv_RingMotionRadius(RING_INFO *ring, int16_t target); -void __cdecl Inv_RingMotionRotation(RING_INFO *ring, int16_t rotation, int16_t target); -void __cdecl Inv_RingMotionCameraPos(RING_INFO *ring, int16_t target); -void __cdecl Inv_RingMotionCameraPitch(RING_INFO *ring, int16_t target); -void __cdecl Inv_RingMotionItemSelect(RING_INFO *ring, INVENTORY_ITEM *inv_item); -void __cdecl Inv_RingMotionItemDeselect(RING_INFO *ring, INVENTORY_ITEM *inv_item); +void __cdecl Inv_Ring_Init(RING_INFO *ring, int16_t type, INVENTORY_ITEM **list, int16_t qty, int16_t current, IMOTION_INFO *imo); +void __cdecl Inv_Ring_GetView(RING_INFO *ring, PHD_3DPOS *viewer); +void __cdecl Inv_Ring_Light(RING_INFO *ring); +void __cdecl Inv_Ring_CalcAdders(RING_INFO *ring, int16_t rotation_duration); +void __cdecl Inv_Ring_DoMotions(RING_INFO *ring); +void __cdecl Inv_Ring_RotateLeft(RING_INFO *ring); +void __cdecl Inv_Ring_RotateRight(RING_INFO *ring); +void __cdecl Inv_Ring_MotionInit(RING_INFO *ring, int16_t frames, int16_t status, int16_t status_target); +void __cdecl Inv_Ring_MotionSetup(RING_INFO *ring, int16_t status, int16_t status_target, int16_t frames); +void __cdecl Inv_Ring_MotionRadius(RING_INFO *ring, int16_t target); +void __cdecl Inv_Ring_MotionRotation(RING_INFO *ring, int16_t rotation, int16_t target); +void __cdecl Inv_Ring_MotionCameraPos(RING_INFO *ring, int16_t target); +void __cdecl Inv_Ring_MotionCameraPitch(RING_INFO *ring, int16_t target); +void __cdecl Inv_Ring_MotionItemSelect(RING_INFO *ring, INVENTORY_ITEM *inv_item); +void __cdecl Inv_Ring_MotionItemDeselect(RING_INFO *ring, INVENTORY_ITEM *inv_item); void __cdecl Init_Requester(REQUEST_INFO *req); void __cdecl Remove_Requester(REQUEST_INFO *req); void __cdecl ReqItemCentreAlign(REQUEST_INFO *req, TEXTSTRING *txt); @@ -1299,16 +1299,16 @@ Tomb2.exe progress according to the function sizes: -33.17% · 66.50% · 0% · 0.32% +34.49% · 65.18% · 0% · 0.32% - - + + void __cdecl Output_WGTMapPersp32FP(int32_t y1, int32_t y2, uint8_t *tex_page); -int32_t __cdecl Inv_Display(int32_t inventory_mode); +int32_t __cdecl Inv_Display(int32_t inventory_mode); void __cdecl BaddyObjects(void); void __cdecl Output_GTMapPersp32FP(int32_t y1, int32_t y2, uint8_t *tex_page); void __cdecl Lara_Draw(ITEM_INFO *item); @@ -1599,7 +1599,7 @@ void __cdecl Output_DrawClippedPoly_Textured(int32_t vtx_count); void __cdecl DoSnowEffect(ITEM_INFO *skidoo); void __cdecl Lara_UseItem(int16_t object_num); -void __cdecl Inv_RingDoMotions(RING_INFO *ring); +void __cdecl Inv_Ring_DoMotions(RING_INFO *ring); void __cdecl DartEmitterControl(int16_t item_num); void __cdecl Output_InsertTransQuad_Sorted(int32_t x, int32_t y, int32_t width, int32_t height, int32_t z); void __cdecl WaterFall(int16_t fx_num); @@ -1645,7 +1645,7 @@ int32_t __cdecl Game_Cutscene_Start(int32_t level_num); int32_t __cdecl Inv_RemoveItem(int32_t item_num); int16_t __cdecl TitleSequence(void); -void __cdecl Inv_RingInit(RING_INFO *ring, int16_t type, INVENTORY_ITEM **list, int16_t qty, int16_t current, IMOTION_INFO *imo); +void __cdecl Inv_Ring_Init(RING_INFO *ring, int16_t type, INVENTORY_ITEM **list, int16_t qty, int16_t current, IMOTION_INFO *imo); void __cdecl ScreenshotPCX(void); bool __cdecl S_Audio_Sample_Load(int32_t sample_id, LPWAVEFORMATEX format, const void *data, int32_t data_size); void __cdecl Lara_State_Compress(ITEM_INFO *item, COLL_INFO *coll); @@ -2022,8 +2022,8 @@ void __thiscall SE_DrawBitmap(BITMAP_RESOURCE *bmpRsrc, HDC hdc, int32_t x, int32_t y); void __cdecl swap_meshes_with_meshswap1(ITEM_INFO *item); void __cdecl swap_meshes_with_meshswap2(ITEM_INFO *item); -void __cdecl Inv_RingMotionInit(RING_INFO *ring, int16_t frames, int16_t status, int16_t status_target); -void __cdecl Inv_RingMotionItemDeselect(RING_INFO *ring, INVENTORY_ITEM *inv_item); +void __cdecl Inv_Ring_MotionInit(RING_INFO *ring, int16_t frames, int16_t status, int16_t status_target); +void __cdecl Inv_Ring_MotionItemDeselect(RING_INFO *ring, INVENTORY_ITEM *inv_item); void __cdecl InitialiseStartInfo(void); void __cdecl IncreaseScreenSize(void); void __cdecl DecreaseScreenSize(void); @@ -2032,7 +2032,7 @@ int32_t __cdecl Music_GetFrames(void); bool __cdecl SE_RegisterSetupWindowClass(void); void __fastcall Output_FlatA(int32_t y0, int32_t y1, uint8_t color_idx); // actually, __watcall, which is esoteric and rarely supported -void __cdecl Inv_RingGetView(RING_INFO *ring, PHD_3DPOS *viewer); +void __cdecl Inv_Ring_GetView(RING_INFO *ring, PHD_3DPOS *viewer); void __cdecl Lara_State_SurfLeft(ITEM_INFO *item, COLL_INFO *coll); void __cdecl Lara_State_SurfRight(ITEM_INFO *item, COLL_INFO *coll); BOOL __cdecl LoadCameras(HANDLE handle); @@ -2046,7 +2046,7 @@ bool __cdecl GetRegistryDwordValue(LPCTSTR lpValueName, DWORD *pValue, DWORD defaultValue); void __cdecl Item_UpdateRoom(ITEM_INFO *item, int32_t height); void __cdecl ControlBirdTweeter(int16_t item_num); -void __cdecl Inv_RingMotionItemSelect(RING_INFO *ring, INVENTORY_ITEM *inv_item); +void __cdecl Inv_Ring_MotionItemSelect(RING_INFO *ring, INVENTORY_ITEM *inv_item); void __cdecl Lara_Col_ClimbLeft(ITEM_INFO *item, COLL_INFO *coll); void __cdecl BaddieBiteEffect(ITEM_INFO *item, BITE_INFO *bite); LRESULT __stdcall SE_NewPropSheetWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); @@ -2165,7 +2165,7 @@ void __cdecl WinVidSetMinWindowSize(int32_t width, int32_t height); void __cdecl WinVidSetMaxWindowSize(int32_t width, int32_t height); void __cdecl lara_normal_effect(ITEM_INFO *item); -void __cdecl Inv_RingLight(RING_INFO *ring); +void __cdecl Inv_Ring_Light(RING_INFO *ring); void __cdecl Lara_State_FastFall(ITEM_INFO *item, COLL_INFO *coll); void __cdecl InitialiseSkidoo(int16_t item_num); bool __cdecl WinVidInit(void); @@ -2295,8 +2295,8 @@ BOOL __cdecl OpenRegistryKey(LPCTSTR lpSubKey); void __cdecl Creature_Initialise(int16_t item_num); int32_t __cdecl Room_FindGridShift(int32_t src, int32_t dst); -void __cdecl Inv_RingRotateLeft(RING_INFO *ring); -void __cdecl Inv_RingRotateRight(RING_INFO *ring); +void __cdecl Inv_Ring_RotateLeft(RING_INFO *ring); +void __cdecl Inv_Ring_RotateRight(RING_INFO *ring); void __cdecl Lara_State_SwanDive(ITEM_INFO *item, COLL_INFO *coll); void __cdecl BridgeTilt2Floor(ITEM_INFO *item, int32_t x, int32_t y, int32_t z, int32_t *height); sub_4471C0 @@ -2309,8 +2309,8 @@ void __cdecl WinInStart(void); void __cdecl ChandelierFX(ITEM_INFO *item); void __cdecl Overlay_DrawModeInfo(void); -void __cdecl Inv_RingCalcAdders(RING_INFO *ring, int16_t rotation_duration); -void __cdecl Inv_RingMotionSetup(RING_INFO *ring, int16_t status, int16_t status_target, int16_t frames); +void __cdecl Inv_Ring_CalcAdders(RING_INFO *ring, int16_t rotation_duration); +void __cdecl Inv_Ring_MotionSetup(RING_INFO *ring, int16_t status, int16_t status_target, int16_t frames); void __cdecl Lara_State_Fallback(ITEM_INFO *item, COLL_INFO *coll); void __cdecl InitialiseMovingBlock(int16_t item_num); void __cdecl DrawBridgeCollision(int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll); @@ -2339,13 +2339,13 @@ void __cdecl InitialiseLevelFlags(void); void __cdecl Text_Draw(void); void __cdecl S_FadeOutInventory(BOOL isFade); -void __cdecl Inv_RingMotionRadius(RING_INFO *ring, int16_t target); +void __cdecl Inv_Ring_MotionRadius(RING_INFO *ring, int16_t target); LPCTSTR __cdecl GetFullPath(LPCTSTR file_name); void __cdecl ScreenClear(bool is_phd_win_size); int32_t __cdecl S_Audio_Sample_CalculateSamplePan(int16_t pan); void __cdecl FreeTexturePages(void); void __cdecl SE_PassMessageToImage(HWND hWnd, UINT uMsg, WPARAM wParam); -void __cdecl Inv_RingMotionCameraPos(RING_INFO *ring, int16_t target); +void __cdecl Inv_Ring_MotionCameraPos(RING_INFO *ring, int16_t target); int32_t __cdecl Text_Remove(TEXTSTRING *string); HRESULT __cdecl WinVidBufferUnlock(LPDDS surface, LPDDSDESC desc); LPDIRECT3DTEXTURE2 __cdecl Create3DTexture(LPDDS surface); @@ -2370,7 +2370,7 @@ uint16_t __cdecl S_COLOUR(int32_t red, int32_t green, int32_t blue); void __cdecl FreePalette(int32_t palette_idx); void __cdecl Matrix_Pop_I(void); -void __cdecl Inv_RingMotionRotation(RING_INFO *ring, int16_t rotation, int16_t target); +void __cdecl Inv_Ring_MotionRotation(RING_INFO *ring, int16_t rotation, int16_t target); void __cdecl DrawMovableBlock(ITEM_INFO *item); void __cdecl WinVidFreeWindow(void); bool __cdecl DInputCreate(void); @@ -2378,7 +2378,7 @@ void __cdecl Lara_InitialiseLoad(int16_t item_num); void __cdecl init_game_malloc(void); void __cdecl S_SetupAboveWater(BOOL underwater); -void __cdecl Inv_RingMotionCameraPitch(RING_INFO *ring, int16_t target); +void __cdecl Inv_Ring_MotionCameraPitch(RING_INFO *ring, int16_t target); void __cdecl SafeFreeTexturePage(int32_t page_idx); void __cdecl AssaultStop(ITEM_INFO *item); int32_t __cdecl GF_DoFrontEndSequence(void); diff --git a/docs/progress.txt b/docs/progress.txt index 821fc4e8..77f16fff 100644 --- a/docs/progress.txt +++ b/docs/progress.txt @@ -653,6 +653,12 @@ typedef PICKUP_INFO { int16_t sprite; } PICKUP_INFO; +typedef enum { + RT_MAIN, + RT_OPTION, + RT_KEYS, +} RING_TYPE; + typedef enum INVENTORY_MODE { INV_GAME_MODE, INV_TITLE_MODE, @@ -1642,7 +1648,24 @@ typedef enum GAME_OBJECT_ID { O_NUMBER_OF = 265, } GAME_OBJECT_ID; -typedef struct imotion_info { +typedef enum { + RNG_OPENING = 0, + RNG_OPEN = 1, + RNG_CLOSING = 2, + RNG_MAIN2OPTION = 3, + RNG_MAIN2KEYS = 4, + RNG_KEYS2MAIN = 5, + RNG_OPTION2MAIN = 6, + RNG_SELECTING = 7, + RNG_SELECTED = 8, + RNG_DESELECTING = 9, + RNG_DESELECT = 10, + RNG_CLOSING_ITEM = 11, + RNG_EXITING_INVENTORY = 12, + RNG_DONE = 13, +} RING_STATUS; + +typedef struct { int16_t count; int16_t status; int16_t status_target; @@ -2064,7 +2087,7 @@ typedef struct { 00422050 0000002C + void __cdecl Overlay_DrawModeInfo(void); # game/inventory.c -00422080 0000119E - int32_t __cdecl Inv_Display(int32_t inventory_mode); +00422080 0000119E + int32_t __cdecl Inv_Display(int32_t inventory_mode); 00423310 00000156 + void __cdecl Inv_Construct(void); 00423470 00000089 - void __cdecl Inv_SelectMeshes(INVENTORY_ITEM *inv_item); 00423500 00000081 - int32_t __cdecl Inv_AnimateInventoryItem(INVENTORY_ITEM *inv_item); @@ -2086,21 +2109,21 @@ typedef struct { 00424CD0 00000110 -R int32_t __cdecl Inv_RemoveItem(int32_t item_num); 00424DE0 000000C1 -R int32_t __cdecl Inv_GetItemOption(int32_t item_num); 00424FD0 00000024 -R void __cdecl RemoveInventoryText(void); -00425000 0000010F -R void __cdecl Inv_RingInit(RING_INFO *ring, int16_t type, INVENTORY_ITEM **list, int16_t qty, int16_t current, IMOTION_INFO *imo); -00425110 00000060 -R void __cdecl Inv_RingGetView(RING_INFO *ring, PHD_3DPOS *viewer); -00425170 00000040 -R void __cdecl Inv_RingLight(RING_INFO *ring); -004251B0 0000002C -R void __cdecl Inv_RingCalcAdders(RING_INFO *ring, int16_t rotation_duration); -004251E0 0000013E -R void __cdecl Inv_RingDoMotions(RING_INFO *ring); -00425320 0000002F -R void __cdecl Inv_RingRotateLeft(RING_INFO *ring); -00425350 0000002F -R void __cdecl Inv_RingRotateRight(RING_INFO *ring); -00425380 00000063 -R void __cdecl Inv_RingMotionInit(RING_INFO *ring, int16_t frames, int16_t status, int16_t status_target); -004253F0 0000002C -R void __cdecl Inv_RingMotionSetup(RING_INFO *ring, int16_t status, int16_t status_target, int16_t frames); -00425420 00000026 -R void __cdecl Inv_RingMotionRadius(RING_INFO *ring, int16_t target); -00425450 00000022 -R void __cdecl Inv_RingMotionRotation(RING_INFO *ring, int16_t rotation, int16_t target); -00425480 00000025 -R void __cdecl Inv_RingMotionCameraPos(RING_INFO *ring, int16_t target); -004254B0 00000020 -R void __cdecl Inv_RingMotionCameraPitch(RING_INFO *ring, int16_t target); -004254D0 0000005D -R void __cdecl Inv_RingMotionItemSelect(RING_INFO *ring, INVENTORY_ITEM *inv_item); -00425530 00000063 -R void __cdecl Inv_RingMotionItemDeselect(RING_INFO *ring, INVENTORY_ITEM *inv_item); +00425000 0000010F -R void __cdecl Inv_Ring_Init(RING_INFO *ring, int16_t type, INVENTORY_ITEM **list, int16_t qty, int16_t current, IMOTION_INFO *imo); +00425110 00000060 -R void __cdecl Inv_Ring_GetView(RING_INFO *ring, PHD_3DPOS *viewer); +00425170 00000040 -R void __cdecl Inv_Ring_Light(RING_INFO *ring); +004251B0 0000002C -R void __cdecl Inv_Ring_CalcAdders(RING_INFO *ring, int16_t rotation_duration); +004251E0 0000013E -R void __cdecl Inv_Ring_DoMotions(RING_INFO *ring); +00425320 0000002F -R void __cdecl Inv_Ring_RotateLeft(RING_INFO *ring); +00425350 0000002F -R void __cdecl Inv_Ring_RotateRight(RING_INFO *ring); +00425380 00000063 -R void __cdecl Inv_Ring_MotionInit(RING_INFO *ring, int16_t frames, int16_t status, int16_t status_target); +004253F0 0000002C -R void __cdecl Inv_Ring_MotionSetup(RING_INFO *ring, int16_t status, int16_t status_target, int16_t frames); +00425420 00000026 -R void __cdecl Inv_Ring_MotionRadius(RING_INFO *ring, int16_t target); +00425450 00000022 -R void __cdecl Inv_Ring_MotionRotation(RING_INFO *ring, int16_t rotation, int16_t target); +00425480 00000025 -R void __cdecl Inv_Ring_MotionCameraPos(RING_INFO *ring, int16_t target); +004254B0 00000020 -R void __cdecl Inv_Ring_MotionCameraPitch(RING_INFO *ring, int16_t target); +004254D0 0000005D -R void __cdecl Inv_Ring_MotionItemSelect(RING_INFO *ring, INVENTORY_ITEM *inv_item); +00425530 00000063 -R void __cdecl Inv_Ring_MotionItemDeselect(RING_INFO *ring, INVENTORY_ITEM *inv_item); # game/invtext.c 004255A0 00000082 -R void __cdecl Init_Requester(REQUEST_INFO *req); @@ -3034,11 +3057,11 @@ typedef struct { 004642E8 - int16_t g_GF_NumSecrets = 3; 00464310 - int16_t g_CineTargetAngle = 0x4000; // PHD_90 004644E0 - int32_t g_OverlayStatus = 1; -004654E0 - int16_t g_InvMainObjectsCount = 8; -00465604 - int16_t g_InvOptionObjectsCount = 4; +004654E0 - int16_t g_Inv_MainObjectsCount = 8; +00465604 - int16_t g_Inv_OptionObjectsCount = 4; 00465618 - BOOL g_GymInvOpenEnabled = TRUE; -00465A50 - int16_t g_InventoryChosen = -1; -00465A54 - INVENTORY_MODE g_InventoryMode = INV_TITLE_MODE; +00465A50 - int16_t g_Inv_Chosen = -1; +00465A54 - INVENTORY_MODE g_Inv_Mode = INV_TITLE_MODE; 00465A5C - int16_t g_OptionSoundVolume = 165; // NOTE: value should be 10 00465A60 - int16_t g_OptionMusicVolume = 255; // NOTE: should be 10 00465AD4 - int32_t g_JumpPermitted = 1; @@ -3147,8 +3170,8 @@ typedef struct { 004D77A4 - BOOL g_StopInventory; 004D77AC - BOOL g_IsDemoLevelType; 004D77B0 - BOOL g_IsDemoLoaded; -004D77C0 - int g_BoundStart; -004D77C4 - int g_BoundEnd; +004D77C0 - int32_t g_BoundStart; +004D77C4 - int32_t g_BoundEnd; 004D77E0 - int32_t g_IsAssaultTimerDisplay; 004D77E4 - BOOL g_IsAssaultTimerActive; 004D77E8 - BOOL g_IsMonkAngry; @@ -3160,21 +3183,20 @@ typedef struct { 004D792C - TEXTSTRING *g_AmmoTextInfo; 004D7930 - TEXTSTRING *g_DisplayModeTextInfo; 004D7934 - DWORD g_DisplayModeInfoTimer; -004D7938 - UINT16 g_InvMainCurrent; -004D793C - UINT16 g_InvKeyObjectsCount; -004D7940 - UINT16 g_InvKeysCurrent; -004D7944 - UINT16 g_InvOptionCurrent; -004D7954 - TEXTSTRING* g_InvRingText; -004D795C - TEXTSTRING* g_InvUpArrow1; -004D7960 - TEXTSTRING* g_InvUpArrow2; -004D7964 - TEXTSTRING* g_InvDownArrow1; -004D7968 - TEXTSTRING* g_InvDownArrow2; +004D7938 - UINT16 g_Inv_MainCurrent; +004D793C - UINT16 g_Inv_KeyObjectsCount; +004D7940 - UINT16 g_Inv_KeysCurrent; +004D7944 - UINT16 g_Inv_OptionCurrent; +004D7954 - TEXTSTRING* g_Inv_RingText; +004D795C - TEXTSTRING* g_Inv_UpArrow1; +004D7960 - TEXTSTRING* g_Inv_UpArrow2; +004D7964 - TEXTSTRING* g_Inv_DownArrow1; +004D7968 - TEXTSTRING* g_Inv_DownArrow2; 004D796C - uint32_t g_InputDB; -004D7978 - uint16_t g_IsInventoryActive; -004D7978 - uint16_t g_IsInventoryActive; -004D79A0 - BOOL g_InvDemoMode; -004D79B4 - BOOL g_IsInvOptionsDelay; -004D79B8 - int32_t g_InvOptionsDelayCounter; +004D7978 - uint16_t g_Inv_IsActive; +004D79A0 - BOOL g_Inv_DemoMode; +004D79B4 - BOOL g_Inv_IsOptionsDelay; +004D79B8 - int32_t g_Inv_OptionsDelayCounter; 004D79BC - uint16_t g_SoundOptionLine; 004D79C0 - REQUEST_INFO g_StatsRequester; 004D7BD8 - ASSAULT_STATS g_Assault; @@ -3306,7 +3328,7 @@ typedef struct { 004D855C - LPDIRECTINPUT g_DInput; 004D8560 - LPDIRECTINPUTDEVICE IDID_SysKeyboard; 0051BDA0 - BOOL g_IsTitleLoaded; -004D7980 - int32_t g_InventoryExtraData[8]; +004D7980 - int32_t g_Inv_ExtraData[8]; 004D8394 - int32_t g_MessageLoopCounter; 004D8384 - bool g_IsGameWindowMinimized; 004D8390 - bool g_IsGameWindowActive; @@ -3328,3 +3350,5 @@ typedef struct { 004D7788 - int32_t g_OriginalRoom; 00465518 - INVENTORY_ITEM *g_Inv_MainList; 00465608 - INVENTORY_ITEM *g_Inv_OptionList; +004655A8 - INVENTORY_ITEM *g_Inv_KeysList; +004644F8 - int32_t g_Inv_NFrames; diff --git a/src/decomp/decomp.c b/src/decomp/decomp.c index 27884ddc..2ef534e8 100644 --- a/src/decomp/decomp.c +++ b/src/decomp/decomp.c @@ -2,6 +2,7 @@ #include "game/camera.h" #include "game/input.h" +#include "game/inventory.h" #include "game/items.h" #include "game/music.h" #include "game/shell.h" @@ -430,20 +431,20 @@ int16_t __cdecl TitleSequence(void) return GFD_START_DEMO; } - if (g_InventoryChosen == O_PHOTO_OPTION) { + if (g_Inv_Chosen == O_PHOTO_OPTION) { return GFD_START_GAME | LV_GYM; } - if (g_InventoryChosen == O_PASSPORT_OPTION) { - const int32_t slot_num = g_InventoryExtraData[1]; + if (g_Inv_Chosen == O_PASSPORT_OPTION) { + const int32_t slot_num = g_Inv_ExtraData[1]; - if (g_InventoryExtraData[0] == 0) { + if (g_Inv_ExtraData[0] == 0) { Inv_RemoveAllItems(); S_LoadGame(&g_SaveGame, sizeof(SAVEGAME_INFO), slot_num); return GFD_START_SAVED_GAME | slot_num; } - if (g_InventoryExtraData[0] == 1) { + if (g_Inv_ExtraData[0] == 1) { InitialiseStartInfo(); int32_t level_id = LV_FIRST; if (g_GameFlow.play_any_level) { diff --git a/src/game/inventory.c b/src/game/inventory.c index c8e7fe03..fefa1243 100644 --- a/src/game/inventory.c +++ b/src/game/inventory.c @@ -1,5 +1,10 @@ #include "game/inventory.h" +#include "game/input.h" +#include "game/matrix.h" +#include "game/music.h" +#include "game/output.h" +#include "game/overlay.h" #include "game/text.h" #include "global/const.h" #include "global/funcs.h" @@ -8,6 +13,8 @@ #define TITLE_RING_OBJECTS 3 #define OPTION_RING_OBJECTS 3 +#define LOW_LIGHT 5120 +#define HIGH_LIGHT 4096 static TEXTSTRING *m_VersionText = NULL; @@ -15,7 +22,7 @@ void __cdecl Inv_Construct(void) { S_SetupAboveWater(0); - if (g_InventoryMode != INV_TITLE_MODE) { + if (g_Inv_Mode != INV_TITLE_MODE) { TempVideoAdjust(g_HiRes, 1.0); } @@ -24,29 +31,29 @@ void __cdecl Inv_Construct(void) g_PhdWinTop = 0; g_PhdWinBottom = g_PhdWinMaxY; - g_IsInventoryActive = 1; - g_InventoryChosen = 0; + g_Inv_IsActive = 1; + g_Inv_Chosen = 0; - if (g_InventoryMode == INV_TITLE_MODE) { - g_InvOptionObjectsCount = TITLE_RING_OBJECTS; + if (g_Inv_Mode == INV_TITLE_MODE) { + g_Inv_OptionObjectsCount = TITLE_RING_OBJECTS; if (g_GameFlow.gym_enabled) { - g_InvOptionObjectsCount++; + g_Inv_OptionObjectsCount++; } m_VersionText = Text_Create(-20, -18, 0, g_TR2XVersion); Text_AlignRight(m_VersionText, 1); Text_AlignBottom(m_VersionText, 1); Text_SetScale(m_VersionText, PHD_ONE * 0.5, PHD_ONE * 0.5); } else { - g_InvOptionObjectsCount = OPTION_RING_OBJECTS; + g_Inv_OptionObjectsCount = OPTION_RING_OBJECTS; Text_Remove(m_VersionText); m_VersionText = NULL; } - for (int i = 0; i < 8; i++) { - g_InventoryExtraData[i] = 0; + for (int32_t i = 0; i < 8; i++) { + g_Inv_ExtraData[i] = 0; } - for (int32_t i = 0; i < g_InvMainObjectsCount; i++) { + for (int32_t i = 0; i < g_Inv_MainObjectsCount; i++) { INVENTORY_ITEM *const inv_item = &g_Inv_MainList[i]; inv_item->meshes_drawn = inv_item->meshes_sel; inv_item->current_frame = 0; @@ -55,7 +62,7 @@ void __cdecl Inv_Construct(void) inv_item->y_rot = 0; } - for (int32_t i = 0; i < g_InvOptionObjectsCount; i++) { + for (int32_t i = 0; i < g_Inv_OptionObjectsCount; i++) { INVENTORY_ITEM *const inv_item = &g_Inv_OptionList[i]; inv_item->current_frame = 0; inv_item->goal_frame = 0; @@ -63,15 +70,646 @@ void __cdecl Inv_Construct(void) inv_item->y_rot = 0; } - g_InvMainCurrent = 0; + g_Inv_MainCurrent = 0; - if (g_GymInvOpenEnabled && g_InventoryMode == INV_TITLE_MODE + if (g_GymInvOpenEnabled && g_Inv_Mode == INV_TITLE_MODE && !g_GameFlow.load_save_disabled && g_GameFlow.gym_enabled) { - g_InvOptionCurrent = 3; // TODO: don't hardcode me + g_Inv_OptionCurrent = 3; // TODO: don't hardcode me g_SoundOptionLine = 0; } else { - g_InvOptionCurrent = 0; + g_Inv_OptionCurrent = 0; g_GymInvOpenEnabled = 0; g_SoundOptionLine = 0; } } + +int32_t __cdecl Inv_Display(int32_t inventory_mode) +{ + RING_INFO ring = { 0 }; + IMOTION_INFO imo = { 0 }; + + bool demo_needed = false; + int32_t v35 = 0; + bool pass_open = false; + if (inventory_mode == INV_KEYS_MODE && !g_Inv_KeyObjectsCount) { + g_Inv_Chosen = NO_OBJECT; + return 0; + } + + Text_Remove(g_AmmoTextInfo); + g_AmmoTextInfo = NULL; + + Output_AlterFOV(80 * PHD_DEGREE); + g_Inv_Mode = inventory_mode; + g_Inv_NFrames = 2; + + Inv_Construct(); + if (inventory_mode == INV_TITLE_MODE) { + S_FadeInInventory(0); + } else { + S_FadeInInventory(1); + } + + Sound_Shutdown(); + if (inventory_mode != INV_TITLE_MODE) { + Music_SetVolume(0); + } + + switch (inventory_mode) { + case INV_TITLE_MODE: + case INV_SAVE_MODE: + case INV_LOAD_MODE: + case INV_DEATH_MODE: + Inv_Ring_Init( + &ring, 1, &g_Inv_OptionList, g_Inv_OptionObjectsCount, + g_Inv_OptionCurrent, &imo); + break; + + case INV_KEYS_MODE: + Inv_Ring_Init( + &ring, 2, &g_Inv_KeysList, g_Inv_KeyObjectsCount, g_Inv_MainCurrent, + &imo); + break; + + default: + if (g_Inv_MainObjectsCount) { + Inv_Ring_Init( + &ring, 0, &g_Inv_MainList, g_Inv_MainObjectsCount, + g_Inv_MainCurrent, &imo); + } else { + Inv_Ring_Init( + &ring, 1, &g_Inv_OptionList, g_Inv_OptionObjectsCount, + g_Inv_OptionCurrent, &imo); + } + break; + } + + Sound_Effect(111, 0, SPM_ALWAYS); + g_Inv_NFrames = 2; + + do { + if (inventory_mode == INV_TITLE_MODE && g_CD_TrackID > 0) { + Music_Init(); + } + Inv_Ring_CalcAdders(&ring, 24); + Input_Update(); + + if (g_Inv_DemoMode) { + if (g_Input != 0) { + return g_GameFlow.on_demo_interrupt; + } + Demo_GetInput(); + if (g_Input == -1) { + return g_GameFlow.on_demo_end; + } + } else if (g_Input != 0) { + g_NoInputCounter = 0; + } + + g_InputDB = GetDebouncedInput(g_Input); + if (g_Inv_Mode != INV_TITLE_MODE || g_Input != 0 || g_InputDB) { + g_NoInputCounter = 0; + g_IsResetFlag = 0; + } else if (g_GameFlow.num_demos || g_GameFlow.no_input_timeout) { + g_NoInputCounter++; + if (g_NoInputCounter > g_GameFlow.no_input_time) { + demo_needed = true; + g_IsResetFlag = 1; + } + } + + if (g_StopInventory) { + return GFD_EXIT_TO_TITLE; + } + + if ((g_Inv_Mode == INV_SAVE_MODE || g_Inv_Mode == INV_LOAD_MODE + || g_Inv_Mode == INV_DEATH_MODE) + && !pass_open) { + g_InputDB = IN_SELECT; + g_Input = 0; + } + + for (int32_t frame = 0; frame < g_Inv_NFrames; frame++) { + if (g_Inv_IsOptionsDelay) { + if (g_Inv_OptionsDelayCounter) { + g_Inv_OptionsDelayCounter--; + } else { + g_Inv_IsOptionsDelay = 0; + } + } + Inv_Ring_DoMotions(&ring); + } + ring.camera.pos.z = ring.radius + 598; + + S_InitialisePolyList(0); + if (g_Inv_Mode == INV_TITLE_MODE) { + Inv_DoInventoryPicture(); + } else { + Inv_DoInventoryBackground(); + } + S_AnimateTextures(g_Inv_NFrames); + + PHD_3DPOS viewpos; + Inv_Ring_GetView(&ring, &viewpos); + Matrix_GenerateW2V(&viewpos); + Inv_Ring_Light(&ring); + + Matrix_Push(); + Matrix_TranslateAbs( + ring.ringpos.pos.x, ring.ringpos.pos.y, ring.ringpos.pos.z); + Matrix_RotYXZ( + ring.ringpos.rot.y, ring.ringpos.rot.x, ring.ringpos.rot.z); + + int32_t angle = 0; + for (int32_t j = 0; j < ring.number_of_objects; j++) { + INVENTORY_ITEM *inv_item = ring.list[j]; + if (j != ring.current_object) { + g_LsAdder = LOW_LIGHT; + for (int32_t k = 0; k < g_Inv_NFrames; k++) { + if (inv_item->y_rot < 0) { + inv_item->y_rot += 256; + } else if (inv_item->y_rot > 0) { + inv_item->y_rot -= 256; + } + } + } else { + for (int32_t k = 0; k < g_Inv_NFrames; k++) { + if (ring.rotating) { + g_LsAdder = LOW_LIGHT; + if (inv_item->y_rot > 0) { + inv_item->y_rot -= 512; + } else if (inv_item->y_rot < 0) { + inv_item->y_rot += 512; + } + } else if ( + imo.status == RNG_SELECTED + || imo.status == RNG_DESELECTING + || imo.status == RNG_SELECTING + || imo.status == RNG_DESELECT + || imo.status == RNG_CLOSING_ITEM) { + g_LsAdder = HIGH_LIGHT; + const int32_t delta = + inv_item->y_rot_sel - inv_item->y_rot; + if (delta != 0) { + if (delta > 0 && delta < 0x8000) { + inv_item->y_rot += 1024; + } else { + inv_item->y_rot -= 1024; + } + inv_item->y_rot &= 0xFC00; + } + } else if ( + ring.number_of_objects == 1 + || (!(g_Input & IN_RIGHT) && !(g_Input & IN_LEFT))) { + g_LsAdder = HIGH_LIGHT; + inv_item->y_rot += 256; + } + } + + if ((imo.status == RNG_OPEN || imo.status == RNG_SELECTING + || imo.status == RNG_SELECTED + || imo.status == RNG_DESELECTING + || imo.status == RNG_DESELECT + || imo.status == RNG_CLOSING_ITEM) + && !ring.rotating && !(g_Input & IN_LEFT) + && !(g_Input & IN_RIGHT)) { + RingNotActive(inv_item); + } + } + + if (imo.status == RNG_OPEN || imo.status == RNG_SELECTING + || imo.status == RNG_SELECTED || imo.status == RNG_DESELECTING + || imo.status == RNG_DESELECT + || imo.status == RNG_CLOSING_ITEM) { + RingIsOpen(&ring); + } else { + RingIsNotOpen(&ring); + } + + if (imo.status == RNG_OPENING || imo.status == RNG_CLOSING + || imo.status == RNG_MAIN2OPTION + || imo.status == RNG_OPTION2MAIN + || imo.status == RNG_EXITING_INVENTORY || imo.status == RNG_DONE + || ring.rotating) { + RingActive(); + } + + Matrix_Push(); + Matrix_RotYXZ(angle, 0, 0); + Matrix_TranslateRel(ring.radius, 0, 0); + Matrix_RotYXZ(0x4000, inv_item->x_rot_pt, 0); + Inv_DrawInventoryItem(inv_item); + Matrix_Pop(); + angle += ring.angle_adder; + } + + Matrix_Pop(); + Overlay_DrawModeInfo(); + Text_Draw(); + S_OutputPolyList(); + Sound_UpdateContinued(); + + const int32_t frames = S_DumpScreen(); + g_Inv_NFrames = frames; + g_Camera.num_frames = frames; + if (g_CurrentLevel) { + g_SaveGame.statistics.timer += frames / 2; + } + + if (!ring.rotating) { + switch (imo.status) { + case RNG_OPEN: + if ((g_Input & IN_RIGHT) != 0 && ring.number_of_objects > 1) { + Inv_Ring_RotateLeft(&ring); + Sound_Effect(108, 0, SPM_ALWAYS); + break; + } + + if ((g_Input & IN_LEFT) != 0 && ring.number_of_objects > 1) { + Inv_Ring_RotateRight(&ring); + Sound_Effect(108, 0, SPM_ALWAYS); + break; + } + + if (g_IsResetFlag + || (((g_InputDB & IN_OPTION) || (g_InputDB & IN_DESELECT)) + && g_Inv_Mode != INV_TITLE_MODE)) { + Sound_Effect(112, 0, SPM_ALWAYS); + g_Inv_Chosen = NO_OBJECT; + if (ring.type != RT_MAIN) { + g_Inv_OptionCurrent = ring.current_object; + } else { + g_Inv_MainCurrent = ring.current_object; + } + if (inventory_mode == INV_TITLE_MODE) { + S_FadeOutInventory(0); + } else { + S_FadeOutInventory(1); + } + Inv_Ring_MotionSetup(&ring, RNG_CLOSING, RNG_DONE, 32); + Inv_Ring_MotionRadius(&ring, 0); + Inv_Ring_MotionCameraPos(&ring, -1536); + Inv_Ring_MotionRotation( + &ring, 0x8000, ring.ringpos.rot.y + 0x8000); + g_Input = 0; + g_InputDB = 0; + } + + if ((g_InputDB & IN_SELECT) != 0) { + if ((g_Inv_Mode == INV_SAVE_MODE + || g_Inv_Mode == INV_LOAD_MODE + || g_Inv_Mode == INV_DEATH_MODE) + && !pass_open) { + pass_open = true; + } + + g_SoundOptionLine = 0; + INVENTORY_ITEM *inv_item; + if (ring.type == RT_MAIN) { + g_Inv_MainCurrent = ring.current_object; + inv_item = *(&g_Inv_MainList + ring.current_object); + } else if (ring.type == RT_OPTION) { + g_Inv_OptionCurrent = ring.current_object; + inv_item = *(&g_Inv_OptionList + ring.current_object); + } else { + g_Inv_KeysCurrent = ring.current_object; + inv_item = *(&g_Inv_KeysList + ring.current_object); + } + + inv_item->goal_frame = inv_item->open_frame; + inv_item->anim_direction = 1; + Inv_Ring_MotionSetup( + &ring, RNG_SELECTING, RNG_SELECTED, 16); + Inv_Ring_MotionRotation( + &ring, 0, + -16384 - ring.angle_adder * ring.current_object); + Inv_Ring_MotionItemSelect(&ring, inv_item); + g_Input = 0; + g_InputDB = 0; + + switch (inv_item->obj_num) { + case O_COMPASS_OPTION: + Sound_Effect(113, 0, SPM_ALWAYS); + break; + + case O_PHOTO_OPTION: + Sound_Effect(109, 0, SPM_ALWAYS); + break; + + case O_PISTOL_OPTION: + case O_SHOTGUN_OPTION: + case O_MAGNUM_OPTION: + case O_UZI_OPTION: + case O_HARPOON_OPTION: + case O_M16_OPTION: + case O_GRENADE_OPTION: + Sound_Effect(114, 0, SPM_ALWAYS); + break; + + default: + Sound_Effect(111, 0, SPM_ALWAYS); + break; + } + } + + if ((g_InputDB & IN_FORWARD) != 0 + && inventory_mode != INV_TITLE_MODE + && inventory_mode != INV_KEYS_MODE) { + if (ring.type == RT_OPTION) { + if (g_Inv_MainObjectsCount > 0) { + Inv_Ring_MotionSetup( + &ring, RNG_CLOSING, RNG_OPTION2MAIN, 24); + Inv_Ring_MotionRadius(&ring, 0); + Inv_Ring_MotionRotation( + &ring, 0x8000, ring.ringpos.rot.y + 0x8000); + Inv_Ring_MotionCameraPitch(&ring, 0x2000); + imo.misc = 0x2000; + } + g_InputDB = 0; + } else if (ring.type == RT_MAIN) { + if (g_Inv_KeyObjectsCount > 0) { + Inv_Ring_MotionSetup( + &ring, RNG_CLOSING, RNG_MAIN2KEYS, 24); + Inv_Ring_MotionRadius(&ring, 0); + Inv_Ring_MotionRotation( + &ring, 0x8000, ring.ringpos.rot.y + 0x8000); + Inv_Ring_MotionCameraPitch(&ring, 0x2000); + imo.misc = 0x2000; + } + g_Input = 0; + g_InputDB = 0; + } + } else if ( + (g_InputDB & IN_BACK) != 0 + && inventory_mode != INV_TITLE_MODE + && inventory_mode != INV_KEYS_MODE) { + if (ring.type == RT_KEYS) { + if (g_Inv_MainObjectsCount > 0) { + Inv_Ring_MotionSetup( + &ring, RNG_CLOSING, RNG_KEYS2MAIN, 24); + Inv_Ring_MotionRadius(&ring, 0); + Inv_Ring_MotionRotation( + &ring, 0x8000, ring.ringpos.rot.y + 0x8000); + Inv_Ring_MotionCameraPitch(&ring, -0x2000); + imo.misc = -0x2000; + } + g_Input = 0; + g_InputDB = 0; + } else if (ring.type == RT_MAIN) { + if (g_Inv_OptionObjectsCount > 0 + && !g_GameFlow.lockout_option_ring) { + Inv_Ring_MotionSetup( + &ring, RNG_CLOSING, RNG_MAIN2OPTION, 24); + Inv_Ring_MotionRadius(&ring, 0); + Inv_Ring_MotionRotation( + &ring, 0x8000, ring.ringpos.rot.y + 0x8000); + Inv_Ring_MotionCameraPitch(&ring, -0x2000); + imo.misc = -0x2000; + } + g_InputDB = 0; + } + } + break; + + case RNG_MAIN2OPTION: + Inv_Ring_MotionSetup(&ring, RNG_OPENING, RNG_OPEN, 24); + Inv_Ring_MotionRadius(&ring, 688); + ring.camera_pitch = -(int16_t)(imo.misc); + imo.camera_pitch_rate = imo.misc / 24; + imo.camera_pitch_target = 0; + ring.list = &g_Inv_OptionList; + ring.type = RT_OPTION; + g_Inv_MainCurrent = ring.current_object; + g_Inv_MainObjectsCount = ring.number_of_objects; + ring.number_of_objects = g_Inv_OptionObjectsCount; + ring.current_object = g_Inv_OptionCurrent; + Inv_Ring_CalcAdders(&ring, 24); + Inv_Ring_MotionRotation( + &ring, 0x8000, + -16384 - ring.angle_adder * ring.current_object); + ring.ringpos.rot.y = imo.rotate_target + 0x8000; + break; + + case RNG_MAIN2KEYS: + Inv_Ring_MotionSetup(&ring, RNG_OPENING, RNG_OPEN, 24); + Inv_Ring_MotionRadius(&ring, 688); + imo.camera_pitch_target = 0; + ring.camera_pitch = -(int16_t)(imo.misc); + imo.camera_pitch_rate = imo.misc / 24; + g_Inv_MainCurrent = ring.current_object; + g_Inv_MainObjectsCount = ring.number_of_objects; + ring.list = &g_Inv_KeysList; + ring.type = RT_KEYS; + ring.number_of_objects = g_Inv_KeyObjectsCount; + ring.current_object = g_Inv_KeysCurrent; + Inv_Ring_CalcAdders(&ring, 24); + Inv_Ring_MotionRotation( + &ring, 0x8000, + -16384 - ring.angle_adder * ring.current_object); + ring.ringpos.rot.y = imo.rotate_target + 0x8000; + break; + + case RNG_KEYS2MAIN: + Inv_Ring_MotionSetup(&ring, RNG_OPENING, RNG_OPEN, 24); + Inv_Ring_MotionRadius(&ring, 688); + ring.camera_pitch = -(int16_t)(imo.misc); + imo.camera_pitch_rate = imo.misc / 24; + imo.camera_pitch_target = 0; + ring.list = &g_Inv_MainList; + ring.type = RT_MAIN; + g_Inv_KeysCurrent = ring.current_object; + ring.number_of_objects = g_Inv_MainObjectsCount; + ring.current_object = g_Inv_MainCurrent; + Inv_Ring_CalcAdders(&ring, 24); + Inv_Ring_MotionRotation( + &ring, 0x8000, + -16384 - ring.angle_adder * ring.current_object); + ring.ringpos.rot.y = imo.rotate_target + 0x8000; + break; + + case RNG_OPTION2MAIN: + Inv_Ring_MotionSetup(&ring, RNG_OPENING, RNG_OPEN, 24); + Inv_Ring_MotionRadius(&ring, 688); + ring.camera_pitch = -(int16_t)(imo.misc); + imo.camera_pitch_rate = imo.misc / 24; + g_Inv_OptionCurrent = ring.current_object; + g_Inv_OptionObjectsCount = ring.number_of_objects; + imo.camera_pitch_target = 0; + ring.list = &g_Inv_MainList; + ring.type = RT_MAIN; + ring.number_of_objects = g_Inv_MainObjectsCount; + ring.current_object = g_Inv_MainCurrent; + Inv_Ring_CalcAdders(&ring, 24); + Inv_Ring_MotionRotation( + &ring, 0x8000, + -16384 - ring.angle_adder * ring.current_object); + ring.ringpos.rot.y = imo.rotate_target + 0x8000; + break; + + case RNG_SELECTED: { + INVENTORY_ITEM *inv_item = ring.list[ring.current_object]; + if (inv_item->obj_num == O_PASSPORT_CLOSED) { + inv_item->obj_num = O_PASSPORT_OPTION; + } + + bool busy = false; + for (int32_t frame = 0; frame < g_Inv_NFrames; frame++) { + busy = false; + if (inv_item->y_rot == inv_item->y_rot_sel) { + busy = Inv_AnimateInventoryItem(inv_item); + } + } + + if (!busy && !g_Inv_IsOptionsDelay) { + do_inventory_options(inv_item); + if (g_InputDB & IN_DESELECT) { + inv_item->sprites = 0; + Inv_Ring_MotionSetup( + &ring, RNG_CLOSING_ITEM, RNG_DESELECT, 0); + g_Input = 0; + g_InputDB = 0; + if (g_Inv_Mode == INV_LOAD_MODE + || g_Inv_Mode == INV_SAVE_MODE) { + Inv_Ring_MotionSetup( + &ring, RNG_CLOSING_ITEM, RNG_EXITING_INVENTORY, + 0); + g_InputDB = 0; + g_Input = 0; + } + } + + if ((g_InputDB & IN_SELECT) != 0) { + inv_item->sprites = 0; + g_Inv_Chosen = inv_item->obj_num; + if (ring.type != RT_MAIN) { + g_Inv_OptionCurrent = ring.current_object; + } else { + g_Inv_MainCurrent = ring.current_object; + } + if (g_Inv_Mode == INV_TITLE_MODE + && (inv_item->obj_num == O_DETAIL_OPTION + || inv_item->obj_num == O_SOUND_OPTION + || inv_item->obj_num == O_CONTROL_OPTION + || inv_item->obj_num == O_GAMMA_OPTION)) { + Inv_Ring_MotionSetup( + &ring, RNG_CLOSING_ITEM, RNG_DESELECT, 0); + } else { + Inv_Ring_MotionSetup( + &ring, RNG_CLOSING_ITEM, RNG_EXITING_INVENTORY, + 0); + } + g_Input = 0; + g_InputDB = 0; + } + } + break; + } + + case RNG_DESELECT: + Sound_Effect(112, 0, SPM_ALWAYS); + Inv_Ring_MotionSetup(&ring, RNG_DESELECTING, RNG_OPEN, 16); + Inv_Ring_MotionRotation( + &ring, 0, -16384 - ring.angle_adder * ring.current_object); + g_Input = 0; + g_InputDB = 0; + break; + + case RNG_CLOSING_ITEM: { + int32_t frame = 0; + INVENTORY_ITEM *inv_item = ring.list[ring.current_object]; + if (g_Inv_NFrames > 0) { + while (Inv_AnimateInventoryItem(inv_item)) { + frame++; + if (frame >= g_Inv_NFrames) { + break; + } + } + + if (inv_item->obj_num == O_PASSPORT_OPTION) { + inv_item->obj_num = O_PASSPORT_CLOSED; + inv_item->current_frame = 0; + } + + imo.count = 16; + imo.status = imo.status_target; + Inv_Ring_MotionItemDeselect(&ring, inv_item); + } + break; + } + + case RNG_EXITING_INVENTORY: + if (!imo.count) { + if (inventory_mode == INV_TITLE_MODE) { + S_FadeOutInventory(0); + } else { + S_FadeOutInventory(1); + } + Inv_Ring_MotionSetup(&ring, RNG_CLOSING, RNG_DONE, 32); + Inv_Ring_MotionRadius(&ring, 0); + Inv_Ring_MotionCameraPos(&ring, -1536); + Inv_Ring_MotionRotation( + &ring, 0x8000, ring.ringpos.rot.y + 0x8000); + } + break; + + default: + break; + } + } + } while (imo.status != RNG_DONE); + + RemoveInventoryText(); + S_FinishInventory(); + g_Inv_IsActive = 0; + + if (g_IsResetFlag) { + return GFD_EXIT_TO_TITLE; + } + + if (demo_needed) { + return GFD_START_DEMO; + } + + if (g_Inv_Chosen == NO_OBJECT) { + if (inventory_mode != INV_TITLE_MODE && g_OptionMusicVolume != 0) { + Music_SetVolume(25 * g_OptionMusicVolume + 5); + } + return 0; + } + + switch (g_Inv_Chosen) { + case O_PASSPORT_OPTION: + if (g_Inv_ExtraData[0] == 1 && g_OptionMusicVolume != 0) { + Music_SetVolume(25 * g_OptionMusicVolume + 5); + } + return 1; + + case O_PHOTO_OPTION: + if (g_GameFlow.gym_enabled) { + g_Inv_ExtraData[1] = 0; + return 1; + } + break; + + case O_PISTOL_OPTION: + case O_SHOTGUN_OPTION: + case O_MAGNUM_OPTION: + case O_UZI_OPTION: + case O_HARPOON_OPTION: + case O_M16_OPTION: + case O_GRENADE_OPTION: + case O_SMALL_MEDIPACK_OPTION: + case O_LARGE_MEDIPACK_OPTION: + case O_FLARES_OPTION: + Lara_UseItem(g_Inv_Chosen); + break; + + default: + break; + } + + if (inventory_mode != INV_TITLE_MODE && g_OptionMusicVolume != 0) { + Music_SetVolume(25 * g_OptionMusicVolume + 5); + } + return 0; +} diff --git a/src/game/inventory.h b/src/game/inventory.h index 22cf08a4..4b36b583 100644 --- a/src/game/inventory.h +++ b/src/game/inventory.h @@ -1,3 +1,6 @@ #pragma once -void Inv_Construct(void); +#include + +void __cdecl Inv_Construct(void); +int32_t __cdecl Inv_Display(int32_t inventory_mode); diff --git a/src/global/const.h b/src/global/const.h index a71629fb..ff662b1f 100644 --- a/src/global/const.h +++ b/src/global/const.h @@ -29,6 +29,7 @@ #define MIN_SQUARE SQUARE(WALL_L / 3) #define NO_BOX (-1) #define NO_ITEM (-1) +#define NO_OBJECT (-1) #define NO_ROOM (-1) #define NO_CAMERA (-1) diff --git a/src/global/funcs.h b/src/global/funcs.h index 33993d28..4f0b4045 100644 --- a/src/global/funcs.h +++ b/src/global/funcs.h @@ -167,7 +167,6 @@ #define InitialiseHair ((void __cdecl (*)(void))0x00420EA0) #define HairControl ((void __cdecl (*)(int32_t in_cutscene))0x00420F20) #define DrawHair ((void __cdecl (*)(void))0x00421920) -#define Inv_Display ((int32_t __cdecl (*)(int32_t inventory_mode))0x00422080) #define Inv_SelectMeshes ((void __cdecl (*)(INVENTORY_ITEM *inv_item))0x00423470) #define Inv_AnimateInventoryItem ((int32_t __cdecl (*)(INVENTORY_ITEM *inv_item))0x00423500) #define Inv_DrawInventoryItem ((void __cdecl (*)(INVENTORY_ITEM *inv_item))0x00423590) @@ -186,21 +185,21 @@ #define Inv_RemoveItem ((int32_t __cdecl (*)(int32_t item_num))0x00424CD0) #define Inv_GetItemOption ((int32_t __cdecl (*)(int32_t item_num))0x00424DE0) #define RemoveInventoryText ((void __cdecl (*)(void))0x00424FD0) -#define Inv_RingInit ((void __cdecl (*)(RING_INFO *ring, int16_t type, INVENTORY_ITEM **list, int16_t qty, int16_t current, IMOTION_INFO *imo))0x00425000) -#define Inv_RingGetView ((void __cdecl (*)(RING_INFO *ring, PHD_3DPOS *viewer))0x00425110) -#define Inv_RingLight ((void __cdecl (*)(RING_INFO *ring))0x00425170) -#define Inv_RingCalcAdders ((void __cdecl (*)(RING_INFO *ring, int16_t rotation_duration))0x004251B0) -#define Inv_RingDoMotions ((void __cdecl (*)(RING_INFO *ring))0x004251E0) -#define Inv_RingRotateLeft ((void __cdecl (*)(RING_INFO *ring))0x00425320) -#define Inv_RingRotateRight ((void __cdecl (*)(RING_INFO *ring))0x00425350) -#define Inv_RingMotionInit ((void __cdecl (*)(RING_INFO *ring, int16_t frames, int16_t status, int16_t status_target))0x00425380) -#define Inv_RingMotionSetup ((void __cdecl (*)(RING_INFO *ring, int16_t status, int16_t status_target, int16_t frames))0x004253F0) -#define Inv_RingMotionRadius ((void __cdecl (*)(RING_INFO *ring, int16_t target))0x00425420) -#define Inv_RingMotionRotation ((void __cdecl (*)(RING_INFO *ring, int16_t rotation, int16_t target))0x00425450) -#define Inv_RingMotionCameraPos ((void __cdecl (*)(RING_INFO *ring, int16_t target))0x00425480) -#define Inv_RingMotionCameraPitch ((void __cdecl (*)(RING_INFO *ring, int16_t target))0x004254B0) -#define Inv_RingMotionItemSelect ((void __cdecl (*)(RING_INFO *ring, INVENTORY_ITEM *inv_item))0x004254D0) -#define Inv_RingMotionItemDeselect ((void __cdecl (*)(RING_INFO *ring, INVENTORY_ITEM *inv_item))0x00425530) +#define Inv_Ring_Init ((void __cdecl (*)(RING_INFO *ring, int16_t type, INVENTORY_ITEM **list, int16_t qty, int16_t current, IMOTION_INFO *imo))0x00425000) +#define Inv_Ring_GetView ((void __cdecl (*)(RING_INFO *ring, PHD_3DPOS *viewer))0x00425110) +#define Inv_Ring_Light ((void __cdecl (*)(RING_INFO *ring))0x00425170) +#define Inv_Ring_CalcAdders ((void __cdecl (*)(RING_INFO *ring, int16_t rotation_duration))0x004251B0) +#define Inv_Ring_DoMotions ((void __cdecl (*)(RING_INFO *ring))0x004251E0) +#define Inv_Ring_RotateLeft ((void __cdecl (*)(RING_INFO *ring))0x00425320) +#define Inv_Ring_RotateRight ((void __cdecl (*)(RING_INFO *ring))0x00425350) +#define Inv_Ring_MotionInit ((void __cdecl (*)(RING_INFO *ring, int16_t frames, int16_t status, int16_t status_target))0x00425380) +#define Inv_Ring_MotionSetup ((void __cdecl (*)(RING_INFO *ring, int16_t status, int16_t status_target, int16_t frames))0x004253F0) +#define Inv_Ring_MotionRadius ((void __cdecl (*)(RING_INFO *ring, int16_t target))0x00425420) +#define Inv_Ring_MotionRotation ((void __cdecl (*)(RING_INFO *ring, int16_t rotation, int16_t target))0x00425450) +#define Inv_Ring_MotionCameraPos ((void __cdecl (*)(RING_INFO *ring, int16_t target))0x00425480) +#define Inv_Ring_MotionCameraPitch ((void __cdecl (*)(RING_INFO *ring, int16_t target))0x004254B0) +#define Inv_Ring_MotionItemSelect ((void __cdecl (*)(RING_INFO *ring, INVENTORY_ITEM *inv_item))0x004254D0) +#define Inv_Ring_MotionItemDeselect ((void __cdecl (*)(RING_INFO *ring, INVENTORY_ITEM *inv_item))0x00425530) #define Init_Requester ((void __cdecl (*)(REQUEST_INFO *req))0x004255A0) #define Remove_Requester ((void __cdecl (*)(REQUEST_INFO *req))0x00425630) #define ReqItemCentreAlign ((void __cdecl (*)(REQUEST_INFO *req, TEXTSTRING *txt))0x004256E0) diff --git a/src/global/types.h b/src/global/types.h index 17c0f5aa..29c95df4 100644 --- a/src/global/types.h +++ b/src/global/types.h @@ -723,6 +723,68 @@ typedef struct { int32_t reserved[4]; } INVENTORY_ITEM; +// clang-format off +typedef enum { + RNG_OPENING = 0, + RNG_OPEN = 1, + RNG_CLOSING = 2, + RNG_MAIN2OPTION = 3, + RNG_MAIN2KEYS = 4, + RNG_KEYS2MAIN = 5, + RNG_OPTION2MAIN = 6, + RNG_SELECTING = 7, + RNG_SELECTED = 8, + RNG_DESELECTING = 9, + RNG_DESELECT = 10, + RNG_CLOSING_ITEM = 11, + RNG_EXITING_INVENTORY = 12, + RNG_DONE = 13, +} RING_STATUS; +// clang-format on + +typedef struct { + int16_t count; + int16_t status; + int16_t status_target; + int16_t radius_target; + int16_t radius_rate; + int16_t camera_ytarget; + int16_t camera_yrate; + int16_t camera_pitch_target; + int16_t camera_pitch_rate; + int16_t rotate_target; + int16_t rotate_rate; + int16_t item_ptxrot_target; + int16_t item_ptxrot_rate; + int16_t item_xrot_target; + int16_t item_xrot_rate; + int32_t item_ytrans_target; + int32_t item_ytrans_rate; + int32_t item_ztrans_target; + int32_t item_ztrans_rate; + int32_t misc; +} IMOTION_INFO; + +typedef struct { + INVENTORY_ITEM **list; + int16_t type; + int16_t radius; + int16_t camera_pitch; + int16_t rotating; + int16_t rot_count; + int16_t current_object; + int16_t target_object; + int16_t number_of_objects; + int16_t angle_adder; + int16_t rot_adder; + int16_t rot_adder_l; + int16_t rot_adder_r; + PHD_3DPOS ringpos; + PHD_3DPOS camera; + XYZ_32 light; + IMOTION_INFO *imo; +} RING_INFO; + typedef enum { GFE_PICTURE, GFE_LIST_START, @@ -912,14 +974,24 @@ typedef enum { LV_FIRST = 1, } LEVEL_TYPE; +// clang-format off typedef enum { - INV_GAME_MODE, - INV_TITLE_MODE, - INV_KEYS_MODE, - INV_SAVE_MODE, - INV_LOAD_MODE, - INV_DEATH_MODE, + RT_MAIN = 0, + RT_OPTION = 1, + RT_KEYS = 2, +} RING_TYPE; +// clang-format on + +// clang-format off +typedef enum { + INV_GAME_MODE = 0, + INV_TITLE_MODE = 1, + INV_KEYS_MODE = 2, + INV_SAVE_MODE = 3, + INV_LOAD_MODE = 4, + INV_DEATH_MODE = 5, } INVENTORY_MODE; +// clang-format on // clang-format off typedef enum { diff --git a/src/global/vars.h b/src/global/vars.h index 60f46625..e50e43dc 100644 --- a/src/global/vars.h +++ b/src/global/vars.h @@ -6,7 +6,6 @@ #include "inject_util.h" // clang-format off - extern const char *g_TR2XVersion; #define g_IID_IDirectDrawSurface3 (*(GUID*)0x00463150) #define g_PerspectiveDistance (*(uint32_t*)0x00464060) // = 0x3000000 @@ -21,13 +20,15 @@ extern const char *g_TR2XVersion; #define g_GF_NumSecrets (*(int16_t*)0x004642E8) // = 3 #define g_CineTargetAngle (*(int16_t*)0x00464310) // = 0x4000 #define g_OverlayStatus (*(int32_t*)0x004644E0) // = 1 -#define g_InvMainObjectsCount (*(int16_t*)0x004654E0) // = 8 +#define g_Inv_NFrames (*(int32_t*)0x004644F8) +#define g_Inv_MainObjectsCount (*(int16_t*)0x004654E0) // = 8 #define g_Inv_MainList (*(INVENTORY_ITEM **)0x00465518) -#define g_InvOptionObjectsCount (*(int16_t*)0x00465604) // = 4 +#define g_Inv_KeysList (*(INVENTORY_ITEM **)0x004655A8) +#define g_Inv_OptionObjectsCount (*(int16_t*)0x00465604) // = 4 #define g_Inv_OptionList (*(INVENTORY_ITEM **)0x00465608) #define g_GymInvOpenEnabled (*(BOOL*)0x00465618) // = TRUE -#define g_InventoryChosen (*(int16_t*)0x00465A50) // = -1 -#define g_InventoryMode (*(INVENTORY_MODE*)0x00465A54) // = INV_TITLE_MODE +#define g_Inv_Chosen (*(int16_t*)0x00465A50) // = -1 +#define g_Inv_Mode (*(INVENTORY_MODE*)0x00465A54) // = INV_TITLE_MODE #define g_OptionSoundVolume (*(int16_t*)0x00465A5C) // = 165 #define g_OptionMusicVolume (*(int16_t*)0x00465A60) // = 255 #define g_JumpPermitted (*(int32_t*)0x00465AD4) // = 1 @@ -133,8 +134,8 @@ extern const char *g_TR2XVersion; #define g_StopInventory (*(BOOL*)0x004D77A4) #define g_IsDemoLevelType (*(BOOL*)0x004D77AC) #define g_IsDemoLoaded (*(BOOL*)0x004D77B0) -#define g_BoundStart (*(int*)0x004D77C0) -#define g_BoundEnd (*(int*)0x004D77C4) +#define g_BoundStart (*(int32_t*)0x004D77C0) +#define g_BoundEnd (*(int32_t*)0x004D77C4) #define g_IsAssaultTimerDisplay (*(int32_t*)0x004D77E0) #define g_IsAssaultTimerActive (*(BOOL*)0x004D77E4) #define g_IsMonkAngry (*(BOOL*)0x004D77E8) @@ -142,22 +143,21 @@ extern const char *g_TR2XVersion; #define g_AmmoTextInfo (*(TEXTSTRING **)0x004D792C) #define g_DisplayModeTextInfo (*(TEXTSTRING **)0x004D7930) #define g_DisplayModeInfoTimer (*(DWORD*)0x004D7934) -#define g_InvMainCurrent (*(UINT16*)0x004D7938) -#define g_InvKeyObjectsCount (*(UINT16*)0x004D793C) -#define g_InvKeysCurrent (*(UINT16*)0x004D7940) -#define g_InvOptionCurrent (*(UINT16*)0x004D7944) -#define g_InvRingText (*(TEXTSTRING**)0x004D7954) -#define g_InvUpArrow1 (*(TEXTSTRING**)0x004D795C) -#define g_InvUpArrow2 (*(TEXTSTRING**)0x004D7960) -#define g_InvDownArrow1 (*(TEXTSTRING**)0x004D7964) -#define g_InvDownArrow2 (*(TEXTSTRING**)0x004D7968) +#define g_Inv_MainCurrent (*(UINT16*)0x004D7938) +#define g_Inv_KeyObjectsCount (*(UINT16*)0x004D793C) +#define g_Inv_KeysCurrent (*(UINT16*)0x004D7940) +#define g_Inv_OptionCurrent (*(UINT16*)0x004D7944) +#define g_Inv_RingText (*(TEXTSTRING**)0x004D7954) +#define g_Inv_UpArrow1 (*(TEXTSTRING**)0x004D795C) +#define g_Inv_UpArrow2 (*(TEXTSTRING**)0x004D7960) +#define g_Inv_DownArrow1 (*(TEXTSTRING**)0x004D7964) +#define g_Inv_DownArrow2 (*(TEXTSTRING**)0x004D7968) #define g_InputDB (*(uint32_t*)0x004D796C) -#define g_IsInventoryActive (*(uint16_t*)0x004D7978) -#define g_IsInventoryActive (*(uint16_t*)0x004D7978) -#define g_InventoryExtraData (*(int32_t(*)[8])0x004D7980) -#define g_InvDemoMode (*(BOOL*)0x004D79A0) -#define g_IsInvOptionsDelay (*(BOOL*)0x004D79B4) -#define g_InvOptionsDelayCounter (*(int32_t*)0x004D79B8) +#define g_Inv_IsActive (*(uint16_t*)0x004D7978) +#define g_Inv_ExtraData (*(int32_t(*)[8])0x004D7980) +#define g_Inv_DemoMode (*(BOOL*)0x004D79A0) +#define g_Inv_IsOptionsDelay (*(BOOL*)0x004D79B4) +#define g_Inv_OptionsDelayCounter (*(int32_t*)0x004D79B8) #define g_SoundOptionLine (*(uint16_t*)0x004D79BC) #define g_StatsRequester (*(REQUEST_INFO*)0x004D79C0) #define g_Assault (*(ASSAULT_STATS*)0x004D7BD8) diff --git a/src/inject_exec.c b/src/inject_exec.c index 2db89c0e..c098525f 100644 --- a/src/inject_exec.c +++ b/src/inject_exec.c @@ -360,6 +360,7 @@ static void Inject_LOS(void) static void Inject_Inventory(void) { + INJECT(1, 0x00422080, Inv_Display); INJECT(1, 0x00423310, Inv_Construct); } diff --git a/src/specific/s_input.c b/src/specific/s_input.c index 80097e6a..16b22e98 100644 --- a/src/specific/s_input.c +++ b/src/specific/s_input.c @@ -314,7 +314,7 @@ bool __cdecl S_Input_Update(void) } } // toggle renderer mode (Shift+F12) - } else if (!g_IsInventoryActive) { + } else if (!g_Inv_IsActive) { new_settings.render_mode = new_settings.render_mode == RM_HARDWARE ? RM_SOFTWARE : RM_HARDWARE;