Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
01b7810
added Crosshair Edge Boundary Box
AL2009man Jun 28, 2025
09df313
remove gyro leftover text
AL2009man Jun 28, 2025
498e166
Merge pull request #631 from AL2009man/CrosshairFix
fgsfdsfgs Aug 23, 2025
bb4fcff
port: fix #650
fgsfdsfgs Aug 25, 2025
6dd3ec7
Temporarily disables RawInput driver
AL2009man Oct 8, 2025
8ea7e7b
Merge pull request #661 from AL2009man/RawInputFix
fgsfdsfgs Oct 8, 2025
857e755
added flag to ignore line-of-sight hits for transparent background su…
joshuarwood Nov 7, 2025
7a728c7
Removing commit that was intended for a different branch
joshuarwood Nov 7, 2025
550f1d3
add flag to ignore line-of-sight hits for transparent background surf…
joshuarwood Nov 7, 2025
f5cbfe6
disable xlu surface hits with a global to avoid initialization errors…
joshuarwood Nov 8, 2025
42ef08d
check surfacetype to better skip glass props
joshuarwood Nov 8, 2025
77dc12e
fix link to fast
Project516 Nov 8, 2025
b53a621
protect against surface indexing errors
joshuarwood Nov 9, 2025
e1dd49f
Merge pull request #669 from joshuarwood/light_fix_for_xlu_prop
fgsfdsfgs Nov 9, 2025
0896860
Merge pull request #670 from Project516/patch-1
fgsfdsfgs Nov 9, 2025
7971136
Merge pull request #668 from joshuarwood/light_fix_for_bg_glass
fgsfdsfgs Nov 9, 2025
f3f2a59
exclude laser doors from los test
joshuarwood Nov 22, 2025
7f68c46
Merge pull request #671 from joshuarwood/light_fix_for_laser
fgsfdsfgs Nov 23, 2025
6b0c4a1
Limit 'Start Armed' option to Combat Simulator
ZenithMDC Dec 4, 2025
c303c81
gfx: mipmaps and anisotropic filtering
Dec 4, 2025
2d390ae
small code simplification
Dec 4, 2025
4bcfedd
Merge pull request #674 from ZenithMDC/limit-start-armed-to-csim
fgsfdsfgs Dec 4, 2025
2d0375d
fixed Crosshair Swivel conflicting when using Mixed Input
AL2009man Dec 4, 2025
8165b50
Merge pull request #677 from AL2009man/CrosshairSwivelFix
fgsfdsfgs Dec 5, 2025
75d1b8f
Prevent Combat Simulator 'Load Settings' clobber
ZenithMDC Dec 7, 2025
a6374b0
Merge pull request #679 from ZenithMDC/fix-cs-load-settings-clobber
fgsfdsfgs Dec 7, 2025
0df84ff
fix homeDir check
qubitnano Dec 20, 2025
4ee8f3c
Corrected Xbox Pad page on `README.md`
AL2009man Dec 20, 2025
50481b7
Merge pull request #683 from qubitnano/bcachefs
fgsfdsfgs Dec 20, 2025
2550ce7
Merge pull request #684 from AL2009man/XboxREADMEFix
fgsfdsfgs Dec 20, 2025
0c82545
Preserve Combat Simulator sim list after Co-Op/Counter-Op
ZenithMDC Dec 7, 2025
2028ae7
changes default PC's Menu bindings to reflect Modern games' Menu UI d…
AL2009man Jan 4, 2026
6e6ffad
Merge pull request #687 from AL2009man/KB/M-Confirm-Cancel
fgsfdsfgs Jan 4, 2026
425b51e
input: fix build with SDL<2.0.16
fgsfdsfgs Jan 7, 2026
246d737
Merge pull request #680 from ZenithMDC/preserve-cs-sim-list
fgsfdsfgs Jan 7, 2026
bcb8c27
Improve scissor operations for upstream.
Jan 29, 2026
55ca51d
Have HUD acknowledge new weapons gifted from NPCs
Jan 30, 2026
cc38868
Suppress gadget notifications in cutscenes
Feb 12, 2026
426f9c6
Fix issue for some cheats across build optimizations
Feb 11, 2026
23aafa4
use texturenum -1 for chr hits because cheap version of chrTestHit re…
joshuarwood Mar 12, 2026
0946cd1
disable bbox padding when performing light los test to prevent shield…
joshuarwood Mar 13, 2026
d4ac8b1
Merge pull request #705 from joshuarwood/fix_chr_light_regression
fgsfdsfgs Mar 13, 2026
fc70da8
add a comment describing PC specific shield handling
joshuarwood Mar 13, 2026
d58a423
Merge pull request #706 from joshuarwood/shield_light_fix
fgsfdsfgs Mar 14, 2026
ccb3c86
fixup keyboard input + vi insert shortcut
cylonicboom Mar 14, 2026
11df50b
Merge pull request #707 from cylonicboom/port
fgsfdsfgs Mar 14, 2026
2626434
Merge pull request #701 from TartanSpartan/fix-cheats-across-optimiza…
fgsfdsfgs Mar 23, 2026
27b2dcc
Merge pull request #700 from TartanSpartan/acknowledge-npc-gifts
fgsfdsfgs Mar 23, 2026
8470d50
Merge pull request #697 from TartanSpartan/fix-scissor-viewport
fgsfdsfgs Mar 23, 2026
7c949ed
Merge pull request #675 from rafccq/port-tex-mips-aniso
fgsfdsfgs Mar 23, 2026
e457aad
Merge remote-tracking branch 'upstream/port' into touch-controls
mgrz18 Apr 22, 2026
e0d5996
Add touch controls with editable on-screen layout
Apr 22, 2026
38af41b
Apply touch pad even when no physical controller is connected
Apr 22, 2026
9f9aa66
ci: make gradlew executable before running
Apr 22, 2026
fc41ab1
fix: include os_thread.h before os_cont.h in touch module
Apr 22, 2026
e0c0d74
gitignore: exclude android build artifacts and local.properties
Apr 22, 2026
7ee540a
Add live-edit mode and CoD-style drag-to-look pad
Apr 22, 2026
d73fd8d
Add MOVE_PAD: CoD-style floating-stick zone for movement
Apr 22, 2026
312a576
Look pad: feed mouse delta instead of right stick velocity
Apr 22, 2026
4d9cde7
Swap default sides and add look-sens slider to edit HUD
Apr 22, 2026
b4962f5
Route MOVE_PAD to rstick so it actually moves the player
Apr 22, 2026
c9125aa
Per-axis look sensitivity, larger range, no center overlap
Apr 22, 2026
7409170
Collapsible edit HUD, full-half pads, centered pad labels
Apr 22, 2026
734c770
Per-button resize bar, invisible non-editable pads
Apr 22, 2026
d19f246
Draw vector icons on buttons instead of text labels
Apr 22, 2026
0c81ad8
Fix SIGBUS on ARM 32bit when starting level 3
emileb Mar 17, 2026
f1117c8
Vertical camera angle wrapping fix
AL2009man Feb 1, 2026
b50166a
UI Accept/Cancel Swap support
AL2009man Jan 20, 2026
d08e375
added Camera/Crosshair Recenter action
AL2009man Dec 8, 2025
da43ef4
Separated Crosshair Sens from Camera Sens
AL2009man Dec 4, 2025
48b3aaf
"Crosshair Speed" is renamed to "Mouse Crosshair Speed"
AL2009man Dec 20, 2025
7747c4e
rename `mouseaimsensy` back to `mouseaimspeedx`, for consistency reasons
AL2009man Dec 24, 2025
71e6011
fix(android): include data.h before SDL.h in input.c
Apr 22, 2026
a29c087
Auto-launch into the game when ROM is already present
Apr 22, 2026
6936342
Configurable idle-fade for the touch overlay
Apr 23, 2026
4ce5378
tune idle fade: 7 s delay, full disappearance
Apr 23, 2026
ac7e71f
docs: rewrite README for the Android touch port
Apr 23, 2026
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
47 changes: 47 additions & 0 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Android APK

