Initial commit

This commit is contained in:
Neo 2020-12-21 22:29:12 +00:00
parent 46f14d9a48
commit d14b5f4088
71 changed files with 28973 additions and 0 deletions

424
.gitignore vendored Normal file
View File

@ -0,0 +1,424 @@
build/
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
.idea/
apk/*.apk
apk/*.old
*.keystore
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# Libs
#lib/cocos
#lib/Dobby
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
.vscode/
abiproxy/build/
lib/cocos_old/
lib/Dobby_old/
sign.bat

20
.gitmodules vendored Normal file
View File

@ -0,0 +1,20 @@
[submodule "lib/Dobby"]
path = lib/Dobby
url = https://github.com/jmpews/Dobby
branch = master
[submodule "lib/cocos"]
path = lib/cocos
url = https://github.com/neobenedict/cocos2d-src-only/
branch = master
[submodule "smali/okhttp-smali"]
path = smali/okhttp-smali
url = https://github.com/neobenedict/okhttp-smali
branch = master
[submodule "lib/untp"]
path = lib/untp
url = https://github.com/neobenedict/untp
branch = develop
[submodule "patches/images"]
path = patches/images
url = https://git.rayshift.io/kamihama/magia-client-image-patches
branch = master

89
CMakeLists.txt Normal file
View File

@ -0,0 +1,89 @@
# CMakeList.txt : CMake project for MagiaClient, include source and define
# project specific logic here.
#
#set(CMAKE_CXX_STANDARD 11)
cmake_minimum_required (VERSION 3.8)
project ("MagiaClient")
set(TARGET_NAME uwasa)
#if (CMAKE_BUILD_TYPE STREQUAL "Debug")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++ -fsanitize=address -fno-omit-frame-pointer")
#else
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++")
#endif(CMAKE_BUILD_TYPE STREQUAL "Debug")
if(CMAKE_BUILD_TYPE STREQUAL "Release")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fvisibility=hidden -fvisibility-inlines-hidden -g0 -O3 -ffunction-sections -fdata-sections")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fvisibility=hidden -fvisibility-inlines-hidden -g0 -O3 -ffunction-sections -fdata-sections")
endif(CMAKE_BUILD_TYPE STREQUAL "Release")
set(DobbyHome ${CMAKE_CURRENT_SOURCE_DIR}/lib/Dobby)
include_directories(
${DobbyHome}/include
${DobbyHome}/builtin-plugin
${DobbyHome}/builtin-plugin/SymbolResolver
${DobbyHome}/external/logging
${DobbyHome}/source
${CMAKE_CURRENT_SOURCE_DIR}/lib
${CMAKE_CURRENT_SOURCE_DIR}/lib/cocos
${CMAKE_CURRENT_SOURCE_DIR}/abiproxy/src
)
include(FetchContent)
FetchContent_Declare(json
GIT_REPOSITORY https://github.com/ArthurSonzogni/nlohmann_json_cmake_fetchcontent
GIT_TAG v3.9.1)
FetchContent_GetProperties(json)
if(NOT json_POPULATED)
FetchContent_Populate(json)
add_subdirectory(${json_SOURCE_DIR} ${json_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Release")
link_libraries("-Wl,--strip-all")
endif(CMAKE_BUILD_TYPE STREQUAL "Release")
add_library( # Sets the name of the library.
${TARGET_NAME}
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
"lib/cocos/math/CCGeometry.cpp"
"lib/cocos/math/Vec2.cpp"
"src/MagiaClient.cpp"
"src/Utils.cpp"
"src/rest/MagiaRest.cpp"
)
find_library(ANDROID_LOG_LIB log)
target_link_libraries(${TARGET_NAME} PRIVATE ${ANDROID_LOG_LIB})
target_link_libraries(${TARGET_NAME} PRIVATE dobby)
target_link_libraries(${TARGET_NAME} PRIVATE nlohmann_json::nlohmann_json)
if (CMAKE_ANDROID_ARCH_ABI STREQUAL "armeabi-v7a")
target_link_libraries(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/abiproxy/build/armeabi-v7a/libabiproxy.so)
message(STATUS "Linking for armeabi-v7a")
endif (CMAKE_ANDROID_ARCH_ABI STREQUAL "armeabi-v7a")
if (CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a")
target_link_libraries(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/abiproxy/build/arm64-v8a/libabiproxy.so)
message(STATUS "Linking for arm64-v8a")
endif (CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a")
macro(SET_OPTION option value)
set(${option} ${value} CACHE INTERNAL "" FORCE)
endmacro()
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
SET_OPTION(DOBBY_DEBUG ON)
endif(CMAKE_BUILD_TYPE STREQUAL "Debug")
SET_OPTION(DOBBY_GENERATE_SHARED OFF)
SET_OPTION(DynamicBinaryInstrument ON)
SET_OPTION(NearBranch ON)
SET_OPTION(Plugin.SymbolResolver ON)
add_subdirectory(${DobbyHome} dobby)

2
README.md Normal file
View File

@ -0,0 +1,2 @@
# magiatranslate
Magia Translate Client Source

39
abiproxy/CMakeLists.txt Normal file
View File

@ -0,0 +1,39 @@
# CMakeList.txt : CMake project for AbiProxy, include source and define
# project specific logic here.
#
#set(CMAKE_CXX_STANDARD 11)
cmake_minimum_required (VERSION 3.8)
project ("AbiProxy")
set(TARGET_NAME abiproxy)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
if(CMAKE_BUILD_TYPE STREQUAL "Release")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fvisibility=hidden -fvisibility-inlines-hidden -g0 -O3 -ffunction-sections -fdata-sections")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fvisibility=hidden -fvisibility-inlines-hidden -g0 -O3 -ffunction-sections -fdata-sections")
endif(CMAKE_BUILD_TYPE STREQUAL "Release")
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/../lib
${CMAKE_CURRENT_SOURCE_DIR}/../lib/cocos
)
if(CMAKE_BUILD_TYPE STREQUAL "Release")
link_libraries("-Wl,--strip-all")
endif(CMAKE_BUILD_TYPE STREQUAL "Release")
add_library( # Sets the name of the library.
${TARGET_NAME}
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
"src/magia/StringsProxy.cc"
"src/magia/DialogueBox.cc")
find_library(ANDROID_LOG_LIB log)
target_link_libraries(${TARGET_NAME} ${ANDROID_LOG_LIB})
macro(SET_OPTION option value)
set(${option} ${value} CACHE INTERNAL "" FORCE)
endmacro()

40
abiproxy/build.bat Normal file
View File

@ -0,0 +1,40 @@
@echo off
:start
set ndk="C:/Android/android-ndk-r16b-windows-x86_64/android-ndk-r16b/"
set /p ndk="Enter ndk Location [C:/Android/android-ndk-r16b-windows-x86_64/android-ndk-r16b/]: "
if not exist %~dp0\build mkdir %~dp0\build
:build
echo Building libraries.
rmdir /S /Q %~dp0\build\armeabi-v7a\
rmdir /S /Q %~dp0\build\arm64-v8a\
mkdir %~dp0\build\armeabi-v7a
mkdir %~dp0\build\arm64-v8a
echo Running cmake armeabi-v7a...
cd %~dp0\build\armeabi-v7a
call "C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO\2019\ENTERPRISE\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\CMAKE\CMake\bin\cmake.exe" -G Ninja -DANDROID_ABI="armeabi-v7a" -DCMAKE_BUILD_TYPE:STRING="Debug" -DCMAKE_INSTALL_PREFIX:PATH="%~dp0\build\armeabi-v7a" -DCMAKE_TOOLCHAIN_FILE:FILEPATH="%ndk%/build/cmake/android.toolchain.cmake" -DCMAKE_MAKE_PROGRAM:FILEPATH="C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja\ninja.exe" "-DANDROID_PLATFORM=android-19" "-DCMAKE_SYSTEM_NAME=Android" "-DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a" "-DCMAKE_ANDROID_NDK=%ndk%" "-DCMAKE_SYSTEM_VERSION=16" "-DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang" "-DCMAKE_ANDROID_STL_TYPE=gnustl_static" "%~dp0\"
if errorlevel 1 goto errorexit
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja\ninja.exe"
if errorlevel 1 goto errorexit
echo Running cmake arm64-v8a...
cd %~dp0\build\arm64-v8a
call "C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO\2019\ENTERPRISE\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\CMAKE\CMake\bin\cmake.exe" -G Ninja -DANDROID_ABI="arm64-v8a" -DCMAKE_BUILD_TYPE:STRING="Debug" -DCMAKE_INSTALL_PREFIX:PATH="%~dp0\build\arm64-v8a" -DCMAKE_TOOLCHAIN_FILE:FILEPATH="%ndk%/build/cmake/android.toolchain.cmake" -DCMAKE_MAKE_PROGRAM:FILEPATH="C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja\ninja.exe" "-DANDROID_PLATFORM=android-19" "-DCMAKE_SYSTEM_NAME=Android" "-DCMAKE_ANDROID_ARCH_ABI=arm64-v8a" "-DCMAKE_ANDROID_NDK=%ndk%" "-DCMAKE_SYSTEM_VERSION=16" "-DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang" "-DCMAKE_ANDROID_STL_TYPE=gnustl_static" "%~dp0\"
if errorlevel 1 goto errorexit
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja\ninja.exe"
if errorlevel 1 goto errorexit
echo Successful.
goto :exit
:errorexit
echo An error has occurred, exiting.
goto exit
:exit
pause

View File

@ -0,0 +1,40 @@
@echo off
:start
set ndk="C:/Android/android-ndk-r16b-windows-x86_64/android-ndk-r16b/"
set /p ndk="Enter ndk Location [C:/Android/android-ndk-r16b-windows-x86_64/android-ndk-r16b/]: "
if not exist %~dp0\build mkdir %~dp0\build
:build
echo Building libraries.
rmdir /S /Q %~dp0\build\armeabi-v7a\
rmdir /S /Q %~dp0\build\arm64-v8a\
mkdir %~dp0\build\armeabi-v7a
mkdir %~dp0\build\arm64-v8a
echo Running cmake armeabi-v7a...
cd %~dp0\build\armeabi-v7a
call "C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO\2019\ENTERPRISE\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\CMAKE\CMake\bin\cmake.exe" -G Ninja -DANDROID_ABI="armeabi-v7a" -DCMAKE_BUILD_TYPE:STRING="Release" -DCMAKE_INSTALL_PREFIX:PATH="%~dp0\build\armeabi-v7a" -DCMAKE_TOOLCHAIN_FILE:FILEPATH="%ndk%/build/cmake/android.toolchain.cmake" -DCMAKE_MAKE_PROGRAM:FILEPATH="C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja\ninja.exe" "-DANDROID_PLATFORM=android-19" "-DCMAKE_SYSTEM_NAME=Android" "-DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a" "-DCMAKE_ANDROID_NDK=%ndk%" "-DCMAKE_SYSTEM_VERSION=16" "-DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang" "-DCMAKE_ANDROID_STL_TYPE=gnustl_static" "%~dp0\"
if errorlevel 1 goto errorexit
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja\ninja.exe"
if errorlevel 1 goto errorexit
echo Running cmake arm64-v8a...
cd %~dp0\build\arm64-v8a
call "C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO\2019\ENTERPRISE\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\CMAKE\CMake\bin\cmake.exe" -G Ninja -DANDROID_ABI="arm64-v8a" -DCMAKE_BUILD_TYPE:STRING="Release" -DCMAKE_INSTALL_PREFIX:PATH="%~dp0\build\arm64-v8a" -DCMAKE_TOOLCHAIN_FILE:FILEPATH="%ndk%/build/cmake/android.toolchain.cmake" -DCMAKE_MAKE_PROGRAM:FILEPATH="C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja\ninja.exe" "-DANDROID_PLATFORM=android-19" "-DCMAKE_SYSTEM_NAME=Android" "-DCMAKE_ANDROID_ARCH_ABI=arm64-v8a" "-DCMAKE_ANDROID_NDK=%ndk%" "-DCMAKE_SYSTEM_VERSION=16" "-DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang" "-DCMAKE_ANDROID_STL_TYPE=gnustl_static" "%~dp0\"
if errorlevel 1 goto errorexit
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja\ninja.exe"
if errorlevel 1 goto errorexit
echo Successful.
goto :exit
:errorexit
echo An error has occurred, exiting.
goto exit
:exit
pause

View File

@ -0,0 +1,39 @@
#include <cstdint>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <functional>
#include "cocos/base/CCRef.h"
#include "cocos2d.h"
#include <android/log.h>
#include "DialogueBox.h"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, "MagiaHook", __VA_ARGS__)
typedef std::function<void(cocos2d::Ref*)> ccMenuCallback;
typedef int *(*openMessageBoxType)(char const* title, char const* body, char const* button, const ccMenuCallback& callback, bool xButton);
__attribute__((visibility("default")))
void DialogueBoxProxy::DialogueBox(void* dialogueBoxPointer) {
LOGI("Called extern dialogue box");
auto openMessageBoxFunc = reinterpret_cast<openMessageBoxType>(dialogueBoxPointer);
auto dontDisappear = std::bind(&DialogueBoxProxy::testCallback, this, std::placeholders::_1);
openMessageBoxFunc("Update required", "An update for Magia Translate is strongly recommended! 2", "OK",
dontDisappear, false);
//sleep(100);
}
//void DialogueBoxProxy::motdBox(void * dialogueboxPointer, void * loadContinuePointer);
void DialogueBoxProxy::testCallback(cocos2d::Ref* sender) {
LOGI("Recalled VALUE");
}
__attribute__((visibility("default")))
DialogueBoxProxy::DialogueBoxProxy() {
}
__attribute__((visibility("default")))
DialogueBoxProxy::~DialogueBoxProxy() {
}

View File

@ -0,0 +1,16 @@
#ifndef __DIALOGUEBOX_H__
#define __DIALOGUEBOX_H__
#include <cstdint>
#include "cocos/base/CCRef.h"
class DialogueBoxProxy {
public:
DialogueBoxProxy();
virtual ~DialogueBoxProxy();
virtual void DialogueBox(void* dialogueBoxPointer);
virtual void testCallback(cocos2d::Ref* sender);
private:
std::function<void(cocos2d::Ref*)> dialogueCallback;
};
#endif

View File

@ -0,0 +1,39 @@
#include "StringsProxy.h"
#include <iostream>
#include <string>
using namespace std;
/*extern "C" StringsProxy* create_object(uintptr_t str)
{
return new StringsProxy(str);
}
extern "C" StringsProxy* create_object(const char* str)
{
return new StringsProxy(str);
}
extern "C" void destroy_object( StringsProxy* object )
{
delete object;
}*/
__attribute__((visibility("default")))
extern "C" StringsProxy::StringsProxy(const char* contents)
{
set_string = std::string(contents);
}
__attribute__((visibility("default")))
extern "C" StringsProxy::StringsProxy(uintptr_t str) {
set_string = *reinterpret_cast<proxy_string*>(str);
}
__attribute__((visibility("default")))
extern "C" const char* StringsProxy::c_str() {
return set_string.c_str();
}
__attribute__((visibility("default")))
extern "C" const uintptr_t* StringsProxy::ptr() {
return reinterpret_cast<uintptr_t *>(&set_string);
}
__attribute__((visibility("default")))
extern "C" StringsProxy::~StringsProxy() {
}

