Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
# Android / Gradle
.gradle/
android/launcher/app/build/
android/launcher/app/jniLibs/
android/launcher/build/
android/launcher/.cxx/
android/launcher/local.properties
*.apk
*.aab
*.jks

# IDE
.idea/
*.iml
.vscode/

# CLAUDE.md is intentionally tracked

## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
Expand Down
149 changes: 149 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project

reVC is a fully reverse-engineered Grand Theft Auto: Vice City (`miami` branch). It builds and runs on Windows, Linux, macOS, FreeBSD, and Android on x86, amd64, arm, and arm64.

## Build Commands

### Linux (Conan + CMake — recommended)
```
conan export vendor/librw librw/master@
mkdir build && cd build
conan install .. reVC/miami@ -if build -o reVC:audio=openal -o librw:platform=gl3 -o librw:gl3_gfxlib=glfw --build missing -s reVC:build_type=RelWithDebInfo -s librw:build_type=RelWithDebInfo
conan build .. -if build -bf build -pf package
```

### Linux (Premake)
```sh
./premake5Linux --with-librw gmake2
cd build && make config=release_x86_64
```

### Windows (Premake + Visual Studio)
```bat
premake-vs2022.cmd
:: Open build/reVC.sln in Visual Studio, build reVC project
```

### macOS (Premake)
```sh
./premake5Linux --with-librw --os=macosx gmake2
cd build && make config=release_x86_64
```

### Build options
- `--with-librw` — build librw alongside reVC (vs. using system/external)
- `--with-lto` — enable Link Time Optimization
- `--with-asan` — enable Address Sanitizer
- `--with-opus` — enable Opus audio codec support
- `--no-git-hash` / `--no-full-paths` — reproducible build options

### CMake options
```
-DREVC_AUDIO=OAL|MSS # audio backend (default OAL)
-DREVC_WITH_OPUS=ON|OFF # Opus support
-DREVC_WITH_SANITIZERS=ON # UBSan
-DREVC_WITH_ASAN=ON # ASan
```

## Architecture

reVC is a single monolithic executable. All game code lives under `src/`, organized by subsystem:

| Directory | Purpose |
|-----------|---------|
| `src/core/` | Core loop, world manager, streaming, pools, frontend, zones, config |
| `src/renderer/` | Rendering: HUD, coronas, particles, shadows, weather, timecycle |
| `src/collision/` | Collision detection and response |
| `src/entities/` | Entity base classes and managers |
| `src/peds/` | Pedestrian AI, animation blending, player control |
| `src/vehicles/` | Vehicle physics, heli, boat, car control |
| `src/weapons/` | Weapon types, bullet traces, explosions |
| `src/objects/` | Dynamic world objects |
| `src/buildings/` | Static building rendering and LOD |
| `src/animation/` | Animation system (AnimBlend) |
| `src/audio/` | Audio system with backends in `audio/oal/` (OpenAL), `audio/eax/` |
| `src/control/` | Gamepad, controller config |
| `src/math/` | Vector, matrix, quaternion math |
| `src/modelinfo/` | Model type information registry |
| `src/save/` | Save/load game state |
| `src/text/` | GXT text system |
| `src/rw/` | RenderWare helper/utility code |

### Platform abstraction (`src/skel/`)

The platform layer follows the RenderWare skeleton pattern. Entry point is `main.cpp` → `WinMain`/`main` → `Game::InitialiseOnceAfterRW()`.

- **`skeleton.h`** — public API (events, input, timer, camera). All platform backends implement this interface.
- **`platform.h`** — platform-specific function declarations (`psInitialize`, `psTimer`, etc.).
- **`glfw/glfw.cpp`** — primary cross-platform backend (Windows OpenGL, Linux, macOS, BSD)
- **`sdl2/sdl2.cpp`** — SDL2 backend used on Android (`LIBRW_SDL2` define)
- **`android/`** — Android-specific JNI bridge (`AndroidMain.cpp`, `JavaWrapper`)
- **`win/`** — Windows-specific D3D8/D3D9 backend (`RWLIBS` or `USE_D3D9`)
- **`crossplatform.cpp/.h`** — filesystem path utilities, locale/language detection, `casepath`

### RenderWare abstraction (`src/fakerw/`)

When building with librw (`LIBRW` define), stub headers in `fakerw/` redirect RenderWare API calls through librw. When building with original RW (`RWLIBS`), the real RenderWare SDK headers are used directly.

### Rendering backends (preprocessor-controlled)

- `RWLIBS` — original RenderWare D3D8 (Windows only)
- `LIBRW` + `RW_D3D9` — librw with Direct3D 9 (Windows only)
- `LIBRW` + `RW_GL3` — librw with OpenGL 3.x via GLFW or SDL2 (all platforms)

### Audio backends

- `AUDIO_MSS` — Miles Sound System (Windows, requires original MSS DLLs)
- `AUDIO_OAL` — OpenAL (cross-platform, default)

