From 67f7dff13ffa0b097c4fa0646daa2bccf0e6c99f Mon Sep 17 00:00:00 2001 From: Finn Hartshorn Date: Tue, 18 Aug 2026 20:41:27 +1000 Subject: [PATCH] Add save logging tool Detours all vanilla Save() methods to log save-file writes, useful for reverse-engineering the savefile format. Standalone new file with no existing callers of its own, so no feature logic from other buckets travels with it. Co-Authored-By: Claude Sonnet 5 --- openzt-detour/src/generated.rs | 81 ++++--- openzt/src/lib.rs | 4 + openzt/src/save_logging.rs | 395 +++++++++++++++++++++++++++++++++ 3 files changed, 448 insertions(+), 32 deletions(-) create mode 100644 openzt/src/save_logging.rs diff --git a/openzt-detour/src/generated.rs b/openzt-detour/src/generated.rs index a8d23e9..0da9d3e 100644 --- a/openzt-detour/src/generated.rs +++ b/openzt-detour/src/generated.rs @@ -3,6 +3,7 @@ #![allow(clippy::type_complexity)] +use std::ffi::c_void; use std::marker::PhantomData; use crate::FunctionDef; @@ -39,7 +40,7 @@ pub mod bfaimgr { pub const EXECUTE_CALL: FunctionDef u32> = FunctionDef{address: 0x00437ccd, function_type: PhantomData}; pub const F_RANDOM_WALK: FunctionDef u32> = FunctionDef{address: 0x0043d948, function_type: PhantomData}; pub const F_PLAY_SET: FunctionDef u32> = FunctionDef{address: 0x0043ddc1, function_type: PhantomData}; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0047b081, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0047b081, function_type: PhantomData}; pub const F_MOVE_MEDIUM_F: FunctionDef u32> = FunctionDef{address: 0x004a31de, function_type: PhantomData}; pub const F_MOVE_FAST_F: FunctionDef u32> = FunctionDef{address: 0x004a5310, function_type: PhantomData}; pub const BFAIMGR: FunctionDef u32> = FunctionDef{address: 0x0050374b, function_type: PhantomData}; @@ -95,7 +96,7 @@ pub mod bfbscall { use super::*; pub const CONSTRUCTOR: FunctionDef u32> = FunctionDef{address: 0x004109fe, function_type: PhantomData}; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x004781e9, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x004781e9, function_type: PhantomData}; } // BFBehaviorSet class functions @@ -223,7 +224,7 @@ pub mod bfentity { pub const VERIFY_SHAPE: FunctionDef = FunctionDef{address: 0x00446995, function_type: PhantomData}; pub const SET_NAME: FunctionDef = FunctionDef{address: 0x00449215, function_type: PhantomData}; pub const LOAD: FunctionDef u32> = FunctionDef{address: 0x0044f866, function_type: PhantomData}; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00477998, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00477998, function_type: PhantomData}; pub const FORCE_ANIM: FunctionDef = FunctionDef{address: 0x00485580, function_type: PhantomData}; pub const MORPH: FunctionDef = FunctionDef{address: 0x004865c4, function_type: PhantomData}; pub const CALC_SHADOW_WORLD_POSITION: FunctionDef = FunctionDef{address: 0x00492def, function_type: PhantomData}; @@ -289,7 +290,7 @@ pub mod bfevent { use super::*; pub const LOAD: FunctionDef bool> = FunctionDef{address: 0x00485f08, function_type: PhantomData}; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0060182e, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0060182e, function_type: PhantomData}; } // BFEventInfo class functions @@ -297,14 +298,14 @@ pub mod bfeventinfo { use super::*; pub const LOAD: FunctionDef bool> = FunctionDef{address: 0x00485e31, function_type: PhantomData}; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00601768, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00601768, function_type: PhantomData}; } // BFEventMgr class functions pub mod bfeventmgr { use super::*; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0047afa5, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0047afa5, function_type: PhantomData}; pub const INIT: FunctionDef u32> = FunctionDef{address: 0x00525f3e, function_type: PhantomData}; pub const CONSTRUCTOR: FunctionDef u32> = FunctionDef{address: 0x0052603f, function_type: PhantomData}; pub const LOAD: FunctionDef u32> = FunctionDef{address: 0x00594d17, function_type: PhantomData}; @@ -367,7 +368,7 @@ pub mod bfgameapp { pub mod bfgamemgr { use super::*; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0047aca5, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0047aca5, function_type: PhantomData}; pub const LOAD: FunctionDef bool> = FunctionDef{address: 0x00594cba, function_type: PhantomData}; } @@ -466,6 +467,7 @@ pub mod bfmap { pub const CLEAR_TILE_TERRAIN: FunctionDef = FunctionDef{address: 0x005b342e, function_type: PhantomData}; pub const GET_ALL_NEIGHBORS: FunctionDef u32> = FunctionDef{address: 0x005b3835, function_type: PhantomData}; pub const CLEAR_SAVED_PATH: FunctionDef = FunctionDef{address: 0x00600414, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00479a1a, function_type: PhantomData}; } // BFMgr class functions @@ -498,7 +500,7 @@ pub mod bfoverlay { pub const REMOVE_FROM_MAP: FunctionDef = FunctionDef{address: 0x00420565, function_type: PhantomData}; pub const BFOVERLAY_0: FunctionDef u32> = FunctionDef{address: 0x00420589, function_type: PhantomData}; pub const LOAD: FunctionDef u32> = FunctionDef{address: 0x0045024d, function_type: PhantomData}; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0047a7ee, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0047a7ee, function_type: PhantomData}; pub const CONSTRUCTOR: FunctionDef u32> = FunctionDef{address: 0x004fc391, function_type: PhantomData}; pub const ADD_TO_MAP: FunctionDef = FunctionDef{address: 0x004fc3cd, function_type: PhantomData}; pub const BFOVERLAY_1: FunctionDef u32> = FunctionDef{address: 0x00624292, function_type: PhantomData}; @@ -724,6 +726,7 @@ pub mod bftile { pub const LOAD: FunctionDef u32> = FunctionDef{address: 0x004c864e, function_type: PhantomData}; pub const REMOVE_EDGE: FunctionDef u32> = FunctionDef{address: 0x004f165b, function_type: PhantomData}; pub const SET_TERRAIN_TYPE: FunctionDef = FunctionDef{address: 0x004f17e0, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00479975, function_type: PhantomData}; } // BFUIMgr class functions @@ -811,7 +814,7 @@ pub mod bfunit { pub const CLEANUP_EVENTS: FunctionDef = FunctionDef{address: 0x0043f4a0, function_type: PhantomData}; pub const IS_NON_PATH_STEEP: FunctionDef u32> = FunctionDef{address: 0x0044045e, function_type: PhantomData}; pub const LOAD: FunctionDef u32> = FunctionDef{address: 0x004547cc, function_type: PhantomData}; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00478252, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00478252, function_type: PhantomData}; pub const SET_HEIGHT_ABOVE_TERRAIN: FunctionDef = FunctionDef{address: 0x00492a51, function_type: PhantomData}; pub const CHECK_ELEVATION: FunctionDef bool> = FunctionDef{address: 0x00493e1c, function_type: PhantomData}; pub const SET_DEST_TILE: FunctionDef = FunctionDef{address: 0x004a7a90, function_type: PhantomData}; @@ -882,7 +885,7 @@ pub mod bfworldmgr { pub const LOAD: FunctionDef u32> = FunctionDef{address: 0x0044f280, function_type: PhantomData}; pub const INIT_UNLOCKED_ENTITIES: FunctionDef = FunctionDef{address: 0x004533bc, function_type: PhantomData}; pub const CONSTRUCTOR: FunctionDef u32> = FunctionDef{address: 0x0046285b, function_type: PhantomData}; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00477b4e, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00477b4e, function_type: PhantomData}; pub const CLEAR: FunctionDef = FunctionDef{address: 0x004c6b18, function_type: PhantomData}; pub const UNLOCK_ENTITY: FunctionDef = FunctionDef{address: 0x00598cdc, function_type: PhantomData}; pub const VERIFY_ENTITY_1: FunctionDef = FunctionDef{address: 0x005b66c4, function_type: PhantomData}; @@ -1497,7 +1500,7 @@ pub mod ztambient { pub const CALC_SHADOW_WORLD_POSITION: FunctionDef = FunctionDef{address: 0x00433cad, function_type: PhantomData}; pub const UPDATE_POSITION: FunctionDef = FunctionDef{address: 0x00434e9c, function_type: PhantomData}; pub const LOAD: FunctionDef u32> = FunctionDef{address: 0x00450261, function_type: PhantomData}; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0047a7fd, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0047a7fd, function_type: PhantomData}; pub const INIT: FunctionDef = FunctionDef{address: 0x004fc145, function_type: PhantomData}; pub const INIT_STATUS_VARS: FunctionDef = FunctionDef{address: 0x004fc160, function_type: PhantomData}; pub const CONSTRUCTOR: FunctionDef u32> = FunctionDef{address: 0x004fc3aa, function_type: PhantomData}; @@ -1564,7 +1567,7 @@ pub mod ztanimal { pub const ADD_TO_MAP: FunctionDef = FunctionDef{address: 0x00449c94, function_type: PhantomData}; pub const CONSTRUCTOR: FunctionDef u32> = FunctionDef{address: 0x00453cc6, function_type: PhantomData}; pub const LOAD: FunctionDef u32> = FunctionDef{address: 0x00455533, function_type: PhantomData}; - pub const SAVE: FunctionDef = FunctionDef{address: 0x00478cff, function_type: PhantomData}; + pub const SAVE: FunctionDef bool> = FunctionDef{address: 0x00478cff, function_type: PhantomData}; pub const GET_UNDESIRABLE_SCENERY_IN_HABITAT: FunctionDef u32> = FunctionDef{address: 0x00483979, function_type: PhantomData}; pub const CHASE_DONE: FunctionDef = FunctionDef{address: 0x004a4d5f, function_type: PhantomData}; pub const STOP_CHASE: FunctionDef = FunctionDef{address: 0x004a5e00, function_type: PhantomData}; @@ -1641,7 +1644,7 @@ pub mod ztapp { pub mod ztawardmgr { use super::*; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0047a064, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0047a064, function_type: PhantomData}; pub const START: FunctionDef u32> = FunctionDef{address: 0x005141e1, function_type: PhantomData}; pub const GET_AWARD: FunctionDef i32> = FunctionDef{address: 0x005a12ec, function_type: PhantomData}; pub const ADD_AWARD: FunctionDef = FunctionDef{address: 0x005a13ed, function_type: PhantomData}; @@ -1730,7 +1733,7 @@ pub mod ztcheat { pub const UPDATE: FunctionDef = FunctionDef{address: 0x00435282, function_type: PhantomData}; pub const RENAME_ENTITY: FunctionDef = FunctionDef{address: 0x0044940b, function_type: PhantomData}; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0047a10c, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0047a10c, function_type: PhantomData}; pub const CLEAR: FunctionDef = FunctionDef{address: 0x004c6a3e, function_type: PhantomData}; pub const GUEST_ENTERS: FunctionDef = FunctionDef{address: 0x004f7ebe, function_type: PhantomData}; pub const INIT: FunctionDef = FunctionDef{address: 0x00514554, function_type: PhantomData}; @@ -1754,7 +1757,7 @@ pub mod ztfence { pub const ADD_TO_MAP: FunctionDef = FunctionDef{address: 0x0044cb57, function_type: PhantomData}; pub const LOAD: FunctionDef u32> = FunctionDef{address: 0x0044ff2d, function_type: PhantomData}; pub const MAKE_GATE: FunctionDef = FunctionDef{address: 0x0046600c, function_type: PhantomData}; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00477e25, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00477e25, function_type: PhantomData}; pub const CAN_DETERIORATE: FunctionDef u32> = FunctionDef{address: 0x004857b9, function_type: PhantomData}; pub const SET_BROKEN: FunctionDef = FunctionDef{address: 0x004858a4, function_type: PhantomData}; pub const MORPH: FunctionDef = FunctionDef{address: 0x0048676c, function_type: PhantomData}; @@ -1818,7 +1821,7 @@ pub mod ztgamemgr { pub const HOURS_AGO: FunctionDef u64> = FunctionDef{address: 0x0041f075, function_type: PhantomData}; pub const TIME_AGO: FunctionDef u32> = FunctionDef{address: 0x0042620a, function_type: PhantomData}; pub const UPDATE_SIM: FunctionDef = FunctionDef{address: 0x00435055, function_type: PhantomData}; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0047acc5, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0047acc5, function_type: PhantomData}; pub const REMOVED_ZOO_DOO: FunctionDef = FunctionDef{address: 0x004a2ee1, function_type: PhantomData}; pub const START_MENU_MUSIC: FunctionDef = FunctionDef{address: 0x004bded9, function_type: PhantomData}; pub const START_MENU_MUSIC_FADE_0: FunctionDef = FunctionDef{address: 0x004c9d67, function_type: PhantomData}; @@ -1994,6 +1997,7 @@ pub mod ztguest { pub const ADD_TRASH: FunctionDef = FunctionDef{address: 0x0059d2c9, function_type: PhantomData}; pub const SEEN_SHOW: FunctionDef u32> = FunctionDef{address: 0x005a2bcd, function_type: PhantomData}; pub const DO_HAPPY_PRICE_CHANGE: FunctionDef = FunctionDef{address: 0x00619245, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0047873e, function_type: PhantomData}; } // ZTGuestType class functions @@ -2013,6 +2017,7 @@ pub mod ztguide { use super::*; pub const GET_RANDOM_ASSIGNED_HABITAT: FunctionDef u32> = FunctionDef{address: 0x0058af73, function_type: PhantomData}; + pub const SAVE: FunctionDef u8> = FunctionDef{address: 0x0047987f, function_type: PhantomData}; } // ZTGuideType class functions @@ -2061,7 +2066,7 @@ pub mod zthabitat { pub const MOVE_GATE_TO: FunctionDef u32> = FunctionDef{address: 0x00466236, function_type: PhantomData}; pub const HAS_KEEPER_ASSIGNED: FunctionDef = FunctionDef{address: 0x00468454, function_type: PhantomData}; pub const GET_POPULARITY: FunctionDef i32> = FunctionDef{address: 0x00468732, function_type: PhantomData}; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00479b73, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00479b73, function_type: PhantomData}; pub const GET_UNDESIRABLE_SCENERY: FunctionDef = FunctionDef{address: 0x00483a67, function_type: PhantomData}; pub const GET_GATE: FunctionDef i32> = FunctionDef{address: 0x00492ca3, function_type: PhantomData}; pub const GET_SPECIES_RATING: FunctionDef f32> = FunctionDef{address: 0x004d92db, function_type: PhantomData}; @@ -2112,7 +2117,7 @@ pub mod zthabitatmgr { pub const UPDATE_SHOW_NEIGHBORS_0: FunctionDef = FunctionDef{address: 0x0045cf65, function_type: PhantomData}; pub const INSTANTIATE: FunctionDef u32> = FunctionDef{address: 0x004635aa, function_type: PhantomData}; pub const REPLACE_FENCE_WITH_GATE: FunctionDef u32> = FunctionDef{address: 0x004666c5, function_type: PhantomData}; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00479a54, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00479a54, function_type: PhantomData}; pub const ENTER_NEW_MONTH: FunctionDef = FunctionDef{address: 0x0048430c, function_type: PhantomData}; pub const MERGE_TANKS: FunctionDef = FunctionDef{address: 0x0048712c, function_type: PhantomData}; pub const GET_MERGE_TANK_WALLS: FunctionDef = FunctionDef{address: 0x00487498, function_type: PhantomData}; @@ -2157,6 +2162,7 @@ pub mod zthelicopter { pub const START_LOOP_SOUND: FunctionDef = FunctionDef{address: 0x0048d645, function_type: PhantomData}; pub const VALIDATE_TANK_POSITION: FunctionDef = FunctionDef{address: 0x005067be, function_type: PhantomData}; pub const SET_DEST_TILE: FunctionDef = FunctionDef{address: 0x0061a117, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0061a0af, function_type: PhantomData}; } // ZTHelicopterType class functions @@ -2185,6 +2191,7 @@ pub mod ztkeeper { pub const REMOVE_FROM_MAP: FunctionDef = FunctionDef{address: 0x00458759, function_type: PhantomData}; pub const NOTIFY_HABITAT_NOT_COMING: FunctionDef = FunctionDef{address: 0x004a879f, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x004796d9, function_type: PhantomData}; } // ZTKeeperType class functions @@ -2212,6 +2219,7 @@ pub mod ztmaint { pub const GET_TERRAIN_COST: FunctionDef = FunctionDef{address: 0x00439c73, function_type: PhantomData}; pub const FINISH_TASK: FunctionDef = FunctionDef{address: 0x004a97e5, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x004794be, function_type: PhantomData}; } // ZTMaintTaskPool class functions @@ -2254,7 +2262,7 @@ pub mod ztmapview { pub const GET_HABITAT: FunctionDef i32> = FunctionDef{address: 0x00468a7d, function_type: PhantomData}; pub const PICK_UP_SELECTED_ENTITY: FunctionDef = FunctionDef{address: 0x0046ab75, function_type: PhantomData}; pub const HANDLE_CHAR: FunctionDef u32> = FunctionDef{address: 0x0046bd7d, function_type: PhantomData}; - pub const SAVE_STATE: FunctionDef u32> = FunctionDef{address: 0x0047abeb, function_type: PhantomData}; + pub const SAVE_STATE: FunctionDef u32> = FunctionDef{address: 0x0047abeb, function_type: PhantomData}; pub const PLACE_ENTITY_ON_MAP_0: FunctionDef u32> = FunctionDef{address: 0x004868cf, function_type: PhantomData}; pub const FOLLOW_SELECTED_ENTITY: FunctionDef = FunctionDef{address: 0x0048c5e9, function_type: PhantomData}; pub const REMOVE_SELECTED_ENTITY: FunctionDef = FunctionDef{address: 0x0048d065, function_type: PhantomData}; @@ -2476,7 +2484,7 @@ pub mod ztscenariotimer { pub const GET_STATE: FunctionDef u32> = FunctionDef{address: 0x0040f121, function_type: PhantomData}; pub const SIZE: FunctionDef = FunctionDef{address: 0x004113d7, function_type: PhantomData}; pub const UPDATE: FunctionDef = FunctionDef{address: 0x0042425d, function_type: PhantomData}; - pub const SAVE: FunctionDef = FunctionDef{address: 0x0047a04c, function_type: PhantomData}; + pub const SAVE: FunctionDef bool> = FunctionDef{address: 0x0047a04c, function_type: PhantomData}; pub const DISPLAY_GOAL: FunctionDef = FunctionDef{address: 0x004f042c, function_type: PhantomData}; pub const GET_TEXT: FunctionDef u32> = FunctionDef{address: 0x004f0484, function_type: PhantomData}; pub const GET_ICON_NAME: FunctionDef = FunctionDef{address: 0x004f0488, function_type: PhantomData}; @@ -2554,6 +2562,7 @@ pub mod ztshow { pub const INIT: FunctionDef = FunctionDef{address: 0x00612c6e, function_type: PhantomData}; pub const CLEAR: FunctionDef = FunctionDef{address: 0x00612c8c, function_type: PhantomData}; pub const ABORT_SHOW: FunctionDef u32> = FunctionDef{address: 0x00612d20, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00612c91, function_type: PhantomData}; } // ZTShowInfo class functions @@ -2574,7 +2583,7 @@ pub mod ztshowinfo { pub const ADD_UNIT_TO_LIST: FunctionDef u32> = FunctionDef{address: 0x005a9a48, function_type: PhantomData}; pub const ADD_UNIT: FunctionDef u32> = FunctionDef{address: 0x005a9c81, function_type: PhantomData}; pub const REMOVE_UNIT: FunctionDef = FunctionDef{address: 0x005a9c96, function_type: PhantomData}; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00610076, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00610076, function_type: PhantomData}; } // ZTShowMgr class functions @@ -2582,7 +2591,7 @@ pub mod ztshowmgr { use super::*; pub const GET_SHOW_INFO: FunctionDef u32> = FunctionDef{address: 0x0041ebfd, function_type: PhantomData}; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00479fa4, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00479fa4, function_type: PhantomData}; pub const ENTER_NEW_MONTH: FunctionDef = FunctionDef{address: 0x004842a2, function_type: PhantomData}; pub const INIT_SHOW_PARAMS: FunctionDef u32> = FunctionDef{address: 0x0051f59b, function_type: PhantomData}; pub const DESTROY: FunctionDef = FunctionDef{address: 0x0057db2e, function_type: PhantomData}; @@ -2594,7 +2603,7 @@ pub mod ztshowmgr { pub mod ztshowscript { use super::*; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0061c825, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0061c825, function_type: PhantomData}; } // ZTShowScriptItem class functions @@ -2603,14 +2612,20 @@ pub mod ztshowscriptitem { pub const CONSTRUCTOR: FunctionDef u32> = FunctionDef{address: 0x004b9024, function_type: PhantomData}; pub const LOAD: FunctionDef u32> = FunctionDef{address: 0x004b9690, function_type: PhantomData}; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0061c471, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0061c471, function_type: PhantomData}; } // ZTShowScriptMgr class functions pub mod ztshowscriptmgr { use super::*; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00479f44, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00479f44, function_type: PhantomData}; +} + +pub mod ztshowscriptstate { + use super::*; + + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0061c95c, function_type: PhantomData}; } // ZTShowState class functions @@ -2621,6 +2636,7 @@ pub mod ztshowstate { pub const CONSTRUCTOR: FunctionDef u32> = FunctionDef{address: 0x004cc9c6, function_type: PhantomData}; pub const ZTSHOW_STATE: FunctionDef u32> = FunctionDef{address: 0x004f28c3, function_type: PhantomData}; pub const CLEAR: FunctionDef u32> = FunctionDef{address: 0x0059f72f, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00612d89, function_type: PhantomData}; } // ZTSoundscape class functions @@ -2643,6 +2659,7 @@ pub mod ztstaff { pub const ZTSTAFF: FunctionDef u32> = FunctionDef{address: 0x004f9d09, function_type: PhantomData}; pub const REASSIGN_HABITATS: FunctionDef u32> = FunctionDef{address: 0x00595237, function_type: PhantomData}; pub const INIT_AFTER_LOAD: FunctionDef u32> = FunctionDef{address: 0x005952dc, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x004795f9, function_type: PhantomData}; } // ZTStaffType class functions @@ -2697,7 +2714,7 @@ pub mod zttankexhibit { pub const DO_DEPTH_SUITABILITY: FunctionDef = FunctionDef{address: 0x005af4b9, function_type: PhantomData}; pub const ADD_WATER_RIPPLES: FunctionDef = FunctionDef{address: 0x005af78f, function_type: PhantomData}; pub const ADD_WATER_RIPPLE: FunctionDef = FunctionDef{address: 0x005af81a, function_type: PhantomData}; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00606398, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00606398, function_type: PhantomData}; pub const SET_SALINITY: FunctionDef u32> = FunctionDef{address: 0x0060644b, function_type: PhantomData}; pub const DRAIN: FunctionDef = FunctionDef{address: 0x006064ed, function_type: PhantomData}; pub const CHECK_ENTITIES_FOR_DRAIN: FunctionDef i32> = FunctionDef{address: 0x0060656e, function_type: PhantomData}; @@ -2721,7 +2738,7 @@ pub mod zttankfilter { pub const REMOVE_FROM_MAP: FunctionDef = FunctionDef{address: 0x0050558c, function_type: PhantomData}; pub const SET_HEALTHY: FunctionDef = FunctionDef{address: 0x00595c8e, function_type: PhantomData}; pub const SERVICE: FunctionDef = FunctionDef{address: 0x00595cad, function_type: PhantomData}; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00615b31, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00615b31, function_type: PhantomData}; pub const SET_BROKEN: FunctionDef = FunctionDef{address: 0x00615c0f, function_type: PhantomData}; pub const DECAY: FunctionDef = FunctionDef{address: 0x00615c29, function_type: PhantomData}; } @@ -2761,7 +2778,7 @@ pub mod zttankwall { pub const START_PORTAL_OPEN_SOUND: FunctionDef = FunctionDef{address: 0x005a35e1, function_type: PhantomData}; pub const ZTTANK_WALL_0: FunctionDef u32> = FunctionDef{address: 0x005ae7a0, function_type: PhantomData}; pub const ZTTANK_WALL_1: FunctionDef u32> = FunctionDef{address: 0x005ae9e4, function_type: PhantomData}; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00605b38, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00605b38, function_type: PhantomData}; } // ZTTankWallType class functions @@ -2794,7 +2811,7 @@ pub mod ztthoughtmgr { use super::*; pub const GET_THOUGHTS_BY_HABITAT: FunctionDef u32> = FunctionDef{address: 0x0046863a, function_type: PhantomData}; - pub const SAVE: FunctionDef bool> = FunctionDef{address: 0x0047a1a2, function_type: PhantomData}; + pub const SAVE: FunctionDef bool> = FunctionDef{address: 0x0047a1a2, function_type: PhantomData}; pub const REMOVE_THOUGHTS_BY_HABITAT: FunctionDef = FunctionDef{address: 0x004ffe56, function_type: PhantomData}; pub const ZTTHOUGHT_MGR: FunctionDef u32> = FunctionDef{address: 0x0057d815, function_type: PhantomData}; pub const LOAD: FunctionDef bool> = FunctionDef{address: 0x0059435b, function_type: PhantomData}; @@ -3162,7 +3179,7 @@ pub mod ztunit { pub const ABORT_SHOW: FunctionDef = FunctionDef{address: 0x0042fa42, function_type: PhantomData}; pub const UPDATE_BUILDING_TILES: FunctionDef u32> = FunctionDef{address: 0x0043b2f6, function_type: PhantomData}; pub const LOAD: FunctionDef u32> = FunctionDef{address: 0x00454488, function_type: PhantomData}; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00478501, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x00478501, function_type: PhantomData}; pub const F_ZOO_MESSAGE_TILE_0: FunctionDef = FunctionDef{address: 0x004807c2, function_type: PhantomData}; pub const F_ZOO_MESSAGE_TILE_1: FunctionDef = FunctionDef{address: 0x0048083d, function_type: PhantomData}; pub const F_EXIT_BUILDING: FunctionDef = FunctionDef{address: 0x0048c522, function_type: PhantomData}; @@ -3234,7 +3251,7 @@ pub mod ztworldmgr { pub const LOAD: FunctionDef u8> = FunctionDef{address: 0x00452e13, function_type: PhantomData}; pub const CONSTRUCTOR: FunctionDef u32> = FunctionDef{address: 0x004611d4, function_type: PhantomData}; pub const CREATE: FunctionDef = FunctionDef{address: 0x0046498e, function_type: PhantomData}; - pub const SAVE: FunctionDef u8> = FunctionDef{address: 0x0047704c, function_type: PhantomData}; + pub const SAVE: FunctionDef u8> = FunctionDef{address: 0x0047704c, function_type: PhantomData}; pub const REMOVE_ALL_TANK_OWNED_TRANSIENTS: FunctionDef = FunctionDef{address: 0x00479eba, function_type: PhantomData}; pub const REMOVE_TRANSIENTS: FunctionDef = FunctionDef{address: 0x00479efa, function_type: PhantomData}; pub const REMOVE_ALL_WATER_EFFECTS: FunctionDef = FunctionDef{address: 0x00479f0b, function_type: PhantomData}; @@ -3268,7 +3285,7 @@ pub mod zoostatus { pub const BUY_PEOPLE_FOOD: FunctionDef = FunctionDef{address: 0x0042df22, function_type: PhantomData}; pub const INCREASE_DONATIONS: FunctionDef = FunctionDef{address: 0x0042ebbe, function_type: PhantomData}; pub const UPDATE: FunctionDef = FunctionDef{address: 0x004351a9, function_type: PhantomData}; - pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0047ad4e, function_type: PhantomData}; + pub const SAVE: FunctionDef u32> = FunctionDef{address: 0x0047ad4e, function_type: PhantomData}; pub const SPEND_MAINT_WAGES: FunctionDef = FunctionDef{address: 0x00483d34, function_type: PhantomData}; pub const FINANCE_CHECKS: FunctionDef = FunctionDef{address: 0x00483f11, function_type: PhantomData}; pub const INCREASE_ENDOWMENT: FunctionDef = FunctionDef{address: 0x0048442b, function_type: PhantomData}; diff --git a/openzt/src/lib.rs b/openzt/src/lib.rs index ef36e83..d897e4a 100644 --- a/openzt/src/lib.rs +++ b/openzt/src/lib.rs @@ -81,6 +81,9 @@ mod zthabitatmgr; /// classes, which drive the zoo's research tree, funding levels and program completion effects. mod ztresearch; +/// Save/load logging detours for understanding savefile format +mod save_logging; + mod experimental; /// Roof tag extension for scenery entities @@ -192,6 +195,7 @@ mod zoo_init { ztmapview::init(); zthabitatmgr::init(); ztresearch::init(); + save_logging::init(); } unsafe { LOAD_LANG_DLLS_DETOUR.call(this) } } diff --git a/openzt/src/save_logging.rs b/openzt/src/save_logging.rs new file mode 100644 index 0000000..6764f06 --- /dev/null +++ b/openzt/src/save_logging.rs @@ -0,0 +1,395 @@ +use openzt_detour_macro::detour_mod; +use tracing::info; + +#[detour_mod] +mod save_detours { + use openzt_detour::generated::{ + bfaimgr::SAVE as BFAIMGR_SAVE, bfbscall::SAVE as BFSCALL_SAVE, bfentity::SAVE as BFENTITY_SAVE, bfevent::SAVE as BFEVENT_SAVE, + bfeventinfo::SAVE as BFEVENTINFO_SAVE, bfeventmgr::SAVE as BFEVENTMGR_SAVE, bfgamemgr::SAVE as BFGAMEMGR_SAVE, bfmap::SAVE as BFMAP_SAVE, + bfoverlay::SAVE as BFOVERLAY_SAVE, bftile::SAVE as BFTILE_SAVE, bfunit::SAVE as BFUNIT_SAVE, bfworldmgr::SAVE as BFWORLDMGR_SAVE, + standalone::WRITE_BYTES_TO_FILE, zoostatus::SAVE as ZOOSTATUS_SAVE, ztambient::SAVE as ZTAMBIENT_SAVE, ztanimal::SAVE as ZTANIMAL_SAVE, + ztawardmgr::SAVE as ZTAWARDMGR_SAVE, ztcheat::SAVE as ZTCHEAT_SAVE, ztfence::SAVE as ZTFENCE_SAVE, + ztgamemgr::SAVE as ZTGAMEMGR_SAVE, ztguest::SAVE as ZTGUEST_SAVE, ztguide::SAVE as ZTGUIDE_SAVE, zthabitat::SAVE as ZTHABITAT_SAVE, + zthabitatmgr::SAVE as ZTHABITATMGR_SAVE, zthelicopter::SAVE as ZTHELICOPTER_SAVE, ztkeeper::SAVE as ZTKEEPER_SAVE, ztmaint::SAVE as ZTMAINT_SAVE, + ztmapview::SAVE_STATE as ZTMAPVIEW_SAVE_STATE, ztresearchmgr::SAVE as ZTRESEARCHMGR_SAVE, + ztscenariotimer::SAVE as ZTSCENARIOTIMER_SAVE, ztshow::SAVE as ZTSHOW_SAVE, ztshowinfo::SAVE as ZTSHOWINFO_SAVE, + ztshowmgr::SAVE as ZTSHOWMGR_SAVE, ztshowscript::SAVE as ZTSHOWSCRIPT_SAVE, ztshowscriptitem::SAVE as ZTSHOWSCRIPTITEM_SAVE, + ztshowscriptmgr::SAVE as ZTSHOWSCRIPTMGR_SAVE, ztshowscriptstate::SAVE as ZTSHOWSCRIPTSTATE_SAVE, ztshowstate::SAVE as ZTSHOWSTATE_SAVE, + ztstaff::SAVE as ZTSTAFF_SAVE, zttankexhibit::SAVE as ZTTANKEXHIBIT_SAVE, zttankfilter::SAVE as ZTTANKFILTER_SAVE, zttankwall::SAVE as ZTTANKWALL_SAVE, + ztthoughtmgr::SAVE as ZTTHOUGHTMGR_SAVE, ztunit::SAVE as ZTUNIT_SAVE, ztworldmgr::SAVE as ZTWORLDMGR_SAVE, + }; + use std::ffi::c_void; + use tracing::info; + + // Standard SAVE detours (thiscall, u32(*const u32, *const u32) -> u32) + #[detour(BFAIMGR_SAVE)] + unsafe extern "thiscall" fn hook_bfaimgr_save(this: *const u32, file: *const i8) -> u32 { + info!("BFAIMGR::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { BFAIMGR_SAVE_DETOUR.call(this, file) }; + info!("BFAIMGR::SAVE returned: {}", result); + result + } + + #[detour(BFSCALL_SAVE)] + unsafe extern "thiscall" fn hook_bfbscall_save(this: *const u32, file: *const u32) -> u32 { + info!("BFBSCALL::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { BFSCALL_SAVE_DETOUR.call(this, file) }; + info!("BFBSCALL::SAVE returned: {}", result); + result + } + + #[detour(BFENTITY_SAVE)] + unsafe extern "thiscall" fn hook_bfentity_save(this: *const u32, file: *const i8) -> u32 { + info!("BFENTITY::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { BFENTITY_SAVE_DETOUR.call(this, file) }; + info!("BFENTITY::SAVE returned: {}", result); + result + } + + #[detour(BFEVENT_SAVE)] + unsafe extern "thiscall" fn hook_bfevent_save(this: *const u32, file: *const i8) -> u32 { + info!("BFEVENT::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { BFEVENT_SAVE_DETOUR.call(this, file) }; + info!("BFEVENT::SAVE returned: {}", result); + result + } + + #[detour(BFEVENTINFO_SAVE)] + unsafe extern "thiscall" fn hook_bfeventinfo_save(this: *const u32, file: *const i8) -> u32 { + info!("BFEVENTINFO::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { BFEVENTINFO_SAVE_DETOUR.call(this, file) }; + info!("BFEVENTINFO::SAVE returned: {}", result); + result + } + + #[detour(BFEVENTMGR_SAVE)] + unsafe extern "thiscall" fn hook_bfeventmgr_save(this: *const u32, file: *const i8) -> u32 { + info!("BFEVENTMGR::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { BFEVENTMGR_SAVE_DETOUR.call(this, file) }; + info!("BFEVENTMGR::SAVE returned: {}", result); + result + } + + #[detour(BFGAMEMGR_SAVE)] + unsafe extern "thiscall" fn hook_bfgamemgr_save(this: *const u32, file: *const i8) -> u32 { + info!("BFGAMEMGR::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { BFGAMEMGR_SAVE_DETOUR.call(this, file) }; + info!("BFGAMEMGR::SAVE returned: {}", result); + result + } + + #[detour(BFMAP_SAVE)] + unsafe extern "thiscall" fn hook_bfmap_save(this: *const u32, file: *const u32) -> u32 { + info!("BFMAP::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { BFMAP_SAVE_DETOUR.call(this, file) }; + info!("BFMAP::SAVE returned: {}", result); + result + } + + #[detour(BFOVERLAY_SAVE)] + unsafe extern "thiscall" fn hook_bfoverlay_save(this: *const u32, file: *const i8) -> u32 { + info!("BFOVERLAY::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { BFOVERLAY_SAVE_DETOUR.call(this, file) }; + info!("BFOVERLAY::SAVE returned: {}", result); + result + } + + #[detour(BFTILE_SAVE)] + unsafe extern "thiscall" fn hook_bftile_save(this: *const u32, file: *const u32) -> u32 { + info!("BFTILE::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { BFTILE_SAVE_DETOUR.call(this, file) }; + info!("BFTILE::SAVE returned: {}", result); + result + } + + #[detour(BFUNIT_SAVE)] + unsafe extern "thiscall" fn hook_bfunit_save(this: *const u32, file: *const u32) -> u32 { + info!("BFUNIT::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { BFUNIT_SAVE_DETOUR.call(this, file) }; + info!("BFUNIT::SAVE returned: {}", result); + result + } + + #[detour(BFWORLDMGR_SAVE)] + unsafe extern "thiscall" fn hook_bfworldmgr_save(this: *const u32, file: *const i8) -> u32 { + info!("BFWORLDMGR::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { BFWORLDMGR_SAVE_DETOUR.call(this, file) }; + info!("BFWORLDMGR::SAVE returned: {}", result); + result + } + + #[detour(ZTAMBIENT_SAVE)] + unsafe extern "thiscall" fn hook_ztambient_save(this: *const u32, file: *const i8) -> u32 { + info!("ZTAMBIENT::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTAMBIENT_SAVE_DETOUR.call(this, file) }; + info!("ZTAMBIENT::SAVE returned: {}", result); + result + } + + #[detour(ZTANIMAL_SAVE)] + unsafe extern "thiscall" fn hook_ztanimal_save(this: *const u32, file: *const u32) -> bool { + info!("ZTANIMAL::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTANIMAL_SAVE_DETOUR.call(this, file) }; + info!("ZTANIMAL::SAVE returned: {}", result); + result + } + + #[detour(ZTAWARDMGR_SAVE)] + unsafe extern "thiscall" fn hook_ztawardmgr_save(this: *const u32, file: *const i8) -> u32 { + info!("ZTAWARDMGR::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTAWARDMGR_SAVE_DETOUR.call(this, file) }; + info!("ZTAWARDMGR::SAVE returned: {}", result); + result + } + + #[detour(ZTFENCE_SAVE)] + unsafe extern "thiscall" fn hook_ztfence_save(this: *const u32, file: *const i8) -> u32 { + info!("ZTFENCE::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTFENCE_SAVE_DETOUR.call(this, file) }; + info!("ZTFENCE::SAVE returned: {}", result); + result + } + + #[detour(ZTGAMEMGR_SAVE)] + unsafe extern "thiscall" fn hook_ztgamemgr_save(this: *const u32, file: *const i8) -> u32 { + info!("ZTGAMEMGR::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTGAMEMGR_SAVE_DETOUR.call(this, file) }; + info!("ZTGAMEMGR::SAVE returned: {}", result); + result + } + + #[detour(ZTGUEST_SAVE)] + unsafe extern "thiscall" fn hook_ztguest_save(this: *const u32, file: *const u32) -> u32 { + info!("ZTGUEST::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTGUEST_SAVE_DETOUR.call(this, file) }; + info!("ZTGUEST::SAVE returned: {}", result); + result + } + + #[detour(ZTGUIDE_SAVE)] + unsafe extern "thiscall" fn hook_ztguide_save(this: *const u32, file: *const u32) -> u8 { + info!("ZTGUIDE::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTGUIDE_SAVE_DETOUR.call(this, file) }; + info!("ZTGUIDE::SAVE returned: {}", result); + result + } + + #[detour(ZTHABITAT_SAVE)] + unsafe extern "thiscall" fn hook_zthabitat_save(this: *const u32, file: *const i8) -> u32 { + info!("ZTHABITAT::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTHABITAT_SAVE_DETOUR.call(this, file) }; + info!("ZTHABITAT::SAVE returned: {}", result); + result + } + + #[detour(ZTHABITATMGR_SAVE)] + unsafe extern "thiscall" fn hook_zthabitatmgr_save(this: *const u32, file: *const i8) -> u32 { + info!("ZTHABITATMGR::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTHABITATMGR_SAVE_DETOUR.call(this, file) }; + info!("ZTHABITATMGR::SAVE returned: {}", result); + result + } + + #[detour(ZTHELICOPTER_SAVE)] + unsafe extern "thiscall" fn hook_zthelicopter_save(this: *const u32, file: *const u32) -> u32 { + info!("ZTHELICOPTER::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTHELICOPTER_SAVE_DETOUR.call(this, file) }; + info!("ZTHELICOPTER::SAVE returned: {}", result); + result + } + + #[detour(ZTKEEPER_SAVE)] + unsafe extern "thiscall" fn hook_ztkeeper_save(this: *const u32, file: *const u32) -> u32 { + info!("ZTKEEPER::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTKEEPER_SAVE_DETOUR.call(this, file) }; + info!("ZTKEEPER::SAVE returned: {}", result); + result + } + + #[detour(ZTRESEARCHMGR_SAVE)] + unsafe extern "thiscall" fn hook_ztresearchmgr_save(this: *const u32, file: *const u32) -> bool { + info!("ZTRESEARCHMGR::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTRESEARCHMGR_SAVE_DETOUR.call(this, file) }; + info!("ZTRESEARCHMGR::SAVE returned: {}", result); + result + } + + #[detour(ZTSCENARIOTIMER_SAVE)] + unsafe extern "thiscall" fn hook_ztscenariotimer_save(this: *const u32, file: *const u32) -> bool { + info!("ZTSCENARIOTIMER::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTSCENARIOTIMER_SAVE_DETOUR.call(this, file) }; + info!("ZTSCENARIOTIMER::SAVE returned: {}", result); + result + } + + #[detour(ZTSHOW_SAVE)] + unsafe extern "thiscall" fn hook_ztshow_save(this: *const u32, file: *const u32) -> u32 { + info!("ZTSHOW::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTSHOW_SAVE_DETOUR.call(this, file) }; + info!("ZTSHOW::SAVE returned: {}", result); + result + } + + #[detour(ZTSHOWINFO_SAVE)] + unsafe extern "thiscall" fn hook_ztshowinfo_save(this: *const u32, file: *const i8) -> u32 { + info!("ZTSHOWINFO::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTSHOWINFO_SAVE_DETOUR.call(this, file) }; + info!("ZTSHOWINFO::SAVE returned: {}", result); + result + } + + #[detour(ZTSHOWMGR_SAVE)] + unsafe extern "thiscall" fn hook_ztshowmgr_save(this: *const u32, file: *const i8) -> u32 { + info!("ZTSHOWMGR::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTSHOWMGR_SAVE_DETOUR.call(this, file) }; + info!("ZTSHOWMGR::SAVE returned: {}", result); + result + } + + #[detour(ZTSHOWSCRIPTITEM_SAVE)] + unsafe extern "thiscall" fn hook_ztshowscriptitem_save(this: *const u32, file: *const i8) -> u32 { + info!("ZTSHOWSCRIPTITEM::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTSHOWSCRIPTITEM_SAVE_DETOUR.call(this, file) }; + info!("ZTSHOWSCRIPTITEM::SAVE returned: {}", result); + result + } + + #[detour(ZTSHOWSCRIPTSTATE_SAVE)] + unsafe extern "thiscall" fn hook_ztshowscriptstate_save(this: *const u32, file: *const u32) -> u32 { + info!("ZTSHOWSCRIPTSTATE::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTSHOWSCRIPTSTATE_SAVE_DETOUR.call(this, file) }; + info!("ZTSHOWSCRIPTSTATE::SAVE returned: {}", result); + result + } + + #[detour(ZTSHOWSTATE_SAVE)] + unsafe extern "thiscall" fn hook_ztshowstate_save(this: *const u32, file: *const u32) -> u32 { + info!("ZTSHOWSTATE::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTSHOWSTATE_SAVE_DETOUR.call(this, file) }; + info!("ZTSHOWSTATE::SAVE returned: {}", result); + result + } + + #[detour(ZTSTAFF_SAVE)] + unsafe extern "thiscall" fn hook_ztstaff_save(this: *const u32, file: *const u32) -> u32 { + info!("ZTSTAFF::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTSTAFF_SAVE_DETOUR.call(this, file) }; + info!("ZTSTAFF::SAVE returned: {}", result); + result + } + + #[detour(ZTTANKEXHIBIT_SAVE)] + unsafe extern "thiscall" fn hook_zttankexhibit_save(this: *const u32, file: *const i8) -> u32 { + info!("ZTTANKEXHIBIT::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTTANKEXHIBIT_SAVE_DETOUR.call(this, file) }; + info!("ZTTANKEXHIBIT::SAVE returned: {}", result); + result + } + + #[detour(ZTTANKFILTER_SAVE)] + unsafe extern "thiscall" fn hook_zttankfilter_save(this: *const u32, file: *const u32) -> u32 { + info!("ZTTANKFILTER::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTTANKFILTER_SAVE_DETOUR.call(this, file) }; + info!("ZTTANKFILTER::SAVE returned: {}", result); + result + } + + #[detour(ZTTANKWALL_SAVE)] + unsafe extern "thiscall" fn hook_zttankwall_save(this: *const u32, file: *const u32) -> u32 { + info!("ZTTANKWALL::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTTANKWALL_SAVE_DETOUR.call(this, file) }; + info!("ZTTANKWALL::SAVE returned: {}", result); + result + } + + #[detour(ZTTHOUGHTMGR_SAVE)] + unsafe extern "thiscall" fn hook_ztthoughtmgr_save(this: *const u32, file: *const i8) -> bool { + info!("ZTTHOUGHTMGR::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTTHOUGHTMGR_SAVE_DETOUR.call(this, file) }; + info!("ZTTHOUGHTMGR::SAVE returned: {}", result); + result + } + + #[detour(ZTUNIT_SAVE)] + unsafe extern "thiscall" fn hook_ztunit_save(this: *const u32, file: *const i8) -> u32 { + info!("ZTUNIT::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTUNIT_SAVE_DETOUR.call(this, file) }; + info!("ZTUNIT::SAVE returned: {}", result); + result + } + + #[detour(ZTWORLDMGR_SAVE)] + unsafe extern "thiscall" fn hook_ztworldmgr_save(this: *const u32, file: *const i8) -> u8 { + info!("ZTWORLDMGR::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTWORLDMGR_SAVE_DETOUR.call(this, file) }; + info!("ZTWORLDMGR::SAVE returned: {}", result); + result + } + + #[detour(ZOOSTATUS_SAVE)] + unsafe extern "thiscall" fn hook_zoostatus_save(this: *const u32, file: *const i8) -> u32 { + info!("ZOOSTATUS::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZOOSTATUS_SAVE_DETOUR.call(this, file) }; + info!("ZOOSTATUS::SAVE returned: {}", result); + result + } + + // SAVE_STATE detour + #[detour(ZTMAPVIEW_SAVE_STATE)] + unsafe extern "thiscall" fn hook_ztmapview_save_state(this: *const u32, file: *const i8) -> u32 { + info!("ZTMAPVIEW::SAVE_STATE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTMAPVIEW_SAVE_STATE_DETOUR.call(this, file) }; + info!("ZTMAPVIEW::SAVE_STATE returned: {}", result); + result + } + + // Non-standard signature SAVE detours + #[detour(ZTCHEAT_SAVE)] + unsafe extern "cdecl" fn hook_ztcheat_save(file: *const i8) -> u32 { + info!("ZTCHEAT::SAVE called: file={:p}", file); + let result = unsafe { ZTCHEAT_SAVE_DETOUR.call(file) }; + info!("ZTCHEAT::SAVE returned: {}", result); + result + } + + #[detour(ZTMAINT_SAVE)] + unsafe extern "thiscall" fn hook_ztmaint_save(this: *const i32, file: *const u32) -> u32 { + info!("ZTMAINT::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTMAINT_SAVE_DETOUR.call(this, file) }; + info!("ZTMAINT::SAVE returned: {}", result); + result + } + + #[detour(ZTSHOWSCRIPT_SAVE)] + unsafe extern "thiscall" fn hook_ztshowscript_save(this: *const c_void, file: *const i8) -> u32 { + info!("ZTSHOWSCRIPT::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTSHOWSCRIPT_SAVE_DETOUR.call(this, file) }; + info!("ZTSHOWSCRIPT::SAVE returned: {}", result); + result + } + + #[detour(ZTSHOWSCRIPTMGR_SAVE)] + unsafe extern "thiscall" fn hook_ztshowscriptmgr_save(this: *const c_void, file: *const i8) -> u32 { + info!("ZTSHOWSCRIPTMGR::SAVE called: this={:p}, file={:p}", this, file); + let result = unsafe { ZTSHOWSCRIPTMGR_SAVE_DETOUR.call(this, file) }; + info!("ZTSHOWSCRIPTMGR::SAVE returned: {}", result); + result + } + + // WRITE_BYTES_TO_FILE detour + #[detour(WRITE_BYTES_TO_FILE)] + unsafe extern "cdecl" fn hook_write_bytes_to_file(source_ptr: *const u32, size_in_bytes: u32, number_of_occurrences: u32, file_ptr: *const i8) -> bool { + info!( + "WRITE_BYTES_TO_FILE called: source={:p}, size={} bytes, count={}, file={:p}", + source_ptr, size_in_bytes, number_of_occurrences, file_ptr + ); + let result = unsafe { WRITE_BYTES_TO_FILE_DETOUR.call(source_ptr, size_in_bytes, number_of_occurrences, file_ptr) }; + result + } +} + +pub fn init() { + if let Err(e) = unsafe { save_detours::init_detours() } { + info!("Error initializing save logging detours: {}", e); + } +}