1
0
mirror of synced 2024-11-27 17:00:53 +01:00

Update song limit patch

This commit is contained in:
BroGamer 2022-12-07 02:58:44 +13:00
parent 5d79fda758
commit 98915e09da
10 changed files with 62 additions and 363 deletions

View File

@ -10,7 +10,7 @@ jobs:
with:
submodules: recursive
- name: Install depends
run: sudo apt-get install -y mingw-w64 clang && rustup target add x86_64-pc-windows-gnu
run: sudo apt-get install -y mingw-w64 clang
- name: Make
run: make dist-no-7z
- uses: actions/upload-artifact@v3

View File

@ -52,8 +52,6 @@ clean:
plugins:
make -C plugins/8.18
make -C plugins/amauth
cd plugins/8.18-song-limit && cargo build --release --target x86_64-pc-windows-gnu
cp plugins/8.18-song-limit/target/x86_64-pc-windows-gnu/release/song_limit_8_18.dll ${TARGET}
strip ${TARGET}/*.dll
.PHONY: dist-no-7z
@ -63,7 +61,6 @@ dist-no-7z: options ${OUT} plugins
mv out/${OUT}.dll out/bnusio.dll
cp ${TARGET}/patches.*.dll out/plugins
cp ${TARGET}/amauth.dll out/plugins
cp ${TARGET}/song_limit_8_18.dll out/plugins
cp -r dist/* out/
.PHONY: dist

View File

@ -1 +0,0 @@
target/

View File

@ -1,67 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "libc"
version = "0.2.135"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
[[package]]
name = "mach"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa"
dependencies = [
"libc",
]
[[package]]
name = "region"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76e189c2369884dce920945e2ddf79b3dff49e071a167dd1817fa9c4c00d512e"
dependencies = [
"bitflags",
"libc",
"mach",
"winapi",
]
[[package]]
name = "song-limit-8-18"
version = "0.1.0"
dependencies = [
"libc",
"region",
"winapi",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View File

@ -1,12 +0,0 @@
[package]
name = "song-limit-8-18"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
libc = "0.2.133"
region = "3.0.0"
winapi = { version = "0.3.9", features = ["libloaderapi"] }

View File

@ -1 +0,0 @@
hard_tabs = true

View File

@ -1,275 +0,0 @@
#![allow(non_snake_case)]
use libc::*;
use std::arch::*;
use winapi::um::libloaderapi::*;
const SONG_DATA_SIZE: usize = 1024 * 1024 * 64;
static mut SONG_DATA: Option<*mut c_void> = None;
static mut HANDLE: Option<usize> = None;
pub unsafe fn gen_jmp(to: usize) -> Box<[u8]> {
// MOV RAX, {TO}
// JMP RAX
Box::new([
0x48,
0xB8,
to as u8,
(to >> 8) as u8,
(to >> 16) as u8,
(to >> 24) as u8,
(to >> 32) as u8,
(to >> 40) as u8,
(to >> 48) as u8,
(to >> 56) as u8,
0xFF,
0xE0,
])
}
macro_rules! primitive_ptr {
($function:expr) => {
$function as *mut ()
};
}
macro_rules! set_crown_data {
($offset:literal, $value:literal) => {
asm!(
"add rsp, 0x28",
"mov rax, qword ptr [rsp + 0x40]",
"push rcx",
"add rax, r14",
"lea rcx, [rax + rax * 8]",
concat!("cmp dword ptr [rdx + rcx * 8 + 0x300], ", $value),
"jge 1f",
concat!("mov dword ptr [rdx + rcx * 8 + 0x300], ", $value),
"1:",
"pop rcx",
"jmp rcx",
in("rdx") SONG_DATA.unwrap(),
in("rcx") HANDLE.unwrap() + $offset,
)
};
}
pub unsafe fn set_crown_data_1() {
set_crown_data!(0x2F3AF1, 1);
}
pub unsafe fn set_crown_data_2() {
set_crown_data!(0x2F3A27, 2);
}
pub unsafe fn set_crown_data_3() {
set_crown_data!(0x2F3C25, 3);
}
macro_rules! set_score_rank {
($offset:literal, $value:literal) => {
asm!(
"add rsp, 0x28",
"push rcx",
"lea rcx, [0xB + RBX * 4]",
"add rcx, rsi",
"add rcx, rbx",
"lea rax, [rcx + rcx * 8]",
concat!("cmp dword ptr [rdx + rax * 8], ", $value),
"jge 1f",
concat!("mov dword ptr [rdx + rax * 8], ", $value),
"1:",
"pop rcx",
"jmp rcx",
in("rcx") HANDLE.unwrap() + $offset,
in("rdx") SONG_DATA.unwrap(),
);
};
}
pub unsafe fn set_score_rank_1() {
set_score_rank!(0x306613, 1);
}
pub unsafe fn set_score_rank_2() {
set_score_rank!(0x306547, 2);
}
pub unsafe fn set_score_rank_3() {
set_score_rank!(0x30647B, 3);
}
pub unsafe fn set_score_rank_4() {
set_score_rank!(0x3068D3, 4);
}
pub unsafe fn set_score_rank_5() {
set_score_rank!(0x306807, 5);
}
pub unsafe fn set_score_rank_6() {
set_score_rank!(0x30673B, 6);
}
pub unsafe fn set_score_rank_7() {
set_score_rank!(0x3069D0, 7);
}
pub unsafe fn set_unknown_data_1() {
asm!(
"add rsp, 0x28",
"lea rcx, [rsi + rsi * 4]",
"add rcx, rdi",
"lea rax, [rcx + rcx * 8]",
"jmp r15",
in("rdx") SONG_DATA.unwrap(),
in("r15") HANDLE.unwrap() + 0x31376A,
);
}
pub unsafe fn set_unknown_data_2() {
asm!(
"add rsp, 0x28",
"lea rcx, [rdi + rdi * 4]",
"add rcx, rbx",
"lea rax, [rcx + rcx * 8]",
"jmp rsi",
in("rdx") SONG_DATA.unwrap(),
in("rsi") HANDLE.unwrap() + 0x313A20,
)
}
pub unsafe fn set_unknown_data_3() {
asm!(
"add rsp, 0x28",
"lea rcx, [rdi + rdi * 4]",
"add rcx, rbx",
"lea rax, [rcx + rcx * 8]",
"jmp r10",
in("rdx") SONG_DATA.unwrap(),
in("r10") HANDLE.unwrap() + 0x313B61,
);
}
pub unsafe fn set_unknown_data_4() {
asm!(
"add rsp, 0x28",
"lea rdx, [rdi + rdi * 4]",
"add rdx, rbx",
"lea rdx, [rdx + rdx * 8]",
"jmp rax",
in("r8") SONG_DATA.unwrap(),
in("rax") HANDLE.unwrap() + 0x313C57,
);
}
pub unsafe fn set_unknown_data_other() {
asm!(
"add rsp, 0x28",
"lea rcx, [rdi + rdi * 4]",
"lea rax, [rbx + 0xB]",
"add rcx, rax",
"lea rax, [rcx + rcx * 8]",
"jmp r10",
in("rdx") SONG_DATA.unwrap(),
in("r10") HANDLE.unwrap() + 0x313D51,
);
}
pub unsafe fn set_crown_data_other() {
asm!(
"add rsp, 0x28",
"lea rdx, [rdi + rdi * 4]",
"add rdx, rbx",
"lea rax, [rdx + rdx * 8]",
"jmp rcx",
in("r8") SONG_DATA.unwrap(),
in("rcx") HANDLE.unwrap() + 0x3140EC,
);
}
pub unsafe fn set_song_data() {
asm!(
"add rsp, 0x28",
"movsxd rax, edi",
"lea rdx, [rax + rax * 4]",
"movsxd rax, ebx",
"add rdx, rax",
"lea rax, [rdx + rdx * 8]",
"lea rbx, [r8 + rax * 8]",
"jmp rcx",
in("r8") SONG_DATA.unwrap(),
in("rcx") HANDLE.unwrap() + 0x31369A,
);
}
#[no_mangle]
pub unsafe extern "C" fn Init() {
let handle = GetModuleHandleA(0 as *const i8) as usize;
HANDLE = Some(handle);
SONG_DATA = Some(malloc(SONG_DATA_SIZE));
memset(SONG_DATA.unwrap(), 0, SONG_DATA_SIZE);
let bytes = gen_jmp(primitive_ptr!(set_crown_data_1) as usize);
write_bytes(primitive_ptr!(handle + 0x2F3AC8), bytes);
let bytes = gen_jmp(primitive_ptr!(set_crown_data_2) as usize);
write_bytes(primitive_ptr!(handle + 0x2F39FE), bytes);
let bytes = gen_jmp(primitive_ptr!(set_crown_data_3) as usize);
write_bytes(primitive_ptr!(handle + 0x2F3BFC), bytes);
let bytes = gen_jmp(primitive_ptr!(set_score_rank_1) as usize);
write_bytes(primitive_ptr!(handle + 0x3065EA), bytes);
let bytes = gen_jmp(primitive_ptr!(set_score_rank_2) as usize);
write_bytes(primitive_ptr!(handle + 0x30651E), bytes);
let bytes = gen_jmp(primitive_ptr!(set_score_rank_3) as usize);
write_bytes(primitive_ptr!(handle + 0x306452), bytes);
let bytes = gen_jmp(primitive_ptr!(set_score_rank_4) as usize);
write_bytes(primitive_ptr!(handle + 0x3068AA), bytes);
let bytes = gen_jmp(primitive_ptr!(set_score_rank_5) as usize);
write_bytes(primitive_ptr!(handle + 0x3067DE), bytes);
let bytes = gen_jmp(primitive_ptr!(set_score_rank_6) as usize);
write_bytes(primitive_ptr!(handle + 0x306712), bytes);
let bytes = gen_jmp(primitive_ptr!(set_score_rank_7) as usize);
write_bytes(primitive_ptr!(handle + 0x3069A2), bytes);
let bytes = gen_jmp(primitive_ptr!(set_unknown_data_1) as usize);
write_bytes(primitive_ptr!(handle + 0x313755), bytes);
let bytes = gen_jmp(primitive_ptr!(set_unknown_data_2) as usize);
write_bytes(primitive_ptr!(handle + 0x313A0B), bytes);
let bytes = gen_jmp(primitive_ptr!(set_unknown_data_3) as usize);
write_bytes(primitive_ptr!(handle + 0x313B4C), bytes);
let bytes = gen_jmp(primitive_ptr!(set_unknown_data_4) as usize);
write_bytes(primitive_ptr!(handle + 0x313C42), bytes);
let bytes = gen_jmp(primitive_ptr!(set_unknown_data_other) as usize);
write_bytes(primitive_ptr!(handle + 0x313D38), bytes);
let bytes = gen_jmp(primitive_ptr!(set_crown_data_other) as usize);
write_bytes(primitive_ptr!(handle + 0x3140D7), bytes);
let bytes = gen_jmp(primitive_ptr!(set_song_data) as usize);
write_bytes(primitive_ptr!(handle + 0x31367B), bytes);
}
#[no_mangle]
pub unsafe extern "C" fn BeforeCard1Insert() {
memset(SONG_DATA.unwrap(), 0, SONG_DATA_SIZE);
}
#[no_mangle]
pub unsafe extern "C" fn BeforeCard2Insert() {
memset(SONG_DATA.unwrap(), 0, SONG_DATA_SIZE);
}
pub unsafe fn write_bytes<T>(location: *mut T, bytes: Box<[u8]>) -> Option<()> {
region::protect(
location,
bytes.len(),
region::Protection::READ_WRITE_EXECUTE,
)
.ok()?;
memcpy(
location as *mut libc::c_void,
std::ptr::addr_of!(*bytes) as *mut c_void,
bytes.len(),
);
Some(())
}

View File

@ -1,8 +1,9 @@
OUT = patches.8.18
CC := clang
TARGET := x86_64-pc-windows-gnu
SRC = dllmain.c
OBJ = ${addprefix ../../${TARGET}/plugins/8.18/,${SRC:.c=.o}}
SRC = dllmain.c song_limits.s
OBJ_NO_PREFIX = dllmain.o song_limits.o
OBJ = ${addprefix ../../${TARGET}/plugins/8.18/,${OBJ_NO_PREFIX}}
EXTERN_SRC = src/helpers.c tomlc99/toml.c minhook/src/buffer.c minhook/src/hook.c minhook/src/trampoline.c minhook/src/hde/hde32.c minhook/src/hde/hde64.c
EXTERN_OBJ = ${addprefix ../../${TARGET}/,${EXTERN_SRC:.c=.o}}
CFLAGS = -std=c99 -I../../src -I../../minhook/include -I../../tomlc99 -Wall -Ofast -target ${TARGET} -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=_WIN32_WINNT_WIN7
@ -23,7 +24,11 @@ options:
../../${TARGET}/plugins/8.18/%.o: %.c
@echo BUILD $@
@${CC} -c ${CFLAGS} $< -o $@
@bear -- ${CC} -c ${CFLAGS} $< -o $@
../../${TARGET}/plugins/8.18/%.o: %.s
@echo BUILD $@
@${CC} -m64 -masm=intel -Wall -Ofast -target ${TARGET} -c $< -o $@
.PHONY: ${OUT}
${OUT}: dirs ${OBJ}

View File

@ -1,6 +1,24 @@
#define BASE_ADDRESS 0x140000000
#include "helpers.h"
const u64 song_data_size = 1024 * 1024 * 64;
void *song_data;
extern void set_song_data_rdx ();
extern void set_song_data_r8 ();
#define GENERATE_CALL(to) \
0x48, 0xB8, (u8)(u64)(to), (u8)((u64)(to) >> 8), (u8)((u64)(to) >> 16), (u8)((u64)(to) >> 24), (u8)((u64)(to) >> 32), (u8)((u64)(to) >> 40), \
(u8)((u64)(to) >> 48), (u8)((u64)(to) >> 56), 0xFF, 0xD0
#define NOPS_NEEDED(start, return_location) WRITE_NOP ((u64)(start) + 12, (u64)(return_location)-1 - (u64)(start)-11)
#define HOOK_SONG_DATA(function, start_loc, ret_loc, handle) \
{ \
WRITE_MEMORY (ASLR (start_loc, handle), u8, GENERATE_CALL (function)); \
NOPS_NEEDED (ASLR (start_loc, handle), ASLR (ret_loc, handle)); \
}
HOOK_DYNAMIC (u8, __fastcall, qrVtable1, u64 a1) { return 1; }
HOOK_DYNAMIC (u8, __fastcall, qrReadFromCOM1, u64 a1) {
*(u32 *)(a1 + 40) = 1;
@ -56,6 +74,31 @@ PreInit () {
WRITE_MEMORY (ASLR (0x140314F46, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x140314F97, handle), i32, 9000);
song_data = malloc (song_data_size);
memset (song_data, 0, song_data_size);
// Song data
HOOK_SONG_DATA (set_song_data_r8, 0x140313678, 0x140313685, handle);
// Crown data
HOOK_SONG_DATA (set_song_data_rdx, 0x1402F3AC2, 0x1402F3AD0, handle);
HOOK_SONG_DATA (set_song_data_rdx, 0x1402F39F8, 0x1402F3A06, handle);
HOOK_SONG_DATA (set_song_data_rdx, 0x1402F3BF6, 0x1402F3C04, handle);
HOOK_SONG_DATA (set_song_data_r8, 0x1403140D4, 0x1403140E1, handle)
// Score ranks
HOOK_SONG_DATA (set_song_data_rdx, 0x1403065E6, 0x1403065F4, handle);
HOOK_SONG_DATA (set_song_data_rdx, 0x14030651A, 0x140306528, handle);
HOOK_SONG_DATA (set_song_data_rdx, 0x14030644E, 0x14030645C, handle);
HOOK_SONG_DATA (set_song_data_rdx, 0x1403068A6, 0x1403068B4, handle);
HOOK_SONG_DATA (set_song_data_rdx, 0x1403067DA, 0x1403067E8, handle);
HOOK_SONG_DATA (set_song_data_rdx, 0x14030670E, 0x14030671C, handle);
HOOK_SONG_DATA (set_song_data_rdx, 0x14030699E, 0x1403069B1, handle);
// Unknown
HOOK_SONG_DATA (set_song_data_rdx, 0x140313752, 0x14031375F, handle);
HOOK_SONG_DATA (set_song_data_rdx, 0x140313A08, 0x140313A15, handle);
HOOK_SONG_DATA (set_song_data_rdx, 0x140313B49, 0x140313B56, handle);
HOOK_SONG_DATA (set_song_data_rdx, 0x140313D35, 0x140313D42, handle);
HOOK_SONG_DATA (set_song_data_r8, 0x140313C3F, 0x140313C4C, handle);
// Save settings cross session without F:/ and G:/ drive
WRITE_MEMORY (ASLR (0x140B5C528, handle), char, "./Setting1.bin");
WRITE_MEMORY (ASLR (0x140B5C538, handle), char, "./Setting2.bin");

View File

@ -0,0 +1,10 @@
.global set_song_data_rdx
.global set_song_data_r8
set_song_data_rdx:
mov rdx, qword ptr song_data [rip]
ret
set_song_data_r8:
mov r8, qword ptr song_data [rip]
ret