Download crates/openwa-core/src/engine/game_session.rs from nmarshall/wormz-a: direct link, hf CLI and curl.
- Browser
- Download file 5.36 kB
-
https://huggingface.co/nmarshall/wormz-a/resolve/main/crates/openwa-core/src/engine/game_session.rs
- Command line
-
hf download hf://nmarshall/wormz-a/crates/openwa-core/src/engine/game_session.rs
-
curl -L -o game_session.rs https://huggingface.co/nmarshall/wormz-a/resolve/main/crates/openwa-core/src/engine/game_session.rs
5.36 kB
| use crate::audio::dssound::DSSound; | |
| use crate::audio::music::Music; | |
| use crate::engine::ddgame_wrapper::DDGameWrapper; | |
| use crate::input::keyboard::DDKeyboard; | |
| use crate::render::display::palette::Palette; | |
| use crate::FieldRegistry; | |
| /// Top-level game session context, allocated once per game run. | |
| /// | |
| /// `G_GAME_SESSION` (0x7A0884) stores a pointer to this struct. Created by | |
| /// `GameSession__Constructor` (0x58BFA0, usercall EAX=this), populated by | |
| /// `GameEngine__InitHardware` (0x56D350), and destroyed by | |
| /// `GameEngine__Shutdown` (0x56DCD0). | |
| /// | |
| /// Lifecycle: | |
| /// ```text | |
| /// GameSession__Run (0x572F50, ESI=GameInfo) | |
| /// ββ alloc 0x120 bytes β GameSession__Constructor (0x58BFA0) | |
| /// ββ G_GAME_SESSION β &this | |
| /// ββ GameEngine__InitHardware β fills subsystem pointers (0xA0β0xC0) | |
| /// ββ game main loop (exit when exit_flag != 0) | |
| /// ββ GameEngine__Shutdown β destroys all subsystems | |
| /// ``` | |
| /// | |
| /// In headless/stats mode (`GameInfo+0xF914 != 0`), `display_gfx` holds a | |
| /// `GameStats` object with a DDInput vtable instead of a real `DisplayGfx`. | |
| pub struct GameSession { | |
| /// 0x000: vtable pointer (class `GameSession`, `PTR_FUN_0066b3f8`) | |
| pub vtable: *mut u8, | |
| pub _unknown_004: [u8; 4], | |
| /// 0x008: main window HWND, stored from `hWnd` in `GameSession__Run` | |
| pub hwnd: u32, | |
| pub _unknown_00c: [u8; 0x18], | |
| /// 0x024: Always set to 1 by GameEngine__InitHardware. | |
| pub init_flag: u32, | |
| /// 0x028: Fullscreen flag β `(GameInfo.home_lock != 0) as u32`. | |
| pub fullscreen_flag: u32, | |
| /// 0x02C: set to 1 on init (role TBD) | |
| pub flag_2c: u32, | |
| pub _unknown_030: [u8; 8], | |
| /// 0x038: back-pointer to the `GameInfo` config struct (ESI from `GameSession__Run`) | |
| pub config_ptr: *mut u8, | |
| /// 0x03C: nonzero = exit the game main loop (checked each frame in `GameSession__Run`) | |
| pub exit_flag: u32, | |
| /// 0x040: game-end status/result code | |
| pub flag_40: u32, | |
| pub _unknown_044: [u8; 0x10], | |
| /// 0x054: display center X = `display_width / 2`. | |
| /// Initialized to `0x80000000` by `GameSession__Constructor`, then overwritten. | |
| pub screen_center_x: i32, | |
| /// 0x058: display center Y = `display_height / 2` | |
| pub screen_center_y: i32, | |
| pub _unknown_05c: [u8; 0x14], | |
| /// 0x070: cursor X at session start (from `GetCursorPos`) | |
| pub cursor_initial_x: i32, | |
| /// 0x074: cursor Y at session start | |
| pub cursor_initial_y: i32, | |
| pub _unknown_078: [u8; 8], | |
| /// 0x080: cursor center X β set to `screen_center_x`, used for `SetCursorPos` | |
| pub cursor_x: i32, | |
| /// 0x084: cursor center Y | |
| pub cursor_y: i32, | |
| pub _unknown_088: [u8; 8], | |
| /// 0x090: `QueryPerformanceFrequency` result low DWORD (0 if QPC unavailable) | |
| pub timer_freq_lo: u32, | |
| /// 0x094: high DWORD | |
| pub timer_freq_hi: u32, | |
| /// 0x098: QPC counter accumulator low DWORD | |
| pub timer_counter_lo: u32, | |
| /// 0x09C: high DWORD | |
| pub timer_counter_hi: u32, | |
| /// 0x0A0: `DDGameWrapper*` β the main game object wrapper (β `DDGame` at `+0x488`) | |
| pub ddgame_wrapper: *mut DDGameWrapper, | |
| /// 0x0A4: `DDKeyboard*` β 0x33C bytes, vtable `DDKeyboard_vtable` (0x66AEC8) | |
| pub keyboard: *mut DDKeyboard, | |
| /// 0x0A8: `DSSound*` β 0xBE0 bytes, vtable `DSSound_vtable` (0x66AF20) | |
| pub sound: *mut DSSound, | |
| /// 0x0AC: Polymorphic display β `DisplayGfx*` (normal) or `DisplayBase*` (headless). | |
| /// Stays `*mut u8` because the concrete type depends on mode. | |
| pub display: *mut u8, | |
| /// 0x0B0: `Palette*` β 0x28 bytes, vtable `Palette_vtable_Maybe` | |
| pub palette: *mut Palette, | |
| /// 0x0B4: Music object β 0x354 bytes (constructor 0x58BC10, vtable 0x66B3E0). | |
| /// Combines playlist controller + embedded streaming audio engine. | |
| pub streaming_audio: *mut Music, | |
| /// 0x0B8: input controller β 0x1800 bytes; null if `param_4 == 0` at init | |
| pub input_ctrl: *mut u8, | |
| /// 0x0BC: timing object β 0x30 bytes (`FUN_0053e950`) | |
| pub timer_obj: *mut u8, | |
| /// 0x0C0: `DDNetGameWrapper*` β 0x2C bytes | |
| pub net_game: *mut u8, | |
| pub _unknown_0c4: [u8; 0x5C], | |
| } | |
| const _: () = assert!(core::mem::size_of::<GameSession>() == 0x120); | |
| // βββ Runtime accessors (DLL-injected context only) ββββββββββββββββββββββ | |
| use crate::address::va; | |
| use crate::engine::ddgame::DDGame; | |
| use crate::rebase::rb; | |
| /// Get the DDGameWrapper pointer from the global game session. | |
| /// | |
| /// Returns null if the session or wrapper hasn't been initialized yet. | |
| pub unsafe fn get_wrapper() -> *mut DDGameWrapper { | |
| let session = *(rb(va::G_GAME_SESSION) as *const *mut GameSession); | |
| if session.is_null() { | |
| return core::ptr::null_mut(); | |
| } | |
| (*session).ddgame_wrapper | |
| } | |
| /// Get the DDGame pointer from the global game session. | |
| /// | |
| /// Follows the chain: G_GAME_SESSION β GameSession.ddgame_wrapper β DDGameWrapper.ddgame. | |
| /// Returns null if any link in the chain is uninitialized. | |
| pub unsafe fn get_ddgame() -> *mut DDGame { | |
| let wrapper = get_wrapper(); | |
| if wrapper.is_null() { | |
| return core::ptr::null_mut(); | |
| } | |
| (*wrapper).ddgame | |
| } | |