Skip to content

Commit e146f92

Browse files
committed
Fix market hall town production display bug
1 parent fca0fed commit e146f92

File tree

7 files changed

+201
-36
lines changed

7 files changed

+201
-36
lines changed

.github/workflows/release.yml

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ jobs:
1414
- run: cargo build --release
1515
- run: |
1616
mkdir mods
17+
mv target/i686-pc-windows-msvc/release/fix_market_hall_production_town.dll ./mods/
1718
mv target/i686-pc-windows-msvc/release/scrollmap_render_all_ships.dll ./mods/
1819
mv target/i686-pc-windows-msvc/release/tavern_show_all_sailors.dll ./mods/
1920
mkdir files

Cargo.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ resolver = "2"
44
members = [
55
"aimcli",
66
"cprcli",
7-
"mod-scrollmap-render-all-ships", "mod-tavern-show-all-sailors",
7+
"mod-fix-market-hall-production-town",
8+
"mod-scrollmap-render-all-ships",
9+
"mod-tavern-show-all-sailors",
810
#"p3-agent",
911
"p3-agent-loader",
1012
"p3-aim",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[package]
2+
name = "mod-fix-market-hall-production-town"
3+
edition = "2021"
4+
version.workspace = true
5+
6+
[lib]
7+
crate-type = ["cdylib"]
8+
name="fix_market_hall_production_town"
9+
10+
[dependencies]
11+
log = { workspace = true }
12+
win_dbg_logger = { workspace = true }
13+
14+
[dependencies.windows]
15+
version = "0.48"
16+
features = [
17+
"Win32_Foundation",
18+
"Win32_System_Memory",
19+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
use log::{debug, error, LevelFilter};
2+
use std::{arch::global_asm, ffi::c_void};
3+
use windows::Win32::{
4+
Foundation::{GetLastError, WIN32_ERROR},
5+
System::Memory::{VirtualProtect, PAGE_EXECUTE_READWRITE, PAGE_PROTECTION_FLAGS},
6+
};
7+
pub static TITLE: &str = concat!(" Weekly production (fixed)", "\0");
8+
const WEEKLY_PRODUCTION_STRING_PTR: *mut *const u8 = 0x006A081C as _;
9+
static SEVEN: f32 = 7.0;
10+
static FTOL_ADDRESS: u32 = 0x00639C28;
11+
static CONTINUATION_ADDRESS: u32 = 0x005DEACC;
12+
static BARREL_PATCH_ADDRESS: u32 = 0x005DEA18;
13+
static BUNDLE_PATCH_ADDRESS: u32 = 0x005DEA73;
14+
15+
#[no_mangle]
16+
pub unsafe extern "C" fn start() -> u32 {
17+
let _ = log::set_logger(&win_dbg_logger::DEBUGGER_LOGGER);
18+
log::set_max_level(LevelFilter::Trace);
19+
20+
// Patch barrels
21+
let barrel_patch_address: u32 = (&barrel_ware_detour) as *const _ as _;
22+
let relative_barrel_patch_address: u32 = barrel_patch_address.wrapping_sub(BARREL_PATCH_ADDRESS) - 5; //TODO move pointer calcs to hooklet
23+
24+
let mut barrel_patch: [u8; 5] = [0; 5];
25+
barrel_patch[0] = 0xe9;
26+
barrel_patch[1..5].copy_from_slice(&relative_barrel_patch_address.to_le_bytes());
27+
let patch_ptr: *mut u8 = BARREL_PATCH_ADDRESS as _;
28+
29+
let mut old_flags: PAGE_PROTECTION_FLAGS = windows::Win32::System::Memory::PAGE_PROTECTION_FLAGS(0);
30+
if !VirtualProtect(patch_ptr as _, 5, PAGE_EXECUTE_READWRITE, &mut old_flags).as_bool() {
31+
let error: WIN32_ERROR = GetLastError();
32+
error!("VirtualProtect PAGE_EXECUTE_READWRITE failed: {:?}", error);
33+
return 1;
34+
}
35+
36+
debug!("Deploying barrel patch at {:x?}", barrel_patch_address as *const u32);
37+
patch_ptr.copy_from(barrel_patch.as_ptr(), barrel_patch.len());
38+
39+
if !VirtualProtect(patch_ptr as _, 5, old_flags, &mut old_flags).as_bool() {
40+
let error: WIN32_ERROR = GetLastError();
41+
error!("VirtualProtect restore failed: {:?}", error);
42+
return 2;
43+
}
44+
45+
// Patch bundles
46+
let bundle_patch_address: u32 = (&bundle_ware_detour) as *const _ as _;
47+
let relative_bundle_patch_address: u32 = bundle_patch_address.wrapping_sub(BUNDLE_PATCH_ADDRESS) - 5; //TODO move pointer calcs to hooklet
48+
49+
let mut bundle_patch: [u8; 5] = [0; 5];
50+
bundle_patch[0] = 0xe9;
51+
bundle_patch[1..5].copy_from_slice(&relative_bundle_patch_address.to_le_bytes());
52+
let patch_ptr: *mut u8 = BUNDLE_PATCH_ADDRESS as _;
53+
54+
let mut old_flags: PAGE_PROTECTION_FLAGS = windows::Win32::System::Memory::PAGE_PROTECTION_FLAGS(0);
55+
if !VirtualProtect(patch_ptr as _, 5, PAGE_EXECUTE_READWRITE, &mut old_flags).as_bool() {
56+
let error: WIN32_ERROR = GetLastError();
57+
error!("VirtualProtect PAGE_EXECUTE_READWRITE failed: {:?}", error);
58+
return 1;
59+
}
60+
61+
debug!("Deploying bundle patch at {:x?}", bundle_patch_address as *const u32);
62+
patch_ptr.copy_from(bundle_patch.as_ptr(), bundle_patch.len());
63+
64+
if !VirtualProtect(patch_ptr as _, 5, old_flags, &mut old_flags).as_bool() {
65+
let error: WIN32_ERROR = GetLastError();
66+
error!("VirtualProtect restore failed: {:?}", error);
67+
return 2;
68+
}
69+
70+
// Patch title
71+
*WEEKLY_PRODUCTION_STRING_PTR = TITLE.as_ptr();
72+
0
73+
}
74+
75+
extern "C" {
76+
static barrel_ware_detour: c_void;
77+
static bundle_ware_detour: c_void;
78+
}
79+
80+
// Barrel wares
81+
global_asm!("
82+
.global {barrel_ware_detour}
83+
{barrel_ware_detour}:
84+
shl edx,0x6
85+
sub edx,eax
86+
lea ebp,[ecx+edx*2]
87+
fild DWORD PTR [esi+ebp*4+0x4]
88+
fstp DWORD PTR [esp+0x20]
89+
fld DWORD PTR [esp+0x20]
90+
fdiv DWORD PTR ds:0x66a91c
91+
fadd QWORD PTR ds:0x66a7d0
92+
call [{ftol_addresss}]
93+
fild DWORD PTR [esi+ebp*4+0xc4]
94+
mov edi,eax
95+
fstp DWORD PTR [esp+0x20]
96+
fld DWORD PTR [esp+0x20]
97+
fdiv DWORD PTR ds:0x66a91c
98+
fmul DWORD PTR ds:{seven}
99+
fadd QWORD PTR ds:0x66a7d0
100+
call [{ftol_addresss}]
101+
fild DWORD PTR [esp+0x18]
102+
fstp DWORD PTR [esp+0x20]
103+
fld DWORD PTR [esp+0x20]
104+
fdiv DWORD PTR ds:0x66a91c
105+
jmp [{continuation_address}]
106+
",
107+
barrel_ware_detour = sym barrel_ware_detour,
108+
ftol_addresss = sym FTOL_ADDRESS,
109+
seven = sym SEVEN,
110+
continuation_address = sym CONTINUATION_ADDRESS);
111+
112+
// Bundle wares
113+
global_asm!("
114+
.global {bundle_ware_detour}
115+
{bundle_ware_detour}:
116+
shl edx,0x6
117+
sub edx,eax
118+
lea ebp,[ecx+edx*2]
119+
fild DWORD PTR [esi+ebp*4+0x4]
120+
fstp DWORD PTR [esp+0x20]
121+
fld DWORD PTR [esp+0x20]
122+
fdiv DWORD PTR ds:0x66a918
123+
fadd QWORD PTR ds:0x66a7d0
124+
call [{ftol_addresss}]
125+
fild DWORD PTR [esi+ebp*4+0xc4]
126+
mov edi,eax
127+
fstp DWORD PTR [esp+0x20]
128+
fld DWORD PTR [esp+0x20]
129+
fdiv DWORD PTR ds:0x66a918
130+
fmul DWORD PTR ds:{seven}
131+
fadd QWORD PTR ds:0x66a7d0
132+
call [{ftol_addresss}]
133+
fild DWORD PTR [esp+0x18]
134+
fstp DWORD PTR [esp+0x20]
135+
fld DWORD PTR [esp+0x20]
136+
fdiv DWORD PTR ds:0x66a918
137+
jmp [{continuation_address}]
138+
",
139+
bundle_ware_detour = sym bundle_ware_detour,
140+
ftol_addresss = sym FTOL_ADDRESS,
141+
seven = sym SEVEN,
142+
continuation_address = sym CONTINUATION_ADDRESS);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub(crate) mod ffi;

mod-scrollmap-render-all-ships/src/ffi.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use std::{arch::global_asm, os::raw::c_void};
1+
use std::{arch::global_asm, ffi::c_void};
22

3-
use log::{debug, error};
3+
use log::{debug, error, LevelFilter};
44
use p3_api::{data::ships::ShipsPtr, p3_access_api::raw_p3_access_api::RawP3AccessApi};
55
use windows::Win32::{
66
Foundation::{GetLastError, WIN32_ERROR},
@@ -13,7 +13,7 @@ pub const P3: RawP3AccessApi = RawP3AccessApi::new();
1313
#[no_mangle]
1414
pub unsafe extern "C" fn start() -> u32 {
1515
let _ = log::set_logger(&win_dbg_logger::DEBUGGER_LOGGER);
16-
log::set_max_level(log::LevelFilter::Trace);
16+
log::set_max_level(LevelFilter::Trace);
1717
let trampoline_address: u32 = (&draw_all_ships_trampoline) as *const _ as _;
1818
let relative_trampoline_address: u32 = trampoline_address.wrapping_sub(PATCH_ADDRESS) - 5; //TODO move pointer calcs to hooklet
1919

+32-32
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,32 @@
1-
use log::{debug, error};
2-
use windows::Win32::{
3-
Foundation::{GetLastError, WIN32_ERROR},
4-
System::Memory::{VirtualProtect, PAGE_EXECUTE_READWRITE, PAGE_PROTECTION_FLAGS},
5-
};
6-
7-
const PATCH_ADDRESS: u32 = 0x005D4CD6;
8-
9-
#[no_mangle]
10-
pub unsafe extern "C" fn start() -> u32 {
11-
let _ = log::set_logger(&win_dbg_logger::DEBUGGER_LOGGER);
12-
log::set_max_level(log::LevelFilter::Trace);
13-
let patch_ptr: *mut u8 = PATCH_ADDRESS as _;
14-
15-
let mut old_flags: PAGE_PROTECTION_FLAGS = windows::Win32::System::Memory::PAGE_PROTECTION_FLAGS(0);
16-
if !VirtualProtect(patch_ptr as _, 5, PAGE_EXECUTE_READWRITE, &mut old_flags).as_bool() {
17-
let error: WIN32_ERROR = GetLastError();
18-
error!("VirtualProtect PAGE_EXECUTE_READWRITE failed: {:?}", error);
19-
return 1;
20-
}
21-
22-
debug!("Patching comparison at {:#x}", PATCH_ADDRESS);
23-
*patch_ptr = 0x64;
24-
25-
if !VirtualProtect(patch_ptr as _, 5, old_flags, &mut old_flags).as_bool() {
26-
let error: WIN32_ERROR = GetLastError();
27-
error!("VirtualProtect restore failed: {:?}", error);
28-
return 2;
29-
}
30-
31-
0
32-
}
1+
use log::{debug, error};
2+
use windows::Win32::{
3+
Foundation::{GetLastError, WIN32_ERROR},
4+
System::Memory::{VirtualProtect, PAGE_EXECUTE_READWRITE, PAGE_PROTECTION_FLAGS},
5+
};
6+
7+
const PATCH_ADDRESS: u32 = 0x005D4CD6;
8+
9+
#[no_mangle]
10+
pub unsafe extern "C" fn start() -> u32 {
11+
let _ = log::set_logger(&win_dbg_logger::DEBUGGER_LOGGER);
12+
log::set_max_level(log::LevelFilter::Trace);
13+
let patch_ptr: *mut u8 = PATCH_ADDRESS as _;
14+
15+
let mut old_flags: PAGE_PROTECTION_FLAGS = windows::Win32::System::Memory::PAGE_PROTECTION_FLAGS(0);
16+
if !VirtualProtect(patch_ptr as _, 5, PAGE_EXECUTE_READWRITE, &mut old_flags).as_bool() {
17+
let error: WIN32_ERROR = GetLastError();
18+
error!("VirtualProtect PAGE_EXECUTE_READWRITE failed: {:?}", error);
19+
return 1;
20+
}
21+
22+
debug!("Patching comparison at {:#x}", PATCH_ADDRESS);
23+
*patch_ptr = 0x64;
24+
25+
if !VirtualProtect(patch_ptr as _, 5, old_flags, &mut old_flags).as_bool() {
26+
let error: WIN32_ERROR = GetLastError();
27+
error!("VirtualProtect restore failed: {:?}", error);
28+
return 2;
29+
}
30+
31+
0
32+
}

0 commit comments

Comments
 (0)