View File

@ -0,0 +1,27 @@
#ifndef __STRINGSPROXY_H__
#define __STRINGSPROXY_H__
#include <string>
typedef std::basic_string<char> proxy_string;
class StringsProxy
{
public:
/* Initialize StringsProxy with a pointer to an existing string */
StringsProxy(uintptr_t str);
/* Initialize StringsProxy with a new string */
StringsProxy(const char* str);
/* Get C string */
virtual const char* c_str();
/* Get pointer to string for injection */
const virtual uintptr_t* ptr();
virtual ~StringsProxy();
private:
proxy_string set_string;
};
#endif

View File

106
build.bat Normal file
View File

@ -0,0 +1,106 @@
@echo off
for /r "%~dp0\apk" %%a in (*.apk) do set apk=%%~dpnxa
if "%apk%" neq "" (
echo Found apk %apk%.
goto :start
)
echo Did not find any MagiReco APK! Add it to the apk/ directory.
goto errorexit
pause
:start
set ndk="C:/Android/android-ndk-r21d/"
set /p ndk="Enter ndk Location [C:/Android/android-ndk-r21d/]: "
if not exist %~dp0\build mkdir %~dp0\build
if exist %~dp0\build\apktool_2.4.1.jar goto apktoolexists
echo Downloading apktool...
CALL curl -A "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64)" -o "%~dp0\build\apktool_2.4.1.jar" -L "https://bitbucket.org/iBotPeaches/apktool/downloads/apktool_2.4.1.jar"
:apktoolexists
if not exist %~dp0\build\app\ goto create
set deleteold=N
set /p deleteold="Remake existing APK work directory (Y/[N])? "
if %deleteold% NEQ Y goto build
:create
echo Removing existing build files...
rmdir /S /Q %~dp0\build\app\
echo Running apktool...
CALL java -jar %~dp0\build\apktool_2.4.1.jar d %apk% -o %~dp0\build\app\
mkdir %~dp0\build\app\smali\com\loadLib\
if not exist %~dp0\build\app\lib\armeabi-v7a mkdir %~dp0\build\app\lib\armeabi-v7a
if not exist %~dp0\build\app\lib\arm64-v8a mkdir %~dp0\build\app\lib\arm64-v8a
echo Applying smali patches...
cd %~dp0
call git apply --stat "%~dp0\patches\NativeBridge.patch"
call git apply --stat "%~dp0\patches\Hook.patch"
call git apply "%~dp0\patches\NativeBridge.patch"
call git apply "%~dp0\patches\Hook.patch"
echo Applying misc patches...
REM call copy /Y "%~dp0\patches\images\story_ui_sprites00_patch.plist" "%~dp0\build\app\assets\package\story\story_ui_sprites00.plist"
REM call copy /Y "%~dp0\patches\images\story_ui_sprites00_patch.png" "%~dp0\build\app\assets\package\story\story_ui_sprites00.png"
call copy /Y "%~dp0\patches\koruri-semibold.ttf" "%~dp0\build\app\assets\fonts\koruri-semibold.ttf"
echo Updating sprites and AndroidManifest.xml...
call python buildassets.py
:build
echo Copying new smali files...
call copy /Y "%~dp0\smali\loader\*.smali" "%~dp0\build\app\smali\com\loadLib\"
mkdir %~dp0\build\app\smali_classes2\io\kamihama\magianative\
echo Copying magianative...
call copy /Y "%~dp0\smali\MagiaNative\app\src\main\java\io\kamihama\magianative\*.smali" "%~dp0\build\app\smali_classes2\io\kamihama\magianative\"
echo Copying libraries...
call robocopy /NFL /NDL /NJH /NJS /nc /ns /e %~dp0\smali\okhttp-smali\okhttp3\ %~dp0\build\app\smali_classes2\okhttp3\
call robocopy /NFL /NDL /NJH /NJS /nc /ns /e %~dp0\smali\okhttp-smali\okio\ %~dp0\build\app\smali_classes2\okio\
echo Copying unknown...
call robocopy /NFL /NDL /NJH /NJS /nc /ns /e %~dp0\patches\unknown\ %~dp0\build\app\unknown\
call copy /Y "%~dp0\patches\strings.xml" "%~dp0\build\app\res\values\strings.xml"
echo Building libraries.
rmdir /S /Q %~dp0\build\armeabi-v7a\
rmdir /S /Q %~dp0\build\arm64-v8a\
mkdir %~dp0\build\armeabi-v7a
mkdir %~dp0\build\arm64-v8a
echo Running cmake armeabi-v7a...
cd %~dp0\build\armeabi-v7a
call "C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO\2019\ENTERPRISE\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\CMAKE\CMake\bin\cmake.exe" -G Ninja -DANDROID_ABI="armeabi-v7a" -DCMAKE_BUILD_TYPE:STRING="Debug" -DCMAKE_INSTALL_PREFIX:PATH="%~dp0\build\armeabi-v7a" -DCMAKE_TOOLCHAIN_FILE:FILEPATH="%ndk%/build/cmake/android.toolchain.cmake" -DCMAKE_MAKE_PROGRAM:FILEPATH="C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja\ninja.exe" "-DANDROID_PLATFORM=19" "-DCMAKE_SYSTEM_NAME=Android" "-DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a" "-DCMAKE_ANDROID_NDK=%ndk%" "-DCMAKE_SYSTEM_VERSION=16" "-DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang" "-DDOBBY_DEBUG=ON" "%~dp0\"
if errorlevel 1 goto errorexit
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja\ninja.exe"
if errorlevel 1 goto errorexit
echo Running cmake arm64-v8a...
cd %~dp0\build\arm64-v8a
call "C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO\2019\ENTERPRISE\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\CMAKE\CMake\bin\cmake.exe" -G Ninja -DANDROID_ABI="arm64-v8a" -DCMAKE_BUILD_TYPE:STRING="Debug" -DCMAKE_INSTALL_PREFIX:PATH="%~dp0\build\arm64-v8a" -DCMAKE_TOOLCHAIN_FILE:FILEPATH="%ndk%/build/cmake/android.toolchain.cmake" -DCMAKE_MAKE_PROGRAM:FILEPATH="C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja\ninja.exe" "-DANDROID_PLATFORM=21" "-DCMAKE_SYSTEM_NAME=Android" "-DCMAKE_ANDROID_ARCH_ABI=arm64-v8a" "-DCMAKE_ANDROID_NDK=%ndk%" "-DCMAKE_SYSTEM_VERSION=16" "-DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang" "-DDOBBY_DEBUG=ON" "%~dp0\"
if errorlevel 1 goto errorexit
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja\ninja.exe"
if errorlevel 1 goto errorexit
echo Copying libraries...
call copy /Y %~dp0\build\armeabi-v7a\libuwasa.so %~dp0\build\app\lib\armeabi-v7a\libuwasa.so
call copy /Y %~dp0\abiproxy\build\armeabi-v7a\libabiproxy.so %~dp0\build\app\lib\armeabi-v7a\libabiproxy.so
call copy /Y %~dp0\build\arm64-v8a\libuwasa.so %~dp0\build\app\lib\arm64-v8a\libuwasa.so
call copy /Y %~dp0\abiproxy\build\arm64-v8a\libabiproxy.so %~dp0\build\app\lib\arm64-v8a\libabiproxy.so
echo Rebuilding APK...
call java -jar %~dp0\build\apktool_2.4.1.jar b %~dp0\build\app\ -o %~dp0\build\magia_patched.apk
:signandupload
echo Signing apk...
call %~dp0\sign.bat
echo Finished!
goto exit
:errorexit
echo An error has occurred, exiting.
goto exit
:exit
pause

106
build_release.bat Normal file
View File

