Skip to content

Commit

Permalink
Merge pull request #14 from KuhakuPixel/feature
Browse files Browse the repository at this point in the history
Enable Optimization for [Modder] and add script to create release binary
  • Loading branch information
KuhakuPixel authored Mar 24, 2023
2 parents 9a42e02 + 1d0c940 commit e4c638b
Show file tree
Hide file tree
Showing 89 changed files with 626 additions and 384 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@
*~
*.swp
*.swo


# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
50 changes: 22 additions & 28 deletions ACE/engine/src/match_store.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,9 @@ void match_storage<T>::set_scan_level(Scan_Utils::E_scan_level scan_level) {

template <typename T>
void match_storage<T>::_iterate(

std::function<void(ADDR addr, T *val_ptr)> on_each_iteration_val_ptr,
std::function<void(ADDR addr, T val)> on_each_iteration_val, size_t max_iter

) {
std::function<void(ADDR addr, T val)> on_each_iteration_val,
size_t max_iter) {

// iterate each matches addresses
size_t current_match_val_idx = 0;
Expand All @@ -39,16 +37,16 @@ void match_storage<T>::_iterate(
// calculate current_addr
ADDR current_addr = Scan_Utils::get_address_of_match_index<T>(
this->scan_level, base_addr, j);
T *current_val_ptr = &(this->matches_value[current_match_val_idx]);
// call callback if only
// the callback is not NULL
if (on_each_iteration_val_ptr != NULL)
on_each_iteration_val_ptr(current_addr, current_val_ptr);
T *val_ptr = &(this->matches_value[current_match_val_idx]);
if (on_each_iteration_val != NULL)
on_each_iteration_val(current_addr, *current_val_ptr);
on_each_iteration_val(current_addr, *val_ptr);
if (on_each_iteration_val_ptr != NULL)
on_each_iteration_val_ptr(current_addr, val_ptr);
}
}
}

