diff --git a/.ci/android/build.sh b/.ci/android/build.sh index 3c1e2f240..727f855d3 100755 --- a/.ci/android/build.sh +++ b/.ci/android/build.sh @@ -1,12 +1,15 @@ #!/bin/bash -ex export NDK_CCACHE=$(which ccache) +[ "$GITHUB_REPOSITORY" = "citra-emu/citra-canary" ] && + BUILD_FLAVOR=canary || + BUILD_FLAVOR=nightly ccache -s cd src/android chmod +x ./gradlew -./gradlew bundleRelease -./gradlew assembleRelease +./gradlew assemble${BUILD_FLAVOR}Release +./gradlew bundle${BUILD_FLAVOR}Release ccache -s diff --git a/.ci/android/upload.sh b/.ci/android/upload.sh index 64258dfd5..1b777d069 100755 --- a/.ci/android/upload.sh +++ b/.ci/android/upload.sh @@ -3,8 +3,21 @@ . ./.ci/common/pre-upload.sh REV_NAME="citra-${GITDATE}-${GITREV}" +[ "${GITHUB_REPOSITORY}" = "citra-emu/citra-canary" ] && + BUILD_FLAVOR=canary || + BUILD_FLAVOR=nightly -cp src/android/app/build/outputs/apk/release/app-release.apk \ +cp src/android/app/build/outputs/apk/${BUILD_FLAVOR}/release/app-${BUILD_FLAVOR}-release.apk \ "artifacts/${REV_NAME}.apk" -cp src/android/app/build/outputs/bundle/release/app-release.aab \ +cp src/android/app/build/outputs/bundle/${BUILD_FLAVOR}Release/app-${BUILD_FLAVOR}-release.aab \ "artifacts/${REV_NAME}.aab" + +if [ ! -z "${ANDROID_KEYSTORE_B64}" ] +then + echo "Signing apk..." + base64 --decode <<< "${ANDROID_KEYSTORE_B64}" > ks.jks + + java -jar $(which apksigner) sign --ks ks.jks \ + --ks-key-alias "${ANDROID_KEY_ALIAS}" \ + --ks-pass env:ANDROID_KEYSTORE_PASS "artifacts/${REV_NAME}.apk" +fi diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d09560add..29f3e3ee8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -129,10 +129,14 @@ jobs: - name: Deps run: | sudo apt-get update - sudo apt-get install ccache -y + sudo apt-get install ccache apksigner -y - name: Build run: ./.ci/android/build.sh - - name: Copy artifacts + - name: Copy and sign artifacts + env: + ANDROID_KEYSTORE_B64: ${{ secrets.ANDROID_KEYSTORE_B64 }} + ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} + ANDROID_KEYSTORE_PASS: ${{ secrets.ANDROID_KEYSTORE_PASS }} run: ./.ci/android/upload.sh - name: Upload uses: actions/upload-artifact@v3 @@ -153,7 +157,7 @@ jobs: TRANSIFEX_API_TOKEN: ${{ secrets.TRANSIFEX_API_TOKEN }} release: runs-on: ubuntu-latest - needs: [build] + needs: [build, android] if: ${{ startsWith(github.ref, 'refs/tags/') }} steps: - uses: actions/download-artifact@v3 @@ -174,4 +178,4 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - asset_paths: '["./**/*.tar.*","./**/*.7z","./**/*.zip"]' + asset_paths: '["./**/*.tar.*","./**/*.7z","./**/*.zip","./**/*.apk","./**/*.aab"]' diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss index 794f09b96..c200819c5 100644 --- a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss +++ b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss @@ -2158,6 +2158,10 @@ PlotWidget { padding: 0px; } +TouchScreenPreview { + qproperty-dotHighlightColor: #3daee9; + background-color: #0f1922; +} QListWidget#selectorList { background-color: #0f1922; @@ -2168,4 +2172,4 @@ QLineEdit, QTreeView#hotkey_list, QScrollArea#scrollArea QTreeView { background-color: #0f1922; -} \ No newline at end of file +} diff --git a/externals/cmake-modules/FindFFmpeg.cmake b/externals/cmake-modules/FindFFmpeg.cmake index 6cb5960bb..cac21c614 100644 --- a/externals/cmake-modules/FindFFmpeg.cmake +++ b/externals/cmake-modules/FindFFmpeg.cmake @@ -116,6 +116,10 @@ function(find_ffmpeg LIBNAME) endforeach() string(TOUPPER ${LIBNAME} LIBNAME_UPPER) file(STRINGS "${FFmpeg_INCLUDE_${LIBNAME}}/lib${LIBNAME}/version.h" _FFmpeg_VERSION_H_CONTENTS REGEX "#define LIB${LIBNAME_UPPER}_VERSION_(MAJOR|MINOR|MICRO) ") + if (EXISTS "${FFmpeg_INCLUDE_${LIBNAME}}/lib${LIBNAME}/version_major.h") + file(STRINGS "${FFmpeg_INCLUDE_${LIBNAME}}/lib${LIBNAME}/version_major.h" _FFmpeg_MAJOR_VERSION_H_CONTENTS REGEX "#define LIB${LIBNAME_UPPER}_VERSION_MAJOR ") + string(APPEND _FFmpeg_VERSION_H_CONTENTS "\n" ${_FFmpeg_MAJOR_VERSION_H_CONTENTS}) + endif() set(_FFmpeg_VERSION_REGEX "([0-9]+)") foreach(v MAJOR MINOR MICRO) if("${_FFmpeg_VERSION_H_CONTENTS}" MATCHES "#define LIB${LIBNAME_UPPER}_VERSION_${v}[\\t ]+${_FFmpeg_VERSION_REGEX}") diff --git a/src/android/app/build.gradle b/src/android/app/build.gradle index 1e70d8d99..a3ea30ffb 100644 --- a/src/android/app/build.gradle +++ b/src/android/app/build.gradle @@ -83,6 +83,17 @@ android { } } + flavorDimensions "version" + productFlavors { + canary { + dimension "version" + applicationIdSuffix ".canary" + } + nightly { + dimension "version" + } + } + externalNativeBuild { cmake { version "3.18.1" @@ -140,5 +151,10 @@ def getVersion() { logger.error('Cannot find git, defaulting to dummy version number') } + if (System.getenv("GITHUB_ACTIONS") != null) { + def gitTag = System.getenv("GIT_TAG_NAME") + versionName = gitTag ?: versionName + } + return versionName } diff --git a/src/citra/citra.cpp b/src/citra/citra.cpp index a9b0b3eca..cf3d51869 100644 --- a/src/citra/citra.cpp +++ b/src/citra/citra.cpp @@ -391,6 +391,9 @@ int main(int argc, char** argv) { return -1; case Core::System::ResultStatus::Success: break; // Expected case + default: + LOG_ERROR(Frontend, "Error while loading ROM: {}", system.GetStatusDetails()); + break; } system.TelemetrySession().AddField(Common::Telemetry::FieldType::App, "Frontend", "SDL"); @@ -437,7 +440,18 @@ int main(int argc, char** argv) { }); while (emu_window->IsOpen()) { - system.RunLoop(); + const auto result = system.RunLoop(); + + switch (result) { + case Core::System::ResultStatus::ShutdownRequested: + emu_window->RequestClose(); + break; + case Core::System::ResultStatus::Success: + break; + default: + LOG_ERROR(Frontend, "Error in main run loop: {}", result, system.GetStatusDetails()); + break; + } } render_thread.join(); diff --git a/src/citra/emu_window/emu_window_sdl2.cpp b/src/citra/emu_window/emu_window_sdl2.cpp index ad02d9a15..d42609a81 100644 --- a/src/citra/emu_window/emu_window_sdl2.cpp +++ b/src/citra/emu_window/emu_window_sdl2.cpp @@ -104,6 +104,10 @@ bool EmuWindow_SDL2::IsOpen() const { return is_open; } +void EmuWindow_SDL2::RequestClose() { + is_open = false; +} + void EmuWindow_SDL2::OnResize() { int width, height; SDL_GetWindowSize(render_window, &width, &height); @@ -134,7 +138,7 @@ void EmuWindow_SDL2::Fullscreen() { EmuWindow_SDL2::EmuWindow_SDL2(bool fullscreen) { // Initialize the window if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0) { - LOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting..."); + LOG_CRITICAL(Frontend, "Failed to initialize SDL2: {}! Exiting...", SDL_GetError()); exit(1); } @@ -258,7 +262,7 @@ void EmuWindow_SDL2::PollEvents() { OnResize(); break; case SDL_WINDOWEVENT_CLOSE: - is_open = false; + RequestClose(); break; } break; @@ -289,7 +293,7 @@ void EmuWindow_SDL2::PollEvents() { OnFingerUp(); break; case SDL_QUIT: - is_open = false; + RequestClose(); break; default: break; diff --git a/src/citra/emu_window/emu_window_sdl2.h b/src/citra/emu_window/emu_window_sdl2.h index 64dec5381..27a0f0787 100644 --- a/src/citra/emu_window/emu_window_sdl2.h +++ b/src/citra/emu_window/emu_window_sdl2.h @@ -46,6 +46,9 @@ public: /// Whether the window is still open, and a close request hasn't yet been sent bool IsOpen() const; + /// Close the window. + void RequestClose(); + /// Creates a new context that is shared with the current context std::unique_ptr CreateSharedContext() const override;