@ -0,0 +1,106 @@
@echo off
for /r "%~dp0\apk" %%a in (*.apk) do set apk=%%~dpnxa
if "%apk%" neq "" (
echo Found apk %apk%.
goto :start
)
echo Did not find any MagiReco APK! Add it to the apk/ directory.
goto errorexit
pause
:start
set ndk="C:/Android/android-ndk-r21d/"
set /p ndk="Enter ndk Location [C:/Android/android-ndk-r21d/]: "
if not exist %~dp0\build mkdir %~dp0\build
if exist %~dp0\build\apktool_2.4.1.jar goto apktoolexists
echo Downloading apktool...
CALL curl -A "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64)" -o "%~dp0\build\apktool_2.4.1.jar" -L "https://bitbucket.org/iBotPeaches/apktool/downloads/apktool_2.4.1.jar"
:apktoolexists
if not exist %~dp0\build\app\ goto create
set deleteold=N
set /p deleteold="Remake existing APK work directory (Y/[N])? "
if %deleteold% NEQ Y goto build
:create
echo Removing existing build files...
rmdir /S /Q %~dp0\build\app\
echo Running apktool...
CALL java -jar %~dp0\build\apktool_2.4.1.jar d %apk% -o %~dp0\build\app\
mkdir %~dp0\build\app\smali\com\loadLib\
if not exist %~dp0\build\app\lib\armeabi-v7a mkdir %~dp0\build\app\lib\armeabi-v7a
if not exist %~dp0\build\app\lib\arm64-v8a mkdir %~dp0\build\app\lib\arm64-v8a
echo Applying smali patches...
cd %~dp0
call git apply --stat "%~dp0\patches\NativeBridge.patch"
call git apply --stat "%~dp0\patches\Hook.patch"
call git apply "%~dp0\patches\NativeBridge.patch"
call git apply "%~dp0\patches\Hook.patch"
echo Applying misc patches...
REM call copy /Y "%~dp0\patches\images\story_ui_sprites00_patch.plist" "%~dp0\build\app\assets\package\story\story_ui_sprites00.plist"
REM call copy /Y "%~dp0\patches\images\story_ui_sprites00_patch.png" "%~dp0\build\app\assets\package\story\story_ui_sprites00.png"
call copy /Y "%~dp0\patches\koruri-semibold.ttf" "%~dp0\build\app\assets\fonts\koruri-semibold.ttf"
echo Updating sprites and AndroidManifest.xml...
call python buildassets.py
:build
echo Copying new smali files...
call copy /Y "%~dp0\smali\loader\*.smali" "%~dp0\build\app\smali\com\loadLib\"
mkdir %~dp0\build\app\smali_classes2\io\kamihama\magianative\
echo Copying magianative...
call copy /Y "%~dp0\smali\MagiaNative\app\src\main\java\io\kamihama\magianative\*.smali" "%~dp0\build\app\smali_classes2\io\kamihama\magianative\"
echo Copying libraries...
call robocopy /NFL /NDL /NJH /NJS /nc /ns /e %~dp0\smali\okhttp-smali\okhttp3\ %~dp0\build\app\smali_classes2\okhttp3\
call robocopy /NFL /NDL /NJH /NJS /nc /ns /e %~dp0\smali\okhttp-smali\okio\ %~dp0\build\app\smali_classes2\okio\
echo Copying unknown...
call robocopy /NFL /NDL /NJH /NJS /nc /ns /e %~dp0\patches\unknown\ %~dp0\build\app\unknown\
call copy /Y "%~dp0\patches\strings.xml" "%~dp0\build\app\res\values\strings.xml"
echo Building libraries.
rmdir /S /Q %~dp0\build\armeabi-v7a\
rmdir /S /Q %~dp0\build\arm64-v8a\
mkdir %~dp0\build\armeabi-v7a
mkdir %~dp0\build\arm64-v8a
echo Running cmake armeabi-v7a...
cd %~dp0\build\armeabi-v7a
call "C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO\2019\ENTERPRISE\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\CMAKE\CMake\bin\cmake.exe" -G Ninja -DANDROID_ABI="armeabi-v7a" -DCMAKE_BUILD_TYPE:STRING="Release" -DCMAKE_INSTALL_PREFIX:PATH="%~dp0\build\armeabi-v7a" -DCMAKE_TOOLCHAIN_FILE:FILEPATH="%ndk%/build/cmake/android.toolchain.cmake" -DCMAKE_MAKE_PROGRAM:FILEPATH="C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja\ninja.exe" "-DANDROID_PLATFORM=19" "-DCMAKE_SYSTEM_NAME=Android" "-DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a" "-DCMAKE_ANDROID_NDK=%ndk%" "-DCMAKE_SYSTEM_VERSION=16" "-DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang" "-DDOBBY_DEBUG=OFF" "%~dp0\"
if errorlevel 1 goto errorexit
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja\ninja.exe"
if errorlevel 1 goto errorexit
echo Running cmake arm64-v8a...
cd %~dp0\build\arm64-v8a
call "C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO\2019\ENTERPRISE\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\CMAKE\CMake\bin\cmake.exe" -G Ninja -DANDROID_ABI="arm64-v8a" -DCMAKE_BUILD_TYPE:STRING="Release" -DCMAKE_INSTALL_PREFIX:PATH="%~dp0\build\arm64-v8a" -DCMAKE_TOOLCHAIN_FILE:FILEPATH="%ndk%/build/cmake/android.toolchain.cmake" -DCMAKE_MAKE_PROGRAM:FILEPATH="C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja\ninja.exe" "-DANDROID_PLATFORM=21" "-DCMAKE_SYSTEM_NAME=Android" "-DCMAKE_ANDROID_ARCH_ABI=arm64-v8a" "-DCMAKE_ANDROID_NDK=%ndk%" "-DCMAKE_SYSTEM_VERSION=16" "-DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang" "-DDOBBY_DEBUG=OFF" "%~dp0\"
if errorlevel 1 goto errorexit
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja\ninja.exe"
if errorlevel 1 goto errorexit
echo Copying libraries...
call copy /Y %~dp0\build\armeabi-v7a\libuwasa.so %~dp0\build\app\lib\armeabi-v7a\libuwasa.so
call copy /Y %~dp0\abiproxy\build\armeabi-v7a\libabiproxy.so %~dp0\build\app\lib\armeabi-v7a\libabiproxy.so
call copy /Y %~dp0\build\arm64-v8a\libuwasa.so %~dp0\build\app\lib\arm64-v8a\libuwasa.so
call copy /Y %~dp0\abiproxy\build\arm64-v8a\libabiproxy.so %~dp0\build\app\lib\arm64-v8a\libabiproxy.so
echo Rebuilding APK...
call java -jar %~dp0\build\apktool_2.4.1.jar b %~dp0\build\app\ -o %~dp0\build\magia_patched.apk
:signandupload
echo Signing apk...
call %~dp0\sign.bat
echo Finished!
goto exit
:errorexit
echo An error has occurred, exiting.
goto exit
:exit
pause

130
buildassets.py Normal file
View File

@ -0,0 +1,130 @@
import sys, os
from PIL import Image
import plistlib
import ast
from pathlib import Path
sys.path.append('lib/untp/src/untp')
import untp
from PyTexturePacker import Packer
from shutil import copyfile
import shutil
def rmdir(directory):
if os.path.exists(directory):
directory = Path(directory)
for item in directory.iterdir():
if item.is_dir():
rmdir(item)
else:
item.unlink()
directory.rmdir()
en_path = "L:/MagiaReco/com.aniplex.magireco.en_1.2.0_checkonly-debugSigned/assets/package/"
jp_path = os.path.dirname(os.path.realpath(__file__)) + "/build/app/assets/package/"
print("EN Path: " + en_path)
print("JP Path: " + jp_path)
en_assets = {}
jp_assets = {}
for path in Path(en_path).rglob('*.png'):
en_assets[path.name] = path
for path in Path(jp_path).rglob('*.png'):
jp_assets[path.name] = path
required_assets = [["quest_image0","quest_image1"],
["data_download0"],
["ef_battle000","ef_battle001"],
["qb_auto_settings0"],
["qb_continue"],
["qb_ef_sp_combo0"],
["qb_help"],
["story_ui_sprites00"],
["toppage_bg_020", "toppage_bg_021"],
["web_ef_magia_lvup0"],
["web_ef_memoria0", "web_ef_memoria1"],
["web_ef_reality_up0"],
["web_ef_strengthening0"],
["qb_menu_top0"]]
ignored_images = ["dl_loading_bar01.png", "qb_menu_top_14.png"]
copyfile(en_path + "/top/toppage_bg_02.ExportJson", jp_path + "/top/toppage_bg_02.ExportJson")
copyfile(en_path + "/memoria/web_ef_memoria.ExportJson", jp_path + "/memoria/web_ef_memoria.ExportJson")
print("Updating AndroidManifest.xml")
path = Path("build/app/AndroidManifest.xml")
text = path.read_text()
text = text.replace("com.aniplex.magireco", "io.kamihama.magiatranslate")
path.write_text(text)
basePath = os.path.dirname(os.path.realpath(__file__))
rmdir("build/assets")
Path("build/assets").mkdir(parents=True, exist_ok=True)
for assets in required_assets:
rmdir("build/assets/work_jp")
Path("build/assets/work_jp").mkdir(parents=True, exist_ok=True)
rmdir("build/assets/work_jp_old")
Path("build/assets/work_jp_old").mkdir(parents=True, exist_ok=True)
rmdir("build/assets/work_en")
Path("build/assets/work_en").mkdir(parents=True, exist_ok=True)
rmdir("build/assets/work_out")
Path("build/assets/work_out").mkdir(parents=True, exist_ok=True)
for asset in assets:
asset_png = asset + ".png"
jp_asset_plist = str(jp_assets[asset_png])[:-4] + ".plist"
jp_asset_png = jp_assets[asset_png]
#print("Working on JP " + jp_asset_plist)
untp.unpacker(str(jp_asset_plist), image_file = str(jp_asset_png), output_dir = "build/assets/work_jp")
untp.unpacker(str(jp_asset_plist), image_file = str(jp_asset_png), output_dir = "build/assets/work_jp_old")
for asset in assets:
asset_png = asset + ".png"
if asset_png in en_assets:
na_asset_plist = str(en_assets[asset_png])[:-4] + ".plist"
na_asset_png = en_assets[asset_png]
#print("Working on NA " + na_asset_plist)
untp.unpacker(str(na_asset_plist), image_file = str(na_asset_png), output_dir = "build/assets/work_en")
#print("Skipping NA %s" % asset_png)
for toCopy in Path("build/assets/work_en").rglob("*.*"):
filename = os.path.basename(str(toCopy))
#print("Copying %s" % str(toCopy)[8:])
if (filename not in ignored_images):
copyfile("build/assets/work_en/" + filename, "build/assets/work_jp/" + filename)
manualPath = basePath + "patches/images/" + assets[0] + "/"
if os.path.exists(manualPath):
print("Adding manual replacements for " + assets[0] + ".")
for toCopy in Path(manualPath).rglob("*.*"):
filename = os.path.basename(str(toCopy))
print("Copying " + filename + "...")
copyfile(toCopy, "build/assets/work_jp/" + filename)
if assets[0] == "toppage_bg_020":
print("Manual override for toppage")
packer = Packer.create(max_width=2048, max_height=1920, bg_color=0x00ffffff, enable_rotated=False)
else:
packer = Packer.create(max_width=2048, max_height=2048, bg_color=0x00ffffff, enable_rotated=False)
if str(assets[0][-1]) == '0':
packer.pack("build/assets/work_jp/", str(assets[0][:-1]) + "%d", output_path="build/assets/work_out/")
else:
packer.pack("build/assets/work_jp/", str(assets[0]), output_path="build/assets/work_out/")
for asset in assets:
asset_png = asset + ".png"
jp_asset_plist = str(jp_assets[asset_png])[:-4] + ".plist"
jp_asset_png = jp_assets[asset_png]
os.remove(jp_asset_png)
os.remove(jp_asset_plist)
savedir = os.path.dirname(jp_asset_png)
print("Saving to %s" % savedir)
file_names = os.listdir("build/assets/work_out/")
for file_name in file_names:
shutil.move(os.path.join("build/assets/work_out/", file_name), savedir)

0
lib/.gitkeep Normal file
View File

1
lib/Dobby Submodule

@ -0,0 +1 @@
Subproject commit 0aec6c146a3140b917d42850f3c48d19e6c64746

1
lib/cocos Submodule

@ -0,0 +1 @@
Subproject commit b06eab6779fa27b6b4518a877ded7131cf9b90c6

1
lib/untp Submodule

@ -0,0 +1 @@
Subproject commit 9d305b40ba0d1bd3f845e0102fa6815b7f2b718c

26
patches/Hook.patch Normal file
View File

@ -0,0 +1,26 @@
diff --git a/build/app/smali/jp/f4samurai/MyApplication.smali b/build/app/smali/jp/f4samurai/MyApplication.smali
index 2a83c1d..c18fa78 100644
--- "a/build/app/smali/jp/f4samurai/MyApplication.smali"
+++ "b/build/app/smali/jp/f4samurai/MyApplication.smali"
@@ -6,6 +6,7 @@
# direct methods
.method public constructor <init>()V
.locals 0
+ invoke-static {}, Lcom/loadLib/libLoader;->loadLib()V
.line 12
invoke-direct {p0}, Landroid/app/Application;-><init>()V
@@ -36,12 +37,7 @@
.end method
.method public onCreate()V
- .locals 1
-
- const-string v0, "19418f5e-aacd-437e-af3e-2c9967abcb2f"
-
- .line 16
- invoke-static {p0, v0}, Lcom/smrtbeat/SmartBeat;->initAndStartSession(Landroid/app/Application;Ljava/lang/String;)V
+ .locals 0
.line 17
invoke-super {p0}, Landroid/app/Application;->onCreate()V

View File

@ -0,0 +1,40 @@
diff --git a/build/app/smali_classes2/jp/f4samurai/bridge/NativeBridge.smali b/build/app/smali_classes2/jp/f4samurai/bridge/NativeBridge.smali
index 0c7b0b1..c283cbc 100644
--- a/build/app/smali_classes2/jp/f4samurai/bridge/NativeBridge.smali
+++ b/build/app/smali_classes2/jp/f4samurai/bridge/NativeBridge.smali
@@ -8,8 +8,6 @@
.field private static sAppActivity:Ljp/f4samurai/AppActivity;
-.field private static sCheatHandler:Ljp/f4samurai/bridge/CheatHandler;
-
.field private static sClipboardManager:Landroid/content/ClipboardManager;
@@ -36,13 +34,6 @@
sput-object v0, Ljp/f4samurai/bridge/NativeBridge;->sAppActivity:Ljp/f4samurai/AppActivity;
.line 34
- new-instance v0, Ljp/f4samurai/bridge/CheatHandler;
-
- sget-object v1, Ljp/f4samurai/bridge/NativeBridge;->sAppActivity:Ljp/f4samurai/AppActivity;
-
- invoke-direct {v0, v1}, Ljp/f4samurai/bridge/CheatHandler;-><init>(Landroid/content/Context;)V
-
- sput-object v0, Ljp/f4samurai/bridge/NativeBridge;->sCheatHandler:Ljp/f4samurai/bridge/CheatHandler;
.line 35
sget-object v0, Ljp/f4samurai/bridge/NativeBridge;->sAppActivity:Ljp/f4samurai/AppActivity;
@@ -354,11 +345,7 @@
.locals 1
.line 180
- sget-object v0, Ljp/f4samurai/bridge/NativeBridge;->sCheatHandler:Ljp/f4samurai/bridge/CheatHandler;
-
- invoke-virtual {v0}, Ljp/f4samurai/bridge/CheatHandler;->isUnauthorizedUser()Z
-
- move-result v0
+ const v0, 0
return v0
.end method

1
patches/images Submodule