### Key configuration

`src/core/config.h` defines all pool sizes, entity limits, and compile-time options. Feature toggles and bugfix guards (e.g., `FIX_BUGS`) are also here. Runtime settings live in `reVC.ini` (not the original `gta_vc.set`).

## Coding Conventions

- **C++ standard**: C++11 maximum — do not use C++14 or later features
- **Types**: Always use project typedefs (`int8`, `uint8`, `int16`, `uint16`, `int32`, `uint32`, `bool`). Never use `unsigned` bare, `char` for non-characters, or Win32 types (`BYTE`, `DWORD`) outside platform-specific code.
- **Pointers**: `int *ptr;` style (asterisk attached to variable, not type)
- **Indentation**: TABS only
- **Brace style**: K&R-ish — brace on next line for functions/structs, same line for control flow. No braces for single-statement bodies. `else` on same line with closing brace.
- **Variable naming**: Hungarian-notation influenced — `f` prefix for float, `i`/`n` for integer, `b` for boolean, `m_` for private members, `ms_` for private static members.
- **Magic numbers**: Avoid. Use enums even when the exact meaning is unknown (`FOOBAR_TYPE_4` over `4`).

## PR Guidelines

Accepted contributions:
- Features that existed in at least one original GTA version
- Bug fixes (behind `FIX_BUGS` preprocessor guard if fixing original behavior)
- Un-reversed platform-specific or unused code
- Making reversed code more accurate (matching original assembly)
- Cross-platform skeleton/compatibility layer improvements
- Translation fixes for original languages

No custom/gameplay features unless guarded by preprocessor conditions, and no mod-like additions.

## Android Port (`android-port` branch)

### Build
```sh
cd android/launcher && ./gradlew assembleDebug
```
Requires NDK 30+, SDK 35+. Prebuilt `.so` files (SDL2, OpenAL, mpg123) are in `vendor/` — run `android/setup_libs.sh` to copy to `jniLibs/`.

### First-launch flow
1. SAF folder picker → user selects GTA VC directory
2. Files validated (`models/gta3.img` must exist)
3. Background copy to `getExternalFilesDir()` via `DocumentsContract` (app-owned files)
4. Game loads from app-private storage — no permissions needed
5. Subsequent launches skip picker