on:
push:
branches: [port, touch-controls]
pull_request:
branches: [port]
workflow_dispatch:

jobs:
build-android:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '17'

- name: Set up Android SDK
uses: android-actions/setup-android@v3

- name: Install NDK and CMake
run: |
yes | sdkmanager --install "ndk;26.1.10909125" "cmake;3.22.1"
echo "ANDROID_NDK_HOME=$ANDROID_HOME/ndk/26.1.10909125" >> $GITHUB_ENV

- name: Install python deps for the asset preprocessor
run: sudo apt-get update && sudo apt-get install -y python3

- name: Build debug APK
working-directory: android
run: |
chmod +x ./gradlew
./gradlew :app:assembleDebug --no-daemon --stacktrace

- name: Upload debug APK
uses: actions/upload-artifact@v4
with:
name: pd-android-debug
path: android/app/build/outputs/apk/debug/*.apk
if-no-files-found: error
312 changes: 102 additions & 210 deletions README.md

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions android/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
*.iml
.gradle
/local.properties
/.idea
.DS_Store
/build
/app/build
/app/.cxx
/captures
.externalNativeBuild
.cxx
Binary file added android/.gradle/8.0/checksums/checksums.lock
Binary file not shown.
Binary file not shown.
Binary file added android/.gradle/8.0/checksums/sha1-checksums.bin
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
Binary file not shown.
Binary file added android/.gradle/8.0/fileChanges/last-build.bin
Binary file not shown.
Binary file added android/.gradle/8.0/fileHashes/fileHashes.bin
Binary file not shown.
Binary file added android/.gradle/8.0/fileHashes/fileHashes.lock
Binary file not shown.
Binary file not shown.
Empty file.
Binary file not shown.
2 changes: 2 additions & 0 deletions android/.gradle/buildOutputCleanup/cache.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#Wed Apr 22 14:01:37 CST 2026
gradle.version=8.0
Binary file not shown.
Binary file added android/.gradle/file-system.probe
Binary file not shown.
Empty file.
8 changes: 8 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@
android:screenOrientation="landscape"
android:configChanges="layoutDirection|locale|orientation|uiMode|screenLayout|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"
android:theme="@style/Theme.PerfectDark.Fullscreen"/>

<!-- LayoutEditorActivity: fullscreen touch-pad layout editor -->
<activity
android:name=".LayoutEditorActivity"
android:exported="false"
android:screenOrientation="landscape"
android:configChanges="layoutDirection|locale|orientation|uiMode|screenLayout|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"
android:theme="@style/Theme.PerfectDark.Fullscreen"/>
</application>

</manifest>
70 changes: 0 additions & 70 deletions android/app/src/main/java/com/perfectdark/port/GameView.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ public class LauncherActivity extends AppCompatActivity {

private View missingRomView;
private TextView infoText;
private Button playButton;
private Button pickRomButton;
private Button editTouchButton;

private final ActivityResultLauncher<String[]> romPicker =
registerForActivityResult(new ActivityResultContracts.OpenDocument(), this::onRomPicked);
Expand All @@ -48,24 +50,54 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {

missingRomView = findViewById(R.id.missingRomContainer);
infoText = findViewById(R.id.infoText);
playButton = findViewById(R.id.playButton);
pickRomButton = findViewById(R.id.pickRomButton);
editTouchButton = findViewById(R.id.editTouchButton);

pickRomButton.setOnClickListener(v -> openRomPicker());
editTouchButton.setOnClickListener(v ->
startActivity(new Intent(this, LayoutEditorActivity.class)));
playButton.setOnClickListener(v -> attemptPlay());

ensureDataDir();
updatePlayEnabled();

// If the ROM is already in place and matches a supported hash, skip
// the menu entirely and drop straight into the game. The user can
// still access the touch layout editor from the in-game EDIT pill.
if (romExists()) {
File target = new File(new File(getExternalFilesDir(null), "data"), ROM_FILE_NAME);
int hashStatus = checkRomHash(target);
if (hashStatus == 0) {
if (checkRomHash(target) == 0) {
startGame();
} else if (hashStatus == 1) {
showV10WarningDialog(target);
} else {
showHashMismatchDialog(target);
}
}
}

@Override
protected void onResume() {
super.onResume();
updatePlayEnabled();
}

private void updatePlayEnabled() {
boolean rom = romExists();
playButton.setEnabled(rom);
infoText.setText(rom ? "Perfect Dark" :
"ROM not found. Select your Perfect Dark NTSC (z64) ROM to proceed.\n" +
"It will be copied to Android/data/com.perfectdark.port/files/data as " +
ROM_FILE_NAME + ".");
}

private void attemptPlay() {
if (!romExists()) return;
File target = new File(new File(getExternalFilesDir(null), "data"), ROM_FILE_NAME);
int hashStatus = checkRomHash(target);
if (hashStatus == 0) {
startGame();
} else if (hashStatus == 1) {
showV10WarningDialog(target);
} else {
showMissingRomUi();
showHashMismatchDialog(target);
}
}

Expand All @@ -83,8 +115,7 @@ private boolean romExists() {
}

private void showMissingRomUi() {
missingRomView.setVisibility(View.VISIBLE);
infoText.setText("ROM not found. Select your Perfect Dark NTSC (z64) ROM to proceed.\nIt will be copied to Android/data/com.perfectdark.port/files/data as " + ROM_FILE_NAME + ".");
updatePlayEnabled();
}

private void openRomPicker() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package com.perfectdark.port;

import android.app.AlertDialog;
import android.content.Context;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

/**
* Fullscreen editor for the touch layout. Shows the same overlay the game
* uses, but in edit mode: tap + drag moves an element, toggling "resize"
* instead stretches its radius. "Save" writes to SharedPreferences.
*/
public class LayoutEditorActivity extends AppCompatActivity {

private TouchOverlayView overlay;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
getWindow().getAttributes().layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
}
hideSystemUI();