@ -0,0 +1 @@
Subproject commit 8ea15ac03dec652206844acf950f7b124d08e166

BIN
patches/koruri-semibold.ttf Normal file

Binary file not shown.

142
patches/strings.xml Normal file
View File

@ -0,0 +1,142 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="abc_action_bar_home_description">Navigate home</string>
<string name="abc_action_bar_up_description">Navigate up</string>
<string name="abc_action_menu_overflow_description">More options</string>
<string name="abc_action_mode_done">Done</string>
<string name="abc_activity_chooser_view_see_all">See all</string>
<string name="abc_activitychooserview_choose_application">Choose an app</string>
<string name="abc_capital_off">OFF</string>
<string name="abc_capital_on">ON</string>
<string name="abc_font_family_body_1_material">sans-serif</string>
<string name="abc_font_family_body_2_material">sans-serif-medium</string>
<string name="abc_font_family_button_material">sans-serif-medium</string>
<string name="abc_font_family_caption_material">sans-serif</string>
<string name="abc_font_family_display_1_material">sans-serif</string>
<string name="abc_font_family_display_2_material">sans-serif</string>
<string name="abc_font_family_display_3_material">sans-serif</string>
<string name="abc_font_family_display_4_material">sans-serif-light</string>
<string name="abc_font_family_headline_material">sans-serif</string>
<string name="abc_font_family_menu_material">sans-serif</string>
<string name="abc_font_family_subhead_material">sans-serif</string>
<string name="abc_font_family_title_material">sans-serif-medium</string>
<string name="abc_search_hint">Search…</string>
<string name="abc_searchview_description_clear">Clear query</string>
<string name="abc_searchview_description_query">Search query</string>
<string name="abc_searchview_description_search">Search</string>
<string name="abc_searchview_description_submit">Submit query</string>
<string name="abc_searchview_description_voice">Voice search</string>
<string name="abc_shareactionprovider_share_with">Share with</string>
<string name="abc_shareactionprovider_share_with_application">Share with %s</string>
<string name="abc_toolbar_collapse_description">Collapse</string>
<string name="app_name">Magia Record JP</string>
<string name="app_type">APP</string>
<string name="build_type">RELEASE</string>
<string name="cast_ad_label">Ad</string>
<string name="cast_casting_to_device">Casting to %1$s</string>
<string name="cast_closed_captions">Closed captions</string>
<string name="cast_closed_captions_unavailable">Closed captions unavailable</string>
<string name="cast_connecting_to_device">Connecting to %1$s</string>
<string name="cast_disconnect">Disconnect</string>
<string name="cast_expanded_controller_ad_image_description">Image displayed while the cast receiver is playing an ad</string>
<string name="cast_expanded_controller_ad_in_progress">Ad in progress…</string>
<string name="cast_expanded_controller_background_image">Album art</string>
<string name="cast_expanded_controller_live_stream_indicator">Live stream</string>
<string name="cast_expanded_controller_loading">Loading…</string>
<string name="cast_expanded_controller_skip_ad_label">Skip</string>
<string name="cast_forward">Forward</string>
<string name="cast_forward_10">Forward ten seconds</string>
<string name="cast_forward_30">Forward thirty seconds</string>
<string name="cast_intro_overlay_button_text">@android:string/ok</string>
<string name="cast_invalid_stream_duration_text">--:--</string>
<string name="cast_invalid_stream_position_text">--:--</string>
<string name="cast_mute">Mute</string>
<string name="cast_notification_connected_message">Connected to %1$s</string>
<string name="cast_notification_connecting_message">Connecting to %1$s</string>
<string name="cast_notification_default_channel_name">Cast</string>
<string name="cast_notification_disconnect">Disconnect</string>
<string name="cast_pause">Pause</string>
<string name="cast_play">Play</string>
<string name="cast_rewind">Rewind</string>
<string name="cast_rewind_10">Rewind ten seconds</string>
<string name="cast_rewind_30">Rewind thirty seconds</string>
<string name="cast_seek_bar">Playback seek control</string>
<string name="cast_skip_next">Skip to next item</string>
<string name="cast_skip_prev">Skip to previous item</string>
<string name="cast_stop">Stop</string>
<string name="cast_stop_live_stream">Stop live stream</string>
<string name="cast_tracks_chooser_dialog_audio">Audio</string>
<string name="cast_tracks_chooser_dialog_cancel">Cancel</string>
<string name="cast_tracks_chooser_dialog_closed_captions">Closed Captions</string>
<string name="cast_tracks_chooser_dialog_default_track_name">Track %1$d</string>
<string name="cast_tracks_chooser_dialog_none">None</string>
<string name="cast_tracks_chooser_dialog_ok">OK</string>
<string name="cast_tracks_chooser_dialog_subtitles">Subtitles</string>
<string name="cast_unmute">Unmute</string>
<string name="common_google_play_services_enable_button">Enable</string>
<string name="common_google_play_services_enable_text">"%1$s won't work unless you enable Google Play services."</string>
<string name="common_google_play_services_enable_title">Enable Google Play services</string>
<string name="common_google_play_services_install_button">Install</string>
<string name="common_google_play_services_install_text">"%1$s won't run without Google Play services, which are missing from your device."</string>
<string name="common_google_play_services_install_title">Get Google Play services</string>
<string name="common_google_play_services_notification_channel_name">Google Play services availability</string>
<string name="common_google_play_services_notification_ticker">Google Play services error</string>
<string name="common_google_play_services_unknown_issue">%1$s is having trouble with Google Play services. Please try again.</string>
<string name="common_google_play_services_unsupported_text">"%1$s won't run without Google Play services, which are not supported by your device."</string>
<string name="common_google_play_services_update_button">Update</string>
<string name="common_google_play_services_update_text">"%1$s won't run unless you update Google Play services."</string>
<string name="common_google_play_services_update_title">Update Google Play services</string>
<string name="common_google_play_services_updating_text">"%1$s won't run without Google Play services, which are currently updating."</string>
<string name="common_google_play_services_wear_update_text">New version of Google Play services needed. It will update itself shortly.</string>
<string name="common_open_on_phone">Open on phone</string>
<string name="common_signin_button_text">Sign in</string>
<string name="common_signin_button_text_long">Sign in with Google</string>
<string name="default_web_client_id">48695978581-l3g2vae3su7td5tilbunf8fpb1875np4.apps.googleusercontent.com</string>
<string name="fcm_channel_id">android_channel_id</string>
<string name="fcm_fallback_notification_channel_label">Miscellaneous</string>
<string name="firebase_database_url">https://kamihama-io.firebaseio.com</string>
<string name="gcm_defaultSenderId">48695978581</string>
<string name="gcm_fallback_notification_channel_label">Miscellaneous</string>
<string name="google_api_key">AIzaSyBlHoCTAsEa1zsIhKfE8nvMVewd0ULYmkw</string>
<string name="google_app_id">1:48695978581:android:bc7cc007c2de2d0e79c2dc</string>
<string name="google_crash_reporting_api_key">AIzaSyBlHoCTAsEa1zsIhKfE8nvMVewd0ULYmkw</string>
<string name="google_storage_bucket">kamihama-io.appspot.com</string>
<string name="mr_button_content_description">Cast button</string>
<string name="mr_cast_button_connected">Cast button. Connected</string>
<string name="mr_cast_button_connecting">Cast button. Connecting</string>
<string name="mr_cast_button_disconnected">Cast button. Disconnected</string>
<string name="mr_chooser_searching">Finding devices</string>
<string name="mr_chooser_title">Cast to</string>
<string name="mr_controller_album_art">Album art</string>
<string name="mr_controller_casting_screen">Casting screen</string>
<string name="mr_controller_close_description">Close</string>
<string name="mr_controller_collapse_group">Collapse</string>
<string name="mr_controller_disconnect">Disconnect</string>
<string name="mr_controller_expand_group">Expand</string>
<string name="mr_controller_no_info_available">No info available</string>
<string name="mr_controller_no_media_selected">No media selected</string>
<string name="mr_controller_pause">Pause</string>
<string name="mr_controller_play">Play</string>
<string name="mr_controller_stop">Stop</string>
<string name="mr_controller_stop_casting">Stop casting</string>
<string name="mr_controller_volume_slider">Volume slider</string>
<string name="mr_system_route_name">System</string>
<string name="mr_user_route_category_name">Devices</string>
<string name="place_autocomplete_clear_button">Clear search</string>
<string name="place_autocomplete_search_hint">Search</string>
<string name="project_id">magireco-754ac</string>
<string name="s1">Save image</string>
<string name="s2">Allow Ad to store image in Picture gallery?</string>
<string name="s3">Accept</string>
<string name="s4">Decline</string>
<string name="s5">Create calendar event</string>
<string name="s6">Allow Ad to create a calendar event?</string>
<string name="s7">Test Ad</string>
<string name="search_menu_title">Search</string>
<string name="server_type">PRODUCT</string>
<string name="status_bar_notification_info_overflow">999+</string>
<string name="tagmanager_preview_dialog_button">Continue</string>
<string name="tagmanager_preview_dialog_message">Preview mode updated.</string>
<string name="tagmanager_preview_dialog_title">Preview</string>
<string name="wallet_buy_button_place_holder">Buy with Google</string>
</resources>

View File

@ -0,0 +1,40 @@
{
"project_info": {
"project_number": "48695978581",
"firebase_url": "https://kamihama-io.firebaseio.com",
"project_id": "kamihama-io",
"storage_bucket": "kamihama-io.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:48695978581:android:bc7cc007c2de2d0e79c2dc",
"android_client_info": {
"package_name": "io.kamihama.magiatranslate"
}
},
"oauth_client": [
{
"client_id": "48695978581-l3g2vae3su7td5tilbunf8fpb1875np4.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyBlHoCTAsEa1zsIhKfE8nvMVewd0ULYmkw"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "48695978581-l3g2vae3su7td5tilbunf8fpb1875np4.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
}
],
"configuration_version": "1"
}

4
requirements.txt Normal file
View File

@ -0,0 +1,4 @@
parse==1.18.0
Pillow==8.0.1
pkg-resources==0.0.0
PyTexturePacker==1.1.0

101
smali/MagiaNative/.gitignore vendored Normal file
View File

@ -0,0 +1,101 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
# Built application files
*.apk
*.aar
*.ap_
*.aab
# Files for the ART/Dalvik VM
*.dex
# Java class files
*.class
# Generated files
bin/
gen/
out/
# Uncomment the following line in case you need and you don't have the release build type files in your app
# release/
# Gradle files
.gradle/
build/
# Local configuration file (sdk path, etc)
local.properties
# Proguard folder generated by Eclipse
proguard/
# Log Files
*.log
# Android Studio Navigation editor temp files
.navigation/
# Android Studio captures folder
captures/
# IntelliJ
*.iml
.idea/workspace.xml
.idea/tasks.xml
.idea/gradle.xml
.idea/assetWizardSettings.xml
.idea/dictionaries
.idea/libraries
# Android Studio 3 in .gitignore file.
.idea/caches
.idea/modules.xml
# Comment next line if keeping position of elements in Navigation Editor is relevant for you
.idea/navEditor.xml
# Keystore files
# Uncomment the following lines if you do not want to check your keystore files in.
#*.jks
#*.keystore
# External native build folder generated in Android Studio 2.2 and later
.externalNativeBuild
.cxx/
# Google Services (e.g. APIs or Firebase)
# google-services.json
# Freeline
freeline.py
freeline/
freeline_project_description.json
# fastlane
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
fastlane/readme.md
# Version control
vcs.xml
# lint
lint/intermediates/
lint/generated/
lint/outputs/
lint/tmp/
# lint/reports/
# Android Profiling
*.hprof

1
smali/MagiaNative/app/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

View File

@ -0,0 +1,29 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "io.kamihama.magianative"
minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.2.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation("com.squareup.okhttp3:okhttp:3.12.9")
}

View File

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@ -0,0 +1,27 @@
package io.kamihama.magianative;
import android.content.Context;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("io.kamihama.magianative", appContext.getPackageName());
}
}

View File

@ -0,0 +1,11 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.kamihama.magianative">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme" />
</manifest>

View File

