mirror of
https://github.com/mrxenginner/reVC.git
synced 2026-10-10 03:43:04 +08:00
[android] Refactor source code port for Android
This commit is contained in:
+62
-5
@@ -20,15 +20,25 @@ header_directories(${PROJECT}_INCLUDES)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/extras/GitSHA1.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/extras/GitSHA1.cpp" @ONLY)
|
||||
list(APPEND ${PROJECT}_SOURCES "${CMAKE_CURRENT_BINARY_DIR}/extras/GitSHA1.cpp")
|
||||
|
||||
add_executable(${EXECUTABLE} WIN32
|
||||
${${PROJECT}_SOURCES}
|
||||
)
|
||||
if(NOT ANDROID)
|
||||
add_executable(${EXECUTABLE} WIN32 ${${PROJECT}_SOURCES})
|
||||
elseif(ANDROID)
|
||||
add_library(${EXECUTABLE} SHARED ${${PROJECT}_SOURCES})
|
||||
endif()
|
||||
|
||||
target_link_libraries(${EXECUTABLE} PRIVATE
|
||||
librw::librw
|
||||
Threads::Threads
|
||||
)
|
||||
|
||||
if(ANDROID)
|
||||
target_link_libraries(${EXECUTABLE} PRIVATE
|
||||
log
|
||||
GLESv3
|
||||
OpenSLES
|
||||
)
|
||||
endif()
|
||||
|
||||
target_include_directories(${EXECUTABLE}
|
||||
PRIVATE
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
|
||||
@@ -49,8 +59,29 @@ if(LIBRW_PLATFORM_D3D9)
|
||||
)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(${EXECUTABLE} PRIVATE CMAKE_BUILD)
|
||||
target_compile_definitions(${EXECUTABLE} PRIVATE USE_OUR_VERSIONING)
|
||||
if(ANDROID)
|
||||
target_compile_definitions(${EXECUTABLE} PRIVATE
|
||||
ANDROID
|
||||
_ANDROID
|
||||
LINUX
|
||||
_LINUX
|
||||
POSIX
|
||||
_POSIX
|
||||
NO_HOOK_MALLOC
|
||||
AL_LIBTYPE_STATIC
|
||||
GNUC
|
||||
RW_GL3
|
||||
LIBRW_SDL2
|
||||
LIBRW
|
||||
AUDIO_OAL
|
||||
USE_OUR_VERSIONING
|
||||
HAVE_EFFICIENT_UNALIGNED_ACCESS
|
||||
VECTORIZE_SINCOS
|
||||
)
|
||||
else()
|
||||
target_compile_definitions(${EXECUTABLE} PRIVATE CMAKE_BUILD)
|
||||
target_compile_definitions(${EXECUTABLE} PRIVATE USE_OUR_VERSIONING)
|
||||
endif()
|
||||
|
||||
if(${PROJECT}_AUDIO STREQUAL "OAL")
|
||||
find_package(OpenAL REQUIRED)
|
||||
@@ -91,6 +122,12 @@ target_compile_definitions(${EXECUTABLE} PRIVATE )
|
||||
|
||||
option(${PROJECT}_WITH_SANITIZERS "Use UB sanitizers (better crash log)" OFF)
|
||||
option(${PROJECT}_WITH_ASAN "Use Address sanitizer (better crash log)" OFF)
|
||||
option(${PROJECT}_DISABLE_WARNINGS "Disable build warnings" ON)
|
||||
|
||||
if(${PROJECT}_DISABLE_WARNINGS)
|
||||
target_compile_options(${EXECUTABLE} PRIVATE
|
||||
-w)
|
||||
endif()
|
||||
|
||||
if(${PROJECT}_WITH_SANITIZERS)
|
||||
target_compile_options(${EXECUTABLE} PUBLIC
|
||||
@@ -105,6 +142,26 @@ if(${PROJECT}_WITH_ASAN)
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
if(ANDROID)
|
||||
target_compile_options(${EXECUTABLE}
|
||||
PRIVATE
|
||||
-pthread
|
||||
-std=c++11
|
||||
-fno-strict-aliasing
|
||||
-fexceptions
|
||||
-Wcast-align
|
||||
-Wuninitialized
|
||||
-Winit-self
|
||||
-Wstrict-aliasing
|
||||
-Wno-reorder
|
||||
-Wno-unknown-pragmas
|
||||
-Wno-unused-function
|
||||
-Wno-unused-but-set-variable
|
||||
-Wno-unused-value
|
||||
-Wno-unused-command-line-argument
|
||||
-faligned-new
|
||||
)
|
||||
endif()
|
||||
target_compile_options(${EXECUTABLE}
|
||||
PRIVATE
|
||||
"-Wall"
|
||||
|
||||
@@ -499,11 +499,15 @@ _FindMP3s(void)
|
||||
printf("MP3 folder path is too long, no place left for file names. MP3 finding aborted.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined ANDROID
|
||||
OutputDebugString("Finding MP3s...");
|
||||
strcpy(path, _mp3DirectoryPath);
|
||||
strcat(path, "/MP3/");
|
||||
#else
|
||||
OutputDebugString("Finding MP3s...");
|
||||
strcpy(path, _mp3DirectoryPath);
|
||||
strcat(path, "\\MP3\\");
|
||||
|
||||
#endif
|
||||
#if !defined(_WIN32)
|
||||
char *actualPath = casepath(path);
|
||||
if (actualPath) {
|
||||
|
||||
+98
-24
@@ -1,14 +1,22 @@
|
||||
#ifndef _WIN32
|
||||
#include "common.h"
|
||||
#ifdef GTA_PC
|
||||
#ifdef GTA_PC || GTA_MOBILE
|
||||
#include "crossplatform.h"
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
#ifndef ANDROID
|
||||
#include <semaphore.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#ifndef ANDROID
|
||||
#include <sys/statvfs.h>
|
||||
#else
|
||||
#include "AndroidMain.h"
|
||||
#include <sys/vfs.h>
|
||||
#define statvfs statfs
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
@@ -24,7 +32,7 @@
|
||||
#include "MemoryMgr.h"
|
||||
|
||||
#define CDDEBUG(f, ...) debug ("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__)
|
||||
#define CDTRACE(f, ...) printf("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__)
|
||||
#define CDTRACE(f, ...) debug ("%s: " f "\n", "cdvd_stream trace", ## __VA_ARGS__)
|
||||
|
||||
#ifdef FLUSHABLE_STREAMING
|
||||
bool flushStream[MAX_CDCHANNELS];
|
||||
@@ -52,32 +60,32 @@ re3_sem_close(sem_t* sem)
|
||||
free(sem);
|
||||
}
|
||||
|
||||
#else
|
||||
#elifndef ANDROID
|
||||
|
||||
#define RE3_SEM_OPEN re3_sem_open
|
||||
sem_t*
|
||||
re3_sem_open(const char* format, ...)
|
||||
{
|
||||
char semName[21];
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
vsprintf(semName, format, va);
|
||||
char semName[21];
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
vsprintf(semName, format, va);
|
||||
|
||||
return sem_open(semName, O_CREAT, 0644, 1);
|
||||
return sem_open(semName, O_CREAT, 0644, 1);
|
||||
}
|
||||
|
||||
#define RE3_SEM_CLOSE re3_sem_close
|
||||
void
|
||||
re3_sem_close(sem_t* sem, const char* format, ...)
|
||||
{
|
||||
sem_close(sem);
|
||||
sem_close(sem);
|
||||
|
||||
char semName[21];
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
vsprintf(semName, format, va);
|
||||
char semName[21];
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
vsprintf(semName, format, va);
|
||||
|
||||
sem_unlink(semName);
|
||||
sem_unlink(semName);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -95,7 +103,11 @@ struct CdReadInfo
|
||||
pthread_t pChannelThread;
|
||||
sem_t *pStartSemaphore;
|
||||
#endif
|
||||
#ifndef ANDROID
|
||||
sem_t *pDoneSemaphore; // used for CdStreamSync
|
||||
#elif ANDROID
|
||||
pthread_mutex_t pDoneSemaphore; // used for CdStreamSync
|
||||
#endif
|
||||
int32 hFile;
|
||||
};
|
||||
|
||||
@@ -108,7 +120,11 @@ char *gImgNames[MAX_CDIMAGES];
|
||||
|
||||
#ifndef ONE_THREAD_PER_CHANNEL
|
||||
pthread_t _gCdStreamThread;
|
||||
#ifndef ANDROID
|
||||
sem_t *gCdStreamSema; // released when we have new thing to read(so channel is set)
|
||||
#elif ANDROID
|
||||
pthread_mutex_t gCdStreamSema; // released when we have new thing to read(so channel is set)
|
||||
#endif
|
||||
int8 gCdStreamThreadStatus; // 0: created 1:priority set up 2:abort now
|
||||
Queue gChannelRequestQ;
|
||||
bool _gbCdStreamOverlapped;
|
||||
@@ -132,21 +148,26 @@ CdStreamInitThread(void)
|
||||
gChannelRequestQ.tail = 0;
|
||||
gChannelRequestQ.size = gNumChannels + 1;
|
||||
ASSERT(gChannelRequestQ.items != nil );
|
||||
gCdStreamSema = RE3_SEM_OPEN("/semaphore_cd_stream");
|
||||
#ifndef ANDROID
|
||||
gCdStreamSema = RE3_SEM_OPEN("/semaphore_cd_stream");
|
||||
|
||||
|
||||
if (gCdStreamSema == SEM_FAILED) {
|
||||
CDTRACE("failed to create stream semaphore");
|
||||
ASSERT(0);
|
||||
return;
|
||||
}
|
||||
if (gCdStreamSema == SEM_FAILED) {
|
||||
CDTRACE("failed to create stream semaphore");
|
||||
ASSERT(0);
|
||||
return;
|
||||
}
|
||||
#elif ANDROID
|
||||
//pthread_mutex_unlock(&gCdStreamSema);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if ( gNumChannels > 0 )
|
||||
{
|
||||
for ( int32 i = 0; i < gNumChannels; i++ )
|
||||
{
|
||||
gpReadInfo[i].pDoneSemaphore = RE3_SEM_OPEN("/semaphore_done%d", i);
|
||||
#ifndef ANDROID
|
||||
gpReadInfo[i].pDoneSemaphore = RE3_SEM_OPEN("/semaphore_done%d", i);
|
||||
|
||||
if (gpReadInfo[i].pDoneSemaphore == SEM_FAILED)
|
||||
{
|
||||
@@ -154,6 +175,9 @@ CdStreamInitThread(void)
|
||||
ASSERT(0);
|
||||
return;
|
||||
}
|
||||
#elif ANDROID
|
||||
//pthread_mutex_unlock(&gpReadInfo[i].doneMutex);
|
||||
#endif
|
||||
|
||||
#ifdef ONE_THREAD_PER_CHANNEL
|
||||
gpReadInfo[i].pStartSemaphore = RE3_SEM_OPEN("/semaphore_start%d", i);
|
||||
@@ -199,14 +223,32 @@ void
|
||||
CdStreamInit(int32 numChannels)
|
||||
{
|
||||
struct statvfs fsInfo;
|
||||
#if defined ANDROID
|
||||
char imgPath[MAX_PATH];
|
||||
if(StorageRootBuffer == NULL) {
|
||||
char pwd[128];
|
||||
getcwd(pwd, 128);
|
||||
setenv("STORAGE_ROOT", pwd, 1);
|
||||
debug("%s\n", pwd);
|
||||
}
|
||||
|
||||
debug("FILES %s\n", StorageRootBuffer);
|
||||
strcpy(imgPath, StorageRootBuffer);
|
||||
strcat(imgPath, "/models/gta3.img");
|
||||
debug("%s\n", imgPath);
|
||||
|
||||
if((statvfs("models/gta3.img", &fsInfo)) < 0)
|
||||
if((statvfs(imgPath, &fsInfo)) < 0)
|
||||
#elifndef ANDROID
|
||||
if((statvfs("models/gta3.img", &fsInfo)) < 0)
|
||||
#endif
|
||||
{
|
||||
CDTRACE("can't get filesystem info");
|
||||
ASSERT(0);
|
||||
return;
|
||||
}
|
||||
#ifdef __linux__
|
||||
#if defined ANDROID
|
||||
_gdwCdStreamFlags = O_RDONLY;
|
||||
#elif defined __linux__
|
||||
_gdwCdStreamFlags = O_RDONLY | O_NOATIME;
|
||||
#else
|
||||
_gdwCdStreamFlags = O_RDONLY;
|
||||
@@ -271,7 +313,11 @@ CdStreamShutdown(void)
|
||||
// Destroying semaphores and free(gpReadInfo) will be done at threads
|
||||
#ifndef ONE_THREAD_PER_CHANNEL
|
||||
gCdStreamThreadStatus = 2;
|
||||
#ifndef ANDROID
|
||||
sem_post(gCdStreamSema);
|
||||
#elif ANDROID
|
||||
pthread_mutex_unlock(&gCdStreamSema);
|
||||
#endif
|
||||
pthread_join(_gCdStreamThread, nil);
|
||||
#else
|
||||
for ( int32 i = 0; i < gNumChannels; i++ ) {
|
||||
@@ -318,7 +364,11 @@ CdStreamRead(int32 channel, void *buffer, uint32 offset, uint32 size)
|
||||
|
||||
#ifndef ONE_THREAD_PER_CHANNEL
|
||||
AddToQueue(&gChannelRequestQ, channel);
|
||||
if ( sem_post(gCdStreamSema) != 0 )
|
||||
#if defined ANDROID
|
||||
if ( pthread_mutex_unlock(&gCdStreamSema) != 0 )
|
||||
#else
|
||||
if ( sem_post(gCdStreamSema) != 0 )
|
||||
#endif
|
||||
printf("Signal Sema Error\n");
|
||||
#else
|
||||
if ( sem_post(pChannel->pStartSemaphore) != 0 )
|
||||
@@ -387,7 +437,11 @@ CdStreamSync(int32 channel)
|
||||
pthread_kill(_gCdStreamThread, SIGUSR1);
|
||||
#endif
|
||||
while (pChannel->bLocked)
|
||||
#ifndef ANDROID
|
||||
sem_wait(pChannel->pDoneSemaphore);
|
||||
#elif ANDROID
|
||||
pthread_mutex_lock(&pChannel->pDoneSemaphore);
|
||||
#endif
|
||||
}
|
||||
pChannel->bReading = false;
|
||||
flushStream[channel] = false;
|
||||
@@ -399,7 +453,11 @@ CdStreamSync(int32 channel)
|
||||
{
|
||||
pChannel->bLocked = true;
|
||||
while (pChannel->bLocked && pChannel->nSectorsToRead != 0){
|
||||
#ifndef ANDROID
|
||||
sem_wait(pChannel->pDoneSemaphore);
|
||||
#elif ANDROID
|
||||
pthread_mutex_lock(&pChannel->pDoneSemaphore);
|
||||
#endif
|
||||
}
|
||||
pChannel->bLocked = false;
|
||||
}
|
||||
@@ -452,7 +510,11 @@ void *CdStreamThread(void *param)
|
||||
|
||||
#ifndef ONE_THREAD_PER_CHANNEL
|
||||
while (gCdStreamThreadStatus != 2) {
|
||||
#ifndef ANDROID
|
||||
sem_wait(gCdStreamSema);
|
||||
#elif ANDROID
|
||||
pthread_mutex_lock(&gCdStreamSema);
|
||||
#endif
|
||||
|
||||
int32 channel = GetFirstInQueue(&gChannelRequestQ);
|
||||
|
||||
@@ -510,7 +572,11 @@ void *CdStreamThread(void *param)
|
||||
if ( pChannel->bLocked )
|
||||
{
|
||||
pChannel->bLocked = 0;
|
||||
#ifndef ANDROID
|
||||
sem_post(pChannel->pDoneSemaphore);
|
||||
#else
|
||||
pthread_mutex_unlock(&pChannel->pDoneSemaphore);
|
||||
#endif
|
||||
}
|
||||
pChannel->bReading = false;
|
||||
}
|
||||
@@ -518,9 +584,17 @@ void *CdStreamThread(void *param)
|
||||
#ifndef ONE_THREAD_PER_CHANNEL
|
||||
for ( int32 i = 0; i < gNumChannels; i++ )
|
||||
{
|
||||
#ifndef ANDROID
|
||||
RE3_SEM_CLOSE(gpReadInfo[i].pDoneSemaphore, "/semaphore_done%d", i);
|
||||
#elif ANDROID
|
||||
pthread_mutex_destroy(&gpReadInfo[i].pDoneSemaphore);
|
||||
#endif
|
||||
}
|
||||
#ifndef ANDROID
|
||||
RE3_SEM_CLOSE(gCdStreamSema, "/semaphore_cd_stream");
|
||||
#elif ANDROID
|
||||
pthread_mutex_destroy(&gCdStreamSema);
|
||||
#endif
|
||||
free(gChannelRequestQ.items);
|
||||
#else
|
||||
RE3_SEM_CLOSE(gpReadInfo[channel].pStartSemaphore, "/semaphore_start%d", channel);
|
||||
|
||||
@@ -26,6 +26,13 @@ CControllerConfigManager::CControllerConfigManager()
|
||||
m_bFirstCapture = false;
|
||||
m_bMouseAssociated = false;
|
||||
|
||||
m_lStickSensX = 1.0f;
|
||||
m_lStickSensY = 1.0f;
|
||||
m_rStickSensX = 1.0f;
|
||||
m_rStickSensY = 1.0f;
|
||||
m_lStickDeadzone = 0.3f;
|
||||
m_rStickDeadzone = 0.3f;
|
||||
|
||||
MakeControllerActionsBlank();
|
||||
InitDefaultControlConfiguration();
|
||||
InitialiseControllerActionNameArray();
|
||||
@@ -47,6 +54,7 @@ void CControllerConfigManager::MakeControllerActionsBlank()
|
||||
|
||||
#ifdef RW_GL3
|
||||
int MapIdToButtonId(int mapId) {
|
||||
#ifndef LIBRW_SDL2
|
||||
switch (mapId) {
|
||||
case GLFW_GAMEPAD_BUTTON_A: // Cross
|
||||
return 2;
|
||||
@@ -84,6 +92,45 @@ int MapIdToButtonId(int mapId) {
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
switch (mapId) {
|
||||
case SDL_CONTROLLER_BUTTON_A: // Cross
|
||||
return 2;
|
||||
case SDL_CONTROLLER_BUTTON_B: // Circle
|
||||
return 1;
|
||||
case SDL_CONTROLLER_BUTTON_X: // Square
|
||||
return 3;
|
||||
case SDL_CONTROLLER_BUTTON_Y: // Triangle
|
||||
return 4;
|
||||
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
|
||||
return 7;
|
||||
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
|
||||
return 8;
|
||||
case SDL_CONTROLLER_BUTTON_BACK:
|
||||
return 9;
|
||||
case SDL_CONTROLLER_BUTTON_START:
|
||||
return 12;
|
||||
case SDL_CONTROLLER_BUTTON_LEFTSTICK:
|
||||
return 10;
|
||||
case SDL_CONTROLLER_BUTTON_RIGHTSTICK:
|
||||
return 11;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_UP:
|
||||
return 13;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
|
||||
return 14;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
|
||||
return 15;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
|
||||
return 16;
|
||||
// SDL2 sends those as axes, so I added them here manually.
|
||||
case 15: // Left trigger
|
||||
return 5;
|
||||
case 16: // Right trigger
|
||||
return 6;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2807,7 +2854,11 @@ void CControllerConfigManager::UpdateJoyButtonState(int32 padnumber)
|
||||
#elif defined RW_GL3
|
||||
if (m_NewState.isGamepad) {
|
||||
for (int32 i = 0; i < MAX_BUTTONS; i++) {
|
||||
#ifndef LIBRW_SDL2
|
||||
if (i == GLFW_GAMEPAD_BUTTON_GUIDE)
|
||||
#else
|
||||
if (i == SDL_CONTROLLER_BUTTON_GUIDE)
|
||||
#endif
|
||||
continue;
|
||||
|
||||
m_aButtonStates[MapIdToButtonId(i)-1] = m_NewState.mappedButtons[i];
|
||||
|
||||
@@ -104,18 +104,18 @@ class CMouseControllerState;
|
||||
class CControllerState;
|
||||
|
||||
|
||||
#define JOY_BUTTONS 16
|
||||
#define JOY_BUTTONS 32
|
||||
#define MAX_BUTTONS (JOY_BUTTONS+1)
|
||||
|
||||
#define ACTIONNAME_LENGTH 40
|
||||
|
||||
#ifdef RW_GL3
|
||||
struct GlfwJoyState {
|
||||
int8 id;
|
||||
bool isGamepad;
|
||||
uint8 numButtons;
|
||||
uint8* buttons;
|
||||
bool mappedButtons[17];
|
||||
struct JoyState {
|
||||
int8 id;
|
||||
bool isGamepad;
|
||||
uint8 numButtons;
|
||||
uint8 buttons[MAX_BUTTONS];
|
||||
bool mappedButtons[MAX_BUTTONS];
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -136,8 +136,8 @@ public:
|
||||
|
||||
bool m_bFirstCapture;
|
||||
#if defined RW_GL3
|
||||
GlfwJoyState m_OldState;
|
||||
GlfwJoyState m_NewState;
|
||||
JoyState m_OldState;
|
||||
JoyState m_NewState;
|
||||
#else
|
||||
DIJOYSTATE2 m_OldState;
|
||||
DIJOYSTATE2 m_NewState;
|
||||
@@ -147,6 +147,8 @@ public:
|
||||
tControllerConfigBind m_aSettings[MAX_CONTROLLERACTIONS][MAX_CONTROLLERTYPES];
|
||||
bool m_aSimCheckers[MAX_SIMS][MAX_CONTROLLERTYPES];
|
||||
bool m_bMouseAssociated;
|
||||
float m_lStickSensX, m_lStickSensY, m_rStickSensX, m_rStickSensY;
|
||||
float m_lStickDeadzone, m_rStickDeadzone;
|
||||
|
||||
#ifdef LOAD_INI_SETTINGS
|
||||
static uint32 ms_padButtonsInited;
|
||||
|
||||
+31
-3
@@ -37,9 +37,21 @@ static myFILE myfiles[NUMFILES];
|
||||
// Case-insensitivity on linux (from https://github.com/OneSadCookie/fcaseopen)
|
||||
void mychdir(char const *path)
|
||||
{
|
||||
#if defined(ANDROID)
|
||||
if(!path) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
char* r = casepath(path, false);
|
||||
if (r) {
|
||||
#if defined(ANDROID)
|
||||
char path[MAX_PATH];
|
||||
strcpy(path, CFileMgr::GetRootDirName());
|
||||
strcat(path, r);
|
||||
chdir(path);
|
||||
#else
|
||||
chdir(r);
|
||||
#endif
|
||||
free(r);
|
||||
} else {
|
||||
errno = ENOENT;
|
||||
@@ -200,8 +212,16 @@ char CFileMgr::ms_dirName[128];
|
||||
void
|
||||
CFileMgr::Initialise(void)
|
||||
{
|
||||
_getcwd(ms_rootDirName, 128);
|
||||
#if defined(ANDROID)
|
||||
if(getenv("STORAGE_ROOT") != NULL) {
|
||||
strcpy(ms_rootDirName, getenv("STORAGE_ROOT"));
|
||||
strcat(ms_rootDirName, "/");
|
||||
debug("Android: Root Dir: %s\n", ms_rootDirName);
|
||||
}
|
||||
#else
|
||||
_getcwd(ms_rootDirName, 128);
|
||||
strcat(ms_rootDirName, "\\");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@@ -213,10 +233,13 @@ CFileMgr::ChangeDir(const char *dir)
|
||||
}
|
||||
if(*dir != '\0'){
|
||||
strcat(ms_dirName, dir);
|
||||
// BUG in the game it seems, it's off by one
|
||||
#ifndef ANDROID
|
||||
// BUG in the game it seems, it's off by one
|
||||
if(dir[strlen(dir)-1] != '\\')
|
||||
strcat(ms_dirName, "\\");
|
||||
#endif
|
||||
}
|
||||
debug("CFileMgr::ChangeDir: %s", ms_dirName);
|
||||
mychdir(ms_dirName);
|
||||
}
|
||||
|
||||
@@ -226,10 +249,13 @@ CFileMgr::SetDir(const char *dir)
|
||||
strcpy(ms_dirName, ms_rootDirName);
|
||||
if(*dir != '\0'){
|
||||
strcat(ms_dirName, dir);
|
||||
// BUG in the game it seems, it's off by one
|
||||
#ifndef ANDROID
|
||||
// BUG in the game it seems, it's off by one
|
||||
if(dir[strlen(dir)-1] != '\\')
|
||||
strcat(ms_dirName, "\\");
|
||||
#endif
|
||||
}
|
||||
debug("CFileMgr::SetDir: %s", ms_dirName);
|
||||
mychdir(ms_dirName);
|
||||
}
|
||||
|
||||
@@ -267,12 +293,14 @@ CFileMgr::LoadFile(const char *file, uint8 *buf, int maxlen, const char *mode)
|
||||
int
|
||||
CFileMgr::OpenFile(const char *file, const char *mode)
|
||||
{
|
||||
debug("CFileMgr::OpenFile: %s", file);
|
||||
return myfopen(file, mode);
|
||||
}
|
||||
|
||||
int
|
||||
CFileMgr::OpenFileForWriting(const char *file)
|
||||
{
|
||||
debug("CFileMgr::OpenFileForWriting: %s", file);
|
||||
return OpenFile(file, "wb");
|
||||
}
|
||||
|
||||
|
||||
+10
-2
@@ -633,10 +633,11 @@ CMenuManager::CentreMousePointer()
|
||||
Point.y = SCREEN_HEIGHT / 2;
|
||||
ClientToScreen(PSGLOBAL(window), &Point);
|
||||
SetCursorPos(Point.x, Point.y);
|
||||
#elif defined RW_GL3
|
||||
#elif defined RW_GL3 && !defined(LIBRW_SDL2)
|
||||
glfwSetCursorPos(PSGLOBAL(window), SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
|
||||
#elif defined(RW_GL3) && defined(LIBRW_SDL2)
|
||||
SDL_WarpMouseInWindow(PSGLOBAL(window), SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
|
||||
#endif
|
||||
|
||||
PSGLOBAL(lastMousePos.x) = SCREEN_WIDTH / 2;
|
||||
PSGLOBAL(lastMousePos.y) = SCREEN_HEIGHT / 2;
|
||||
}
|
||||
@@ -4946,6 +4947,13 @@ CMenuManager::ProcessUserInput(uint8 goDown, uint8 goUp, uint8 optionSelected, u
|
||||
PSGLOBAL(joy1)->GetCapabilities(&devCaps);
|
||||
ControlsManager.InitDefaultControlConfigJoyPad(devCaps.dwButtons);
|
||||
}
|
||||
#elif defined(LIBRW_SDL2) // TODO SDL2 the part below seems unnecessary SDL2 (at least on Linux), remove in the future
|
||||
/*if (PSGLOBAL(joy1id) != -1 && SDL_IsGameController(PSGLOBAL(joy1id))) {
|
||||
SDL_Joystick* joy1 = SDL_JoystickOpen(PSGLOBAL(joy1id));
|
||||
int count = SDL_JoystickNumButtons(joy1);
|
||||
SDL_JoystickClose(joy1);
|
||||
ControlsManager.InitDefaultControlConfigJoyPad(count);
|
||||
}*/
|
||||
#else
|
||||
if (PSGLOBAL(joy1id) != -1 && glfwJoystickPresent(PSGLOBAL(joy1id))) {
|
||||
int count;
|
||||
|
||||
+26
-10
@@ -871,9 +871,13 @@ CMouseControllerState CMousePointerStateHelper::GetMouseSetUp()
|
||||
}
|
||||
#else
|
||||
// It seems there is no way to get number of buttons on mouse, so assign all buttons if we have mouse.
|
||||
double xpos = 1.0f, ypos;
|
||||
#if !defined(LIBRW_SDL2)
|
||||
double xpos = 1.0f, ypos;
|
||||
glfwGetCursorPos(PSGLOBAL(window), &xpos, &ypos);
|
||||
|
||||
#else
|
||||
int xpos = 1, ypos;
|
||||
SDL_GetMouseState(&xpos, &ypos);
|
||||
#endif
|
||||
if (xpos != 0.f) {
|
||||
state.MMB = true;
|
||||
state.RMB = true;
|
||||
@@ -931,8 +935,13 @@ void CPad::UpdateMouse()
|
||||
#else
|
||||
if ( IsForegroundApp() && PSGLOBAL(cursorIsInWindow) )
|
||||
{
|
||||
double xpos = 1.0f, ypos;
|
||||
#ifdef LIBRW_SDL2
|
||||
int xpos = 1, ypos;
|
||||
int mouseState = SDL_GetMouseState(&xpos, &ypos);
|
||||
#else
|
||||
double xpos = 1.0f, ypos;
|
||||
glfwGetCursorPos(PSGLOBAL(window), &xpos, &ypos);
|
||||
#endif
|
||||
if (xpos == 0.f)
|
||||
return;
|
||||
|
||||
@@ -951,12 +960,19 @@ void CPad::UpdateMouse()
|
||||
|
||||
PCTempMouseControllerState.x = (float)(signX * (xpos - PSGLOBAL(lastMousePos.x)));
|
||||
PCTempMouseControllerState.y = (float)(signy * (ypos - PSGLOBAL(lastMousePos.y)));
|
||||
#ifdef LIBRW_SDL2
|
||||
PCTempMouseControllerState.LMB = !!(mouseState & SDL_BUTTON(1));
|
||||
PCTempMouseControllerState.RMB = !!(mouseState & SDL_BUTTON(3));
|
||||
PCTempMouseControllerState.MMB = !!(mouseState & SDL_BUTTON(2));
|
||||
PCTempMouseControllerState.MXB1 = !!(mouseState & SDL_BUTTON(4));
|
||||
PCTempMouseControllerState.MXB2 = !!(mouseState & SDL_BUTTON(5));
|
||||
#else
|
||||
PCTempMouseControllerState.LMB = glfwGetMouseButton(PSGLOBAL(window), GLFW_MOUSE_BUTTON_LEFT);
|
||||
PCTempMouseControllerState.RMB = glfwGetMouseButton(PSGLOBAL(window), GLFW_MOUSE_BUTTON_RIGHT);
|
||||
PCTempMouseControllerState.MMB = glfwGetMouseButton(PSGLOBAL(window), GLFW_MOUSE_BUTTON_MIDDLE);
|
||||
PCTempMouseControllerState.MXB1 = glfwGetMouseButton(PSGLOBAL(window), GLFW_MOUSE_BUTTON_4);
|
||||
PCTempMouseControllerState.MXB2 = glfwGetMouseButton(PSGLOBAL(window), GLFW_MOUSE_BUTTON_5);
|
||||
|
||||
#endif
|
||||
if (PSGLOBAL(mouseWheel) > 0)
|
||||
PCTempMouseControllerState.WHEELUP = 1;
|
||||
else if (PSGLOBAL(mouseWheel) < 0)
|
||||
@@ -1631,14 +1647,14 @@ void CPad::AffectFromXinput(uint32 pad)
|
||||
float rx = (float)xstate.Gamepad.sThumbRX / (float)0x7FFF;
|
||||
float ry = (float)xstate.Gamepad.sThumbRY / (float)0x7FFF;
|
||||
|
||||
if (Abs(lx) > 0.3f || Abs(ly) > 0.3f) {
|
||||
PCTempJoyState.LeftStickX = (int32)(lx * 128.0f);
|
||||
PCTempJoyState.LeftStickY = (int32)(-ly * 128.0f);
|
||||
if (Abs(lx) > ControlsManager.m_lStickDeadzone || Abs(ly) > ControlsManager.m_lStickDeadzone) {
|
||||
PCTempJoyState.LeftStickX = (int32)(lx * 128.0f * ControlsManager.m_lStickSensX);
|
||||
PCTempJoyState.LeftStickY = (int32)(-ly * 128.0f * ControlsManager.m_lStickSensY);
|
||||
}
|
||||
|
||||
if (Abs(rx) > 0.3f || Abs(ry) > 0.3f) {
|
||||
PCTempJoyState.RightStickX = (int32)(rx * 128.0f);
|
||||
PCTempJoyState.RightStickY = (int32)(-ry * 128.0f);
|
||||
if (Abs(rx) > ControlsManager.m_rStickDeadzone || Abs(ry) > ControlsManager.m_rStickDeadzone) {
|
||||
PCTempJoyState.RightStickX = (int32)(rx * 128.0f * ControlsManager.m_rStickSensX);
|
||||
PCTempJoyState.RightStickY = (int32)(-ry * 128.0f * ControlsManager.m_rStickSensY);
|
||||
}
|
||||
|
||||
XINPUT_VIBRATION VibrationState;
|
||||
|
||||
+5
-1
@@ -21,6 +21,10 @@
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#if defined ANDROID
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
#ifdef __MWERKS__
|
||||
#define AUDIO_MSS
|
||||
#define RWLIBS // codewarrior doesn't support project level defines - so not even this is enough, but still catches most ifdefs
|
||||
@@ -341,7 +345,7 @@ void re3_usererror(const char *format, ...);
|
||||
#define DEBUGBREAK() __debugbreak();
|
||||
|
||||
// Switch to enable development messages.
|
||||
#if 1
|
||||
#if 0
|
||||
#define DEV(f, ...)
|
||||
#else
|
||||
#define DEV(f, ...) re3_debug("[DEV]: " f, ## __VA_ARGS__)
|
||||
|
||||
+12
-4
@@ -26,9 +26,11 @@ enum Config {
|
||||
PEDMODELSIZE = 130,
|
||||
VEHICLEMODELSIZE = 110,
|
||||
TWODFXSIZE = 1210,
|
||||
|
||||
MAXVEHICLESLOADED = 50, // 70 on mobile
|
||||
|
||||
#if defined ANDROID
|
||||
MAXVEHICLESLOADED = 70,
|
||||
#else
|
||||
MAXVEHICLESLOADED = 50, // 70 on mobile
|
||||
#endif
|
||||
NUMOBJECTINFO = 210,
|
||||
|
||||
// Pool sizes
|
||||
@@ -154,12 +156,14 @@ enum Config {
|
||||
#define GTA_PC
|
||||
//#define GTA_PS2
|
||||
//#define GTA_XBOX
|
||||
#define GTA_MOBILE
|
||||
|
||||
// Version defines
|
||||
#define GTAVC_PS2 400
|
||||
#define GTAVC_PC_10 410
|
||||
#define GTAVC_PC_11 411
|
||||
#define GTAVC_PC_JAP 412
|
||||
#define GTAVC_ANDROID 413 // ANDROID 413?
|
||||
// TODO? maybe something for xbox or android?
|
||||
|
||||
#define GTA_VERSION GTAVC_PC_11
|
||||
@@ -290,7 +294,7 @@ enum Config {
|
||||
#define EXTENDED_OFFSCREEN_DESPAWN_RANGE // Use onscreen despawn range for offscreen peds and vehicles to avoid them despawning in the distance when you look
|
||||
// away
|
||||
|
||||
#if defined(__LP64__) || defined(_WIN64)
|
||||
#if defined(__LP64__) || defined(_WIN64) || defined(__aarch64__)
|
||||
#define FIX_BUGS_64 // Must have fixes to be able to run 64 bit build
|
||||
#endif
|
||||
|
||||
@@ -306,6 +310,10 @@ enum Config {
|
||||
#define MISSION_SWITCHER // from debug menu
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID
|
||||
#define USE_FILE_LOG
|
||||
#endif
|
||||
|
||||
// Rendering/display
|
||||
#define ASPECT_RATIO_SCALE // Not just makes everything scale with aspect ratio, also adds support for all aspect ratios
|
||||
#define PROPER_SCALING // use original DEFAULT_SCREEN_WIDTH/DEFAULT_SCREEN_HEIGHT from PS2 instead of PC(R* changed HEIGHT here to make radar look better, but broke other hud elements aspect ratio).
|
||||
|
||||
+10
-2
@@ -1084,8 +1084,10 @@ DisplayGameDebugText()
|
||||
sprintf(verA,
|
||||
#if defined _WIN32
|
||||
"Win "
|
||||
#elif defined __linux__
|
||||
#elif defined __linux__ && !defined ANDROID
|
||||
"Linux "
|
||||
#elif defined(ANDROID)
|
||||
"Android "
|
||||
#elif defined __APPLE__
|
||||
"Mac OS X "
|
||||
#elif defined __FreeBSD__
|
||||
@@ -1093,8 +1095,14 @@ DisplayGameDebugText()
|
||||
#else
|
||||
"Posix-compliant "
|
||||
#endif
|
||||
#if defined __LP64__ || defined _WIN64
|
||||
#if defined __LP64__ || defined _WIN64 || defined __aarch64__
|
||||
#if defined ANDROID
|
||||
"arm64-v8a "
|
||||
#else
|
||||
"64-bit "
|
||||
#endif
|
||||
#elif defined ANDROID
|
||||
"armeabi-v7a "
|
||||
#else
|
||||
"32-bit "
|
||||
#endif
|
||||
|
||||
+16
-6
@@ -136,6 +136,9 @@ CustomFrontendOptionsPopulate(void)
|
||||
#ifdef EXTENDED_PIPELINES
|
||||
const char *vehPipelineNames[] = { "FED_MFX", "FED_NEO" };
|
||||
const char *off_on[] = { "FEM_OFF", "FEM_ON" };
|
||||
#if defined ANDROID
|
||||
CFileMgr::ChangeDir("\\");
|
||||
#endif
|
||||
fd = CFileMgr::OpenFile("neo/neo.txd","r");
|
||||
if (fd) {
|
||||
#ifdef GRAPHICS_MENU_OPTIONS
|
||||
@@ -1212,7 +1215,7 @@ void re3_assert(const char *expr, const char *filename, unsigned int lineno, con
|
||||
strcat_s(re3_buff, re3_buffsize, "(Press Retry to debug the application)");
|
||||
|
||||
|
||||
nCode = ::MessageBoxA(nil, re3_buff, "REVC Assertion Failed!",
|
||||
nCode = ::MessageBoxA(nil, re3_buff, "reVC Assertion Failed!",
|
||||
MB_ABORTRETRYIGNORE|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL);
|
||||
|
||||
if (nCode == IDABORT)
|
||||
@@ -1233,7 +1236,7 @@ void re3_assert(const char *expr, const char *filename, unsigned int lineno, con
|
||||
abort();
|
||||
#else
|
||||
// TODO
|
||||
printf("\nREVC ASSERT FAILED\n\tFile: %s\n\tLine: %d\n\tFunction: %s\n\tExpression: %s\n",filename,lineno,func,expr);
|
||||
printf("\nreVC ASSERT FAILED\n\tFile: %s\n\tLine: %d\n\tFunction: %s\n\tExpression: %s\n",filename,lineno,func,expr);
|
||||
assert(false);
|
||||
#endif
|
||||
}
|
||||
@@ -1250,7 +1253,9 @@ void re3_debug(const char *format, ...)
|
||||
vsprintf(re3_buff, format, va);
|
||||
#endif
|
||||
va_end(va);
|
||||
|
||||
#if defined ANDROID
|
||||
__android_log_print(ANDROID_LOG_DEBUG, "reVC-DEBUG", re3_buff);
|
||||
#endif
|
||||
printf("%s", re3_buff);
|
||||
CDebug::DebugAddText(re3_buff);
|
||||
#endif
|
||||
@@ -1273,7 +1278,9 @@ void re3_trace(const char *filename, unsigned int lineno, const char *func, cons
|
||||
|
||||
sprintf(buff, "[%s.%s:%d]: %s", filename, func, lineno, re3_buff);
|
||||
#endif
|
||||
|
||||
#if defined ANDROID
|
||||
__android_log_print(ANDROID_LOG_DEBUG, "reVC-TRACE", buff);
|
||||
#endif
|
||||
OutputDebugString(buff);
|
||||
}
|
||||
#endif
|
||||
@@ -1287,14 +1294,17 @@ void re3_usererror(const char *format, ...)
|
||||
vsprintf_s(re3_buff, re3_buffsize, format, va);
|
||||
va_end(va);
|
||||
|
||||
::MessageBoxA(nil, re3_buff, "REVC Error!",
|
||||
::MessageBoxA(nil, re3_buff, "reVC Error!",
|
||||
MB_OK|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL);
|
||||
|
||||
raise(SIGABRT);
|
||||
_exit(3);
|
||||
#else
|
||||
vsprintf(re3_buff, format, va);
|
||||
printf("\nREVC Error!\n\t%s\n",re3_buff);
|
||||
#if defined ANDROID
|
||||
__android_log_print(ANDROID_LOG_ERROR, "reVC-ERROR", re3_buff);
|
||||
#endif
|
||||
printf("\nreVC Error!\n\t%s\n",re3_buff);
|
||||
assert(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
#include "SaveBuf.h"
|
||||
|
||||
int gBuildings;
|
||||
#if defined ANDROID
|
||||
int g_iLastRenderedObject;
|
||||
#endif
|
||||
|
||||
CEntity::CEntity(void)
|
||||
{
|
||||
@@ -415,6 +418,9 @@ CEntity::PreRender(void)
|
||||
void
|
||||
CEntity::Render(void)
|
||||
{
|
||||
#if defined ANDROID
|
||||
g_iLastRenderedObject = this->m_modelIndex;
|
||||
#endif
|
||||
if(m_rwObject){
|
||||
bImBeingRendered = true;
|
||||
if(RwObjectGetType(m_rwObject) == rpATOMIC)
|
||||
|
||||
+6
-1
@@ -19,7 +19,12 @@ C_PcSave PcSaveHelper;
|
||||
void
|
||||
C_PcSave::SetSaveDirectory(const char *path)
|
||||
{
|
||||
sprintf(DefaultPCSaveFileName, "%s\\%s", path, "GTAVCsf");
|
||||
#if defined ANDROID
|
||||
sprintf(DefaultPCSaveFileName, "%s/%s", path, "GTAVCsf");
|
||||
debug("SetSaveDirectory: %s", DefaultPCSaveFileName);
|
||||
#else
|
||||
sprintf(DefaultPCSaveFileName, "%s\\%s", path, "GTAVCsf");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -0,0 +1,432 @@
|
||||
//
|
||||
// Created by mrxenginner on 13/07/2025.
|
||||
//
|
||||
|
||||
#if defined ANDROID
|
||||
|
||||
#include "AndroidMain.h"
|
||||
#include "JavaWrapper.h"
|
||||
#include "logger/log.h"
|
||||
#include <SDL_hints.h>
|
||||
#include <SDL_main.h>
|
||||
#include <SignalHandler.h>
|
||||
#include <patch/patch.h>
|
||||
|
||||
JavaVM* javaVM = NULL;
|
||||
char* StorageRootBuffer = NULL;
|
||||
uintptr_t g_libREVC = NULL;
|
||||
|
||||
bool AndWrapper::AppInitialized = false;
|
||||
bool AndWrapper::AppStarted = false;
|
||||
|
||||
JAVA_WRAPPER Java_org_libsdl_app_SDLActivity_nativeSetupJNI(JNIEnv* env, jobject initGame)
|
||||
{
|
||||
if(!javaVM) {
|
||||
env->GetJavaVM(&javaVM);
|
||||
}
|
||||
|
||||
g_pJavaWrapper = new CJavaWrapper(env, initGame);
|
||||
}
|
||||
|
||||
JAVA_WRAPPER Java_com_revc_game_core_REVC_setGamePath(JNIEnv *env, jobject obj, jstring value)
|
||||
{
|
||||
const char* root = env->GetStringUTFChars(value, NULL);
|
||||
setenv("STORAGE_ROOT", root, 1);
|
||||
|
||||
StorageRootBuffer = getenv("STORAGE_ROOT");
|
||||
debug("Storage Root: %s", StorageRootBuffer);
|
||||
|
||||
env->ReleaseStringUTFChars(value, root);
|
||||
}
|
||||
|
||||
bool AndWrapper::InitLibraries() {
|
||||
g_libREVC = Patch::FindLib("libreVC.so");
|
||||
|
||||
if (!g_libREVC) {
|
||||
Logger::Log("[ERROR]: Required libraries not found!");
|
||||
return false;
|
||||
}
|
||||
|
||||
Logger::Log("[INFO]: libreVC base: 0x%X", g_libREVC);
|
||||
return true;
|
||||
}
|
||||
|
||||
void AndWrapper::TimeInitialize() {
|
||||
struct timeval v0;
|
||||
|
||||
gettimeofday(&v0, NULL);
|
||||
// base_time = (double)v0.tv_usec / 1000000.0 + (double)v0.tv_sec;
|
||||
}
|
||||
|
||||
void* AndWrapper::GetJNI() {
|
||||
return CJavaWrapper::GetEnv();
|
||||
}
|
||||
|
||||
void* AndWrapper::GetJNIFunc() {
|
||||
return CJavaWrapper::GetEnv();
|
||||
}
|
||||
|
||||
void* AndWrapper::GetObj() {
|
||||
//return s_event_globalThiz;
|
||||
}
|
||||
|
||||
const char* AndWrapper::GetAppId()
|
||||
{
|
||||
/*JNIEnv* CurrentJNIEnv; // x19
|
||||
jobject v1; // x20
|
||||
const char *v2; // x21
|
||||
jboolean v4[4]; // [xsp+Ch] [xbp-14h] BYREF
|
||||
|
||||
if (!staticAppId[0]) {
|
||||
CurrentJNIEnv = CJavaWrapper::GetEnv();
|
||||
|
||||
v1 = _JNIEnv::CallObjectMethod(CurrentJNIEnv, s_event_globalThiz, s_GetAppId);
|
||||
v2 = CurrentJNIEnv->functions->GetStringUTFChars(CurrentJNIEnv, (jstring)v1, v4);
|
||||
strcpy(staticAppId, v2);
|
||||
CurrentJNIEnv->functions->ReleaseStringUTFChars(CurrentJNIEnv, (jstring)v1, v2);
|
||||
CurrentJNIEnv->functions->DeleteLocalRef(CurrentJNIEnv, v1);
|
||||
}
|
||||
return staticAppId;*/
|
||||
}
|
||||
|
||||
const char* AndWrapper::GetDeviceID()
|
||||
{
|
||||
/*JNIEnv *CurrentJNIEnv; // x19
|
||||
jobject v1; // x20
|
||||
const char *v2; // x21
|
||||
jboolean v4[4]; // [xsp+Ch] [xbp-24h] BYREF
|
||||
|
||||
CurrentJNIEnv = NVThreadGetCurrentJNIEnv();
|
||||
v1 = JNIEnv::CallObjectMethod(CurrentJNIEnv, s_event_globalThiz, s_GetDeviceID);
|
||||
v2 = CurrentJNIEnv->functions->GetStringUTFChars(CurrentJNIEnv, (jstring)v1, v4);
|
||||
strncpy(staticDeviceID, v2, 0x80uLL);
|
||||
CurrentJNIEnv->functions->ReleaseStringUTFChars(CurrentJNIEnv, (jstring)v1, v2);
|
||||
CurrentJNIEnv->functions->DeleteLocalRef(CurrentJNIEnv, v1);
|
||||
return staticDeviceID;*/
|
||||
}
|
||||
|
||||
int AndWrapper::GetDeviceInfo(int index)
|
||||
{
|
||||
//JNIEnv *CurrentJNIEnv; // x0
|
||||
|
||||
//CurrentJNIEnv = NVThreadGetCurrentJNIEnv();
|
||||
//return _JNIEnv::CallIntMethod(CurrentJNIEnv, s_event_globalThiz, s_GetDeviceInfo, (unsigned int)index);
|
||||
}
|
||||
|
||||
bool AndWrapper::IsAppInstalled(const char* app)
|
||||
{
|
||||
/*_JNIEnv *CurrentJNIEnv; // x20
|
||||
__int64 v3; // x19
|
||||
bool v4; // w21
|
||||
|
||||
CurrentJNIEnv = NVThreadGetCurrentJNIEnv();
|
||||
v3 = (__int64)CurrentJNIEnv->functions->NewStringUTF(CurrentJNIEnv, app);
|
||||
v4 = _JNIEnv::CallBooleanMethod(CurrentJNIEnv, s_event_globalThiz, s_IsAppInstalled, v3) != 0;
|
||||
CurrentJNIEnv->functions->DeleteLocalRef(CurrentJNIEnv, (jobject)v3);
|
||||
return v4;*/
|
||||
}
|
||||
|
||||
void AndWrapper::OpenLink(const char* link)
|
||||
{
|
||||
/*_JNIEnv *CurrentJNIEnv; // x20
|
||||
__int64 v3; // x19
|
||||
|
||||
CurrentJNIEnv = NVThreadGetCurrentJNIEnv();
|
||||
v3 = (__int64)CurrentJNIEnv->functions->NewStringUTF(CurrentJNIEnv, link);
|
||||
_JNIEnv::CallVoidMethod(CurrentJNIEnv, s_event_globalThiz, s_OpenLink, v3);
|
||||
CurrentJNIEnv->functions->DeleteLocalRef(CurrentJNIEnv, (jobject)v3);*/
|
||||
}
|
||||
|
||||
bool AndWrapper::DeviceIsTV()
|
||||
{
|
||||
//_JNIEnv *CurrentJNIEnv; // x0
|
||||
|
||||
//CurrentJNIEnv = NVThreadGetCurrentJNIEnv();
|
||||
//return _JNIEnv::CallBooleanMethod(CurrentJNIEnv, s_event_globalThiz, s_IsTV) != 0;
|
||||
}
|
||||
|
||||
int AndWrapper::DeviceLocale()
|
||||
{
|
||||
// _JNIEnv *CurrentJNIEnv; // x0
|
||||
|
||||
// CurrentJNIEnv = NVThreadGetCurrentJNIEnv();
|
||||
// return _JNIEnv::CallIntMethod(CurrentJNIEnv, s_event_globalThiz, s_GetDeviceLocale);
|
||||
}
|
||||
|
||||
int AndWrapper::DeviceType()
|
||||
{
|
||||
//_JNIEnv *CurrentJNIEnv; // x0
|
||||
|
||||
//CurrentJNIEnv = NVThreadGetCurrentJNIEnv();
|
||||
//return _JNIEnv::CallIntMethod(CurrentJNIEnv, s_event_globalThiz, s_GetDeviceType);
|
||||
}
|
||||
|
||||
void AndWrapper::SystemInitialize()
|
||||
{
|
||||
|
||||
}
|
||||
/*
|
||||
int32_t __fastcall NVEventAppMain(int32_t argc, char **argv)
|
||||
{
|
||||
_QWORD *v4; // x8
|
||||
pthread_key_t v5; // w0
|
||||
__int64 v6; // x21
|
||||
_BOOL4 v7; // w21
|
||||
_JNIEnv *CurrentJNIEnv; // x0
|
||||
_JNIEnv *v9; // x0
|
||||
jint v10; // w0
|
||||
__int64 v11; // x22
|
||||
__int64 v12; // x22
|
||||
_JNIEnv *v13; // x0
|
||||
int v14; // w8
|
||||
_JNIEnv *v15; // x0
|
||||
_JNIEnv *v16; // x0
|
||||
double v17; // d8
|
||||
bool v18; // w19
|
||||
double v19; // d1
|
||||
double v20; // d0
|
||||
double v21; // d12
|
||||
double v22; // d8
|
||||
float v23; // s0
|
||||
char v24; // w20
|
||||
pthread_mutexattr_t *v25; // x19
|
||||
pthread_mutexattr_t *v26; // x19
|
||||
pthread_mutexattr_t *v27; // x19
|
||||
struct timeval v29; // [xsp+0h] [xbp-90h] BYREF
|
||||
int data; // [xsp+1Ch] [xbp-74h] BYREF
|
||||
|
||||
OS_ApplicationPreinit();
|
||||
AND_KeyboardInitialize();
|
||||
memset(lastGamepadAxis, 0, sizeof(lastGamepadAxis));
|
||||
gettimeofday(&v29, 0LL);
|
||||
base_time = (double)v29.tv_usec / 1000000.0 + (double)v29.tv_sec;
|
||||
if ( !ANDThread_Initted )
|
||||
{
|
||||
pthread_key_create(&ANDThreadStorageKey, ANDThreadData::Destroy);
|
||||
v4 = malloc(0x18uLL);
|
||||
v5 = ANDThreadStorageKey;
|
||||
v4[1] = 0LL;
|
||||
v4[2] = 0LL;
|
||||
*v4 = 0LL;
|
||||
pthread_setspecific(v5, v4);
|
||||
ANDThread_Initted = 1;
|
||||
}
|
||||
v6 = operator new(0x30uLL);
|
||||
pthread_mutexattr_init((pthread_mutexattr_t *)(v6 + 40));
|
||||
pthread_mutexattr_settype((pthread_mutexattr_t *)(v6 + 40), 1);
|
||||
pthread_mutex_init((pthread_mutex_t *)v6, (const pthread_mutexattr_t *)(v6 + 40));
|
||||
fileMutex = (OSMutex)v6;
|
||||
if ( DoInitGraphics )
|
||||
initGraphics();
|
||||
v7 = 0;
|
||||
if ( IsInitGraphics )
|
||||
goto LABEL_8;
|
||||
while ( IsAndroidPaused || !v7 )
|
||||
{
|
||||
while ( 1 )
|
||||
{
|
||||
++NVEventAppMain(int,char **)::iter;
|
||||
v7 = ProcessEvents(0);
|
||||
if ( !IsInitGraphics )
|
||||
break;
|
||||
LABEL_8:
|
||||
if ( !IsAndroidPaused )
|
||||
goto LABEL_12;
|
||||
}
|
||||
}
|
||||
LABEL_12:
|
||||
pthread_mutex_lock((pthread_mutex_t *)AndroidEGLContext);
|
||||
CurrentJNIEnv = NVThreadGetCurrentJNIEnv();
|
||||
if ( CurrentJNIEnv && s_event_globalThiz )
|
||||
{
|
||||
if ( !_JNIEnv::CallBooleanMethod(CurrentJNIEnv, s_event_globalThiz, s_makeCurrent) )
|
||||
__android_log_print(3, "NVEvent", "Error: MakeCurrent failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
__android_log_print(3, "NVEvent", "Error: No valid JNI env in MakeCurrent");
|
||||
}
|
||||
AND_WRAPPER::SystemInitialize();
|
||||
v9 = NVThreadGetCurrentJNIEnv();
|
||||
v10 = _JNIEnv::CallIntMethod(v9, s_event_globalThiz, s_GetDeviceType);
|
||||
isLowMemoryDevice = (((unsigned int)v10 >> 1) & 1) == 0 || v10 >> 6 < 250;
|
||||
v11 = operator new(0x30uLL);
|
||||
pthread_mutexattr_init((pthread_mutexattr_t *)(v11 + 40));
|
||||
pthread_mutexattr_settype((pthread_mutexattr_t *)(v11 + 40), 1);
|
||||
pthread_mutex_init((pthread_mutex_t *)v11, (const pthread_mutexattr_t *)(v11 + 40));
|
||||
billingMutex = (OSMutex)v11;
|
||||
v12 = operator new(0x30uLL);
|
||||
pthread_mutexattr_init((pthread_mutexattr_t *)(v12 + 40));
|
||||
pthread_mutexattr_settype((pthread_mutexattr_t *)(v12 + 40), 1);
|
||||
pthread_mutex_init((pthread_mutex_t *)v12, (const pthread_mutexattr_t *)(v12 + 40));
|
||||
gameServiceMutex = (OSMutex)v12;
|
||||
s_conflictHandler = 0LL;
|
||||
if ( OS_ApplicationInitialize(argc, (const char **)argv) )
|
||||
{
|
||||
data = 0;
|
||||
AND_AppInitialized = 1;
|
||||
v13 = NVThreadGetCurrentJNIEnv();
|
||||
if ( _JNIEnv::CallBooleanMethod(v13, s_event_globalThiz, s_IsWifiAvailable) )
|
||||
{
|
||||
v14 = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
v15 = NVThreadGetCurrentJNIEnv();
|
||||
if ( !_JNIEnv::CallBooleanMethod(v15, s_event_globalThiz, s_IsNetworkAvailable) )
|
||||
goto LABEL_23;
|
||||
v14 = 1;
|
||||
}
|
||||
data = v14;
|
||||
LABEL_23:
|
||||
OS_ApplicationEvent(OSET_NetworkChanged, &data);
|
||||
v16 = NVThreadGetCurrentJNIEnv();
|
||||
if ( v16 && s_event_globalThiz )
|
||||
{
|
||||
if ( !_JNIEnv::CallBooleanMethod(v16, s_event_globalThiz, s_unMakeCurrent) )
|
||||
__android_log_print(3, "NVEvent", "Error: UnMakeCurrent failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
__android_log_print(3, "NVEvent", "Error: No valid JNI env in UnMakeCurrent");
|
||||
}
|
||||
pthread_mutex_unlock((pthread_mutex_t *)AndroidEGLContext);
|
||||
if ( OS_ApplicationStartup(windowSize[0], windowSize[1], argc, (const char **)argv) )
|
||||
{
|
||||
AND_AppStarted = 1;
|
||||
gettimeofday(&v29, 0LL);
|
||||
if ( !v7 )
|
||||
{
|
||||
v17 = (double)v29.tv_usec / 1000000.0 + (double)v29.tv_sec;
|
||||
do
|
||||
{
|
||||
v18 = ProcessEvents(0);
|
||||
while ( !v18 )
|
||||
{
|
||||
if ( !IsAndroidPaused )
|
||||
break;
|
||||
if ( IsAndroidInMultiplayer )
|
||||
break;
|
||||
v18 = ProcessEvents(0);
|
||||
usleep(0x61A8u);
|
||||
}
|
||||
gettimeofday(&v29, 0LL);
|
||||
if ( v29.tv_usec > 1000000 || v29.tv_usec < 0 )
|
||||
v19 = OS_TimeAccurate(void)::last_current_time
|
||||
- (double)(unsigned int)OS_TimeAccurate(void)::last_current_time
|
||||
+ 0.00033;
|
||||
else
|
||||
v19 = (double)v29.tv_usec / 1000000.0;
|
||||
v20 = v19 + (double)v29.tv_sec;
|
||||
OS_TimeAccurate(void)::last_current_time = v20;
|
||||
if ( v20 - OS_TimeAccurate(void)::lastPrint > 5.0 )
|
||||
OS_TimeAccurate(void)::lastPrint = v19 + (double)v29.tv_sec;
|
||||
v21 = v20 - base_time;
|
||||
v22 = v20 - base_time - v17;
|
||||
v23 = v22;
|
||||
v24 = OS_ApplicationTick(v23);
|
||||
AND_GamepadUpdate();
|
||||
AND_FileUpdate(v22);
|
||||
AND_BillingUpdate(0);
|
||||
v17 = v21;
|
||||
}
|
||||
while ( !v18 && (v24 & 1) != 0 );
|
||||
}
|
||||
OS_ApplicationEvent(OSET_RequestExit, 0LL);
|
||||
pthread_key_delete(ANDThreadStorageKey);
|
||||
if ( items )
|
||||
{
|
||||
free(items);
|
||||
items = 0LL;
|
||||
numItems = 0;
|
||||
}
|
||||
v25 = (pthread_mutexattr_t *)billingMutex;
|
||||
if ( billingMutex )
|
||||
{
|
||||
pthread_mutex_destroy((pthread_mutex_t *)billingMutex);
|
||||
pthread_mutexattr_destroy(v25 + 5);
|
||||
operator delete(v25);
|
||||
}
|
||||
billingMutex = 0LL;
|
||||
AND_ClearAchievementData(1);
|
||||
v26 = (pthread_mutexattr_t *)billingMutex;
|
||||
if ( billingMutex )
|
||||
{
|
||||
pthread_mutex_destroy((pthread_mutex_t *)billingMutex);
|
||||
pthread_mutexattr_destroy(v26 + 5);
|
||||
operator delete(v26);
|
||||
}
|
||||
v27 = (pthread_mutexattr_t *)fileMutex;
|
||||
if ( fileMutex )
|
||||
{
|
||||
pthread_mutex_destroy((pthread_mutex_t *)fileMutex);
|
||||
pthread_mutexattr_destroy(v27 + 5);
|
||||
operator delete(v27);
|
||||
}
|
||||
fileMutex = 0LL;
|
||||
}
|
||||
else
|
||||
{
|
||||
OS_ApplicationEvent(OSET_RequestExit, 0LL);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}*/
|
||||
/*
|
||||
void __fastcall OS_ApplicationEvent(OSEventType type, void *data)
|
||||
{
|
||||
switch ( type )
|
||||
{
|
||||
case OSET_RequestExit:
|
||||
RsGlobal.quit = TRUE;
|
||||
//OS_ThreadWait(mainThread);
|
||||
break;
|
||||
|
||||
case OSET_Pause:
|
||||
SaveGameForPause(eSaveTypes::eExitSave, 0LL);
|
||||
CTimer::StartUserPause();
|
||||
if ( !CPad::GetPad(0)->DisablePlayerControls
|
||||
&& !gMobileMenu.screenStack.numEntries
|
||||
&& !CCutsceneMgr::IntroTextIsActiveHack
|
||||
&& !CCutsceneMgr::ms_running
|
||||
&& !gMobileMenu.pendingScreen
|
||||
&& !CTouchInterface::AnyWidgetsUsingAltBack() )
|
||||
{
|
||||
if (FindPlayerPed())
|
||||
bPendingPause = 1;
|
||||
}
|
||||
CAEAudioHardware::PauseOpenAL((CAEAudioHardware *)&AEAudioHardware, 1);
|
||||
break;
|
||||
case OSET_Resume:
|
||||
OS_ThreadUnmakeCurrent();
|
||||
CTimer::Update();
|
||||
if ( !gMobileMenu.screenStack.numEntries && !gMobileMenu.pendingScreen )
|
||||
CTimer::EndUserPause();
|
||||
CAEAudioHardware::PauseOpenAL((CAEAudioHardware *)&AEAudioHardware, 0);
|
||||
break;
|
||||
case OSET_LowMemory:
|
||||
//DoLowMemoryCleanup = 1;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
JNI_WRAPPER int InitializeGame() {
|
||||
debug("Initialize Game");
|
||||
|
||||
if (!AndWrapper::InitLibraries()) return NULL;
|
||||
|
||||
int argc = 0;
|
||||
char* argv[1] = { nullptr };
|
||||
|
||||
SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeLeft LandscapeRight");
|
||||
// SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
|
||||
|
||||
CrashHandler::SetupSignalHandlers();
|
||||
|
||||
int result = SDL_main(argc, argv);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// Created by mrxenginner on 13/07/2025.
|
||||
//
|
||||
|
||||
#ifndef REVC_ANDROIDMAIN_H
|
||||
#define REVC_ANDROIDMAIN_H
|
||||
|
||||
#if defined ANDROID
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define JNI_WRAPPER extern "C" __attribute__ ((visibility("default")))
|
||||
#define JAVA_WRAPPER extern "C" JNIEXPORT void JNICALL
|
||||
|
||||
extern uintptr_t g_libREVC;
|
||||
extern char* StorageRootBuffer;
|
||||
|
||||
namespace AndWrapper {
|
||||
extern bool AppInitialized;
|
||||
extern bool AppStarted;
|
||||
|
||||
bool InitLibraries();
|
||||
void SystemInitialize();
|
||||
void TimeInitialize();
|
||||
void* GetJNI();
|
||||
void* GetJNIFunc();
|
||||
void* GetObj();
|
||||
const char* GetAppId();
|
||||
const char* GetDeviceID();
|
||||
int GetDeviceInfo(int index);
|
||||
bool IsAppInstalled(const char* app);
|
||||
void OpenLink(const char* link);
|
||||
bool DeviceIsTV();
|
||||
int DeviceLocale();
|
||||
int DeviceType();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //REVC_ANDROIDMAIN_H
|
||||
@@ -0,0 +1,73 @@
|
||||
//
|
||||
// Created by mrxenginner on 14/07/2025.
|
||||
//
|
||||
|
||||
#include "common.h"
|
||||
#include "JavaWrapper.h"
|
||||
|
||||
#if defined ANDROID
|
||||
|
||||
extern "C" JavaVM *javaVM;
|
||||
|
||||
JNIEnv* CJavaWrapper::GetEnv() {
|
||||
|
||||
JNIEnv* env = NULL;
|
||||
|
||||
int getEnvStat = javaVM->GetEnv((void**)&env, JNI_VERSION_1_6);
|
||||
|
||||
if (getEnvStat == JNI_EDETACHED) {
|
||||
debug("GetEnv: not attached");
|
||||
if (javaVM->AttachCurrentThread(&env, NULL) != 0) {
|
||||
debug("Failed to attach");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (getEnvStat == JNI_EVERSION) {
|
||||
debug("GetEnv: version not supported");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (getEnvStat == JNI_ERR) {
|
||||
debug("GetEnv: JNI_ERR");
|
||||
return NULL;
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
void CJavaWrapper::ExitGame() {
|
||||
|
||||
JNIEnv* env = GetEnv();
|
||||
|
||||
if (!env) {
|
||||
debug("No env");
|
||||
return;
|
||||
}
|
||||
|
||||
env->CallVoidMethod(this->activity, this->s_ExitGame);
|
||||
}
|
||||
|
||||
CJavaWrapper::CJavaWrapper(JNIEnv *env, jobject activity) {
|
||||
this->activity = env->NewGlobalRef(activity);
|
||||
|
||||
jclass nvEventClass = env->GetObjectClass(activity);
|
||||
|
||||
if (!nvEventClass) {
|
||||
debug("nvEventClass null");
|
||||
return;
|
||||
}
|
||||
|
||||
s_ExitGame = env->GetMethodID(nvEventClass, "exitGame", "()V");
|
||||
env->DeleteLocalRef(nvEventClass);
|
||||
env->DeleteLocalRef(activity);
|
||||
}
|
||||
|
||||
CJavaWrapper::~CJavaWrapper() {
|
||||
JNIEnv* pEnv = GetEnv();
|
||||
if (pEnv) {
|
||||
pEnv->DeleteGlobalRef(this->activity);
|
||||
}
|
||||
}
|
||||
|
||||
CJavaWrapper* g_pJavaWrapper = nullptr;
|
||||
#endif
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// Created by mrxenginner on 14/07/2025.
|
||||
//
|
||||
|
||||
#ifndef REVC_CJAVAWRAPPER_H
|
||||
#define REVC_CJAVAWRAPPER_H
|
||||
|
||||
#if defined ANDROID
|
||||
|
||||
#include <jni.h>
|
||||
#include <string>
|
||||
|
||||
#define EXCEPTION_CHECK(env) \
|
||||
if ((env)->ExceptionCheck()) \
|
||||
{ \
|
||||
(env)->ExceptionDescribe(); \
|
||||
(env)->ExceptionClear(); \
|
||||
return; \
|
||||
}
|
||||
|
||||
class CJavaWrapper
|
||||
{
|
||||
jmethodID s_ExitGame;
|
||||
public:
|
||||
jobject activity;
|
||||
|
||||
CJavaWrapper(JNIEnv* env, jobject activity);
|
||||
~CJavaWrapper();
|
||||
|
||||
void ExitGame();
|
||||
|
||||
// static methods
|
||||
static JNIEnv* GetEnv();
|
||||
};
|
||||
|
||||
extern CJavaWrapper* g_pJavaWrapper;
|
||||
#endif
|
||||
|
||||
#endif //REVC_CJAVAWRAPPER_H
|
||||
@@ -0,0 +1,65 @@
|
||||
//
|
||||
// Created by mrxenginner on 11/05/2025.
|
||||
//
|
||||
|
||||
#if defined ANDROID
|
||||
|
||||
#include "common.h"
|
||||
#include "log.h"
|
||||
#include "AndroidMain.h"
|
||||
|
||||
extern char* StorageRootBuffer;
|
||||
|
||||
void Logger::Log(const char *fmt, ...)
|
||||
{
|
||||
static char buffer[512]{};
|
||||
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
va_list arg;
|
||||
va_start(arg, fmt);
|
||||
vsnprintf(buffer, sizeof(buffer), fmt, arg);
|
||||
va_end(arg);
|
||||
#if defined ANDROID
|
||||
__android_log_write(ANDROID_LOG_INFO, "LOG", buffer);
|
||||
#endif
|
||||
#ifdef USE_FILE_LOG
|
||||
static FILE* flLog = nullptr;
|
||||
|
||||
if(flLog == nullptr && StorageRootBuffer != nullptr) {
|
||||
sprintf(buffer, "%slog.txt", StorageRootBuffer);
|
||||
flLog = fopen(buffer, "ab");
|
||||
}
|
||||
|
||||
if(flLog == nullptr) return;
|
||||
fprintf(flLog, "%s\n", buffer);
|
||||
fflush(flLog);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Logger::CrashLog(const char* fmt, ...)
|
||||
{
|
||||
static char buffer[512]{};
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
va_list arg;
|
||||
va_start(arg, fmt);
|
||||
vsnprintf(buffer, sizeof(buffer), fmt, arg);
|
||||
va_end(arg);
|
||||
#if defined ANDROID
|
||||
__android_log_write(ANDROID_LOG_FATAL, "CRASH LOG", buffer);
|
||||
#endif
|
||||
#ifdef USE_FILE_LOG
|
||||
static FILE* flLog = nullptr;
|
||||
|
||||
if (flLog == nullptr && StorageRootBuffer != nullptr) {
|
||||
sprintf(buffer, "%scrash_log.txt", StorageRootBuffer);
|
||||
flLog = fopen(buffer, "ab");
|
||||
}
|
||||
|
||||
if (flLog == nullptr) return;
|
||||
fprintf(flLog, "%s\n", buffer);
|
||||
fflush(flLog);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// Created by mrxenginner on 11/05/2025.
|
||||
//
|
||||
|
||||
#ifndef REVC_LOGGER_H
|
||||
#define REVC_LOGGER_H
|
||||
|
||||
#if defined ANDROID
|
||||
|
||||
namespace Logger {
|
||||
void Log(const char* fmt, ...);
|
||||
void CrashLog(const char* fmt, ...);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// Created by mrxenginner on 14/07/2025.
|
||||
//
|
||||
|
||||
#ifndef REVC_PATCH_H
|
||||
#define REVC_PATCH_H
|
||||
|
||||
#if defined ANDROID
|
||||
|
||||
#include "common.h"
|
||||
#include <dlfcn.h>
|
||||
|
||||
class Patch {
|
||||
public:
|
||||
static uintptr_t FindLib(const char* libName)
|
||||
{
|
||||
#if defined ANDROID
|
||||
void* handle = dlopen(libName, RTLD_LAZY);
|
||||
|
||||
if (handle) {
|
||||
void* symbol = dlsym(handle, "InitializeGame");
|
||||
if (symbol) {
|
||||
Dl_info info;
|
||||
if (dladdr(symbol, &info) != 0) {
|
||||
return reinterpret_cast<uintptr_t>(info.dli_fbase);
|
||||
}
|
||||
}
|
||||
dlclose(handle);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // REVC_PATCH_H
|
||||
@@ -0,0 +1,102 @@
|
||||
//
|
||||
// Created by mrxenginner on 11/05/2025.
|
||||
//
|
||||
|
||||
#if defined ANDROID
|
||||
|
||||
#include "SignalHandler.h"
|
||||
#include "../logger/log.h"
|
||||
#include "StackTrace.h"
|
||||
|
||||
#include <csignal>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
extern int16 g_usLastProcessedModelIndexAutomobile;
|
||||
extern int g_iLastProcessedModelIndexAutoEnt;
|
||||
|
||||
extern int g_iLastProcessedSkinCollision;
|
||||
extern int g_iLastProcessedEntityCollision;
|
||||
extern char lastFile[123];
|
||||
extern int g_iLastRenderedObject;
|
||||
extern int lastNvEvent;
|
||||
extern CVector lastPos;
|
||||
char g_iLastBlock[123];
|
||||
char streamimgState[255];
|
||||
|
||||
namespace CrashHandler {
|
||||
static struct sigaction oldHandlers[4]; // 0: SEGV, 1: ABRT, 2: FPE, 3: BUS
|
||||
|
||||
void PrintBuildCrashInfo()
|
||||
{
|
||||
time_t currentTime = time(nullptr);
|
||||
tm* timeInfo = localtime(¤tTime);
|
||||
|
||||
Logger::CrashLog("Crash time: %d:%d:%d %d:%d:%d", timeInfo->tm_mday, timeInfo->tm_mon, timeInfo->tm_year, timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec);
|
||||
Logger::CrashLog("Build times: %s %s. ABI: %s", __TIME__, __DATE__, (ANDROID_x32 ? "armeabi-v7a" : "arm64-v8a"));
|
||||
Logger::CrashLog("Last processed auto and entity: %d %d", g_usLastProcessedModelIndexAutomobile, g_iLastProcessedModelIndexAutoEnt);
|
||||
Logger::CrashLog("Last rendered object: %d", g_iLastRenderedObject);
|
||||
}
|
||||
|
||||
void SignalHandler(int signum, siginfo_t* info, void* contextPtr) {
|
||||
auto* context = static_cast<ucontext_t*>(contextPtr);
|
||||
|
||||
struct sigaction* oldHandler = nullptr;
|
||||
const char* signalName = nullptr;
|
||||
|
||||
switch (signum) {
|
||||
case SIGSEGV:
|
||||
oldHandler = &oldHandlers[0];
|
||||
signalName = "SIGSEGV";
|
||||
Logger::CrashLog(" ");
|
||||
break;
|
||||
case SIGABRT:
|
||||
oldHandler = &oldHandlers[1];
|
||||
signalName = "SIGABRT";
|
||||
Logger::CrashLog(" ");
|
||||
break;
|
||||
case SIGFPE:
|
||||
oldHandler = &oldHandlers[2];
|
||||
signalName = "SIGFPE";
|
||||
break;
|
||||
case SIGBUS:
|
||||
oldHandler = &oldHandlers[3];
|
||||
signalName = "SIGBUS";
|
||||
break;
|
||||
default:
|
||||
Logger::CrashLog("Unhandled signal: %d", signum);
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldHandler && oldHandler->sa_sigaction) {
|
||||
oldHandler->sa_sigaction(signum, info, contextPtr);
|
||||
}
|
||||
|
||||
PrintBuildCrashInfo();
|
||||
Logger::CrashLog("%s | Fault address: 0x%X", signalName, info->si_addr);
|
||||
PRINT_CRASH_STATES(context);
|
||||
CStackTrace::printBacktrace();
|
||||
}
|
||||
|
||||
void SetupSignalHandlers() {
|
||||
struct {
|
||||
int signal;
|
||||
int index;
|
||||
} signals[] = {
|
||||
{ SIGSEGV, 0 },
|
||||
{ SIGABRT, 1 },
|
||||
{ SIGFPE, 2 },
|
||||
{ SIGBUS, 3 },
|
||||
};
|
||||
|
||||
for (const auto& s : signals) {
|
||||
struct sigaction act {};
|
||||
act.sa_sigaction = SignalHandler;
|
||||
sigemptyset(&act.sa_mask);
|
||||
act.sa_flags = SA_SIGINFO;
|
||||
sigaction(s.signal, &act, &oldHandlers[s.index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// Created by mrxenginner on 11/05/2025.
|
||||
//
|
||||
|
||||
#ifndef REVC_SIGNALHANDLER_H
|
||||
#define REVC_SIGNALHANDLER_H
|
||||
|
||||
#if defined ANDROID
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace CrashHandler {
|
||||
void SetupSignalHandlers();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //REVC_SIGNALHANDLER_H
|
||||
@@ -0,0 +1,67 @@
|
||||
//
|
||||
// Created by mrxenginner on 13/07/2025.
|
||||
//
|
||||
|
||||
#ifndef REVC_STACKTRACE_H
|
||||
#define REVC_STACKTRACE_H
|
||||
|
||||
#if defined ANDROID
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <execinfo.h>
|
||||
#include <unwind.h>
|
||||
|
||||
extern uintptr_t g_libREVC;
|
||||
|
||||
#if ANDROID_x32
|
||||
#define PRINT_CRASH_STATES(context) \
|
||||
Logger::CrashLog("register states:"); \
|
||||
Logger::CrashLog("r0: 0x%X, r1: 0x%X, r2: 0x%X, r3: 0x%X", (context)->uc_mcontext.arm_r0, (context)->uc_mcontext.arm_r1, (context)->uc_mcontext.arm_r2, (context)->uc_mcontext.arm_r3); \
|
||||
Logger::CrashLog("r4: 0x%x, r5: 0x%x, r6: 0x%x, r7: 0x%x", (context)->uc_mcontext.arm_r4, (context)->uc_mcontext.arm_r5, (context)->uc_mcontext.arm_r6, (context)->uc_mcontext.arm_r7); \
|
||||
Logger::CrashLog("r8: 0x%x, r9: 0x%x, sl: 0x%x, fp: 0x%x", (context)->uc_mcontext.arm_r8, (context)->uc_mcontext.arm_r9, (context)->uc_mcontext.arm_r10, (context)->uc_mcontext.arm_fp); \
|
||||
Logger::CrashLog("ip: 0x%x, sp: 0x%x, lr: 0x%x, pc: 0x%x", (context)->uc_mcontext.arm_ip, (context)->uc_mcontext.arm_sp, (context)->uc_mcontext.arm_lr, (context)->uc_mcontext.arm_pc); \
|
||||
Logger::CrashLog("1: libreVC.so + 0x%X", context->uc_mcontext.arm_pc - g_libREVC); \
|
||||
Logger::CrashLog("2: libreVC.so + 0x%X", context->uc_mcontext.arm_lr - g_libREVC);
|
||||
#else
|
||||
#define PRINT_CRASH_STATES(context) \
|
||||
Logger::CrashLog("1: libreVC.so + 0x%llx", context->uc_mcontext.pc - g_libREVC); \
|
||||
Logger::CrashLog("2: libreVC.so + 0x%llx", context->uc_mcontext.regs[30] - g_libREVC);
|
||||
#endif
|
||||
|
||||
class CStackTrace
|
||||
{
|
||||
public:
|
||||
static void printBacktrace()
|
||||
{
|
||||
Logger::CrashLog("------------ START BACKTRACE ------------");
|
||||
Logger::CrashLog(" ");
|
||||
PrintStackTrace();
|
||||
}
|
||||
|
||||
private:
|
||||
static _Unwind_Reason_Code TraceFunction(_Unwind_Context* context, void* arg) {
|
||||
uintptr_t pc = _Unwind_GetIP(context);
|
||||
|
||||
Dl_info info;
|
||||
if (dladdr(reinterpret_cast<void*>(pc), &info) && info.dli_sname != nullptr) {
|
||||
Logger::CrashLog("[adr: %p reVC: %p] %s\n",
|
||||
reinterpret_cast<void*>(pc),
|
||||
reinterpret_cast<void*>(pc - g_libREVC),
|
||||
info.dli_sname);
|
||||
} else {
|
||||
Logger::CrashLog("[adr: %p reVC: %p] name not found\n",
|
||||
reinterpret_cast<void*>(pc),
|
||||
reinterpret_cast<void*>(pc - g_libREVC));
|
||||
}
|
||||
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
|
||||
static void PrintStackTrace() {
|
||||
_Unwind_Backtrace(TraceFunction, nullptr);
|
||||
}
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "common.h"
|
||||
#include "crossplatform.h"
|
||||
#include "FileMgr.h"
|
||||
|
||||
// Codes compatible with Windows and Linux
|
||||
#ifndef _WIN32
|
||||
@@ -91,7 +92,11 @@ void GetDateFormat(int unused1, int unused2, SYSTEMTIME* in, int unused3, char*
|
||||
linuxTime.tm_hour = in->wHour;
|
||||
linuxTime.tm_min = in->wMinute;
|
||||
linuxTime.tm_sec = in->wSecond;
|
||||
strftime(out, size, nl_langinfo(D_FMT), &linuxTime);
|
||||
#if defined ANDROID
|
||||
strftime(out, size, "%Y-%m-%d", &linuxTime);
|
||||
#else
|
||||
strftime(out, size, nl_langinfo(D_FMT), &linuxTime);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FileTimeToSystemTime(time_t* writeTime, SYSTEMTIME* out) {
|
||||
@@ -212,6 +217,20 @@ char* casepath(char const* path, bool checkPathFirst)
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if defined(ANDROID) // TODO: Android is fuck!!!
|
||||
char cwd[MAX_PATH];
|
||||
getcwd(cwd, sizeof(cwd));
|
||||
|
||||
char* pos = strstr(p, CFileMgr::GetRootDirName());
|
||||
if (pos != NULL) {
|
||||
pos += strlen(CFileMgr::GetRootDirName());
|
||||
p = pos;
|
||||
}
|
||||
d = opendir(cwd);
|
||||
out[0] = '.';
|
||||
out[1] = 0;
|
||||
rl = 1;
|
||||
#else
|
||||
if (p[0] == '/' || p[0] == '\\')
|
||||
{
|
||||
d = opendir("/");
|
||||
@@ -223,6 +242,7 @@ char* casepath(char const* path, bool checkPathFirst)
|
||||
out[1] = 0;
|
||||
rl = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool cantProceed = false; // just convert slashes in what's left in string, don't correct case of letters(because we can't)
|
||||
bool mayBeTrailingSlash = false;
|
||||
@@ -273,7 +293,7 @@ char* casepath(char const* path, bool checkPathFirst)
|
||||
|
||||
if (!e)
|
||||
{
|
||||
printf("casepath couldn't find dir/file \"%s\", full path was %s\n", c, path);
|
||||
debug("casepath couldn't find dir/file \"%s\", full path was %s\n", c, path);
|
||||
// No match, add original name and continue converting further slashes.
|
||||
strcpy(out + rl, c);
|
||||
rl += strlen(c);
|
||||
@@ -288,7 +308,7 @@ char* casepath(char const* path, bool checkPathFirst)
|
||||
}
|
||||
|
||||
if (rl > l + 2) {
|
||||
printf("\n\ncasepath: Corrected path length is longer then original+2:\n\tOriginal: %s (%zu chars)\n\tCorrected: %s (%zu chars)\n\n", path, l, out, rl);
|
||||
debug("\n\ncasepath: Corrected path length is longer then original+2:\n\tOriginal: %s (%zu chars)\n\tCorrected: %s (%zu chars)\n\n", path, l, out, rl);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef LIBRW_SDL2
|
||||
#include <SDL.h>
|
||||
#endif
|
||||
|
||||
// This is the common include for platform/renderer specific skeletons(glfw.cpp, win.cpp etc.) and using cross platform things (like Windows directories wrapper, platform specific global arrays etc.)
|
||||
// Functions that's different on glfw and win but have same signature, should be located on platform.h.
|
||||
|
||||
@@ -62,16 +66,20 @@ int _caserename(const char *old_filename, const char *new_filename);
|
||||
#define caserename _caserename
|
||||
#endif
|
||||
|
||||
#ifdef RW_GL3
|
||||
#if defined(RW_GL3)
|
||||
typedef struct
|
||||
{
|
||||
#if defined(LIBRW_SDL2)
|
||||
SDL_Window* window;
|
||||
#else
|
||||
GLFWwindow* window;
|
||||
#endif
|
||||
RwBool fullScreen;
|
||||
RwV2d lastMousePos;
|
||||
double mouseWheel; // glfw doesn't cache it
|
||||
bool cursorIsInWindow;
|
||||
RwInt8 joy1id;
|
||||
RwInt8 joy2id;
|
||||
RwInt8 joy1id;
|
||||
RwInt8 joy2id;
|
||||
}
|
||||
psGlobalType;
|
||||
|
||||
@@ -166,6 +174,7 @@ void GetDateFormat(int, int, SYSTEMTIME*, int, char*, int);
|
||||
|
||||
#ifdef __SWITCH__
|
||||
|
||||
#ifndef LIBRW_SDL2
|
||||
// tweak glfw values for switch to match expected pc bindings
|
||||
#ifdef GLFW_GAMEPAD_BUTTON_A
|
||||
#undef GLFW_GAMEPAD_BUTTON_A
|
||||
@@ -186,6 +195,7 @@ void GetDateFormat(int, int, SYSTEMTIME*, int, char*, int);
|
||||
#undef GLFW_GAMEPAD_BUTTON_Y
|
||||
#endif
|
||||
#define GLFW_GAMEPAD_BUTTON_Y 2
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -774,7 +774,7 @@ HandlePadButtonUp(RsPadButtonStatus *padButtonStatus)
|
||||
|
||||
ControlsManager.UpdateJoyButtonState(padNumber);
|
||||
|
||||
for ( int32 i = 1; i < _TODOCONST(16); i++ )
|
||||
for ( int32 i = 0; i < _TODOCONST(16); i++ ) // 1 > 0 TODO: Fixed a button handling for-loop?
|
||||
{
|
||||
RsPadButtons btn = rsPADNULL;
|
||||
if ( ControlsManager.m_aButtonStates[i] == FALSE )
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -54,6 +54,11 @@
|
||||
|
||||
bool bAllCarCheat;
|
||||
|
||||
#if defined ANDROID
|
||||
int16 g_usLastProcessedModelIndexAutomobile = 0;
|
||||
int g_iLastProcessedModelIndexAutoEnt = 0;
|
||||
#endif
|
||||
|
||||
RwObject *GetCurrentAtomicObjectCB(RwObject *object, void *data);
|
||||
|
||||
bool CAutomobile::m_sAllTaxiLights;
|
||||
@@ -3024,7 +3029,10 @@ CAutomobile::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints)
|
||||
{
|
||||
int i;
|
||||
CColModel *colModel;
|
||||
|
||||
#if defined ANDROID
|
||||
g_usLastProcessedModelIndexAutomobile = ent->GetModelIndex();
|
||||
g_iLastProcessedModelIndexAutoEnt = ent->GetModelIndex();
|
||||
#endif
|
||||
if(GetStatus() != STATUS_SIMPLE)
|
||||
bVehicleColProcessed = true;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user