FrameLayout root = new FrameLayout(this);
root.setBackgroundColor(0xFF101014);
setContentView(root, new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));

overlay = new TouchOverlayView(this);
overlay.setInternalHudVisible(false);
overlay.setEditMode(true);
root.addView(overlay, new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT));

root.addView(buildHud(this), new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.WRAP_CONTENT,
Gravity.TOP));

Toast.makeText(this,
"Toca un control para arrastrarlo. Activa RESIZE para cambiar su tamaño.",
Toast.LENGTH_LONG).show();
}

private View buildHud(Context ctx) {
LinearLayout bar = new LinearLayout(ctx);
bar.setOrientation(LinearLayout.HORIZONTAL);
bar.setGravity(Gravity.CENTER_VERTICAL);
bar.setPadding(16, 16, 16, 16);
bar.setBackgroundColor(0x88000000);

TextView title = new TextView(ctx);
title.setText("Touch Layout");
title.setTextColor(0xFFFFFFFF);
title.setTextSize(18);
LinearLayout.LayoutParams titleLp = new LinearLayout.LayoutParams(0,
ViewGroup.LayoutParams.WRAP_CONTENT, 1f);
bar.addView(title, titleLp);

// Per-button resize is done by tapping a button inside the overlay,
// so no global RESIZE toggle is needed here.

Button reset = new Button(ctx);
reset.setText("RESET");
reset.setOnClickListener(v -> new AlertDialog.Builder(this)
.setMessage("Restablecer el layout predeterminado?")
.setPositiveButton("Sí", (d, w) -> {
TouchLayout.resetDefaults(this);
overlay.reloadLayout();
})
.setNegativeButton("No", null)
.show());
bar.addView(reset);

Button save = new Button(ctx);
save.setText("GUARDAR");
save.setOnClickListener(v -> {
overlay.getLayout().save(this);
Toast.makeText(this, "Layout guardado", Toast.LENGTH_SHORT).show();
finish();
});
bar.addView(save);

Button back = new Button(ctx);
back.setText("CANCELAR");
back.setOnClickListener(v -> finish());
bar.addView(back);

return bar;
}

private void hideSystemUI() {
View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
decorView.setSystemUiVisibility(uiOptions);
}
}
Loading