@ -0,0 +1,73 @@
.class final Lio/kamihama/magianative/RestClient$1;
.super Ljava/lang/Object;
.source "RestClient.java"
# interfaces
.implements Ljavax/net/ssl/X509TrustManager;
# annotations
.annotation system Ldalvik/annotation/EnclosingMethod;
value = Lio/kamihama/magianative/RestClient;->getUnsafeOkHttpClient()Lokhttp3/OkHttpClient;
.end annotation
.annotation system Ldalvik/annotation/InnerClass;
accessFlags = 0x8
name = null
.end annotation
# direct methods
.method constructor <init>()V
.registers 1
.prologue
.line 86
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
# virtual methods
.method public checkClientTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V
.registers 3
.param p1, "chain" # [Ljava/security/cert/X509Certificate;
.param p2, "authType" # Ljava/lang/String;
.annotation system Ldalvik/annotation/Throws;
value = {
Ljava/security/cert/CertificateException;
}
.end annotation
.prologue
.line 89
return-void
.end method
.method public checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V
.registers 3
.param p1, "chain" # [Ljava/security/cert/X509Certificate;
.param p2, "authType" # Ljava/lang/String;
.annotation system Ldalvik/annotation/Throws;
value = {
Ljava/security/cert/CertificateException;
}
.end annotation
.prologue
.line 93
return-void
.end method
.method public getAcceptedIssuers()[Ljava/security/cert/X509Certificate;
.registers 2
.prologue
.line 97
const/4 v0, 0x0
new-array v0, v0, [Ljava/security/cert/X509Certificate;
return-object v0
.end method

View File

@ -0,0 +1,43 @@
.class final Lio/kamihama/magianative/RestClient$2;
.super Ljava/lang/Object;
.source "RestClient.java"
# interfaces
.implements Ljavax/net/ssl/HostnameVerifier;
# annotations
.annotation system Ldalvik/annotation/EnclosingMethod;
value = Lio/kamihama/magianative/RestClient;->getUnsafeOkHttpClient()Lokhttp3/OkHttpClient;
.end annotation
.annotation system Ldalvik/annotation/InnerClass;
accessFlags = 0x8
name = null
.end annotation
# direct methods
.method constructor <init>()V
.registers 1
.prologue
.line 110
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
# virtual methods
.method public verify(Ljava/lang/String;Ljavax/net/ssl/SSLSession;)Z
.registers 4
.param p1, "hostname" # Ljava/lang/String;
.param p2, "session" # Ljavax/net/ssl/SSLSession;
.prologue
.line 113
const/4 v0, 0x1
return v0
.end method

View File

@ -0,0 +1,34 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillType="evenOdd"
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
android:strokeWidth="1"
android:strokeColor="#00000000">
<aapt:attr name="android:fillColor">
<gradient
android:endX="78.5885"
android:endY="90.9159"
android:startX="48.7653"
android:startY="61.0927"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

View File

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#008577"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#008577</color>
<color name="colorPrimaryDark">#00574B</color>
<color name="colorAccent">#D81B60</color>
</resources>

View File

@ -0,0 +1,3 @@
<resources>
<string name="app_name">MagiaNative</string>
</resources>

View File

@ -0,0 +1,11 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>

View File

@ -0,0 +1,17 @@
package io.kamihama.magianative;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}

View File

@ -0,0 +1,27 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

View File

@ -0,0 +1,20 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true

Binary file not shown.

View File

@ -0,0 +1,6 @@
#Mon Sep 21 21:15:19 BST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip

172
smali/MagiaNative/gradlew vendored Normal file
View File

@ -0,0 +1,172 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

84
smali/MagiaNative/gradlew.bat vendored Normal file
View File

@ -0,0 +1,84 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -0,0 +1 @@
include ':app', ':magianativelib'

View File

@ -0,0 +1,44 @@
.class final Lcom/loadLib/libLoader$1;
.super Ljava/lang/Object;
.source "libLoader.java"
# interfaces
.implements Ljava/lang/Runnable;
# annotations
.annotation system Ldalvik/annotation/EnclosingMethod;
value = Lcom/JvRuit/Ldr;->loadLib()V
.end annotation
.annotation system Ldalvik/annotation/InnerClass;
accessFlags = 0x8
name = null
.end annotation
# direct methods
.method constructor <init>()V
.locals 0
.prologue
.line 14
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
# virtual methods
.method public run()V
.locals 1
.prologue
.line 17
const-string/jumbo v0, "uwasa"
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
.line 18
return-void
.end method

View File

@ -0,0 +1,36 @@
.class public Lcom/loadLib/libLoader;
.super Landroid/app/Activity;
.source "libLoader.java"
# direct methods
.method public constructor <init>()V
.locals 0
.prologue
.line 12
invoke-direct {p0}, Landroid/app/Activity;-><init>()V
return-void
.end method
.method public static loadLib()V
.locals 4
.prologue
.line 14
new-instance v0, Landroid/os/Handler;
invoke-direct {v0}, Landroid/os/Handler;-><init>()V
new-instance v1, Lcom/loadLib/libLoader$1;
invoke-direct {v1}, Lcom/loadLib/libLoader$1;-><init>()V
const-wide/16 v2, 0x1
invoke-virtual {v0, v1, v2, v3}, Landroid/os/Handler;->postDelayed(Ljava/lang/Runnable;J)Z
.line 20
return-void
.end method

1
smali/okhttp-smali Submodule

@ -0,0 +1 @@
Subproject commit 0c50e8e3935b66710255d73588735fde19a28683

12
src/Config.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef CONFIG_H
#define CONFIG_H
#include <cstdio>
#include <string>
#include <sstream>
#include <iostream>
/**************************
* Magia Translate Ver *
**************************/
#define MT_VERSION 110
#endif

747
src/MagiaClient.cpp Normal file
View File

@ -0,0 +1,747 @@
#include <jni.h>
#include <cstdint>
#include <android/log.h>
#include <dobby.h>
#include <memory.h>
#include <dlfcn.h>
#include <cstdio>
#include <cstdlib>
#include "Utils.h"
#include <string>
#include <thread>
#include <pthread.h>
#include <string.h>
#include <libgen.h>
#include "Config.h"
#include <cocos2d.h>
#include "libmadomagi.h"
#include "magia/StringsProxy.h"
#include "magia/DialogueBox.h"
#include "rest/MagiaRest.h"
const char* libName = "libmadomagi_native.so";
const char* hookName = "libuwasa.so";
JavaVM* gJvm = nullptr;
static jobject gClassLoader;
static jmethodID gFindClassMethod;
uintptr_t libBase = 0;
//namespace fs = std::filesystem; ndk 22+ required
struct hook_loop_args {
std::string libso;
};
uintptr_t storyMessageUnitStartOffset = 0;
uintptr_t storyMessageUnitCreateMessageAreaOffset = 0;
uintptr_t storyLogUnitAddMessageOffset = 0;
uintptr_t storyLogUnitAddNarrationOffset = 0;
uintptr_t storyCharaUnitonTextHomeOffset = 0;
uintptr_t storyNarrationUnitCreateLabelOffset = 0;
uintptr_t initCenterWidthOutline = 0;
int max_threads = 10;
void* openMessageBoxPtr = nullptr;
uintptr_t* resourceUrlPtr = nullptr;
bool initialized = false;
const std::string assetBase = "/magica/resource";
const std::string assetTrunk = "/download/asset/master";
const std::string assetScenario = "/resource/scenario";
void* urlEndpoints[] = {nullptr, nullptr, nullptr};
StringsProxy* koruriFont = new StringsProxy("fonts/koruri-semibold.ttf");
typedef int *(*setUrlType)(int *);
typedef int *(*setResourceType)(int *, unsigned int *);
typedef uintptr_t *(*UrlConfigImplResourceType)(uintptr_t &a1, int a2, unsigned int a3, int a4);
// Hooked functions
void *(*setPositionHooked)(uintptr_t label, cocos2d::Vec2 const& position);
void *(*setMaxLineWidthHooked)(uintptr_t label, float length);
void *(*setDimensionsHooked)(uintptr_t label, float width, float a3);
void *(*urlConfigResourceHooked)(void* a1, UrlConfigResourceType type); // There is also api, chat, web, etc for other endpoints
//void* urlConfig_ImplObj = nullptr;
// Cocos functions
typedef cocos2d::Director* (*director_type)(void* dummy);
typedef const cocos2d::Size& (*get_win_size_type)(cocos2d::Director* director);
typedef cocos2d::Vec2 (*get_visible_origin_type)(cocos2d::Director* director);
director_type getDirector;
get_win_size_type getWinSize;
get_visible_origin_type getVisibleOrigin;
/* BROKEN
void testDialogue() {
if (openMessageBoxPtr != nullptr) {
auto x = DialogueBoxProxy();
x.DialogueBox(openMessageBoxPtr);
}
}*/
jclass findClass(JNIEnv* env, const char* name) {
return static_cast<jclass>(env->CallObjectMethod(gClassLoader, gFindClassMethod, env->NewStringUTF(name)));
}
void displayMessage(const std::string& title, const std::string& description) {
auto env = getEnv(gJvm);
const char* cocosHelper = "org/cocos2dx/lib/Cocos2dxHelper";
const char* showDialogueBox = "showDialog";
std::string signature = "(" + std::string(getJNISignature(title, description)) + ")V";
jclass klass = findClass(env, cocosHelper);
if (klass == nullptr) {
LOGE("No Cocos2dxHelper found.");
return;
}
jmethodID mid = env->GetStaticMethodID(klass, showDialogueBox, signature.c_str());
if (mid == nullptr) {
LOGE("No showDialog found.");
return;
}
jstring str1 = env->NewStringUTF(title.c_str());
jstring str2 = env->NewStringUTF(description.c_str());
env->CallStaticObjectMethod(klass, mid, str1, str2);
}
int *(*sceneLayerManagerCreateSceneLayerOld)(uintptr_t *sceneLayerManager, BaseSceneLayerInfo* sceneLayerInfo);
int *sceneLayerManagerCreateSceneLayer(uintptr_t *sceneLayerManager, BaseSceneLayerInfo* sceneLayerInfo) {
auto sceneType = sceneLayerInfo->layerType;
if (sceneType >= BaseSceneLayerType::BaseSceneLayerTypeMaxValue || sceneType < 0) {
LOGW("Unknown scene triggered. %d", sceneType);
}
else {
LOGD("Scene layer changed to: %s", BaseSceneLayerTypeStrings[sceneType]);
}
if (!initialized && sceneType == BaseSceneLayerType::WebSceneLayer) { // Set up everything here
auto rest = MagiaRest(gJvm);
switch(rest.Endpoint()) {
case MAGIAREST_EMPTY:
{
auto emptyMessage = string_format("Unable to connect to the translation server. Restart the app to retry, or continue to play in Japanese. (Response length: %zu)",
rest.EndpointStringLength());
displayMessage("MagiaTranslate Error", emptyMessage.c_str());
break;
}
case MAGIAREST_ERROR:
{
auto errorMessage = string_format("An error has occurred. Restart the app to retry, or continue to play in Japanese.\nError: %s", rest.GetEndpointError().c_str());
displayMessage("MagiaTranslate Error", errorMessage.c_str());
break;
}
case MAGIAREST_SUCCESS:
{
auto ver = rest.GetEndpointVersion();
if (MT_VERSION < ver) {
LOGI("Version update required.");
auto updateMessage = string_format("A new version of MagiaTranslate is available, please update your app at kamihama.io. Continuing may result in crashes.\nApp version installed: %d\nApp version available: %d",
MT_VERSION, ver);
displayMessage("MagiaTranslate Update", updateMessage.c_str());
}
auto endpointUrl = rest.GetEndpointUrl();
if (endpointUrl.empty()) {
LOGW("Empty endpoint URL.");
displayMessage("MagiaTranslate Error", "Error 115 has occurred, the returned translate endpoint URL is empty, please try again later.");
break;
}
// Set max download threads
auto mt = rest.GetMaxThreads();
if (mt > 0) {
LOGD("Set maximum threads from API, value %d.", mt);
max_threads = mt;
}
const std::string assetNameBase = endpointUrl + assetBase;
const std::string assetNameFull = endpointUrl + assetBase + assetTrunk;
const std::string assetNameScript = endpointUrl + assetBase + assetTrunk + assetScenario;
// new keyword to stop freeing
StringsProxy* assetNameBaseProxy = new StringsProxy(assetNameBase.c_str());
StringsProxy* assetNameFullProxy = new StringsProxy(assetNameFull.c_str());
StringsProxy* assetNameScriptProxy = new StringsProxy(assetNameScript.c_str());
LOGD("Setting endpoint URLs.");
urlEndpoints[UrlConfigResourceType::BaseUrl] = (void*)assetNameBaseProxy->ptr();
urlEndpoints[UrlConfigResourceType::TrunkUrl] = (void*)assetNameFullProxy->ptr();
urlEndpoints[UrlConfigResourceType::ScenarioUrl] = (void*)assetNameScriptProxy->ptr();
LOGD("Finished setting endpoint URLs.");
break;
}
}
initialized = true;
auto y = sceneLayerManagerCreateSceneLayerOld(sceneLayerManager, sceneLayerInfo);
return y;
}
return sceneLayerManagerCreateSceneLayerOld(sceneLayerManager, sceneLayerInfo);
}
// Change function to fetch resource URLs
void* urlConfigResource(void* a1, UrlConfigResourceType type) {
LOGD("Fetching URL config resource %d", (int)type);
if (type < UrlConfigResourceType::UrlConfigResourceTypeMaxValue) {
if (urlEndpoints[type] != nullptr) {
return (void *)urlEndpoints[type];
}
else {
LOGW("Nullptr endpoint found for endpoint type %d!", (int)type);
}
}
return urlConfigResourceHooked(a1, type);
}
void* (*cocosCreateLabelHooked)(const uintptr_t* textPtr, const uintptr_t* fontPtr, float textSize, cocos2d::Size const& cocosSize, cocos2d::TextHAlignment hAlign, cocos2d::TextVAlignment vAlign);
void* cocosCreateLabel(const uintptr_t* textPtr, const uintptr_t* fontPtr, float textSize, cocos2d::Size const& cocosSize, cocos2d::TextHAlignment hAlign, cocos2d::TextVAlignment vAlign) {
uintptr_t addr = reinterpret_cast<uintptr_t>(__builtin_extract_return_addr(__builtin_return_address(0)));
LOGD("Label created at %p (%p), size %.1f.", (void*) addr, (void*)(addr - libBase), textSize);
if (storyMessageUnitCreateMessageAreaOffset != 0 && addr >= storyMessageUnitCreateMessageAreaOffset) {
uintptr_t difference = addr - storyMessageUnitCreateMessageAreaOffset;
if (difference <= 0x200) {
LOGD("Setting new text font for main story text.");
if (textSize == 27.0) {
textSize = 30.0;
}
return cocosCreateLabelHooked(textPtr, koruriFont->ptr(), textSize, cocosSize, hAlign, vAlign);
}
}
if (storyNarrationUnitCreateLabelOffset != 0 && addr >= storyNarrationUnitCreateLabelOffset) {
uintptr_t difference = addr - storyNarrationUnitCreateLabelOffset;
if (difference <= 0x200) { // 0x8e
LOGD("Setting new narration text font. Difference: %p", (void*)difference);
return cocosCreateLabelHooked(textPtr, koruriFont->ptr(), textSize, cocosSize, hAlign, vAlign);
}
}
if (initCenterWidthOutline != 0 && addr >= initCenterWidthOutline) {
uintptr_t difference = addr - initCenterWidthOutline;
if (difference <= 0x200) {
LOGD("Setting new home text font and size.");
textSize = textSize * 0.85;
return cocosCreateLabelHooked(textPtr, koruriFont->ptr(), textSize, cocosSize, hAlign, vAlign);
}
}
if (storyLogUnitAddMessageOffset != 0 && addr >= storyLogUnitAddMessageOffset) {
uintptr_t difference = addr - storyLogUnitAddMessageOffset;
if (difference <= 0x640) { // 0xec, 0x54e
LOGD("Setting new log text font. Difference: %p", (void*)difference);
return cocosCreateLabelHooked(textPtr, koruriFont->ptr(), textSize, cocosSize, hAlign, vAlign);
}
}
if (storyLogUnitAddNarrationOffset != 0 && addr >= storyLogUnitAddNarrationOffset) {
uintptr_t difference = addr - storyLogUnitAddNarrationOffset;
if (difference <= 0x640) { // 0x43e, 0x5b0
LOGD("Setting new log text font (narration). Difference: %p", (void*)difference);
return cocosCreateLabelHooked(textPtr, koruriFont->ptr(), textSize, cocosSize, hAlign, vAlign);
}
}
return cocosCreateLabelHooked(textPtr, fontPtr, textSize, cocosSize, hAlign, vAlign);
}
// New functions
void *setPositionNew(uintptr_t label, cocos2d::Vec2 const& position) {
uintptr_t addr = reinterpret_cast<uintptr_t>(__builtin_extract_return_addr(__builtin_return_address(0)));
//LOGI("Move at %p to x: %.2f, y: %.2f", (addr - libBase), position.x, position.y);
// Story message boxes
if (storyMessageUnitStartOffset != 0 && addr >= storyMessageUnitStartOffset) {
uintptr_t difference = addr - storyMessageUnitStartOffset;
// Alignment of main text in box
if (difference <= 0x200) { // Offset = 0x76 as of 2.15
LOGD("Moving story text.");
//LOGI("Difference: %p", difference);
//LOGD("old [message] x: %.2f, y: %.2f", position.x, position.y);
// Move text to the left and up a bit
if (position.x == -222.0 && position.y == 20.0) {
cocos2d::Vec2 newPosition = cocos2d::Vec2(-368.0, 25.0);
//LOGD("new 1 x: %.2f, y: %.2f", newPosition.x, newPosition.y);
return setPositionHooked(label, newPosition);
}
else if (position.x == -207.0 && position.y == 30.0) {
cocos2d::Vec2 newPosition = cocos2d::Vec2(-360.0, 40.0);
//LOGD("new 2 x: %.2f, y: %.2f", newPosition.x, newPosition.y);
return setPositionHooked(label, newPosition);
}
}
}
// Names alignment
if (storyMessageUnitCreateMessageAreaOffset != 0 && addr >= storyMessageUnitCreateMessageAreaOffset) {
uintptr_t difference = addr - storyMessageUnitCreateMessageAreaOffset;
//LOGI("Difference: %p", difference);
// Move names into the right place
if (difference <= 0x600) { // Offset = 0x35e as of 2.15
//LOGD("old [name] x: %.2f, y: %.2f", position.x, position.y);
LOGD("Moving story name.");
if (position.x == -215.0 && position.y == 57.0) { // Left names
cocos2d::Vec2 newPosition = cocos2d::Vec2(-320.0, 55.0);
//LOGD("new l-1 x: %.2f, y: %.2f", newPosition.x, newPosition.y);
return setPositionHooked(label, newPosition);
}
else if (position.x == -55.0 && position.y == 57.0) { // Center names
cocos2d::Vec2 newPosition = cocos2d::Vec2(30.0, 55.0);
//LOGD("new m-1 x: %.2f, y: %.2f", newPosition.x, newPosition.y);
return setPositionHooked(label, newPosition);
}
else if (position.x == 215.0 && position.y == 57.0) { // Right names
cocos2d::Vec2 newPosition = cocos2d::Vec2(320.0, 55.0);
//LOGD("new r-1 x: %.2f, y: %.2f", newPosition.x, newPosition.y);
return setPositionHooked(label, newPosition);
}
}
}
// History
if (storyLogUnitAddMessageOffset != 0 && addr >= storyLogUnitAddMessageOffset) {
uintptr_t difference = addr - storyLogUnitAddMessageOffset;
//LOGI("LOG MESSAGE: %.2f %.2f", position.x, position.y);
//LOGI("Difference: %p", (void *)difference);
if (position.y >= 55.50 && position.y <= 56.50 && difference <= 0x800) {
float newPosX = position.x + 125.0;
//LOGD("Moved log text from %.2f to %.2f", position.x, newPosX);
cocos2d::Vec2 newPosition = cocos2d::Vec2(newPosX, 66.50);
return setPositionHooked(label, newPosition);
}
else if (difference <= 0x200 && position.x == 70.00) {
LOGD("Moving left-aligned name down in the log.");
auto newY = position.y - 15.0;
cocos2d::Vec2 newPosition = cocos2d::Vec2(position.x, newY);
return setPositionHooked(label, newPosition);
}
else if (difference <= 0x200 && position.x == 500.00) { // Names on the right
LOGD("Moving name further to the right in log.");
auto newX = position.x + 200;
auto newY = position.y - 15.0;
cocos2d::Vec2 newPosition = cocos2d::Vec2(newX, newY);
return setPositionHooked(label, newPosition);
}
else if (difference <= 0x200 && position.x == 280.00) { // Names in the center, 280.00?
LOGD("Moving center name to the left in the log.");
auto newX = 71.50;
auto newY = position.y;
cocos2d::Vec2 newPosition = cocos2d::Vec2(newX, newY);
return setPositionHooked(label, newPosition);
}
}
return setPositionHooked(label, position);
}
void *setMaxLineWidthNew(uintptr_t label, float length) {
//LOGI("Hook triggered - line length");
uintptr_t addr = reinterpret_cast<uintptr_t>(__builtin_extract_return_addr(__builtin_return_address(0)));
//LOGI("%p", (addr - libBase));
if (storyMessageUnitCreateMessageAreaOffset != 0 && addr >= storyMessageUnitCreateMessageAreaOffset) {
uintptr_t difference = addr - storyMessageUnitCreateMessageAreaOffset;
//LOGI("Difference: %p", difference);
// Make lines longer
if (difference <= 0x244 && length == 410.0) { // Offset = 0x144 as of 2.15
LOGD("Set line length from 410.0 to 810.0");
length = 810.0;
}
}
return setMaxLineWidthHooked(label, length);
}
void *setDimensionsNew(uintptr_t label, float width, float height) {
uintptr_t addr = reinterpret_cast<uintptr_t>(__builtin_extract_return_addr(__builtin_return_address(0)));
uintptr_t difference = addr - storyLogUnitAddMessageOffset;
//LOGI("Difference [dimensions]: %p, addr: %p", difference, addr);
if (storyLogUnitAddMessageOffset != 0 && addr >= storyLogUnitAddMessageOffset) {
//LOGI("%p, %.2f, %.2f", label, width, a3);
if (difference <= 0x900 && width == 410.0) { // Offset = 0x5ac as of 2.15
LOGD("Set dimensions for log from 410.0 to 710.0.");
return setDimensionsHooked(label, 710.0, height);
}
}
//LOGD("Dimensions: %f, %f", width, height);
return setDimensionsHooked(label, width, height);
}
// Fix the position of homeText under live2d girls
cocos2d::Size (*lbGetViewPositionHooked)(float x, float y);
cocos2d::Size lbGetViewPositionNew(float x, float y) {
uintptr_t addr = reinterpret_cast<uintptr_t>(__builtin_extract_return_addr(__builtin_return_address(0)));
uintptr_t difference = addr - storyCharaUnitonTextHomeOffset;
//LOGI("Difference (viewPos): %p, addr: %p", (void*)difference, (void*)addr);
if (storyCharaUnitonTextHomeOffset != 0 && addr >= storyCharaUnitonTextHomeOffset) {
if (difference <= 0x1000) {
auto oldx = x;
auto oldy = y;
x = x - 30.0;
y = y - 30.0;
LOGD("Set live2d subtitle dimensions from (%f, %f) to (%f, %f).", oldx, oldy, x, y);
}
}
#if defined(__aarch64__)
return lbGetViewPositionHooked(x, y);
#endif
//LOGI("Size 1: %f, size 2: %f", sizes.width, sizes.height);
// Reimplement from scratch because arm is bugged (also this segfaults on arm64)
auto director = getDirector((void *)0x00);
//LOGI("Obtained director at %p.", (void*) director);
auto dirSize = getWinSize(director);
//LOGI("Obtained winsize, %f %f.", dirSize.width, dirSize.height);
auto origin = getVisibleOrigin(director);
//LOGI("Obtained visible origin, %f %f.", origin.x, origin.y);
auto sizes = cocos2d::Size();
sizes.width = origin.x + x + (float)dirSize.width * 0.5;
sizes.height = origin.y + y + (float)dirSize.height * 0.5;
//sizes.width = origin.x + x + (float)dirSize.width * 0.5;
//sizes.height = origin.y + y + (float)dirSize.height * 0.5;
//LOGI("NEW size 1: %f, size 2: %f", sizes.width, sizes.height);
return sizes;
}
pthread_mutex_t *(*setUriDebugOld)(uintptr_t a1, uintptr_t st);
pthread_mutex_t *setUriDebug(uintptr_t a1, uintptr_t stri) {
auto mut = setUriDebugOld(a1, stri);
auto y = StringsProxy(stri);
auto outstr = y.c_str();
LOGI("Uri base set: %s", outstr);
return mut;
}
pthread_mutex_t *(*http2SessionSetMaxConnectionNumOld)(uintptr_t *session, int max);
pthread_mutex_t *http2SessionSetMaxConnectionNum(uintptr_t *session, int max) {
if (max == 4) {
max = max_threads;
}
LOGD("Set max number of connections to %d.", max);
return http2SessionSetMaxConnectionNumOld(session, max);
}
void initialization_error(const char* error) {
LOGE("%s", error);
auto errorMsg = string_format("A critical error has occurred, MagiaTranslate will not work properly and may crash. Please report this error on GitHub or Discord.\n%s", error);
displayMessage("MagiaTranslate Error", errorMsg);
}
// Hook loop function. We run this in a separate thread so it doesn't block the main thread.
void *hook_loop(void *arguments) {
std::unique_ptr<hook_loop_args> args((struct hook_loop_args *)arguments);
auto libLocation = (args->libso).c_str();
LOGI("Library location: %s", libLocation);
while(libBase == 0) {
libBase = get_libBase(libName);
}
LOGI("Base address: %p", (void*)libBase);
// Hook resource endpoint
void *resourceHook = lookup_symbol(libLocation, "_ZNK9UrlConfig8resourceENS_8Resource4TypeE"); // UrlConfig::resource(UrlConfig::Resource::Type)const
if (DobbyHook(resourceHook, (void *)urlConfigResource, (void **)&urlConfigResourceHooked) == RS_SUCCESS) {
LOGI("Successfully hooked UrlConfig::resource.");
}
else {
initialization_error("Failed to hook UrlConfig::resource.");
pthread_exit(NULL);
}
// Hook scene creator
void *sceneHook = lookup_symbol(libLocation, "_ZN17SceneLayerManager16createSceneLayerEP18BaseSceneLayerInfo"); //_DWORD __fastcall SceneLayerManager::createSceneLayer(SceneLayerManager *__hidden this, BaseSceneLayerInfo *)
if (DobbyHook(sceneHook, (void *)sceneLayerManagerCreateSceneLayer, (void **)&sceneLayerManagerCreateSceneLayerOld) == RS_SUCCESS) {
LOGI("Successfully hooked SceneLayerManager::createSceneLayer.");
}
else {
initialization_error("Failed to hook SceneLayerManager::createSceneLayer.");
pthread_exit(NULL);
}
// Speed up downloads
void *maxDlHook = lookup_symbol(libLocation, "_ZN5http212Http2Session19setMaxConnectionNumEi"); //_DWORD __fastcall http2::Http2Session::setMaxConnectionNum(http2::Http2Session *__hidden this, int)
if (DobbyHook(maxDlHook, (void *)http2SessionSetMaxConnectionNum, (void **)&http2SessionSetMaxConnectionNumOld) == RS_SUCCESS) {
LOGI("Successfully hooked http2::Http2Session::setMaxConnectionNum.");
}
else {
LOGW("Failed to hook http2::Http2Session::setMaxConnectionNum.");
}
//openMessageBoxPtr = lookup_symbol(libLocation, "_ZN10MessageBox4openEPKcS1_S1_RKSt8functionIFvPN7cocos2d3RefEEEb");
//LOGI("Set openMessageBox ptr to %p", openMessageBoxPtr);
// For debugging
//DobbyHook(lookup_symbol(libLocation, "_ZN5http212Http2Session6setURIERKSs"), (void *)setUriDebug, (void **)&setUriDebugOld); - crashes arm32 now.
// Hooks
void *cocos2dnodeSetPosition = lookup_symbol(libLocation, "_ZN7cocos2d4Node11setPositionERKNS_4Vec2E");
// cocos2d::Node::setPosition(cocos2d::Vec2 const&)
if (cocos2dnodeSetPosition != nullptr) {
LOGD("Found cocos2d::Node::setPosition at %p.", (void *)cocos2dnodeSetPosition);
if (DobbyHook(cocos2dnodeSetPosition, (void *)setPositionNew, (void **)&setPositionHooked) == RS_SUCCESS) {
LOGI("Successfully hooked cocos2d::Node::setPosition.");
}
else {
initialization_error("Unable to hook cocos2d::Node::setPosition.");
pthread_exit(NULL);
}
}
else {
initialization_error("Unable to hook cocos2d::Node::setPosition.");
pthread_exit(NULL);
}
void *cocos2dlineLength = lookup_symbol(libLocation, "_ZN7cocos2d5Label15setMaxLineWidthEf");
// cocos2d::Label::setMaxLineWidth(float)
if (cocos2dlineLength != nullptr) {
LOGD("Found cocos2d::Label::setMaxLineWidth at %p.", (void *)cocos2dlineLength);
if (DobbyHook(cocos2dlineLength, (void *)setMaxLineWidthNew, (void **)&setMaxLineWidthHooked) == RS_SUCCESS) {
LOGI("Successfully hooked cocos2d::Label::setMaxLineWidth.");
}
else {
initialization_error("Unable to hook cocos2d::Label::setMaxLineWidth.");
pthread_exit(NULL);
}
}
else {
initialization_error("Unable to hook cocos2d::Label::setMaxLineWidth.");
pthread_exit(NULL);
}
void *cocos2dsetDimensions = lookup_symbol(libLocation, "_ZN7cocos2d5Label13setDimensionsEff");
//_DWORD __fastcall cocos2d::Label::setDimensions(cocos2d::Label *__hidden this, float, float)
if (cocos2dsetDimensions != nullptr) {
LOGD("Found cocos2d::Label::setDimensions at %p.", (void *)cocos2dsetDimensions);
if (DobbyHook(cocos2dsetDimensions, (void *)setDimensionsNew, (void **)&setDimensionsHooked) == RS_SUCCESS) {
LOGI("Successfully hooked cocos2d::Label::setDimensions.");
}
else {
initialization_error("Unable to hook cocos2d::Label::setDimensions.");
pthread_exit(NULL);
}
}
else {
initialization_error("Unable to hook cocos2d::Label::setDimensions.");
pthread_exit(NULL);
}
// For moving live2d subtitles
void *lbGetViewPosition = lookup_symbol(libLocation, "_ZN9LbUtility15getViewPositionEff");
//_DWORD __fastcall LbUtility::getViewPosition(LbUtility *__hidden this, float, float)
if (lbGetViewPosition != nullptr) {
LOGD("Found LbUtility::getViewPosition at %p.", (void *)lbGetViewPosition);
if (DobbyHook(lbGetViewPosition, (void *)lbGetViewPositionNew, (void **)&lbGetViewPositionHooked) == RS_SUCCESS) {
LOGI("Successfully hooked LbUtility::getViewPosition.");
}
else {
initialization_error("Unable to hook LbUtility::getViewPosition.");
pthread_exit(NULL);
}
}
else {
initialization_error("Unable to hook LbUtility::getViewPosition.");
pthread_exit(NULL);
}
// Change font
void *cocosCreateLabelPtr = lookup_symbol(libLocation, "_ZN7cocos2d5Label13createWithTTFERKSsS2_fRKNS_4SizeENS_14TextHAlignmentENS_14TextVAlignmentE");
if (cocosCreateLabelPtr != nullptr) {
LOGD("Found cocos2d::Label::createWithTTF at %p.", (void *)cocosCreateLabel);
if (DobbyHook(cocosCreateLabelPtr, (void*) cocosCreateLabel, (void **)& cocosCreateLabelHooked) == RS_SUCCESS) {
LOGI("Successfully hooked cocos2d::Label::createWithTTF.");
}
else {
initialization_error("Unable to hook cocos2d::Label::createWithTTF.");
pthread_exit(NULL);
}
}
else {
initialization_error("Unable to hook cocos2d::Label::createWithTTF.");
pthread_exit(NULL);
}
// Find key functions, TODO: Tidy up into 1 nice loop
void *storyMessageUnitTextStart = lookup_symbol(libLocation, "_ZN16StoryMessageUnit9textStartENS_11TextPosType13TextPosType__E");
// StoryMessageUnit::textStart(StoryMessageUnit::TextPosType::TextPosType__)
if (storyMessageUnitTextStart == nullptr) {
initialization_error("Unable to find a pointer for StoryMessageUnit::textStart.");
pthread_exit(NULL);
}
storyMessageUnitStartOffset = reinterpret_cast<uintptr_t>(storyMessageUnitTextStart);
void *storyMessageUnitCreateMessageArea = lookup_symbol(libLocation, "_ZN16StoryMessageUnit17createMessageAreaENS_11TextPosType13TextPosType__E");
// StoryMessageUnit::createMessageArea(StoryMessageUnit::TextPosType::TextPosType__)
if (storyMessageUnitCreateMessageArea == nullptr) {
initialization_error("Unable to find a pointer for StoryMessageUnit::createMessageArea.");
pthread_exit(NULL);
}
storyMessageUnitCreateMessageAreaOffset = reinterpret_cast<uintptr_t>(storyMessageUnitCreateMessageArea);
void *storyLogUnitAddMessage = lookup_symbol(libLocation, "_ZN12StoryLogUnit10addMessageENS_11MessageType13MessageType__ERKSs");
if (storyLogUnitAddMessage == nullptr) {
initialization_error("Unable to find a pointer for StoryLogUnit::addMessage.");
pthread_exit(NULL);
}
storyLogUnitAddMessageOffset = reinterpret_cast<uintptr_t>(storyLogUnitAddMessage);
void *storyLogUnitAddNarrationOffsetPtr = lookup_symbol(libLocation, "_ZN12StoryLogUnit19addNarrationMessageERKSs");
if (storyLogUnitAddNarrationOffsetPtr == nullptr) {
initialization_error("Unable to find a pointer for StoryLogUnit::addNarrationMessage.");
pthread_exit(NULL);
}
storyLogUnitAddNarrationOffset = reinterpret_cast<uintptr_t>(storyLogUnitAddNarrationOffsetPtr);
void *storyCharaUnitonTextHome = lookup_symbol(libLocation, "_ZN14StoryCharaUnit10onTextHomeESt10shared_ptrI16StoryTurnCommandEb");
// StoryCharaUnit::onTextHome(std::shared_ptr<StoryTurnCommand>, bool)
if (storyCharaUnitonTextHome == nullptr) {
initialization_error("Unable to find a pointer for StoryCharaUnit::onTextHome.");
pthread_exit(NULL);
}
storyCharaUnitonTextHomeOffset = reinterpret_cast<uintptr_t>(storyCharaUnitonTextHome);
void *initLabelCWO = lookup_symbol(libLocation, "_ZN9LbUtility27initLabelCenterWidthOutlineEPN7cocos2d4NodeERPNS0_5LabelEPKcfNS0_4Vec2EiNS0_4SizeEiNS0_7Color4BEiSA_");
// LbUtility::initLabelCenterWidthOutline(cocos2d::Node *, cocos2d::Label *&, char const*, float, cocos2d::Vec2, int, cocos2d::Size, int, cocos2d::Color4B, int, cocos2d::Color4B)
if (initLabelCWO == nullptr) {
initialization_error("Unable to find a pointer for LbUtility::initLabelCenterWidthOutline.");
pthread_exit(NULL);
}
initCenterWidthOutline = reinterpret_cast<uintptr_t>(initLabelCWO);
void* storyNarrationUnitCreateLabelPtr = lookup_symbol(libLocation, "_ZN18StoryNarrationUnit11createLabelEv");
if (storyNarrationUnitCreateLabelPtr == nullptr) {
initialization_error("Unable to find a pointer for StoryNarrationUnit::createLabel.");
pthread_exit(NULL);
}
storyNarrationUnitCreateLabelOffset = reinterpret_cast<uintptr_t>(storyNarrationUnitCreateLabelPtr);
// Cocos functions
void *directorPtr = lookup_symbol(libLocation, "_ZN7cocos2d8Director11getInstanceEv");
if (directorPtr == nullptr) {
initialization_error("Unable to find a pointer for cocos2d::Director::getInstance()");
pthread_exit(NULL);
}
getDirector = (director_type) directorPtr;
void* getWinSizePtr = lookup_symbol(libLocation, "_ZNK7cocos2d8Director10getWinSizeEv");
if (getWinSizePtr == nullptr) {
initialization_error("Unable to find a pointer for cocos2d::Director::getWinSize()");
pthread_exit(NULL);
}
getWinSize = (get_win_size_type) getWinSizePtr;
void* getVisibleOriginPtr = lookup_symbol(libLocation, "_ZNK7cocos2d8Director16getVisibleOriginEv");
if (getVisibleOriginPtr == nullptr) {
initialization_error("Unable to find a pointer for cocos2d::Director::getVisibleOrigin()");
pthread_exit(NULL);
}
getVisibleOrigin = (get_visible_origin_type) getVisibleOriginPtr;
LOGI("Exiting hook thread.");
pthread_exit(NULL);
}
__attribute__((constructor))
void hook_main() {
}
extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) {
LOGI("Starting MagiaHook.");
gJvm = vm; // cache the JavaVM pointer
Dl_info dlInfo;
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK)
{
return -1;
}
// https://stackoverflow.com/a/16302771/9665729
// Cache ClassLoader object due to threading bug
auto randomClass = env->FindClass("org/cocos2dx/lib/Cocos2dxHelper");
jclass classClass = env->GetObjectClass(randomClass);
auto classLoaderClass = env->FindClass("java/lang/ClassLoader");
auto getClassLoaderMethod = env->GetMethodID(classClass, "getClassLoader",
"()Ljava/lang/ClassLoader;");
gClassLoader = env->NewGlobalRef(env->CallObjectMethod(randomClass, getClassLoaderMethod));
gFindClassMethod = env->GetMethodID(classLoaderClass, "findClass",
"(Ljava/lang/String;)Ljava/lang/Class;");
if (dladdr((const void*) hook_main, &dlInfo))
{
//fs::path ilso = fs::path(dlInfo.dli_fname).remove_filename(); ndk 22+ required
//ilso /= "il2cpp.so"; ndk 22+ required
hook_loop_args* args = new hook_loop_args;
auto ilso = (std::string) dirname((char *)dlInfo.dli_fname);
ilso += "/";
ilso += libName;
//if (fs::exists(ilso)) { ndk 22+ required
if (!file_exists(ilso)) {
// Fix for some devices
auto this_ilso = get_libFoldername(hookName);
if (this_ilso.empty()) {
LOGE("Failed to locate shared library %s. Checked: %s", libName, ilso.c_str());
return JNI_VERSION_1_6;
}
auto ilso2 = this_ilso.substr(0, this_ilso.length() - strlen(hookName) - 1);
ilso2 += libName;
if (!file_exists(ilso2)) {
LOGE("Failed to load shared library %s. Checked: %s", libName, ilso2.c_str());
return JNI_VERSION_1_6;
}
args->libso = ilso2;
}
else {
args->libso = ilso;
}
pthread_t ptid;
if (pthread_create(&ptid, NULL, &hook_loop, args) != 0) {
LOGE("Hooking thread failed to start.");
return JNI_VERSION_1_6;
}
}
return JNI_VERSION_1_6;
}

