From 6d01d921f6da61070988b6f719b1d64ca5d77024 Mon Sep 17 00:00:00 2001 From: djdiskmachine <110535302+djdiskmachine@users.noreply.github.com> Date: Sat, 6 Dec 2025 12:00:49 +0000 Subject: [PATCH 01/18] Add initial Android patches --- projects/Makefile | 4 +- projects/Makefile.ANDROID | 98 +++++++++++++++++++ projects/resources/ANDROID/mapping.xml | 20 ++++ sources/Adapters/LINUX/System/LINUXSystem.cpp | 19 ++++ sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp | 18 +++- .../Unix/FileSystem/UnixFileSystem.cpp | 2 +- sources/Adapters/Unix/Process/UnixProcess.cpp | 14 ++- sources/Adapters/Unix/Process/UnixProcess.h | 3 + sources/Application/Instruments/WavFile.cpp | 2 +- sources/System/Console/Logger.cpp | 7 ++ 10 files changed, 181 insertions(+), 6 deletions(-) create mode 100644 projects/Makefile.ANDROID create mode 100644 projects/resources/ANDROID/mapping.xml diff --git a/projects/Makefile b/projects/Makefile index f735c9d7..32a3ad62 100644 --- a/projects/Makefile +++ b/projects/Makefile @@ -111,6 +111,7 @@ RG35XXPLUSDIRS := $(LINUXDIRS) $(DUMMYMIDIDIRS) $(SDL2DIRS) $(SDL2AUDIODIRS) STEAMDIRS := $(LINUXDIRS) $(JACKDIRS) $(RTAUDIODIRS) $(RTMIDIDIRS) $(SDLDIRS) X64DIRS := $(LINUXDIRS) $(RTMIDIDIRS) $(SDL2DIRS) $(SDL2AUDIODIRS) X86DIRS := $(LINUXDIRS) $(RTMIDIDIRS) $(SDL2DIRS) $(SDL2AUDIODIRS) +ANDROIDDIRS := $(LINUXDIRS) $(DUMMYMIDIDIRS) $(SDL2DIRS) $(SDL2AUDIODIRS) #--------------------------------------------------------------------------------- # Consoles/Embedded @@ -330,6 +331,7 @@ RG35XXPLUSFILES := $(LINUXFILES) $(SDLAUDIOFILES) $(DUMMYMIDIFILES) STEAMFILES := $(LINUXFILES) $(RTAUDIOFILES) $(RTMIDIFILES) $(JACKFILES) X64FILES := $(LINUXFILES) $(RTMIDIFILES) $(SDLAUDIOFILES) X86FILES := $(LINUXFILES) $(RTMIDIFILES) $(SDLAUDIOFILES) +ANDROIDFILES := $(LINUXFILES) $(DUMMYMIDIFILES) $(SDLAUDIOFILES) #--------------------------------------------------------------------------------- # Consoles/Embedded @@ -464,7 +466,7 @@ W32FILES := \ #--------------------------------------------------------------------------------- TARGET := $(TITLE) -BUILD := build$(PLATFORM) +BUILD ?= build$(PLATFORM) SOURCES := $($(PLATFORM)DIRS) $(COMMONDIRS) INCLUDES := diff --git a/projects/Makefile.ANDROID b/projects/Makefile.ANDROID new file mode 100644 index 00000000..29915346 --- /dev/null +++ b/projects/Makefile.ANDROID @@ -0,0 +1,98 @@ +-include $(PWD)/rules_base + +#--------------------------------------------------------------------------------- +# Android-specific Makefile for LittleGPTracker +# This Makefile produces libmain.so for SDL2 Android apps +#--------------------------------------------------------------------------------- + +# Determine ABI and set toolchain accordingly +ABI ?= arm64-v8a +NDK_PATH ?= $(ANDROID_NDK_HOME) + +# Override BUILD directory to be ABI-specific +BUILD := build$(PLATFORM)_$(ABI) + +ifeq ($(ABI),armeabi-v7a) + TOOLCHAIN_PREFIX := armv7a-linux-androideabi + ARCH_FLAGS := -march=armv7-a -mfloat-abi=softfp -mfpu=neon + ANDROID_API := 21 +else ifeq ($(ABI),arm64-v8a) + TOOLCHAIN_PREFIX := aarch64-linux-android + ARCH_FLAGS := -march=armv8-a + ANDROID_API := 21 +else + $(error Unsupported ABI: $(ABI)) +endif + +# Set up NDK toolchain +TOOLCHAIN := $(NDK_PATH)/toolchains/llvm/prebuilt/linux-x86_64 +CC := $(TOOLCHAIN)/bin/$(TOOLCHAIN_PREFIX)$(ANDROID_API)-clang +CXX := $(TOOLCHAIN)/bin/$(TOOLCHAIN_PREFIX)$(ANDROID_API)-clang++ +AR := $(TOOLCHAIN)/bin/llvm-ar +STRIP := $(TOOLCHAIN)/bin/llvm-strip + +# Platform definition +PLATFORM := ANDROID + +# Android-specific defines +DEFINES := \ + -DPLATFORM_$(PLATFORM) \ + -DANDROID \ + -D__ANDROID__ \ + -DCPP_MEMORY \ + -DSDL2 \ + -DSDLAUDIO \ + -DDUMMYMIDI + +# Android doesn't support RtMidi - use dummy MIDI instead +# -DRTMIDI \ +# -D_FEAT_MIDI_MULTITHREAD + +# Add _64BIT for arm64-v8a builds +ifeq ($(ABI),arm64-v8a) +DEFINES += -D_64BIT +endif +# SDL2 paths (these should be set by Gradle) +SDL_INCLUDE ?= /path/to/SDL2/include +SDL_LIB ?= /path/to/SDL2/libs/$(ABI) + +# Optimization and compilation flags +OPT_FLAGS := -O2 -fno-strict-aliasing +# For debugging, use: +# OPT_FLAGS := -g -O0 + +INCLUDES := -I$(SDL_INCLUDE) -I$(PWD)/../sources + +# Android requires position-independent code +CFLAGS := $(OPT_FLAGS) $(DEFINES) $(INCLUDES) $(ARCH_FLAGS) \ + -fPIC \ + -ffunction-sections \ + -fdata-sections \ + -Wall \ + -Wno-unused-variable + +CXXFLAGS := $(CFLAGS) -std=gnu++11 -fexceptions -frtti + +# Linker flags for shared library +LDFLAGS := -shared \ + $(ARCH_FLAGS) \ + -Wl,--gc-sections \ + -Wl,--no-undefined \ + -L$(SDL_LIB) + +# Libraries to link +LIBS := -lSDL2 \ + -lGLESv2 \ + -lGLESv1_CM \ + -llog \ + -landroid \ + -lOpenSLES + +# Output configuration +OUTPUT := ../libmain_$(ABI) +EXTENSION := so + +# Build rule for shared library +%.so: $(OFILES) + $(CXX) $(LDFLAGS) -o $@ $(OFILES) $(LIBS) + $(STRIP) --strip-unneeded $@ \ No newline at end of file diff --git a/projects/resources/ANDROID/mapping.xml b/projects/resources/ANDROID/mapping.xml new file mode 100644 index 00000000..ea90d496 --- /dev/null +++ b/projects/resources/ANDROID/mapping.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + diff --git a/sources/Adapters/LINUX/System/LINUXSystem.cpp b/sources/Adapters/LINUX/System/LINUXSystem.cpp index 39031ff1..c9ad6b6e 100644 --- a/sources/Adapters/LINUX/System/LINUXSystem.cpp +++ b/sources/Adapters/LINUX/System/LINUXSystem.cpp @@ -64,6 +64,24 @@ void LINUXSystem::Boot(int argc,char **argv) { FileSystem::Install(new UnixFileSystem()); // Install aliases +#ifdef __ANDROID__ + // On Android, we MUST use external storage so users can access files via file manager + const char* storagePath = SDL_AndroidGetExternalStoragePath(); + if (storagePath) { + Trace::Log("ANDROID", "External storage path: %s", storagePath); + Path::SetAlias("bin", storagePath); + Path::SetAlias("root", storagePath); + } else { + Trace::Error("Failed to get Android external storage - app won't be able to access files!"); + // Still set internal storage as last resort, but warn user + storagePath = SDL_AndroidGetInternalStoragePath(); + if (storagePath) { + Trace::Error("Using internal storage (not accessible via file manager): %s", storagePath); + Path::SetAlias("bin", storagePath); + Path::SetAlias("root", storagePath); + } + } +#else char buff[1024]; ssize_t len = ::readlink("/proc/self/exe",buff,sizeof(buff)-1); if (len != -1) @@ -76,6 +94,7 @@ void LINUXSystem::Boot(int argc,char **argv) { } Path::SetAlias("bin",dirname(buff)) ; Path::SetAlias("root",".") ; +#endif // always use stdout, user can capture in launch script Trace::GetInstance()->SetLogger(*(new StdOutLogger())); diff --git a/sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp b/sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp index 7f4eb05a..3b0cd53c 100644 --- a/sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp +++ b/sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp @@ -12,8 +12,13 @@ SDLGUIWindowImp *instance_ ; +#ifdef __ANDROID__ +unsigned short appWidth=240 ; +unsigned short appHeight=320 ; +#else unsigned short appWidth=320 ; unsigned short appHeight=240 ; +#endif SDLGUIWindowImp::SDLGUIWindowImp(GUICreateWindowParams &p) { @@ -37,7 +42,7 @@ SDLGUIWindowImp::SDLGUIWindowImp(GUICreateWindowParams &p) if (displayModeRet < 0) { Trace::Error("DISPLAY","No display mode found. Error Code: %d.", displayModeRet); } - + NAssert(displayModeRet >= 0); #if defined(PLATFORM_PSP) @@ -48,6 +53,13 @@ SDLGUIWindowImp::SDLGUIWindowImp(GUICreateWindowParams &p) int screenWidth = 320; int screenHeight = 240; windowed_ = false; + #elif defined(__ANDROID__) + // Use full screen dimensions on Android + int screenWidth = displayMode.w; + int screenHeight = displayMode.h; + windowed_ = false; + + SDL_Log("DISPLAY: Android - using full display: %dx%d", screenWidth, screenHeight); #else int screenWidth = displayMode.w; int screenHeight = displayMode.h; @@ -80,6 +92,10 @@ SDLGUIWindowImp::SDLGUIWindowImp(GUICreateWindowParams &p) #ifdef PLATFORM_PSP mult_ = 1; + #elif __ANDROID__ + // Calculate multiplier based on screen size + int multFromSize=MIN(screenHeight/appHeight,screenWidth/appWidth); + mult_ = multFromSize - 1; #else int multFromSize=MIN(screenHeight/appHeight,screenWidth/appWidth); const char *mult=Config::GetInstance()->GetValue("SCREENMULT") ; diff --git a/sources/Adapters/Unix/FileSystem/UnixFileSystem.cpp b/sources/Adapters/Unix/FileSystem/UnixFileSystem.cpp index c4a38950..db13732c 100644 --- a/sources/Adapters/Unix/FileSystem/UnixFileSystem.cpp +++ b/sources/Adapters/Unix/FileSystem/UnixFileSystem.cpp @@ -4,7 +4,7 @@ #include #include #include -#ifdef _64BIT +#if defined(_64BIT) || defined(__ANDROID__) #include #else #include diff --git a/sources/Adapters/Unix/Process/UnixProcess.cpp b/sources/Adapters/Unix/Process/UnixProcess.cpp index 9912ded5..773bb140 100644 --- a/sources/Adapters/Unix/Process/UnixProcess.cpp +++ b/sources/Adapters/Unix/Process/UnixProcess.cpp @@ -22,13 +22,23 @@ SysSemaphore *UnixProcessFactory::CreateNewSemaphore(int initialcount, int maxco } ; UnixSysSemaphore::UnixSysSemaphore(int initialcount,int maxcount) { +#ifdef __ANDROID__ + // Android doesn't reliably support named semaphores, use unnamed ones + sem_init(&unnamed_sem_, 0, initialcount); + sem_ = &unnamed_sem_; +#else sem_=sem_open("n0ssemaphore",O_CREAT,S_IRUSR|S_IWUSR , 0 ); -} ; +#endif +} UnixSysSemaphore::~UnixSysSemaphore() { +#ifdef __ANDROID__ + sem_destroy(&unnamed_sem_); +#else sem_close(sem_) ; sem_unlink("n0ssemaphore") ; -} ; +#endif +} SysSemaphoreResult UnixSysSemaphore::Wait() { sem_wait(sem_) ; diff --git a/sources/Adapters/Unix/Process/UnixProcess.h b/sources/Adapters/Unix/Process/UnixProcess.h index f69181e3..4ffa7ddb 100644 --- a/sources/Adapters/Unix/Process/UnixProcess.h +++ b/sources/Adapters/Unix/Process/UnixProcess.h @@ -20,5 +20,8 @@ class UnixSysSemaphore:public SysSemaphore { virtual SysSemaphoreResult Post() ; private: sem_t *sem_ ; +#ifdef __ANDROID__ + sem_t unnamed_sem_; // Storage for unnamed semaphore on Android +#endif } ; #endif diff --git a/sources/Application/Instruments/WavFile.cpp b/sources/Application/Instruments/WavFile.cpp index 96fc2cc4..4eab39c0 100644 --- a/sources/Application/Instruments/WavFile.cpp +++ b/sources/Application/Instruments/WavFile.cpp @@ -79,7 +79,7 @@ WavFile *WavFile::Open(const char *path) { file->Read(fileBuffer,filesize,1) ; uchar *ptr=fileBuffer ;*/ -//Trace::Dump("Loading sample from %s",path) ; + Trace::Log("WAV", "Loading sample from %s", path); long position=0 ; diff --git a/sources/System/Console/Logger.cpp b/sources/System/Console/Logger.cpp index 6dfa7bbc..dac09b55 100644 --- a/sources/System/Console/Logger.cpp +++ b/sources/System/Console/Logger.cpp @@ -1,9 +1,16 @@ #include "Logger.h" #include +#ifdef __ANDROID__ +#include +#endif void StdOutLogger::AddLine(const char *line) { +#ifdef __ANDROID__ + SDL_Log("%s", line); +#else std::cout << line << std::endl ; +#endif } // ---------------------------------------------- From a2ab331ec4fba9de242f939ded716ff146bad7c0 Mon Sep 17 00:00:00 2001 From: djdiskmachine <110535302+djdiskmachine@users.noreply.github.com> Date: Mon, 11 May 2026 18:25:24 +0000 Subject: [PATCH 02/18] clang-format --- sources/Adapters/LINUX/System/LINUXSystem.cpp | 21 ++++++++++--------- sources/Adapters/Unix/Process/UnixProcess.h | 2 +- sources/Application/Instruments/WavFile.cpp | 19 ++++++++--------- sources/System/Console/Logger.cpp | 2 +- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/sources/Adapters/LINUX/System/LINUXSystem.cpp b/sources/Adapters/LINUX/System/LINUXSystem.cpp index c9ad6b6e..aae6de0a 100644 --- a/sources/Adapters/LINUX/System/LINUXSystem.cpp +++ b/sources/Adapters/LINUX/System/LINUXSystem.cpp @@ -65,8 +65,9 @@ void LINUXSystem::Boot(int argc,char **argv) { // Install aliases #ifdef __ANDROID__ - // On Android, we MUST use external storage so users can access files via file manager - const char* storagePath = SDL_AndroidGetExternalStoragePath(); + // On Android, we MUST use external storage so users can access files via + // file manager + const char* storagePath = SDL_AndroidGetExternalStoragePath(); if (storagePath) { Trace::Log("ANDROID", "External storage path: %s", storagePath); Path::SetAlias("bin", storagePath); @@ -96,17 +97,17 @@ void LINUXSystem::Boot(int argc,char **argv) { Path::SetAlias("root",".") ; #endif - // always use stdout, user can capture in launch script - Trace::GetInstance()->SetLogger(*(new StdOutLogger())); + // always use stdout, user can capture in launch script + Trace::GetInstance()->SetLogger(*(new StdOutLogger())); - // Process arguments - Config::GetInstance()->ProcessArguments(argc,argv) ; + // Process arguments + Config::GetInstance()->ProcessArguments(argc, argv); - // Install GUI Factory - I_GUIWindowFactory::Install(new GUIFactory()) ; + // Install GUI Factory + I_GUIWindowFactory::Install(new GUIFactory()); - // Install Timers - TimerService::GetInstance()->Install(new SDLTimerService()) ; + // Install Timers + TimerService::GetInstance()->Install(new SDLTimerService()); #ifdef JACKAUDIO Trace::Log("System","Installing JACK audio") ; diff --git a/sources/Adapters/Unix/Process/UnixProcess.h b/sources/Adapters/Unix/Process/UnixProcess.h index 4ffa7ddb..c62731b8 100644 --- a/sources/Adapters/Unix/Process/UnixProcess.h +++ b/sources/Adapters/Unix/Process/UnixProcess.h @@ -21,7 +21,7 @@ class UnixSysSemaphore:public SysSemaphore { private: sem_t *sem_ ; #ifdef __ANDROID__ - sem_t unnamed_sem_; // Storage for unnamed semaphore on Android + sem_t unnamed_sem_; // Storage for unnamed semaphore on Android #endif } ; #endif diff --git a/sources/Application/Instruments/WavFile.cpp b/sources/Application/Instruments/WavFile.cpp index 4eab39c0..c18f324a 100644 --- a/sources/Application/Instruments/WavFile.cpp +++ b/sources/Application/Instruments/WavFile.cpp @@ -72,16 +72,15 @@ WavFile *WavFile::Open(const char *path) { WavFile *wav=new WavFile(file) ; - - // Get data - -/* file->Seek(0,SEEK_SET) ; - file->Read(fileBuffer,filesize,1) ; - uchar *ptr=fileBuffer ;*/ - - Trace::Log("WAV", "Loading sample from %s", path); - - long position=0 ; + // Get data + + /* file->Seek(0,SEEK_SET) ; + file->Read(fileBuffer,filesize,1) ; + uchar *ptr=fileBuffer ;*/ + + Trace::Log("WAV", "Loading sample from %s", path); + + long position=0 ; // Read 'RIFF' diff --git a/sources/System/Console/Logger.cpp b/sources/System/Console/Logger.cpp index dac09b55..8263d12f 100644 --- a/sources/System/Console/Logger.cpp +++ b/sources/System/Console/Logger.cpp @@ -7,7 +7,7 @@ void StdOutLogger::AddLine(const char *line) { #ifdef __ANDROID__ - SDL_Log("%s", line); + SDL_Log("%s", line); #else std::cout << line << std::endl ; #endif From 041eaa22a7bee03ff72ec7b65853c5063bbcf1ca Mon Sep 17 00:00:00 2001 From: djdiskmachine Date: Fri, 15 May 2026 22:47:48 +0200 Subject: [PATCH 03/18] Add android subrepo --- .gitmodules | 3 +++ android | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 android diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..482d85a6 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "android"] + path = android + url = git@github.com:djdiskmachine/littlepiggytracker-android.git diff --git a/android b/android new file mode 160000 index 00000000..69aad727 --- /dev/null +++ b/android @@ -0,0 +1 @@ +Subproject commit 69aad7279337621670011fbad59a6542367bdf4a From 8b136dfe4d996173553641f0ad9435456f270971 Mon Sep 17 00:00:00 2001 From: djdiskmachine <110535302+djdiskmachine@users.noreply.github.com> Date: Mon, 18 May 2026 19:20:21 +0000 Subject: [PATCH 04/18] Regular screen scaling for Android Remove special case in SDLGUIWindowImpl Add check job --- .github/workflows/check.yml | 31 +++++++++++++++++++ android | 1 - sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp | 15 ++------- 3 files changed, 34 insertions(+), 13 deletions(-) delete mode 160000 android diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 923883dc..79a07e8c 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -426,3 +426,34 @@ jobs: name: LGPT-${{ github.job }}-${{ github.sha }}.zip path: projects/*.zip if-no-files-found: error + + + android: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4.1.7 + with: + submodules: recursive + + - name: Build Android APK + working-directory: android + run: ./gradlew assembleDebug + + - name: Package build + working-directory: projects + run: | + TAG=$(curl -s https://api.github.com/repos/djdiskmachine/lgpt-resources/releases/latest | grep '"tag_name"' | head -1 | cut -d'"' -f4) + curl -L -o lgpt-resources.zip https://github.com/djdiskmachine/lgpt-resources/archive/refs/tags/${TAG}.zip + unzip lgpt-resources.zip + mv lgpt-resources-${TAG}/*/ ./resources/packaging + rm -rf lgpt-resources* + mv ../android/app/build/outputs/apk/debug/app-debug.apk ./LittlePiggyTracker.apk + ./resources/packaging/lgpt_package.sh + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: LGPT-${{ github.job }}-${{ github.sha }}.zip + path: projects/*.zip + if-no-files-found: error diff --git a/android b/android deleted file mode 160000 index 69aad727..00000000 --- a/android +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 69aad7279337621670011fbad59a6542367bdf4a diff --git a/sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp b/sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp index 3b0cd53c..28b744f1 100644 --- a/sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp +++ b/sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp @@ -12,13 +12,8 @@ SDLGUIWindowImp *instance_ ; -#ifdef __ANDROID__ -unsigned short appWidth=240 ; -unsigned short appHeight=320 ; -#else unsigned short appWidth=320 ; -unsigned short appHeight=240 ; -#endif +unsigned short appHeight = 240; SDLGUIWindowImp::SDLGUIWindowImp(GUICreateWindowParams &p) { @@ -91,12 +86,8 @@ SDLGUIWindowImp::SDLGUIWindowImp(GUICreateWindowParams &p) } #ifdef PLATFORM_PSP - mult_ = 1; - #elif __ANDROID__ - // Calculate multiplier based on screen size - int multFromSize=MIN(screenHeight/appHeight,screenWidth/appWidth); - mult_ = multFromSize - 1; - #else + mult_ = 1; +#else int multFromSize=MIN(screenHeight/appHeight,screenWidth/appWidth); const char *mult=Config::GetInstance()->GetValue("SCREENMULT") ; if (mult) From 189a5b4cf177daf8b1a3072387041779d28f70c2 Mon Sep 17 00:00:00 2001 From: djdiskmachine <110535302+djdiskmachine@users.noreply.github.com> Date: Mon, 18 May 2026 19:50:18 +0000 Subject: [PATCH 05/18] Update android submodule HEAD to Fine-tuning --- android | 1 + 1 file changed, 1 insertion(+) create mode 160000 android diff --git a/android b/android new file mode 160000 index 00000000..ae5c8752 --- /dev/null +++ b/android @@ -0,0 +1 @@ +Subproject commit ae5c8752256072dc1a3252134112e69cc6db4a3e From 08b76a8e02186eec11e7a1d8ee35a902afda20f1 Mon Sep 17 00:00:00 2001 From: djdiskmachine <110535302+djdiskmachine@users.noreply.github.com> Date: Mon, 18 May 2026 19:59:50 +0000 Subject: [PATCH 06/18] Subrepo CI Fixes --- android | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android b/android index ae5c8752..e3a15045 160000 --- a/android +++ b/android @@ -1 +1 @@ -Subproject commit ae5c8752256072dc1a3252134112e69cc6db4a3e +Subproject commit e3a1504589c0f5caa1dcea2be0caf2f4367eb69a From c4107682f212d0d88b3e3b773e52af8207fe3512 Mon Sep 17 00:00:00 2001 From: djdiskmachine <110535302+djdiskmachine@users.noreply.github.com> Date: Mon, 18 May 2026 20:06:25 +0000 Subject: [PATCH 07/18] CI sdk stuff --- .github/workflows/check.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 79a07e8c..1aec6d9a 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -436,6 +436,11 @@ jobs: with: submodules: recursive + - name: Setup Android SDK and NDK + run: | + echo "sdk.dir=$ANDROID_SDK_ROOT" > android/local.properties + sdkmanager "ndk;27.2.12479018" + - name: Build Android APK working-directory: android run: ./gradlew assembleDebug From 84a74e18eaeed053af67ae77dc3aed3938070180 Mon Sep 17 00:00:00 2001 From: djdiskmachine <110535302+djdiskmachine@users.noreply.github.com> Date: Mon, 18 May 2026 20:08:42 +0000 Subject: [PATCH 08/18] Banan --- .github/workflows/check.yml | 2 +- .gitmodules | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 1aec6d9a..86c1bfe2 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -439,7 +439,7 @@ jobs: - name: Setup Android SDK and NDK run: | echo "sdk.dir=$ANDROID_SDK_ROOT" > android/local.properties - sdkmanager "ndk;27.2.12479018" + $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager "ndk;27.2.12479018" - name: Build Android APK working-directory: android diff --git a/.gitmodules b/.gitmodules index 482d85a6..51eb5323 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "android"] path = android - url = git@github.com:djdiskmachine/littlepiggytracker-android.git + url = https://github.com/djdiskmachine/littlepiggytracker-android.git From 7e83725cab2e827fa31497904c24055aeb1a187d Mon Sep 17 00:00:00 2001 From: djdiskmachine <110535302+djdiskmachine@users.noreply.github.com> Date: Mon, 18 May 2026 20:11:58 +0000 Subject: [PATCH 09/18] Banan --- .github/workflows/check.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 86c1bfe2..54dfaf19 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -440,6 +440,7 @@ jobs: run: | echo "sdk.dir=$ANDROID_SDK_ROOT" > android/local.properties $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager "ndk;27.2.12479018" + echo "ndk.dir=$ANDROID_SDK_ROOT/ndk/27.2.12479018" >> android/local.properties - name: Build Android APK working-directory: android From 35ae27c697d8199ade841406dccbd230651560ad Mon Sep 17 00:00:00 2001 From: djdiskmachine <110535302+djdiskmachine@users.noreply.github.com> Date: Mon, 18 May 2026 20:15:14 +0000 Subject: [PATCH 10/18] Banan --- .github/workflows/check.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 54dfaf19..268a8b60 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -439,8 +439,8 @@ jobs: - name: Setup Android SDK and NDK run: | echo "sdk.dir=$ANDROID_SDK_ROOT" > android/local.properties - $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager "ndk;27.2.12479018" - echo "ndk.dir=$ANDROID_SDK_ROOT/ndk/27.2.12479018" >> android/local.properties + $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager "ndk;27.0.12077973" + echo "ndk.dir=$ANDROID_SDK_ROOT/ndk/27.0.12077973" >> android/local.properties - name: Build Android APK working-directory: android From 065c9b0dbcb00fd03c8fb044b6bf5bc1ac821673 Mon Sep 17 00:00:00 2001 From: djdiskmachine <110535302+djdiskmachine@users.noreply.github.com> Date: Mon, 18 May 2026 20:31:49 +0000 Subject: [PATCH 11/18] banan --- .github/workflows/check.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 268a8b60..ec151631 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -436,8 +436,10 @@ jobs: with: submodules: recursive - - name: Setup Android SDK and NDK + - name: Setup build environment run: | + sudo apt update + sudo apt install -y make pkgconf libsdl2-dev libasound2-plugins libjack-dev python3-pillow echo "sdk.dir=$ANDROID_SDK_ROOT" > android/local.properties $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager "ndk;27.0.12077973" echo "ndk.dir=$ANDROID_SDK_ROOT/ndk/27.0.12077973" >> android/local.properties From b75edf1dc40ee125ae550237b6876f02516d0f15 Mon Sep 17 00:00:00 2001 From: djdiskmachine <110535302+djdiskmachine@users.noreply.github.com> Date: Mon, 18 May 2026 20:42:51 +0000 Subject: [PATCH 12/18] banan --- .github/workflows/check.yml | 2 +- projects/resources/packaging/lgpt_package.sh | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index ec151631..ff6710d8 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -439,7 +439,7 @@ jobs: - name: Setup build environment run: | sudo apt update - sudo apt install -y make pkgconf libsdl2-dev libasound2-plugins libjack-dev python3-pillow + sudo apt install -y make python3-pillow echo "sdk.dir=$ANDROID_SDK_ROOT" > android/local.properties $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager "ndk;27.0.12077973" echo "ndk.dir=$ANDROID_SDK_ROOT/ndk/27.0.12077973" >> android/local.properties diff --git a/projects/resources/packaging/lgpt_package.sh b/projects/resources/packaging/lgpt_package.sh index 968f7731..f908dfeb 100755 --- a/projects/resources/packaging/lgpt_package.sh +++ b/projects/resources/packaging/lgpt_package.sh @@ -22,6 +22,7 @@ collect_resources() { #1PLATFORM #2lgpt.*-exe if [ "$1" == "PSP" ] || [ "$1" == "GARLIC" ] || [ "$1" == "RG35XXPLUS" ] || + [ "$1" == "ANDROID" ] || [ "$1" == "BITTBOY" ]; then # All files go in the root folder zip -9 $PACKAGE -j $CONTENTS elif [ "$1" == "MACOS" ]; then # .app is a folder @@ -55,5 +56,6 @@ collect_resources BITTBOY lgpt-bittboy.elf collect_resources GARLICPLUS lgpt-garlicplus.elf collect_resources RG35XXPLUS lgpt-rg35xxplus.elf collect_resources MACOS LittleGPTracker.app +collect_resources ANDROID LittleGPTracker.apk # collect_resources RS97 lgpt.dge # collect_resources STEAM lgpt.steam-exe From d0891321f206ae1a27107dfba387837e77dde3a7 Mon Sep 17 00:00:00 2001 From: djdiskmachine <110535302+djdiskmachine@users.noreply.github.com> Date: Mon, 18 May 2026 20:59:54 +0000 Subject: [PATCH 13/18] LittlePiggyTracker.apk --- projects/resources/packaging/lgpt_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/resources/packaging/lgpt_package.sh b/projects/resources/packaging/lgpt_package.sh index f908dfeb..c66d4f3e 100755 --- a/projects/resources/packaging/lgpt_package.sh +++ b/projects/resources/packaging/lgpt_package.sh @@ -56,6 +56,6 @@ collect_resources BITTBOY lgpt-bittboy.elf collect_resources GARLICPLUS lgpt-garlicplus.elf collect_resources RG35XXPLUS lgpt-rg35xxplus.elf collect_resources MACOS LittleGPTracker.app -collect_resources ANDROID LittleGPTracker.apk +collect_resources ANDROID LittlePiggyTracker.apk # collect_resources RS97 lgpt.dge # collect_resources STEAM lgpt.steam-exe From 8b7e894a2960fe1ac945f8c4d693c45aecdd1256 Mon Sep 17 00:00:00 2001 From: djdiskmachine Date: Tue, 19 May 2026 20:08:27 +0200 Subject: [PATCH 14/18] Fix black screen onResume Required for Android port sdlWindow->ProcessExpose called onResume in Android --- android | 2 +- projects/Makefile | 4 ++-- projects/Makefile.ANDROID | 4 ++++ sources/Adapters/SDL2/GUI/SDLEventManager.cpp | 7 +++++++ sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp | 2 ++ sources/Application/AppWindow.cpp | 12 ++++++++++++ sources/Application/AppWindow.h | 3 ++- sources/UIFramework/SimpleBaseClasses/GUIWindow.h | 2 ++ 8 files changed, 32 insertions(+), 4 deletions(-) diff --git a/android b/android index e3a15045..d7ec1e52 160000 --- a/android +++ b/android @@ -1 +1 @@ -Subproject commit e3a1504589c0f5caa1dcea2be0caf2f4367eb69a +Subproject commit d7ec1e52989c0d6aa0d1d860d8d25ee1a263e864 diff --git a/projects/Makefile b/projects/Makefile index c41a37ca..33ff12df 100644 --- a/projects/Makefile +++ b/projects/Makefile @@ -111,7 +111,7 @@ RG35XXPLUSDIRS := $(LINUXDIRS) $(DUMMYMIDIDIRS) $(SDL2DIRS) $(SDL2AUDIODIRS) STEAMDIRS := $(LINUXDIRS) $(JACKDIRS) $(RTAUDIODIRS) $(RTMIDIDIRS) $(SDLDIRS) X64DIRS := $(LINUXDIRS) $(RTMIDIDIRS) $(SDL2DIRS) $(SDL2AUDIODIRS) X86DIRS := $(LINUXDIRS) $(RTMIDIDIRS) $(SDL2DIRS) $(SDL2AUDIODIRS) -ANDROIDDIRS := $(LINUXDIRS) $(DUMMYMIDIDIRS) $(SDL2DIRS) $(SDL2AUDIODIRS) +ANDROIDDIRS := $(LINUXDIRS) $(DUMMYMIDIDIRS) $(SDL2DIRS) $(SDL2AUDIODIRS) $(ANDROIDJNIDIRS) #--------------------------------------------------------------------------------- # Consoles/Embedded @@ -331,7 +331,7 @@ RG35XXPLUSFILES := $(LINUXFILES) $(SDLAUDIOFILES) $(DUMMYMIDIFILES) STEAMFILES := $(LINUXFILES) $(RTAUDIOFILES) $(RTMIDIFILES) $(JACKFILES) X64FILES := $(LINUXFILES) $(RTMIDIFILES) $(SDLAUDIOFILES) X86FILES := $(LINUXFILES) $(RTMIDIFILES) $(SDLAUDIOFILES) -ANDROIDFILES := $(LINUXFILES) $(DUMMYMIDIFILES) $(SDLAUDIOFILES) +ANDROIDFILES := $(LINUXFILES) $(DUMMYMIDIFILES) $(SDLAUDIOFILES) $(ANDROIDJNIFILES) #--------------------------------------------------------------------------------- # Consoles/Embedded diff --git a/projects/Makefile.ANDROID b/projects/Makefile.ANDROID index 29915346..668d54f4 100644 --- a/projects/Makefile.ANDROID +++ b/projects/Makefile.ANDROID @@ -88,6 +88,10 @@ LIBS := -lSDL2 \ -landroid \ -lOpenSLES +# Android-specific JNI extras +ANDROIDJNIDIRS := ../sources/System/Android +ANDROIDJNIFILES := AndroidJNI.o + # Output configuration OUTPUT := ../libmain_$(ABI) EXTENSION := so diff --git a/sources/Adapters/SDL2/GUI/SDLEventManager.cpp b/sources/Adapters/SDL2/GUI/SDLEventManager.cpp index 0c035b7e..a3a314b3 100644 --- a/sources/Adapters/SDL2/GUI/SDLEventManager.cpp +++ b/sources/Adapters/SDL2/GUI/SDLEventManager.cpp @@ -141,12 +141,19 @@ int SDLEventManager::MainLoop() switch (event.window.event) { case SDL_WINDOWEVENT_EXPOSED: + // SDL2 docs: surface re-acquisition is NOT needed + // on expose, only on resize. Just update content. + appWindow->Update() ; + break; case SDL_WINDOWEVENT_RESIZED: case SDL_WINDOWEVENT_SIZE_CHANGED: sdlWindow->ProcessExpose() ; break; } break ; + case SDL_APP_DIDENTERFOREGROUND: + sdlWindow->ProcessExpose() ; + break ; case SDL_USEREVENT: sdlWindow->ProcessUserEvent(event) ; break ; diff --git a/sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp b/sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp index 28b744f1..5540341a 100644 --- a/sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp +++ b/sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp @@ -526,6 +526,8 @@ void SDLGUIWindowImp::ProcessExpose() { // Expose and resize events will cause a new surface to be needed. surface_ = SDL_GetWindowSurface(window_); + _window->ForceFullRedraw(); // surface re-acquired: force full bitmap+char + // redraw _window->Update() ; } diff --git a/sources/Application/AppWindow.cpp b/sources/Application/AppWindow.cpp index 587ccc47..169f9228 100644 --- a/sources/Application/AppWindow.cpp +++ b/sources/Application/AppWindow.cpp @@ -445,6 +445,14 @@ AppWindow *AppWindow::Create(GUICreateWindowParams ¶ms) { void AppWindow::SetDirty() { _isDirty = true; }; +void AppWindow::ForceFullRedraw() { + // Invalidate screen cache so Flush() redraws every character cell, + // not just changed ones. Needed after surface re-acquisition on resume. + memset(_preScreen, 0xFF, 1200); + memset(_preScreenProp, 0xFF, 1200); + _isDirty = true; +}; + bool AppWindow::onEvent(GUIEvent &event) { // We need to tell the app to quit once we're out of the @@ -523,6 +531,10 @@ void AppWindow::onUpdate() { LoadProject(_newProjectToLoad.c_str()); return; } + if (_isDirty) { + _isDirty = false; + Redraw(); + } Flush(); }; diff --git a/sources/Application/AppWindow.h b/sources/Application/AppWindow.h index a312bda6..1bdcdc75 100644 --- a/sources/Application/AppWindow.h +++ b/sources/Application/AppWindow.h @@ -34,7 +34,8 @@ class AppWindow : public GUIWindow, I_Observer, Status { virtual void Clear(bool all = false); virtual void ClearRect(GUIRect &rect); virtual void SetColor(ColorDefinition cd); - void SetDirty(); + virtual void SetDirty(); + virtual void ForceFullRedraw(); protected: // GUIWindow implementation virtual bool onEvent(GUIEvent &event); diff --git a/sources/UIFramework/SimpleBaseClasses/GUIWindow.h b/sources/UIFramework/SimpleBaseClasses/GUIWindow.h index 04fbbae1..85d56c2e 100644 --- a/sources/UIFramework/SimpleBaseClasses/GUIWindow.h +++ b/sources/UIFramework/SimpleBaseClasses/GUIWindow.h @@ -42,6 +42,8 @@ class GUIWindow: public I_GUIGraphics { virtual void Lock() ; virtual void Unlock() ; virtual void Update() ; + virtual void SetDirty() {}; + virtual void ForceFullRedraw() {} ; virtual void onUpdate()=0 ; // virtual void Save() ; // virtual void Restore() ; From 5bab511a923c79afc71bcf80f4ecac000047a98a Mon Sep 17 00:00:00 2001 From: djdiskmachine Date: Tue, 19 May 2026 21:13:19 +0200 Subject: [PATCH 15/18] Forgot JNI file --- sources/System/Android/AndroidJNI.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 sources/System/Android/AndroidJNI.cpp diff --git a/sources/System/Android/AndroidJNI.cpp b/sources/System/Android/AndroidJNI.cpp new file mode 100644 index 00000000..a0f764a9 --- /dev/null +++ b/sources/System/Android/AndroidJNI.cpp @@ -0,0 +1,23 @@ +#ifdef __ANDROID__ + +#include +#include "Application/Application.h" +#include "Application/AppWindow.h" + +extern "C" { + +JNIEXPORT void JNICALL +Java_org_neocities_djdiskmachine_lgpt_1android_LgptSDLActivity_invalidateScreen(JNIEnv *env, jobject thiz) +{ + Application *app = Application::GetInstance(); + if (app) { + AppWindow *appWindow = static_cast(app->GetWindow()); + if (appWindow) { + appWindow->SetDirty(); + } + } +} + +} + +#endif // __ANDROID__ From cf54c8743e674058c6eed714f99182f669311cda Mon Sep 17 00:00:00 2001 From: djdiskmachine Date: Fri, 22 May 2026 05:47:40 +0200 Subject: [PATCH 16/18] Tap to move display surface clang-format --- .gitmodules | 2 +- android | 2 +- sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp | 18 +++++++++--------- sources/Adapters/Unix/Process/UnixProcess.cpp | 6 +++--- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.gitmodules b/.gitmodules index 51eb5323..482d85a6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "android"] path = android - url = https://github.com/djdiskmachine/littlepiggytracker-android.git + url = git@github.com:djdiskmachine/littlepiggytracker-android.git diff --git a/android b/android index d7ec1e52..ba64baa0 160000 --- a/android +++ b/android @@ -1 +1 @@ -Subproject commit d7ec1e52989c0d6aa0d1d860d8d25ee1a263e864 +Subproject commit ba64baa050300c91d3925eab62fc38c1bf1ce979 diff --git a/sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp b/sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp index 5540341a..8af4c58f 100644 --- a/sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp +++ b/sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp @@ -37,7 +37,7 @@ SDLGUIWindowImp::SDLGUIWindowImp(GUICreateWindowParams &p) if (displayModeRet < 0) { Trace::Error("DISPLAY","No display mode found. Error Code: %d.", displayModeRet); } - + NAssert(displayModeRet >= 0); #if defined(PLATFORM_PSP) @@ -48,25 +48,25 @@ SDLGUIWindowImp::SDLGUIWindowImp(GUICreateWindowParams &p) int screenWidth = 320; int screenHeight = 240; windowed_ = false; - #elif defined(__ANDROID__) +#elif defined(__ANDROID__) // Use full screen dimensions on Android int screenWidth = displayMode.w; int screenHeight = displayMode.h; windowed_ = false; SDL_Log("DISPLAY: Android - using full display: %dx%d", screenWidth, screenHeight); - #else +#else int screenWidth = displayMode.w; int screenHeight = displayMode.h; - #endif - - #if defined(RS97) +#endif + +#if defined(RS97) /* Pick the best bitdepth for the RS97 as it will select 32 as its default, even though that's slow */ bitDepth_ = 16; - #else +#else bitDepth_ = SDL_BITSPERPIXEL(displayMode.format); - #endif - +#endif + const char * driverName = SDL_GetVideoDriver(0); Trace::Log("DISPLAY","Using driver %s. Screen (%d,%d) Bpp:%d",driverName,screenWidth,screenHeight,bitDepth_); diff --git a/sources/Adapters/Unix/Process/UnixProcess.cpp b/sources/Adapters/Unix/Process/UnixProcess.cpp index 773bb140..8df06601 100644 --- a/sources/Adapters/Unix/Process/UnixProcess.cpp +++ b/sources/Adapters/Unix/Process/UnixProcess.cpp @@ -23,8 +23,8 @@ SysSemaphore *UnixProcessFactory::CreateNewSemaphore(int initialcount, int maxco UnixSysSemaphore::UnixSysSemaphore(int initialcount,int maxcount) { #ifdef __ANDROID__ - // Android doesn't reliably support named semaphores, use unnamed ones - sem_init(&unnamed_sem_, 0, initialcount); + // Android doesn't reliably support named semaphores, use unnamed ones + sem_init(&unnamed_sem_, 0, initialcount); sem_ = &unnamed_sem_; #else sem_=sem_open("n0ssemaphore",O_CREAT,S_IRUSR|S_IWUSR , 0 ); @@ -33,7 +33,7 @@ UnixSysSemaphore::UnixSysSemaphore(int initialcount,int maxcount) { UnixSysSemaphore::~UnixSysSemaphore() { #ifdef __ANDROID__ - sem_destroy(&unnamed_sem_); + sem_destroy(&unnamed_sem_); #else sem_close(sem_) ; sem_unlink("n0ssemaphore") ; From f5b9dea8b815fa8144823ddabda0e42f494ca878 Mon Sep 17 00:00:00 2001 From: djdiskmachine Date: Sat, 23 May 2026 13:59:32 +0200 Subject: [PATCH 17/18] clang-format --- sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp b/sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp index 8af4c58f..3e88bf34 100644 --- a/sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp +++ b/sources/Adapters/SDL2/GUI/SDLGUIWindowImp.cpp @@ -53,7 +53,6 @@ SDLGUIWindowImp::SDLGUIWindowImp(GUICreateWindowParams &p) int screenWidth = displayMode.w; int screenHeight = displayMode.h; windowed_ = false; - SDL_Log("DISPLAY: Android - using full display: %dx%d", screenWidth, screenHeight); #else int screenWidth = displayMode.w; From 0b2e092491536f021c0d9c8ac7615380ef0ca231 Mon Sep 17 00:00:00 2001 From: djdiskmachine Date: Fri, 29 May 2026 06:22:23 +0200 Subject: [PATCH 18/18] Logcat logger and config bug fix --- android | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android b/android index ba64baa0..f00d4d94 160000 --- a/android +++ b/android @@ -1 +1 @@ -Subproject commit ba64baa050300c91d3925eab62fc38c1bf1ce979 +Subproject commit f00d4d94af4aed37cde85e0236107b06d59c5894