// FIXME :using this function crash gives bug when attach mem scanner in apk
template <typename T>
void match_storage<T>::iterate(

Expand All @@ -65,24 +63,20 @@ void match_storage<T>::iterate_val(
std::function<void(ADDR addr, T val)> on_each_iteration,
size_t max_iter) const {

// iterate each matches addresses
size_t current_match_val_idx = 0;
for (size_t i = 0; i < this->get_chunk_count(); i++) {
size_t match_chunk_matches_cnt = this->matches_records[i].match_count;
size_t base_addr = this->matches_records[i].base_addr;

for (size_t j = 0; j < match_chunk_matches_cnt;
j++, current_match_val_idx++) {
// iteration has reached max, exit from function
if (current_match_val_idx >= max_iter)
return;
// calculate current_addr
ADDR current_addr = Scan_Utils::get_address_of_match_index<T>(
this->scan_level, base_addr, j);
T val = this->matches_value[current_match_val_idx];
on_each_iteration(current_addr, val);
}
}
/*
* reuse non const function in const, this looks ugly but
* its better than code duplication
* https://stackoverflow.com/a/5008580/14073678
*
* some SO answer said that calling this function on a const object
* will yield undefined behavior
*
* https://stackoverflow.com/a/8325449/14073678
*
* but it is fine since [_iterate] call in below, won't modify anything
*/
const_cast<match_storage<T> *>(this)->_iterate(NULL, on_each_iteration,
max_iter);
}

template <typename T>
Expand Down
37 changes: 20 additions & 17 deletions ACE/engine/src/match_store.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,29 +210,32 @@ template <typename T> class match_storage {
void set_scan_level(Scan_Utils::E_scan_level scan_level);

/*
* low level function to iterate through each matches
* */
void _iterate(

std::function<void(ADDR addr, T *val_ptr)> on_each_iteration_val_ptr =
NULL,
std::function<void(ADDR addr, T val)> on_each_iteration_val = NULL,
size_t max_iter = SIZE_MAX

);

/*
* iterate the each matches and call
* iterate each matches, it provides 2 callback,
*
* [on_each_iteration]: called on each iteration
* [on_each_iteration_val]: called on each iteration
* it takes 2 parameter which is the current match address
* and a pointer to the address's value, caller can get
* andaddress's value, caller can get
* the match value of the address or update its match
* value
*
* [on_each_iteration_val_ptr]: same as [on_each_iteration_val], but instead
* of having match's value as parameter, it gives pointer to match's value so
* caller can change/update its value when needed
*
* [max_iter]: the maximum amount of iteration
* */
void iterate(std::function<void(ADDR addr, T *val_ptr)> on_each_iteration,
size_t max_iter = SIZE_MAX);

void _iterate(

std::function<void(ADDR addr, T *val_ptr)> on_each_iteration_val_ptr,
std::function<void(ADDR addr, T val)> on_each_iteration_val,
size_t max_iter

);
void iterate(

std::function<void(ADDR addr, T *val_ptr)> on_each_iteration,
size_t max_iter = SIZE_MAX);
void iterate_val(

std::function<void(ADDR addr, T val)> on_each_iteration,
Expand Down
4 changes: 2 additions & 2 deletions ACE/engine/src/scanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,9 +351,9 @@ void ACE_scanner<T>::write_val_to_current_scan_results(T val) {
if (this->endian_scan_type == E_endian_scan_type::swapped)
val = swap_endian<T>(val);

this->current_scan_result.iterate(
this->current_scan_result.iterate_val(

[&](ADDR addr, T *val_ptr) {
[&](ADDR addr, T old_val) {
// reset errno
errno = 0;
ssize_t ret_val = this->process_rw->write_val((byte *)(addr), val);
Expand Down
8 changes: 1 addition & 7 deletions ACE/readme.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
# ACE Engine
# ![this icon is generated by DALL-E-2](./docs/icon.png)

game hacking and memory scanner/editor for linux and android

- I plan to make it work on linux first, before porting to
android, and first make a program that is runnable through adb

docs on building/running/testing [here](./docs/)



114 changes: 114 additions & 0 deletions ACE_release.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
"""
Make ACE's release for linux desktop and android (multi archs) automatically
This script run cmake and makefile to generate the build
for running a bash command in a directory
don't use cd but use cwd parameter
https://stackoverflow.com/questions/21406887/subprocess-changing-directory
"""

import subprocess
import os
import shutil
import multiprocessing
from typing import List
from util import assert_is_dir_and_exist, assert_is_file_and_exist, mkdir_overwrite

LINUX_RELEASE_DIR = "./linux"
ANDROID_RELEASE_DIR = "./android"

ANDROID_ARCH_ABI_ARR = [
"armeabi-v7a",
"arm64-v8a",
"x86",
"x86_64",
]
# need to be set to at least 23
# for process_vm_read support
# see ACE's cmake for more detail
ANDROID_PLATFORM = "android-23"

CMAKELIST_PATH = "./ACE/engine/"
BUILD_DIR = "./build"


def gen_make_and_make_ACE(
build_dir: str,
install_dir: str,
CMAKElist_dir_path: str,
toolchain_path: str = None,
extra_args: List[str] = None,
# by default, use all cpu for fastest compilation
# https://unix.stackexchange.com/questions/208568/how-to-determine-the-maximum-number-to-pass-to-make-j-option
# https://stackoverflow.com/a/1006337/14073678
cpu_count_for_compile: int = multiprocessing.cpu_count(),
):

# recreate build and release directory in case its previously
# not empty
mkdir_overwrite(build_dir)
mkdir_overwrite(install_dir)
# get abs path when possible
assert_is_dir_and_exist(install_dir)
install_path = os.path.abspath(install_dir)

assert_is_dir_and_exist(CMAKElist_dir_path)
CMAKElist_path = os.path.abspath(CMAKElist_dir_path)

if toolchain_path != None:
assert_is_file_and_exist(toolchain_path)
toolchain_path = os.path.abspath(toolchain_path)
print(f"install path: {install_path}")
# generate makefile and run make
CMAKE_cmd_args = [
"cmake",
CMAKElist_path,
"-DCMAKE_BUILD_TYPE=Release",
# set install prefix
# https://stackoverflow.com/questions/6003374/what-is-cmake-equivalent-of-configure-prefix-dir-make-all-install
"-DCMAKE_INSTALL_PREFIX:PATH=" + install_path,
]
# append extra arguments
if extra_args != None:
CMAKE_cmd_args += extra_args
pass
# use custom toolchain if provided
if toolchain_path != None:
CMAKE_cmd_args.append("-DCMAKE_TOOLCHAIN_FILE=" + toolchain_path)
# run cmake
subprocess.run(CMAKE_cmd_args, cwd=build_dir)
# make the program and install to the specified target
subprocess.run(
["make", "all", "install", f"-j{cpu_count_for_compile}"], cwd=build_dir
)


def make_release(release_dir: str, android_toolchain_file: str):
# ============================ android =====================
# recreate build dir for building engine
android_release_dir = os.path.join(release_dir, ANDROID_RELEASE_DIR)
for arch in ANDROID_ARCH_ABI_ARR:
# create directory for specific arch release
current_android_release_dir = os.path.join(android_release_dir, arch)
#
gen_make_and_make_ACE(
build_dir=BUILD_DIR,
install_dir=current_android_release_dir,
CMAKElist_dir_path=CMAKELIST_PATH,
toolchain_path=android_toolchain_file,
extra_args=[
"-DANDROID_ABI=" + arch,
"-DANDROID_PLATFORM=" + ANDROID_PLATFORM,
],
)

# ============================ linux =====================
# recreate build dir for building engine
linux_release_dir = os.path.join(release_dir, LINUX_RELEASE_DIR)
gen_make_and_make_ACE(
build_dir=BUILD_DIR,
install_dir=linux_release_dir,
CMAKElist_dir_path=CMAKELIST_PATH,
toolchain_path=None,
)
76 changes: 76 additions & 0 deletions DEV_GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Developer Guide

## Build instruction
### clone repo
#### https
```
git clone --recurse-submodules https://github.com/KuhakuPixel/AceTheGame.git
```
#### ssh
```
git clone --recurse-submodules [email protected]:KuhakuPixel/AceTheGame.git
```
## Project Structure
specific build instruction is provided at the readme of each subproject.

Folder | Description
----------------------------- | -----------------------------------------------
[ACE](./ACE/) | Memory scanner and editor for linux and android
[Modder](./Modder) | Attaching a memory scanner and editor service in the apk itself so you can read/write memory without roo

## Making Release

### With Docker
- need to have docker installed

#### build the docker image

```
python ./docker_build.py
```

#### Grabbing the build binaries

1. run the image first

```
python ./docker_run_shell.py
```
2.
running
```
docker ps
```

should give
(the container ID might be different, so you need to adjust your arguments)
```
CONTAINER ID IMAGE COMMAND CREATED STATUS
e46afdd42728 ace_the_game "bash" About a minute ago Up About a minute
```
3. copying the folder to your machine

```
sudo docker cp e46afdd42728:/release .
```

now you should have `release` folder in the current directory


### Without Docker
A python script `./make_release.py` is provided to automatically create binary release for each project
(You need to download [NDK](https://developer.android.com/ndk/downloads)

```
python ./make_release.py [PATH_TO_android.toolchain.cmake]
```

example:
```
python ./make_release.py ~/Android/Sdk/ndk/25.1.8937393/build/cmake/android.toolchain.cmake
```

the script will create `release` folder



Loading

0 comments on commit e4c638b

Please sign in to comment.