150
src/Utils.cpp Normal file
View File

@ -0,0 +1,150 @@
#include "Utils.h"
#include <jni.h>
#include <unistd.h>
#include <cstdint>
#include <android/log.h>
#include <dlfcn.h>
#include <cstdio>
#include <cstdlib>
#include <sys/stat.h>
#include <string>
#include <memory>
#include <sstream>
#include <stdexcept>
#include <errno.h>
#include <error.h>
typedef unsigned long DWORD;
uintptr_t get_libBase(const char* libName) {
FILE *fp;
uintptr_t addr = 0;
char filename[32], buffer[1024];
snprintf(filename, sizeof(filename), "/proc/%d/maps", getpid());
fp = fopen(filename, "rt");
if (fp != NULL) {
while (fgets(buffer, sizeof(buffer), fp)) {
if (strstr(buffer, libName)) {
addr = (uintptr_t) strtoul(buffer, NULL, 16);
break;
}
}
fclose(fp);
}
return addr;
}
std::string get_libFoldername(const char* libName) {
FILE *fp;
uintptr_t addr = 0;
char filename[32], buffer[1024];
snprintf(filename, sizeof(filename), "/proc/%d/maps", getpid());
fp = fopen(filename, "rt");
if (fp != NULL) {
while (fgets(buffer, sizeof(buffer), fp)) {
if (strstr(buffer, libName)) {
std::string delimiter = "/";
std::string strBuffer = buffer;
std::string token = strBuffer.substr(strBuffer.find(delimiter), std::string::npos);
return token;
break;
}
}
fclose(fp);
}
return "";
}
//uintptr_t getRealOffset(const char* libName, uintptr_t address) {
//if (libBase == 0) {
//libBase = get_libBase(libName);
//}
//return (libBase + address);
//}
void* lookup_symbol(const char* path, const char* symbolname)
{
void *imagehandle = dlopen(path, RTLD_GLOBAL | RTLD_NOW);
if (imagehandle != NULL){
void * sym = dlsym(imagehandle, symbolname);
if (sym != NULL){
return sym;
}
else{
LOGI("(lookup_symbol) dlsym didn't work\n");
return NULL;
}
}
else{
LOGI("(lookup_symbol) dlerror: %s\n",dlerror());
return NULL;
}
}
bool file_exists (const std::string& name) {
struct stat buffer;
return (stat (name.c_str(), &buffer) == 0);
}
std::string getJNISignature() {
return "";
}
std::string getJNISignature(bool) {
return "Z";
}
std::string getJNISignature(char) {
return "C";
}
std::string getJNISignature(short) {
return "S";
}
std::string getJNISignature(int) {
return "I";
}
std::string getJNISignature(long) {
return "J";
}
std::string getJNISignature(float) {
return "F";
}
std::string getJNISignature(double) {
return "D";
}
std::string getJNISignature(const char*) {
return "Ljava/lang/String;";
}
std::string getJNISignature(const std::string&) {
return "Ljava/lang/String;";
}
JNIEnv* getEnv(JavaVM* gJvm) {
JNIEnv *env;
int status = gJvm->GetEnv((void**)&env, JNI_VERSION_1_6);
if(status < 0) {
status = gJvm->AttachCurrentThread(&env, NULL);
if(status < 0) {
LOGW("Null JNIEnv obtained!");
return nullptr;
}
}
return env;
}
jclass findClass(JNIEnv* env, jobject gClassLoader, jmethodID gFindClassMethod, const char* name) {
return static_cast<jclass>(env->CallObjectMethod(gClassLoader, gFindClassMethod, env->NewStringUTF(name)));
}
std::string longlong_to_string( unsigned long long value ){
std::ostringstream os;
os << value;
return os.str();
}

