Skip to content

Commit 5faca7e

Browse files
committed
Bump hooklet version, add town hall details mod
1 parent 9cd8240 commit 5faca7e

File tree

13 files changed

+303
-219
lines changed

13 files changed

+303
-219
lines changed

Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ exclude = [
3030
version = "0.1.6"
3131

3232
[workspace.dependencies]
33-
#hooklet = "^0.1.5"
34-
hooklet = { path = "../hooklet" }
33+
hooklet = "^0.1.6"
3534
clap = { version = "4.3.0", features = ["derive"] }
3635
simple_logger = "4.1"
3736
log = "0.4"

mod-fix-invulnerable-ship-artillery-slots/src/ffi.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{arch::global_asm, ffi::c_void};
22

3-
use hooklet::X86Rel32Type;
3+
use hooklet::windows::x86::{deploy_rel32_raw, X86Rel32Type};
44
use log::{debug, LevelFilter};
55

66
const PATCH_ADDRESS_1: u32 = 0x0061FDDB;
@@ -14,11 +14,11 @@ pub unsafe extern "C" fn start() -> u32 {
1414
let _ = log::set_logger(&win_dbg_logger::DEBUGGER_LOGGER);
1515
log::set_max_level(LevelFilter::Trace);
1616

17-
if hooklet::deploy_rel32_raw(PATCH_ADDRESS_1 as _, (&fix_index_calc1) as *const _ as _, X86Rel32Type::Jump).is_err() {
17+
if deploy_rel32_raw(PATCH_ADDRESS_1 as _, (&fix_index_calc1) as *const _ as _, X86Rel32Type::Jump).is_err() {
1818
return 1;
1919
}
2020

21-
if hooklet::deploy_rel32_raw(PATCH_ADDRESS_2 as _, (&fix_index_calc2) as *const _ as _, X86Rel32Type::Jump).is_err() {
21+
if deploy_rel32_raw(PATCH_ADDRESS_2 as _, (&fix_index_calc2) as *const _ as _, X86Rel32Type::Jump).is_err() {
2222
return 2;
2323
}
2424

mod-high-res/src/ffi.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::{
55
sync::atomic::{AtomicPtr, Ordering},
66
};
77

8-
use hooklet::{CallRel32Hook, X86Rel32Type};
8+
use hooklet::windows::x86::{deploy_rel32_raw, hook_call_rel32, CallRel32Hook, X86Rel32Type};
99
use log::debug;
1010
use p3_api::{
1111
data::{class27::Class27Ptr, ddraw_fill_solid_rect, ddraw_set_constant_color, ddraw_set_render_dest, get_resolution_height, get_resolution_width},
@@ -47,7 +47,7 @@ pub unsafe extern "C" fn start() -> u32 {
4747
let _ = log::set_logger(&win_dbg_logger::DEBUGGER_LOGGER);
4848
log::set_max_level(log::LevelFilter::Trace);
4949

50-
if hooklet::deploy_rel32_raw(
50+
if deploy_rel32_raw(
5151
CALCULATE_RESOLUTION_ON_OPTIONS_MENU_CLOSE_PATCH_ADDRESS as _,
5252
(&calculate_resolution_after_options_screen) as *const _ as _,
5353
X86Rel32Type::Jump,
@@ -58,7 +58,7 @@ pub unsafe extern "C" fn start() -> u32 {
5858
}
5959

6060
// Replace the mapping from class24 resolution field to width and height values
61-
if hooklet::deploy_rel32_raw(
61+
if deploy_rel32_raw(
6262
CALCULATE_RESOLUTION_BEFORE_SCENE_LOAD_PATCH_ADDRESS as _,
6363
(&calculate_resolution_before_scene_load) as *const _ as _,
6464
X86Rel32Type::Jump,
@@ -69,7 +69,7 @@ pub unsafe extern "C" fn start() -> u32 {
6969
}
7070

7171
// Replace the mapping from ui options resolution field to width and height values
72-
if hooklet::deploy_rel32_raw(
72+
if deploy_rel32_raw(
7373
CALCULATE_RESOLUTION_AFTER_SCENE_LOAD_PATCH_ADDRESS as _,
7474
(&calculate_resolution_after_scene_load) as *const _ as _,
7575
X86Rel32Type::Jump,
@@ -80,7 +80,7 @@ pub unsafe extern "C" fn start() -> u32 {
8080
}
8181

8282
debug!("Deploying resolution dependent ui positioning patch");
83-
if hooklet::deploy_rel32_raw(
83+
if deploy_rel32_raw(
8484
REPOSITION_UI_ELEMENTS_PATCH_ADDRESS as _,
8585
(&reposition_ui_elements) as *const _ as _,
8686
X86Rel32Type::Jump,
@@ -91,7 +91,7 @@ pub unsafe extern "C" fn start() -> u32 {
9191
}
9292

9393
debug!("Deploying resolution dependent top bar ui positioning patch");
94-
if hooklet::deploy_rel32_raw(
94+
if deploy_rel32_raw(
9595
REPOSITION_UI_ELEMENTS_TOP_BAR_PATCH_ADDRESS as _,
9696
(&reposition_ui_elements_top_bar) as *const _ as _,
9797
X86Rel32Type::Jump,
@@ -103,7 +103,7 @@ pub unsafe extern "C" fn start() -> u32 {
103103

104104
// Fix empty bottom right corner
105105
debug!("Deploying render_all_objects_hook");
106-
match hooklet::hook_call_rel32(PCSTR::from_raw(ptr::null()), 0x28649, maybe_render_all_objects_hook as usize) {
106+
match hook_call_rel32(PCSTR::from_raw(ptr::null()), 0x28649, maybe_render_all_objects_hook as usize as u32) {
107107
Ok(hook) => {
108108
HOOK_PTR.store(Box::into_raw(Box::new(hook)), Ordering::SeqCst);
109109
}
@@ -112,10 +112,10 @@ pub unsafe extern "C" fn start() -> u32 {
112112

113113
// Fix acceleration map
114114
debug!("Deploying dddraw_dll.dll decode_supported_files hook to replace the background image");
115-
match hooklet::hook_call_rel32(
115+
match hook_call_rel32(
116116
PCSTR::from_raw(c"aim.dll".as_ptr() as _),
117117
0x2984,
118-
ddraw_dll_decode_supported_files_hook as usize,
118+
ddraw_dll_decode_supported_files_hook as usize as u32,
119119
) {
120120
Ok(hook) => {
121121
debug!("Hook {hook:?} set");
@@ -126,7 +126,7 @@ pub unsafe extern "C" fn start() -> u32 {
126126

127127
// Fix acceleration map
128128
debug!("Deploying load screen settings from accelMap.ini");
129-
match hooklet::hook_call_rel32(PCSTR::from_raw(ptr::null()), 0x12C5, class73_place_ui_element_hook as usize) {
129+
match hook_call_rel32(PCSTR::from_raw(ptr::null()), 0x12C5, class73_place_ui_element_hook as usize as u32) {
130130
Ok(hook) => {
131131
debug!("Hook {hook:?} set");
132132
LOAD_ACCEL_MAP_INI_HOOK_PTR.store(Box::into_raw(Box::new(hook)), Ordering::SeqCst);

mod-shipyard-details/src/ffi.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::{
33
ffi::{c_void, CStr, CString},
44
};
55

6-
use hooklet::X86Rel32Type;
6+
use hooklet::windows::x86::{deploy_rel32_raw, X86Rel32Type};
77
use log::debug;
88
use p3_api::{
99
data::{
@@ -42,7 +42,7 @@ pub unsafe extern "C" fn start() -> u32 {
4242
let _ = log::set_logger(&win_dbg_logger::DEBUGGER_LOGGER);
4343
log::set_max_level(log::LevelFilter::Trace);
4444

45-
if hooklet::deploy_rel32_raw(
45+
if deploy_rel32_raw(
4646
SHIPYARD_WINDOW_OPEN_PATCH_ADDRESS as _,
4747
(&ui_shipyard_window_open_detour) as *const _ as _,
4848
X86Rel32Type::Jump,
@@ -52,7 +52,7 @@ pub unsafe extern "C" fn start() -> u32 {
5252
return 1;
5353
}
5454

55-
if hooklet::deploy_rel32_raw(
55+
if deploy_rel32_raw(
5656
LOAD_SHIPYARD_SELECTED_PAGE_PATCH_ADDRESS as _,
5757
(&load_shipyard_selected_page_detour) as *const _ as _,
5858
X86Rel32Type::Jump,

mod-town-hall-details/src/ffi.rs

Lines changed: 43 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,22 @@
11
use std::{
22
arch::global_asm,
3-
ffi::{c_void, CStr, CString},
4-
ptr,
3+
ffi::c_void,
4+
mem, ptr,
55
sync::atomic::{AtomicPtr, Ordering},
66
};
77

8-
use hooklet::{FunctionPointerHook, X86Rel32Type};
8+
use hooklet::windows::x86::{deploy_rel32_raw, hook_call_rel32, CallRel32Hook, FunctionPointerHook, X86Rel32Type};
9+
use hooklet::windows::x86::hook_function_pointer;
910
use log::debug;
10-
use p3_api::{
11-
data::{class48::Class48Ptr, ddraw_set_constant_color, ddraw_set_text_mode, ui_render_text_at},
12-
game_world::GAME_WORLD_PTR,
13-
missions::alderman_missions::{AldermanMissionDataPtr, FoundTownPtr},
14-
scheduled_tasks::{
15-
scheduled_task::{ScheduledTaskData, ScheduledTaskPtr},
16-
SCHEDULED_TASKS_PTR,
17-
},
18-
ui::{
19-
font::{self, get_normal_font},
20-
ui_town_hall_window::UITownHallWindowPtr,
21-
},
22-
};
11+
use p3_api::ui::ui_town_hall_window::UITownHallWindowPtr;
2312
use windows::core::PCSTR;
2413

25-
pub static TOWN: &CStr = c"Town";
26-
pub static TASK_DUE_IN: &CStr = c"Rescheduling in";
27-
pub static EFFECTIVE_PRODUCTION: &CStr = c"Effective Production";
28-
2914
const TOWN_HALL_WINDOW_OPEN_POINTER_OFFSET: u32 = UITownHallWindowPtr::VTABLE_OFFSET + 0x120;
3015
pub static TOWN_HALL_WINDOW_OPEN_HOOK_PTR: AtomicPtr<FunctionPointerHook> = AtomicPtr::new(std::ptr::null_mut());
3116

17+
const TOWN_HALL_SIDEPANEL_SET_SELECTED_PAGE_PATCH_OFFSET: u32 = 0x1A94BC;
18+
pub static TOWN_HALL_SIDEPANEL_SET_SELECTED_PAGE_HOOK_PTR: AtomicPtr<CallRel32Hook> = AtomicPtr::new(std::ptr::null_mut());
19+
3220
const LOAD_TOWN_HALL_SELECTED_PAGE_PATCH_ADDRESS: u32 = 0x005E09AC;
3321
static LOAD_TOWN_HALL_SELECTED_PAGE_CONTINUATION: u32 = 0x005E09B2;
3422

@@ -37,108 +25,69 @@ pub unsafe extern "C" fn start() -> u32 {
3725
let _ = log::set_logger(&win_dbg_logger::DEBUGGER_LOGGER);
3826
log::set_max_level(log::LevelFilter::Trace);
3927

40-
debug!("Hooking town hall's open function through vtable");
41-
match hooklet::hook_function_pointer(
28+
debug!("Hooking town hall window's open function through vtable");
29+
match hook_function_pointer(
4230
PCSTR::from_raw(ptr::null()),
4331
TOWN_HALL_WINDOW_OPEN_POINTER_OFFSET,
44-
town_hall_open_hook as usize as u32,
32+
town_hall_window_open_hook as usize as u32,
4533
) {
4634
Ok(hook) => {
47-
debug!("Hook {hook:?} set");
35+
debug!("Hook {hook:X?} set");
4836
TOWN_HALL_WINDOW_OPEN_HOOK_PTR.store(Box::into_raw(Box::new(hook)), Ordering::SeqCst);
4937
}
5038
Err(_) => {
5139
return 1;
5240
}
5341
}
5442

43+
debug!("Hooking sidepanel's call to ui_town_hall_window_set_selected_page");
44+
match hook_call_rel32(
45+
PCSTR::from_raw(ptr::null()),
46+
TOWN_HALL_SIDEPANEL_SET_SELECTED_PAGE_PATCH_OFFSET,
47+
town_hall_window_set_selected_page_hook as usize as u32,
48+
) {
49+
Ok(hook) => {
50+
debug!("Hook {hook:X?} set");
51+
TOWN_HALL_SIDEPANEL_SET_SELECTED_PAGE_HOOK_PTR.store(Box::into_raw(Box::new(hook)), Ordering::SeqCst);
52+
}
53+
Err(_) => {
54+
return 2;
55+
}
56+
}
57+
5558
debug!("Detouring town hall's rendering function at the selected page switch");
56-
if hooklet::deploy_rel32_raw(
59+
if deploy_rel32_raw(
5760
LOAD_TOWN_HALL_SELECTED_PAGE_PATCH_ADDRESS as _,
5861
(&load_town_hall_selected_page_detour) as *const _ as _,
5962
X86Rel32Type::Jump,
6063
)
6164
.is_err()
6265
{
63-
return 2;
66+
return 3;
6467
}
6568

6669
0
6770
}
6871

6972
#[no_mangle]
70-
pub unsafe extern "thiscall" fn town_hall_open_hook(ui_town_hall_window_address: u32) {
71-
crate::handle_open(ui_town_hall_window_address)
73+
unsafe extern "thiscall" fn town_hall_window_open_hook(ui_town_hall_window_address: u32) {
74+
let orig_address = (*TOWN_HALL_WINDOW_OPEN_HOOK_PTR.load(Ordering::SeqCst)).old_absolute;
75+
let orig: extern "thiscall" fn(a1: u32) = mem::transmute(orig_address);
76+
orig(ui_town_hall_window_address);
77+
crate::handle_open()
7278
}
7379

7480
#[no_mangle]
75-
pub unsafe extern "thiscall" fn town_hall_rendering_hook() -> i32 {
76-
crate::handle_selected_page_switch()
77-
}
78-
79-
pub unsafe fn render_aldermans_office_modifications(window: &UITownHallWindowPtr) {
80-
let next_mission_index = window.get_next_mission_index();
81-
if next_mission_index == 0 {
82-
return;
83-
}
84-
85-
let selected_mission_index = window.get_selected_alderman_mission_index();
86-
if selected_mission_index == 0xff {
87-
return;
88-
}
89-
let task_index = window.get_task_index(selected_mission_index);
90-
let task = SCHEDULED_TASKS_PTR.get_scheduled_task(task_index);
91-
let data = match task.get_data() {
92-
Some(e) => e,
93-
None => return,
94-
};
95-
96-
let mission = match data {
97-
ScheduledTaskData::AldermanMission(mission) => mission,
98-
_ => return,
99-
};
100-
match mission.get_data() {
101-
AldermanMissionDataPtr::FoundTownPtr(ptr) => render_aldermans_office_modifications_found_town(window, &task, &ptr),
102-
AldermanMissionDataPtr::OverlandTradeRoute(_ptr) => {}
103-
AldermanMissionDataPtr::NotoriousPirate(_ptr) => {}
104-
AldermanMissionDataPtr::PirateHideout(_ptr) => {}
105-
AldermanMissionDataPtr::SupplyProblems(_ptr) => {}
106-
}
81+
unsafe extern "thiscall" fn town_hall_window_set_selected_page_hook(ui_town_hall_window_address: u32, page: u32) {
82+
let orig_address = (*TOWN_HALL_SIDEPANEL_SET_SELECTED_PAGE_HOOK_PTR.load(Ordering::SeqCst)).old_absolute;
83+
let orig: extern "thiscall" fn(ui_town_hall_window_address: u32, page: u32) = mem::transmute(orig_address);
84+
orig(ui_town_hall_window_address, page);
85+
crate::handle_set_selected_page(page)
10786
}
10887

109-
unsafe fn render_aldermans_office_modifications_found_town(window: &UITownHallWindowPtr, task: &ScheduledTaskPtr, data: &FoundTownPtr) {
110-
let town = data.get_town();
111-
let effective = data.get_production_effective();
112-
let class48 = Class48Ptr::new();
113-
class48.set_ignore_below_gradient(0);
114-
class48.set_gradient_y(0);
115-
116-
ddraw_set_constant_color(0xff000000);
117-
ddraw_set_text_mode(2);
118-
font::ddraw_set_font(get_normal_font());
119-
let x = window.get_x();
120-
let mut y = window.get_y() + 60;
121-
122-
ui_render_text_at(x + 120, y, TASK_DUE_IN.to_bytes());
123-
let due_in = task.get_due_timestamp() - GAME_WORLD_PTR.get_game_time_raw();
124-
let task_due_in_cstring = CString::new(format!("{due_in}")).unwrap();
125-
ui_render_text_at(x + 420, y, task_due_in_cstring.to_bytes());
126-
y += 20;
127-
128-
ui_render_text_at(x + 120, y, TOWN.to_bytes());
129-
let town_cstring = CString::new(format!("{town:?}")).unwrap();
130-
ui_render_text_at(x + 420, y, town_cstring.to_bytes());
131-
y += 20;
132-
133-
ui_render_text_at(x + 120, y, EFFECTIVE_PRODUCTION.to_bytes());
134-
let mut effective_string = String::new();
135-
for facility in effective {
136-
effective_string.push_str(&format!("{facility:?}, "));
137-
}
138-
effective_string.pop();
139-
effective_string.pop();
140-
let effective_cstring = CString::new(effective_string).unwrap();
141-
ui_render_text_at(x + 420, y, effective_cstring.to_bytes());
88+
#[no_mangle]
89+
unsafe extern "thiscall" fn town_hall_selected_page_switch_hook() -> i32 {
90+
crate::handle_selected_page_switch()
14291
}
14392

14493
extern "C" {
@@ -161,5 +110,5 @@ pop ecx
161110
jmp [{continuation}]
162111
",
163112
load_town_hall_selected_page_detour = sym load_town_hall_selected_page_detour,
164-
town_hall_rendering_hook = sym town_hall_rendering_hook,
113+
town_hall_rendering_hook = sym town_hall_selected_page_switch_hook,
165114
continuation = sym LOAD_TOWN_HALL_SELECTED_PAGE_CONTINUATION);

0 commit comments

Comments
 (0)