### Key changes from upstream
- `FileMgr.cpp` — `\` → `/` conversion (Windows paths)
- `sdl2.cpp` — SDL hints, `STORAGE_ROOT` via `SDL_AndroidGetExternalStoragePath`
- `crossplatform.cpp` — `casepath` does `opendir`/`readdir`; works because FUSE is case-insensitive
- `AndroidManifest.xml` — `extractNativeLibs=true` (SDL2 needs filesystem .so), landscape, gamepad-only
- `CdStream_posix.cpp` — Android uses `statfs` not `statvfs`, pthread mutex instead of semaphore
52 changes: 44 additions & 8 deletions android/launcher/app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@
#
# Description:
# This file defines the root CMake configuration for the reVC – Mobile Edition,
# targeting the Android platform via the Android NDK. It initializes the build system
# for the mobile game, integrates shared cross-platform sources, configures compiler settings,
# and handles dependency resolution.
# targeting the Android platform via the Android NDK. It sets up prebuilt libraries
# (SDL2, OpenAL, mpg123) and then includes the main game CMake build.
# ==================================================================================================

cmake_minimum_required(VERSION 3.22.1 FATAL_ERROR)

message(" ")
message("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
message("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
message(" * 🌐 reVC – Build Configuration Initialized")
message(" * 🔧 Preparing Android platform modules and environment configuration...")
message("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
message("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
message(" ")

# ────────────────────────────────────────────────────────────────────────────────
Expand All @@ -38,17 +37,54 @@ get_filename_component(REVC_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE)
set(REVC_GAME_DIR "${REVC_ROOT_DIR}/../../../")
message(" * 📂 Game source directory set to: ${REVC_GAME_DIR}")

# ────────────────────────────────────────────────────────────────────────────────
# 📦 Prebuilt Native Libraries for Android
# ────────────────────────────────────────────────────────────────────────────────

# SDL2
add_library(SDL2::SDL2 SHARED IMPORTED)
set_target_properties(SDL2::SDL2 PROPERTIES
IMPORTED_LOCATION "${REVC_GAME_DIR}/vendor/sdl2/libs/Android/${ANDROID_ABI}/libSDL2.so"
INTERFACE_INCLUDE_DIRECTORIES "${REVC_GAME_DIR}/vendor/sdl2/include"
)
message(" * 📦 SDL2 prebuilt: ${ANDROID_ABI}")

# OpenAL
add_library(OpenAL::OpenAL SHARED IMPORTED)
set_target_properties(OpenAL::OpenAL PROPERTIES
IMPORTED_LOCATION "${REVC_GAME_DIR}/vendor/openal-soft/libs/Android/${ANDROID_ABI}/libopenal.so"
INTERFACE_INCLUDE_DIRECTORIES "${REVC_GAME_DIR}/vendor/openal-soft/include"
)
message(" * 📦 OpenAL prebuilt: ${ANDROID_ABI}")

# mpg123
add_library(MPG123::libmpg123 SHARED IMPORTED)
set_target_properties(MPG123::libmpg123 PROPERTIES
IMPORTED_LOCATION "${REVC_GAME_DIR}/vendor/mpg123/lib/Android/${ANDROID_ABI}/libmpg123.so"
INTERFACE_INCLUDE_DIRECTORIES "${REVC_GAME_DIR}/vendor/mpg123/include"
)
message(" * 📦 mpg123 prebuilt: ${ANDROID_ABI}")

# ────────────────────────────────────────────────────────────────────────────────
# ➕ Add Game Subdirectory If Available
# ────────────────────────────────────────────────────────────────────────────────
if(IS_DIRECTORY "${REVC_GAME_DIR}" AND EXISTS "${REVC_GAME_DIR}/CMakeLists.txt")
message(" * ➕ Including Game module from: ${REVC_GAME_DIR}")
message(" ")
message("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
message("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
message(" * 🚀 Initiating Game module build configuration...")
message("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
message("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
message(" ")
#add_subdirectory(${REVC_GAME_DIR} ${CMAKE_BINARY_DIR}/game_build)

set(REVC_AUDIO "OAL" CACHE STRING "Audio" FORCE)
set(REVC_VENDORED_LIBRW ON CACHE BOOL "Use vendored librw" FORCE)
set(REVC_INSTALL OFF CACHE BOOL "Install" FORCE)

add_subdirectory(${REVC_GAME_DIR} ${CMAKE_BINARY_DIR}/game_build)

# Force lowercase output name — System.loadLibrary("revc") looks for librevc.so
set_target_properties(reVC PROPERTIES LIBRARY_OUTPUT_NAME revc)

else()
message(" * ⚠️ Game source directory or CMakeLists.txt not found at: ${REVC_GAME_DIR}")
message(FATAL_ERROR " * ❗ Please ensure the game module sources are available for the build.")
Expand Down
8 changes: 3 additions & 5 deletions android/launcher/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ android {

defaultConfig {
applicationId "com.revc.game"
minSdk 24
minSdk 26
targetSdk 35
versionCode 1
versionName "reVC-0.0.1"

ndkVersion '27.2.12479018'
ndkVersion '30.0.15729638'

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

ndk {
abiFilters "armeabi-v7a"/*, "arm64-v8a"*/
abiFilters "armeabi-v7a", "arm64-v8a"
}
}

Expand All @@ -37,7 +37,6 @@ android {
minifyEnabled true
shrinkResources true
jniDebuggable false
renderscriptDebuggable false

proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
Expand All @@ -54,7 +53,6 @@ android {
debuggable true
minifyEnabled false
jniDebuggable true
renderscriptDebuggable true
}
}

Expand Down
29 changes: 14 additions & 15 deletions android/launcher/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,22 @@
android:glEsVersion="0x00020000"
android:required="true"/>

<!-- Touchscreen support -->
<!-- Game controller support. Not required: a required gamepad feature
hides the app in the Android/Google TV launcher when no pad is paired. -->
<uses-feature
android:name="android.hardware.touchscreen"
android:name="android.hardware.gamepad"
android:required="false" />

<!-- Game controller support -->
<!-- No touchscreen and Leanback support so the app installs/shows on TV -->
<uses-feature
android:name="android.hardware.bluetooth"
android:name="android.hardware.touchscreen"
android:required="false" />
<uses-feature
android:name="android.hardware.gamepad"
android:name="android.software.leanback"
android:required="false" />

<uses-feature
android:name="android.hardware.bluetooth"
android:required="false" />
<uses-feature
android:name="android.hardware.usb.host"
Expand All @@ -65,6 +70,7 @@
android:smallScreens="true" />

<application
android:extractNativeLibs="true"
android:gwpAsanMode="always"
android:isGame="true"
android:appCategory="game"
Expand All @@ -73,6 +79,7 @@
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:banner="@drawable/banner"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
Expand All @@ -81,18 +88,9 @@
android:theme="@style/Theme.ReVC"
tools:targetApi="31">

<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<activity
android:name="org.libsdl.app.SDLActivity"
android:screenOrientation="sensorLandscape"
android:alwaysRetainTaskState="true"
android:launchMode="singleInstance"
android:hardwareAccelerated="true"
Expand All @@ -104,6 +102,7 @@
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
</activity>

Expand Down
36 changes: 0 additions & 36 deletions android/launcher/app/src/main/java/com/revc/game/MainActivity.java

This file was deleted.

Loading