75
src/Utils.h Normal file
View File

@ -0,0 +1,75 @@
#ifndef UTILS_H
#define UTILS_H
#include <jni.h>
#include <unistd.h>
#include <cstdint>
#include <android/log.h>
#include <dlfcn.h>
#include <cstdio>
#include <cstdlib>
#include <sys/stat.h>
#include <string>
#include <memory>
#include <stdexcept>
#if DEBUG
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "MagiaHook", __VA_ARGS__)
#else
#define LOGD(...) do {} while(false)
#endif
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, "MagiaHook", __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "MagiaHook", __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, "MagiaHook", __VA_ARGS__)
typedef unsigned long DWORD;
uintptr_t get_libBase(const char* libName);
std::string get_libFoldername(const char* libName);
void* lookup_symbol(const char* path, const char* symbolname);
bool file_exists (const std::string& name);
std::string getJNISignature();
std::string getJNISignature(bool);
std::string getJNISignature(char);
std::string getJNISignature(short);
std::string getJNISignature(int);
std::string getJNISignature(long);
std::string getJNISignature(float);
std::string getJNISignature(double);
std::string getJNISignature(const char*);
std::string getJNISignature(const std::string&);
template <typename T>
std::string getJNISignature(T x) {
// This template should never be instantiated
static_assert(sizeof(x) == 0, "Unsupported argument type");
return "";
}
template <typename T, typename... Ts>
std::string getJNISignature(T x, Ts... xs) {
return getJNISignature(x) + getJNISignature(xs...);
}
JNIEnv* getEnv(JavaVM* gJvm);
jclass findClass(JNIEnv* env, jobject gClassLoader, jmethodID gFindClassMethod, const char* name);
// https://stackoverflow.com/a/26221725/9665729
template<typename ... Args>
std::string string_format( const std::string& format, Args ... args )
{
size_t size = snprintf( nullptr, 0, format.c_str(), args ... ) + 1; // Extra space for '\0'
if( size <= 0 ){ throw std::runtime_error( "Error during formatting." ); }
std::unique_ptr<char[]> buf( new char[ size ] );
snprintf( buf.get(), size, format.c_str(), args ... );
return std::string( buf.get(), buf.get() + size - 1 ); // We don't want the '\0' inside
}
std::string longlong_to_string( unsigned long long value );
#endif

25447
src/include/nlohmann/json.hpp Normal file

File diff suppressed because it is too large Load Diff

85
src/libmadomagi.h Normal file
View File

@ -0,0 +1,85 @@
enum BaseSceneLayerType {
DebugMenuSceneLayer,
CameraSceneLayer,
WebSceneLayer,
StartupSceneLayer,
PrologueSceneLayer,
AnotherQuestSceneLayer,
TopSceneLayer,
EventStoryRaidSceneLayer,
EventBranchSceneLayer,
EventSingleRaidSceneLayer,
EventDungeonSceneLayer,
EventRaidSceneLayer,
QuestBattleSceneLayer,
QuestUnitTestSceneLayer,
EvolutionSceneLayer,
MemoriaSceneLayer,
GachaSceneLayer,
StorySceneLayer,
StoryViewerSceneLayer,
Live2dViewerSceneLayer,
MovieSceneLayer,
DownloadSceneLayer,
DebugSelectURLSceneLayer,
QuestStoredDataSceneLayer,
InputTextSceneLayer,
LoadingSceneLayer,
ErrorSceneLayer,
NetworkErrorSceneLayer,
TapSceneLayer,
EmotionBoardSceneLayer,
BaseSceneLayerTypeMaxValue
};
char const* BaseSceneLayerTypeStrings[] {
"DebugMenuSceneLayer",
"CameraSceneLayer",
"WebSceneLayer",
"StartupSceneLayer",
"PrologueSceneLayer",
"AnotherQuestSceneLayer",
"TopSceneLayer",
"EventStoryRaidSceneLayer",
"EventBranchSceneLayer",
"EventSingleRaidSceneLayer",
"EventDungeonSceneLayer",
"EventRaidSceneLayer",
"QuestBattleSceneLayer",
"QuestUnitTestSceneLayer",
"EvolutionSceneLayer",
"MemoriaSceneLayer",
"GachaSceneLayer",
"StorySceneLayer",
"StoryViewerSceneLayer",
"Live2dViewerSceneLayer",
"MovieSceneLayer",
"DownloadSceneLayer",
"DebugSelectURLSceneLayer",
"QuestStoredDataSceneLayer",
"InputTextSceneLayer",
"LoadingSceneLayer",
"ErrorSceneLayer",
"NetworkErrorSceneLayer",
"TapSceneLayer",
"EmotionBoardSceneLayer"
};
#if defined(__arm__)
struct BaseSceneLayerInfo {
char unk[24];
BaseSceneLayerType layerType;
};
#elif defined(__aarch64__)
struct BaseSceneLayerInfo {
char unk[36];
BaseSceneLayerType layerType;
};
#endif
enum UrlConfigResourceType {
BaseUrl,
TrunkUrl,
ScenarioUrl,
UrlConfigResourceTypeMaxValue
};

93
src/rest/MagiaRest.cpp Normal file
View File

@ -0,0 +1,93 @@
#include <jni.h>
#include "../Utils.h"
#include "../Config.h"
#include <nlohmann/json.hpp>
#include <string.h>
#include <string>
#include "MagiaRest.h"
const char* restClient = "io/kamihama/magianative/RestClient";
using json = nlohmann::json;
MagiaRest::MagiaRest(JavaVM* gJvm) {
LOGD("Setting up MagiaRest.");
env = getEnv(gJvm);
klass = env->FindClass(restClient);
jmethodID clientCtor = env->GetMethodID(klass, "<init>", "()V");
magiaRestObj = env->NewObject(klass, clientCtor);
LOGD("Finished setting up MagiaRest.");
}
int MagiaRest::Endpoint() {
const char* callHandshake = "GetEndpoint";
std::string signature = "(I)Ljava/lang/String;";
jmethodID messageid = env->GetMethodID(klass, callHandshake, signature.c_str());
LOGD("Calling GetEndpoint via JNI.");
endpointJString = (jstring)env->CallObjectMethod(magiaRestObj, messageid, MT_VERSION);
endpointChar = env->GetStringUTFChars(endpointJString, 0);
if (strcmp(endpointChar, "") == 0) {
LOGW("Null response returned from endpoint, an error has occurred, or Kamihama is down.");
return MAGIAREST_EMPTY;
}
LOGD("Successfully retrieved Endpoint JSON.");
if (json::accept(endpointChar)) {
endpointValid = true;
endpointJson = json::parse(endpointChar);
if (endpointJson["status"] != 200) {
LOGW("Non-success result returned.");
return MAGIAREST_ERROR;
}
}
return endpointValid ? MAGIAREST_SUCCESS : MAGIAREST_EMPTY;
}
size_t MagiaRest::EndpointStringLength() {
if (endpointChar == NULL) {
return MAGIAREST_EMPTY;
}
else {
auto size = std::strlen(endpointChar);
return size;
}
}
std::string MagiaRest::GetEndpointUrl() {
if (endpointJson != NULL && endpointJson.contains("response") && endpointJson["response"].contains("endpoint")) {
return endpointJson["response"]["endpoint"];
}
LOGW("No endpoint URL found in JSON response.");
return "";
}
std::string MagiaRest::GetEndpointError() {
if (endpointJson != NULL && endpointJson.contains("message")) {
return endpointJson["message"];
}
LOGW("No message found in JSON response.");
return "";
}
int MagiaRest::GetEndpointVersion() {
if (endpointJson != NULL && endpointJson.contains("response") && endpointJson["response"].contains("version")) {
return (int)endpointJson["response"]["version"];
}
LOGW("No version number found in JSON response.");
return 0;
}
int MagiaRest::GetMaxThreads() {
if (endpointJson != NULL && endpointJson.contains("response") && endpointJson["response"].contains("max_threads")) {
return (int)endpointJson["response"]["max_threads"];
}
LOGW("No version number found in JSON response.");
return 0;
}
MagiaRest::~MagiaRest() {
if (endpointJString != NULL || endpointChar != NULL) {
env->ReleaseStringUTFChars(endpointJString, endpointChar);
}
}

43
src/rest/MagiaRest.h Normal file
View File

@ -0,0 +1,43 @@
#ifndef MAGIAREST_H
#define MAGIAREST_H
#include <jni.h>
#include <nlohmann/json.hpp>
#include <string.h>
using json = nlohmann::json;
#define MAGIAREST_EMPTY 0
#define MAGIAREST_SUCCESS 1
#define MAGIAREST_ERROR 2
// Rest class using JNI
class MagiaRest {
public:
MagiaRest(JavaVM* gJvm);
int Endpoint();
size_t EndpointStringLength();
std::string GetEndpointUrl();
std::string GetEndpointError();
int GetEndpointVersion();
int GetMaxThreads();
~MagiaRest();
private:
JNIEnv* env;
jclass klass;
jobject magiaRestObj;
jstring endpointJString = NULL;
const char *endpointChar = NULL;
bool endpointValid = false;
json endpointJson = NULL;
};
#endif