Merge branch 'main' into metal

This commit is contained in:
SamoZ256 2024-08-30 08:59:37 +02:00 committed by GitHub
commit 41ee2e75ae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
36 changed files with 469 additions and 203 deletions

View File

@ -1,9 +0,0 @@
#include <stdio.h>
#include "./../src/Common/version.h"
// output current Cemu version for CI workflow. Do not modify
int main()
{
printf("%d.%d", EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR);
return 0;
}

View File

@ -3,10 +3,10 @@ name: Build Cemu
on: on:
workflow_call: workflow_call:
inputs: inputs:
deploymode: next_version_major:
required: false required: false
type: string type: string
experimentalversion: next_version_minor:
required: false required: false
type: string type: string
@ -24,25 +24,17 @@ jobs:
submodules: "recursive" submodules: "recursive"
fetch-depth: 0 fetch-depth: 0
- name: Setup release mode parameters (for deploy) - name: Setup release mode parameters
if: ${{ inputs.deploymode == 'release' }}
run: | run: |
echo "BUILD_MODE=release" >> $GITHUB_ENV echo "BUILD_MODE=release" >> $GITHUB_ENV
echo "BUILD_FLAGS=" >> $GITHUB_ENV echo "BUILD_FLAGS=" >> $GITHUB_ENV
echo "Build mode is release" echo "Build mode is release"
- name: Setup debug mode parameters (for continous build) - name: Setup build flags for version
if: ${{ inputs.deploymode != 'release' }} if: ${{ inputs.next_version_major != '' }}
run: | run: |
echo "BUILD_MODE=debug" >> $GITHUB_ENV echo "[INFO] Version ${{ inputs.next_version_major }}.${{ inputs.next_version_minor }}"
echo "BUILD_FLAGS=" >> $GITHUB_ENV echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEMULATOR_VERSION_MAJOR=${{ inputs.next_version_major }} -DEMULATOR_VERSION_MINOR=${{ inputs.next_version_minor }}" >> $GITHUB_ENV
echo "Build mode is debug"
- name: Setup version for experimental
if: ${{ inputs.experimentalversion != '' }}
run: |
echo "[INFO] Experimental version ${{ inputs.experimentalversion }}"
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEXPERIMENTAL_VERSION=${{ inputs.experimentalversion }}" >> $GITHUB_ENV
- name: "Install system dependencies" - name: "Install system dependencies"
run: | run: |
@ -81,12 +73,10 @@ jobs:
cmake --build build cmake --build build
- name: Prepare artifact - name: Prepare artifact
if: ${{ inputs.deploymode == 'release' }}
run: mv bin/Cemu_release bin/Cemu run: mv bin/Cemu_release bin/Cemu
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
if: ${{ inputs.deploymode == 'release' }}
with: with:
name: cemu-bin-linux-x64 name: cemu-bin-linux-x64
path: ./bin/Cemu path: ./bin/Cemu
@ -128,24 +118,17 @@ jobs:
with: with:
submodules: "recursive" submodules: "recursive"
- name: Setup release mode parameters (for deploy) - name: Setup release mode parameters
if: ${{ inputs.deploymode == 'release' }}
run: | run: |
echo "BUILD_MODE=release" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append echo "BUILD_MODE=release" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
echo "BUILD_FLAGS=" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append echo "BUILD_FLAGS=" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
echo "Build mode is release" echo "Build mode is release"
- name: Setup debug mode parameters (for continous build) - name: Setup build flags for version
if: ${{ inputs.deploymode != 'release' }} if: ${{ inputs.next_version_major != '' }}
run: | run: |
echo "BUILD_MODE=debug" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append echo "[INFO] Version ${{ inputs.next_version_major }}.${{ inputs.next_version_minor }}"
echo "BUILD_FLAGS=" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEMULATOR_VERSION_MAJOR=${{ inputs.next_version_major }} -DEMULATOR_VERSION_MINOR=${{ inputs.next_version_minor }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
echo "Build mode is debug"
- name: Setup version for experimental
if: ${{ inputs.experimentalversion != '' }}
run: |
echo "[INFO] Experimental version ${{ inputs.experimentalversion }}"
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEXPERIMENTAL_VERSION=${{ inputs.experimentalversion }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
- name: "Setup cmake" - name: "Setup cmake"
uses: jwlawson/actions-setup-cmake@v2 uses: jwlawson/actions-setup-cmake@v2
@ -184,57 +167,45 @@ jobs:
cmake --build . --config ${{ env.BUILD_MODE }} cmake --build . --config ${{ env.BUILD_MODE }}
- name: Prepare artifact - name: Prepare artifact
if: ${{ inputs.deploymode == 'release' }}
run: Rename-Item bin/Cemu_release.exe Cemu.exe run: Rename-Item bin/Cemu_release.exe Cemu.exe
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
if: ${{ inputs.deploymode == 'release' }}
with: with:
name: cemu-bin-windows-x64 name: cemu-bin-windows-x64
path: ./bin/Cemu.exe path: ./bin/Cemu.exe
build-macos: build-macos:
runs-on: macos-12 runs-on: macos-14
steps: steps:
- name: "Checkout repo" - name: "Checkout repo"
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
submodules: "recursive" submodules: "recursive"
- name: Setup release mode parameters (for deploy) - name: Setup release mode parameters
if: ${{ inputs.deploymode == 'release' }}
run: | run: |
echo "BUILD_MODE=release" >> $GITHUB_ENV echo "BUILD_MODE=release" >> $GITHUB_ENV
echo "BUILD_FLAGS=" >> $GITHUB_ENV echo "BUILD_FLAGS=" >> $GITHUB_ENV
echo "Build mode is release" echo "Build mode is release"
- name: Setup debug mode parameters (for continous build)
if: ${{ inputs.deploymode != 'release' }} - name: Setup build flags for version
if: ${{ inputs.next_version_major != '' }}
run: | run: |
echo "BUILD_MODE=debug" >> $GITHUB_ENV echo "[INFO] Version ${{ inputs.next_version_major }}.${{ inputs.next_version_minor }}"
echo "BUILD_FLAGS=" >> $GITHUB_ENV echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEMULATOR_VERSION_MAJOR=${{ inputs.next_version_major }} -DEMULATOR_VERSION_MINOR=${{ inputs.next_version_minor }}" >> $GITHUB_ENV
echo "Build mode is debug"
- name: Setup version for experimental
if: ${{ inputs.experimentalversion != '' }}
run: |
echo "[INFO] Experimental version ${{ inputs.experimentalversion }}"
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEXPERIMENTAL_VERSION=${{ inputs.experimentalversion }}" >> $GITHUB_ENV
- name: "Install system dependencies" - name: "Install system dependencies"
run: | run: |
brew update brew update
brew install llvm@15 ninja nasm automake libtool brew install ninja nasm automake libtool
brew install cmake ninja
- name: "Build and install molten-vk" - name: "Install molten-vk"
run: | run: |
git clone https://github.com/KhronosGroup/MoltenVK.git curl -L -O https://github.com/KhronosGroup/MoltenVK/releases/download/v1.2.9/MoltenVK-macos.tar
cd MoltenVK tar xf MoltenVK-macos.tar
git checkout bf097edc74ec3b6dfafdcd5a38d3ce14b11952d6 sudo mkdir -p /usr/local/lib
./fetchDependencies --macos sudo cp MoltenVK/MoltenVK/dynamic/dylib/macOS/libMoltenVK.dylib /usr/local/lib
make macos
make install
- name: "Setup cmake" - name: "Setup cmake"
uses: jwlawson/actions-setup-cmake@v2 uses: jwlawson/actions-setup-cmake@v2
@ -265,9 +236,8 @@ jobs:
cd build cd build
cmake .. ${{ env.BUILD_FLAGS }} \ cmake .. ${{ env.BUILD_FLAGS }} \
-DCMAKE_BUILD_TYPE=${{ env.BUILD_MODE }} \ -DCMAKE_BUILD_TYPE=${{ env.BUILD_MODE }} \
-DCMAKE_OSX_ARCHITECTURES=x86_64 \
-DMACOS_BUNDLE=ON \ -DMACOS_BUNDLE=ON \
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@15/bin/clang \
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@15/bin/clang++ \
-G Ninja -G Ninja
- name: "Build Cemu" - name: "Build Cemu"
@ -275,7 +245,6 @@ jobs:
cmake --build build cmake --build build
- name: Prepare artifact - name: Prepare artifact
if: ${{ inputs.deploymode == 'release' }}
run: | run: |
mkdir bin/Cemu_app mkdir bin/Cemu_app
mv bin/Cemu_release.app bin/Cemu_app/Cemu.app mv bin/Cemu_release.app bin/Cemu_app/Cemu.app
@ -289,7 +258,6 @@ jobs:
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
if: ${{ inputs.deploymode == 'release' }}
with: with:
name: cemu-bin-macos-x64 name: cemu-bin-macos-x64
path: ./bin/Cemu.dmg path: ./bin/Cemu.dmg

View File

@ -16,6 +16,3 @@ on:
jobs: jobs:
build: build:
uses: ./.github/workflows/build.yml uses: ./.github/workflows/build.yml
with:
deploymode: release
experimentalversion: 999999

View File

@ -1,20 +1,83 @@
name: Deploy experimental release name: Deploy experimental release
on: on:
workflow_dispatch: workflow_dispatch:
inputs:
changelog0:
description: 'Enter the changelog lines for this release. Each line is a feature / bullet point. Do not use dash.'
required: true
type: string
changelog1:
description: 'Feature 2'
required: false
type: string
changelog2:
description: 'Feature 3'
required: false
type: string
changelog3:
description: 'Feature 4'
required: false
type: string
changelog4:
description: 'Feature 5'
required: false
type: string
changelog5:
description: 'Feature 6'
required: false
type: string
changelog6:
description: 'Feature 7'
required: false
type: string
changelog7:
description: 'Feature 8'
required: false
type: string
changelog8:
description: 'Feature 9'
required: false
type: string
changelog9:
description: 'Feature 10'
required: false
type: string
jobs: jobs:
calculate-version:
name: Calculate Version
uses: ./.github/workflows/determine_release_version.yml
call-release-build: call-release-build:
uses: ./.github/workflows/build.yml uses: ./.github/workflows/build.yml
needs: calculate-version
with: with:
deploymode: release next_version_major: ${{ needs.calculate-version.outputs.next_version_major }}
experimentalversion: ${{ github.run_number }} next_version_minor: ${{ needs.calculate-version.outputs.next_version_minor }}
deploy: deploy:
name: Deploy experimental release name: Deploy experimental release
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
needs: call-release-build needs: [call-release-build, calculate-version]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate changelog
id: generate_changelog
run: |
CHANGELOG=""
if [ -n "${{ github.event.inputs.changelog0 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog0 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog1 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog1 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog2 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog2 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog3 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog3 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog4 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog4 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog5 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog5 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog6 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog6 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog7 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog7 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog8 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog8 }}\n"; fi
if [ -n "${{ github.event.inputs.changelog9 }}" ]; then CHANGELOG="$CHANGELOG- ${{ github.event.inputs.changelog9 }}\n"; fi
echo -e "$CHANGELOG"
echo "RELEASE_BODY=$CHANGELOG" >> $GITHUB_ENV
- uses: actions/download-artifact@v4 - uses: actions/download-artifact@v4
with: with:
name: cemu-bin-linux-x64 name: cemu-bin-linux-x64
@ -40,15 +103,13 @@ jobs:
mkdir upload mkdir upload
sudo apt install zip sudo apt install zip
- name: Get version - name: Set version dependent vars
run: | run: |
echo "Experimental version: ${{ github.run_number }}" echo "Version: ${{ needs.calculate-version.outputs.next_version }}"
ls echo "CEMU_FOLDER_NAME=Cemu_${{ needs.calculate-version.outputs.next_version }}"
gcc -o getversion .github/getversion.cpp echo "CEMU_VERSION=${{ needs.calculate-version.outputs.next_version }}"
./getversion echo "CEMU_FOLDER_NAME=Cemu_${{ needs.calculate-version.outputs.next_version }}" >> $GITHUB_ENV
echo "Cemu CI version: $(./getversion)" echo "CEMU_VERSION=${{ needs.calculate-version.outputs.next_version }}" >> $GITHUB_ENV
echo "CEMU_FOLDER_NAME=Cemu_$(./getversion)-${{ github.run_number }}" >> $GITHUB_ENV
echo "CEMU_VERSION=$(./getversion)-${{ github.run_number }}" >> $GITHUB_ENV
- name: Create release from windows-bin - name: Create release from windows-bin
run: | run: |
@ -83,4 +144,8 @@ jobs:
wget -O ghr.tar.gz https://github.com/tcnksm/ghr/releases/download/v0.15.0/ghr_v0.15.0_linux_amd64.tar.gz wget -O ghr.tar.gz https://github.com/tcnksm/ghr/releases/download/v0.15.0/ghr_v0.15.0_linux_amd64.tar.gz
tar xvzf ghr.tar.gz; rm ghr.tar.gz tar xvzf ghr.tar.gz; rm ghr.tar.gz
echo "[INFO] Release tag: v${{ env.CEMU_VERSION }}" echo "[INFO] Release tag: v${{ env.CEMU_VERSION }}"
ghr_v0.15.0_linux_amd64/ghr -prerelease -t ${{ secrets.GITHUB_TOKEN }} -n "Cemu ${{ env.CEMU_VERSION }} (Experimental)" -b "Cemu experimental release" "v${{ env.CEMU_VERSION }}" ./upload CHANGELOG_UNESCAPED=$(printf "%s\n" "${{ env.RELEASE_BODY }}" | sed 's/\\n/\n/g')
RELEASE_BODY=$(printf "%s\n%s" \
"**Changelog:**" \
"$CHANGELOG_UNESCAPED")
ghr_v0.15.0_linux_amd64/ghr -draft -t ${{ secrets.GITHUB_TOKEN }} -n "Cemu ${{ env.CEMU_VERSION }}" -b "$RELEASE_BODY" "v${{ env.CEMU_VERSION }}" ./upload

View File

@ -0,0 +1,74 @@
name: Calculate Next Version from release history
on:
workflow_dispatch:
workflow_call:
outputs:
next_version:
description: "The next semantic version"
value: ${{ jobs.calculate-version.outputs.next_version }}
next_version_major:
description: "The next semantic version (major)"
value: ${{ jobs.calculate-version.outputs.next_version_major }}
next_version_minor:
description: "The next semantic version (minor)"
value: ${{ jobs.calculate-version.outputs.next_version_minor }}
jobs:
calculate-version:
runs-on: ubuntu-latest
outputs:
next_version: ${{ steps.calculate_next_version.outputs.next_version }}
next_version_major: ${{ steps.calculate_next_version.outputs.next_version_major }}
next_version_minor: ${{ steps.calculate_next_version.outputs.next_version_minor }}
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Get all releases
id: get_all_releases
run: |
# Fetch all releases and check for API errors
RESPONSE=$(curl -s -o response.json -w "%{http_code}" "https://api.github.com/repos/${{ github.repository }}/releases?per_page=100")
if [ "$RESPONSE" -ne 200 ]; then
echo "Failed to fetch releases. HTTP status: $RESPONSE"
cat response.json
exit 1
fi
# Extract and sort tags
ALL_TAGS=$(jq -r '.[].tag_name' response.json | grep -E '^v[0-9]+\.[0-9]+(-[0-9]+)?$' | sed 's/-.*//' | sort -V | tail -n 1)
# Exit if no tags were found
if [ -z "$ALL_TAGS" ]; then
echo "No valid tags found."
exit 1
fi
echo "::set-output name=tag::$ALL_TAGS"
# echo "tag=$ALL_TAGS" >> $GITHUB_STATE
- name: Calculate next semver minor
id: calculate_next_version
run: |
LATEST_VERSION=${{ steps.get_all_releases.outputs.tag }}
# strip 'v' prefix and split into major.minor
LATEST_VERSION=${LATEST_VERSION//v/}
IFS='.' read -r -a VERSION_PARTS <<< "$LATEST_VERSION"
MAJOR=${VERSION_PARTS[0]}
MINOR=${VERSION_PARTS[1]}
# increment the minor version
MINOR=$((MINOR + 1))
NEXT_VERSION="${MAJOR}.${MINOR}"
echo "Major: $MAJOR"
echo "Minor: $MINOR"
echo "Next version: $NEXT_VERSION"
echo "::set-output name=next_version::$NEXT_VERSION"
echo "::set-output name=next_version_major::$MAJOR"
echo "::set-output name=next_version_minor::$MINOR"

View File

@ -16,11 +16,11 @@
- [Compiling Errors](#compiling-errors) - [Compiling Errors](#compiling-errors)
- [Building Errors](#building-errors) - [Building Errors](#building-errors)
- [macOS](#macos) - [macOS](#macos)
- [On Apple Silicon Macs, Rosetta 2 and the x86_64 version of Homebrew must be used](#on-apple-silicon-macs-rosetta-2-and-the-x86_64-version-of-homebrew-must-be-used)
- [Installing brew](#installing-brew) - [Installing brew](#installing-brew)
- [Installing Dependencies](#installing-dependencies) - [Installing Tool Dependencies](#installing-tool-dependencies)
- [Build Cemu using CMake and Clang](#build-cemu-using-cmake-and-clang) - [Installing Library Dependencies](#installing-library-dependencies)
- [Updating Cemu and source code](#updating-cemu-and-source-code) - [Build Cemu using CMake](#build-cemu-using-cmake)
- [Updating Cemu and source code](#updating-cemu-and-source-code)
## Windows ## Windows
@ -141,31 +141,41 @@ If you are getting a different error than any of the errors listed above, you ma
## macOS ## macOS
To compile Cemu, a recent enough compiler and STL with C++20 support is required! LLVM 13 and To compile Cemu, a recent enough compiler and STL with C++20 support is required! LLVM 13 and below
below, built in LLVM, and Xcode LLVM don't support the C++20 feature set required. The OpenGL graphics don't support the C++20 feature set required, so either install LLVM from Homebrew or make sure that
API isn't support on macOS, Vulkan must be used. Additionally Vulkan must be used through the you have a recent enough version of Xcode. Xcode 15 is known to work. The OpenGL graphics API isn't
Molten-VK compatibility layer supported on macOS, so Vulkan must be used through the Molten-VK compatibility layer.
### On Apple Silicon Macs, Rosetta 2 and the x86_64 version of Homebrew must be used
You can skip this section if you have an Intel Mac. Every time you compile, you need to perform steps 2.
1. `softwareupdate --install-rosetta` # Install Rosetta 2 if you don't have it. This only has to be done once
2. `arch -x86_64 zsh` # run an x64 shell
### Installing brew ### Installing brew
1. `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"` 1. `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`
2. `eval "$(/usr/local/Homebrew/bin/brew shellenv)"` # set x86_64 brew env 2. Set up the Homebrew shell environment:
1. **On an Intel Mac:** `eval "$(/usr/local/Homebrew/bin/brew shellenv)"`
2. **On an Apple Silicon Mac:** eval `"$(/opt/homebrew/bin/brew shellenv)"`
### Installing Dependencies ### Installing Tool Dependencies
`brew install boost git cmake llvm ninja nasm molten-vk automake libtool` The native versions of these can be used regardless of what type of Mac you have.
`brew install git cmake ninja nasm automake libtool`
### Installing Library Dependencies
**On Apple Silicon Macs, Rosetta 2 and the x86_64 version of Homebrew must be used to install these dependencies:**
1. `softwareupdate --install-rosetta` # Install Rosetta 2 if you don't have it. This only has to be done once
2. `arch -x86_64 zsh` # run an x64 shell
3. `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`
4. `eval "$(/usr/local/Homebrew/bin/brew shellenv)"`
Then install the dependencies:
`brew install boost molten-vk`
### Build Cemu using CMake
### Build Cemu using CMake and Clang
1. `git clone --recursive https://github.com/cemu-project/Cemu` 1. `git clone --recursive https://github.com/cemu-project/Cemu`
2. `cd Cemu` 2. `cd Cemu`
3. `cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -G Ninja` 3. `cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DCMAKE_OSX_ARCHITECTURES=x86_64 -G Ninja`
4. `cmake --build build` 4. `cmake --build build`
5. You should now have a Cemu executable file in the /bin folder, which you can run using `./bin/Cemu_release`. 5. You should now have a Cemu executable file in the /bin folder, which you can run using `./bin/Cemu_release`.

View File

@ -5,18 +5,19 @@ set(CMAKE_CXX_FLAGS_DEBUG "-g")
option(ENABLE_VCPKG "Enable the vcpkg package manager" ON) option(ENABLE_VCPKG "Enable the vcpkg package manager" ON)
option(MACOS_BUNDLE "The executable when built on macOS will be created as an application bundle" OFF) option(MACOS_BUNDLE "The executable when built on macOS will be created as an application bundle" OFF)
set(EXPERIMENTAL_VERSION "" CACHE STRING "") # used by CI script to set experimental version
if (EXPERIMENTAL_VERSION) # used by CI script to set version:
add_definitions(-DEMULATOR_VERSION_MINOR=${EXPERIMENTAL_VERSION}) set(EMULATOR_VERSION_MAJOR "0" CACHE STRING "")
execute_process( set(EMULATOR_VERSION_MINOR "0" CACHE STRING "")
COMMAND git log --format=%h -1 set(EMULATOR_VERSION_PATCH "0" CACHE STRING "")
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
OUTPUT_VARIABLE GIT_HASH execute_process(
OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND git log --format=%h -1
) WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
add_definitions(-DEMULATOR_HASH=${GIT_HASH}) OUTPUT_VARIABLE GIT_HASH
endif() OUTPUT_STRIP_TRAILING_WHITESPACE
)
add_definitions(-DEMULATOR_HASH=${GIT_HASH})
if (ENABLE_VCPKG) if (ENABLE_VCPKG)
# check if vcpkg is shallow and unshallow it if necessary # check if vcpkg is shallow and unshallow it if necessary
@ -65,6 +66,10 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_compile_definitions($<$<CONFIG:Debug>:CEMU_DEBUG_ASSERT>) # if build type is debug, set CEMU_DEBUG_ASSERT add_compile_definitions($<$<CONFIG:Debug>:CEMU_DEBUG_ASSERT>) # if build type is debug, set CEMU_DEBUG_ASSERT
add_definitions(-DEMULATOR_VERSION_MAJOR=${EMULATOR_VERSION_MAJOR})
add_definitions(-DEMULATOR_VERSION_MINOR=${EMULATOR_VERSION_MINOR})
add_definitions(-DEMULATOR_VERSION_PATCH=${EMULATOR_VERSION_PATCH})
set_property(GLOBAL PROPERTY USE_FOLDERS ON) set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# enable link time optimization for release builds # enable link time optimization for release builds
@ -90,6 +95,7 @@ endif()
if (APPLE) if (APPLE)
enable_language(OBJC OBJCXX) enable_language(OBJC OBJCXX)
set(CMAKE_OSX_DEPLOYMENT_TARGET "12.0")
endif() endif()
if (UNIX AND NOT APPLE) if (UNIX AND NOT APPLE)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -117,7 +117,13 @@ add_library (ih264d
"decoder/ivd.h" "decoder/ivd.h"
) )
if (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64") if (CMAKE_OSX_ARCHITECTURES)
set(IH264D_ARCHITECTURE ${CMAKE_OSX_ARCHITECTURES})
else()
set(IH264D_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR})
endif()
if (IH264D_ARCHITECTURE STREQUAL "x86_64" OR IH264D_ARCHITECTURE STREQUAL "amd64" OR IH264D_ARCHITECTURE STREQUAL "AMD64")
set(LIBAVCDEC_X86_INCLUDES "common/x86" "decoder/x86") set(LIBAVCDEC_X86_INCLUDES "common/x86" "decoder/x86")
include_directories("common/" "decoder/" ${LIBAVCDEC_X86_INCLUDES}) include_directories("common/" "decoder/" ${LIBAVCDEC_X86_INCLUDES})
target_sources(ih264d PRIVATE target_sources(ih264d PRIVATE
@ -140,7 +146,7 @@ target_sources(ih264d PRIVATE
"decoder/x86/ih264d_function_selector_sse42.c" "decoder/x86/ih264d_function_selector_sse42.c"
"decoder/x86/ih264d_function_selector_ssse3.c" "decoder/x86/ih264d_function_selector_ssse3.c"
) )
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") elseif(IH264D_ARCHITECTURE STREQUAL "aarch64" OR IH264D_ARCHITECTURE STREQUAL "arm64")
enable_language( C CXX ASM ) enable_language( C CXX ASM )
set(LIBAVCDEC_ARM_INCLUDES "common/armv8" "decoder/arm") set(LIBAVCDEC_ARM_INCLUDES "common/armv8" "decoder/arm")
include_directories("common/" "decoder/" ${LIBAVCDEC_ARM_INCLUDES}) include_directories("common/" "decoder/" ${LIBAVCDEC_ARM_INCLUDES})
@ -178,7 +184,7 @@ target_sources(ih264d PRIVATE
) )
target_compile_options(ih264d PRIVATE -DARMV8) target_compile_options(ih264d PRIVATE -DARMV8)
else() else()
message(FATAL_ERROR "ih264d unknown architecture: ${CMAKE_SYSTEM_PROCESSOR}") message(FATAL_ERROR "ih264d unknown architecture: ${IH264D_ARCHITECTURE}")
endif() endif()
if(MSVC) if(MSVC)

View File

@ -10,6 +10,8 @@ curl -sSfL https://github.com"$(curl https://github.com/probonopd/go-appimage/re
chmod a+x mkappimage.AppImage chmod a+x mkappimage.AppImage
curl -sSfLO "https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh" curl -sSfLO "https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh"
chmod a+x linuxdeploy-plugin-gtk.sh chmod a+x linuxdeploy-plugin-gtk.sh
curl -sSfLO "https://github.com/darealshinji/linuxdeploy-plugin-checkrt/releases/download/continuous/linuxdeploy-plugin-checkrt.sh"
chmod a+x linuxdeploy-plugin-checkrt.sh
if [[ ! -e /usr/lib/x86_64-linux-gnu ]]; then if [[ ! -e /usr/lib/x86_64-linux-gnu ]]; then
sed -i 's#lib\/x86_64-linux-gnu#lib64#g' linuxdeploy-plugin-gtk.sh sed -i 's#lib\/x86_64-linux-gnu#lib64#g' linuxdeploy-plugin-gtk.sh
@ -39,7 +41,8 @@ export NO_STRIP=1
-d "${GITHUB_WORKSPACE}"/AppDir/info.cemu.Cemu.desktop \ -d "${GITHUB_WORKSPACE}"/AppDir/info.cemu.Cemu.desktop \
-i "${GITHUB_WORKSPACE}"/AppDir/info.cemu.Cemu.png \ -i "${GITHUB_WORKSPACE}"/AppDir/info.cemu.Cemu.png \
-e "${GITHUB_WORKSPACE}"/AppDir/usr/bin/Cemu \ -e "${GITHUB_WORKSPACE}"/AppDir/usr/bin/Cemu \
--plugin gtk --plugin gtk \
--plugin checkrt
if ! GITVERSION="$(git rev-parse --short HEAD 2>/dev/null)"; then if ! GITVERSION="$(git rev-parse --short HEAD 2>/dev/null)"; then
GITVERSION=experimental GITVERSION=experimental

View File

@ -525,7 +525,7 @@ void LatteSHRC_UpdateGSBaseHash(uint8* geometryShaderPtr, uint32 geometryShaderS
// update hash from geometry shader data // update hash from geometry shader data
uint64 gsHash1 = 0; uint64 gsHash1 = 0;
uint64 gsHash2 = 0; uint64 gsHash2 = 0;
_calculateShaderProgramHash((uint32*)geometryShaderPtr, geometryShaderSize, &hashCacheVS, &gsHash1, &gsHash2); _calculateShaderProgramHash((uint32*)geometryShaderPtr, geometryShaderSize, &hashCacheGS, &gsHash1, &gsHash2);
// get geometry shader // get geometry shader
uint64 gsHash = gsHash1 + gsHash2; uint64 gsHash = gsHash1 + gsHash2;
gsHash += (uint64)_activeVertexShader->ringParameterCount; gsHash += (uint64)_activeVertexShader->ringParameterCount;

View File

@ -12,9 +12,9 @@ uint32 RendererShader::GeneratePrecompiledCacheId()
v += (uint32)(*s); v += (uint32)(*s);
s++; s++;
} }
v += (EMULATOR_VERSION_LEAD * 1000000u); v += (EMULATOR_VERSION_MAJOR * 1000000u);
v += (EMULATOR_VERSION_MAJOR * 10000u); v += (EMULATOR_VERSION_MINOR * 10000u);
v += (EMULATOR_VERSION_MINOR * 100u); v += (EMULATOR_VERSION_PATCH * 100u);
// settings that can influence shaders // settings that can influence shaders
v += (uint32)g_current_game_profile->GetAccurateShaderMul() * 133; v += (uint32)g_current_game_profile->GetAccurateShaderMul() * 133;

View File

@ -125,7 +125,7 @@ std::vector<VulkanRenderer::DeviceInfo> VulkanRenderer::GetDevices()
VkApplicationInfo app_info{}; VkApplicationInfo app_info{};
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
app_info.pApplicationName = EMULATOR_NAME; app_info.pApplicationName = EMULATOR_NAME;
app_info.applicationVersion = VK_MAKE_VERSION(EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR); app_info.applicationVersion = VK_MAKE_VERSION(EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR, EMULATOR_VERSION_PATCH);
app_info.pEngineName = EMULATOR_NAME; app_info.pEngineName = EMULATOR_NAME;
app_info.engineVersion = app_info.applicationVersion; app_info.engineVersion = app_info.applicationVersion;
app_info.apiVersion = apiVersion; app_info.apiVersion = apiVersion;
@ -339,7 +339,7 @@ VulkanRenderer::VulkanRenderer()
VkApplicationInfo app_info{}; VkApplicationInfo app_info{};
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
app_info.pApplicationName = EMULATOR_NAME; app_info.pApplicationName = EMULATOR_NAME;
app_info.applicationVersion = VK_MAKE_VERSION(EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR); app_info.applicationVersion = VK_MAKE_VERSION(EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR, EMULATOR_VERSION_PATCH);
app_info.pEngineName = EMULATOR_NAME; app_info.pEngineName = EMULATOR_NAME;
app_info.engineVersion = app_info.applicationVersion; app_info.engineVersion = app_info.applicationVersion;
app_info.apiVersion = apiVersion; app_info.apiVersion = apiVersion;

View File

@ -511,6 +511,8 @@ namespace iosu
return CallHandler_GetBlackList(fpdClient, vecIn, numVecIn, vecOut, numVecOut); return CallHandler_GetBlackList(fpdClient, vecIn, numVecIn, vecOut, numVecOut);
case FPD_REQUEST_ID::GetFriendListEx: case FPD_REQUEST_ID::GetFriendListEx:
return CallHandler_GetFriendListEx(fpdClient, vecIn, numVecIn, vecOut, numVecOut); return CallHandler_GetFriendListEx(fpdClient, vecIn, numVecIn, vecOut, numVecOut);
case FPD_REQUEST_ID::UpdateCommentAsync:
return CallHandler_UpdateCommentAsync(fpdClient, vecIn, numVecIn, vecOut, numVecOut);
case FPD_REQUEST_ID::UpdatePreferenceAsync: case FPD_REQUEST_ID::UpdatePreferenceAsync:
return CallHandler_UpdatePreferenceAsync(fpdClient, vecIn, numVecIn, vecOut, numVecOut); return CallHandler_UpdatePreferenceAsync(fpdClient, vecIn, numVecIn, vecOut, numVecOut);
case FPD_REQUEST_ID::AddFriendRequestByPlayRecordAsync: case FPD_REQUEST_ID::AddFriendRequestByPlayRecordAsync:
@ -719,18 +721,23 @@ namespace iosu
nnResult CallHandler_GetMyComment(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut) nnResult CallHandler_GetMyComment(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut)
{ {
static constexpr uint32 MY_COMMENT_LENGTH = 0x12; // are comments utf16? Buffer length is 0x24
if(numVecIn != 0 || numVecOut != 1) if(numVecIn != 0 || numVecOut != 1)
return FPResult_InvalidIPCParam; return FPResult_InvalidIPCParam;
if(vecOut->size != MY_COMMENT_LENGTH*sizeof(uint16be))
{
cemuLog_log(LogType::Force, "GetMyComment: Unexpected output size");
return FPResult_InvalidIPCParam;
}
std::basic_string<uint16be> myComment; std::basic_string<uint16be> myComment;
myComment.resize(MY_COMMENT_LENGTH); if(g_fpd.nexFriendSession)
memcpy(vecOut->basePhys.GetPtr(), myComment.data(), MY_COMMENT_LENGTH*sizeof(uint16be)); {
return 0; if(vecOut->size != MY_COMMENT_LENGTH * sizeof(uint16be))
{
cemuLog_log(LogType::Force, "GetMyComment: Unexpected output size");
return FPResult_InvalidIPCParam;
}
nexComment myNexComment;
g_fpd.nexFriendSession->getMyComment(myNexComment);
myComment = StringHelpers::FromUtf8(myNexComment.commentString);
}
myComment.insert(0, 1, '\0');
memcpy(vecOut->basePhys.GetPtr(), myComment.c_str(), MY_COMMENT_LENGTH * sizeof(uint16be));
return FPResult_Ok;
} }
nnResult CallHandler_GetMyPreference(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut) nnResult CallHandler_GetMyPreference(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut)
@ -1143,6 +1150,36 @@ namespace iosu
return FPResult_Ok; return FPResult_Ok;
} }
nnResult CallHandler_UpdateCommentAsync(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut)
{
std::unique_lock _l(g_fpd.mtxFriendSession);
if (numVecIn != 1 || numVecOut != 0)
return FPResult_InvalidIPCParam;
if (!g_fpd.nexFriendSession)
return FPResult_RequestFailed;
uint32 messageLength = vecIn[0].size / sizeof(uint16be);
DeclareInputPtr(newComment, uint16be, messageLength, 0);
if (messageLength == 0 || newComment[messageLength-1] != 0)
{
cemuLog_log(LogType::Force, "UpdateCommentAsync: Message must contain at least a null-termination character");
return FPResult_InvalidIPCParam;
}
IPCCommandBody* cmd = ServiceCallDelayCurrentResponse();
auto utf8_comment = StringHelpers::ToUtf8(newComment, messageLength);
nexComment temporaryComment;
temporaryComment.ukn0 = 0;
temporaryComment.commentString = utf8_comment;
temporaryComment.ukn1 = 0;
g_fpd.nexFriendSession->updateCommentAsync(temporaryComment, [cmd](NexFriends::RpcErrorCode result) {
if (result != NexFriends::ERR_NONE)
return ServiceCallAsyncRespond(cmd, FPResult_RequestFailed);
ServiceCallAsyncRespond(cmd, FPResult_Ok);
});
return FPResult_Ok;
}
nnResult CallHandler_UpdatePreferenceAsync(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut) nnResult CallHandler_UpdatePreferenceAsync(FPDClient* fpdClient, IPCIoctlVector* vecIn, uint32 numVecIn, IPCIoctlVector* vecOut, uint32 numVecOut)
{ {
std::unique_lock _l(g_fpd.mtxFriendSession); std::unique_lock _l(g_fpd.mtxFriendSession);

View File

@ -212,6 +212,7 @@ namespace iosu
static const int RELATIONSHIP_FRIEND = 3; static const int RELATIONSHIP_FRIEND = 3;
static const int GAMEMODE_MAX_MESSAGE_LENGTH = 0x80; // limit includes null-terminator character, so only 0x7F actual characters can be used static const int GAMEMODE_MAX_MESSAGE_LENGTH = 0x80; // limit includes null-terminator character, so only 0x7F actual characters can be used
static const int MY_COMMENT_LENGTH = 0x12;
enum class FPD_REQUEST_ID enum class FPD_REQUEST_ID
{ {
@ -245,6 +246,7 @@ namespace iosu
CheckSettingStatusAsync = 0x7596, CheckSettingStatusAsync = 0x7596,
GetFriendListEx = 0x75F9, GetFriendListEx = 0x75F9,
GetFriendRequestListEx = 0x76C1, GetFriendRequestListEx = 0x76C1,
UpdateCommentAsync = 0x7726,
UpdatePreferenceAsync = 0x7727, UpdatePreferenceAsync = 0x7727,
RemoveFriendAsync = 0x7789, RemoveFriendAsync = 0x7789,
DeleteFriendFlagsAsync = 0x778A, DeleteFriendFlagsAsync = 0x778A,

View File

@ -140,7 +140,7 @@ namespace coreinit
// we are in single-core mode and the lock will never be released unless we let other threads resume work // we are in single-core mode and the lock will never be released unless we let other threads resume work
// to avoid an infinite loop we have no choice but to yield the thread even it is in an uninterruptible state // to avoid an infinite loop we have no choice but to yield the thread even it is in an uninterruptible state
if( !OSIsInterruptEnabled() ) if( !OSIsInterruptEnabled() )
cemuLog_log(LogType::APIErrors, "OSUninterruptibleSpinLock_Acquire(): Lock is occupied which requires a wait but current thread is already in an uninterruptible state (Avoid cascaded OSDisableInterrupts and/or OSUninterruptibleSpinLock)"); cemuLog_logOnce(LogType::APIErrors, "OSUninterruptibleSpinLock_Acquire(): Lock is occupied which requires a wait but current thread is already in an uninterruptible state (Avoid cascaded OSDisableInterrupts and/or OSUninterruptibleSpinLock)");
while (!spinlock->ownerThread.atomic_compare_exchange(nullptr, currentThread)) while (!spinlock->ownerThread.atomic_compare_exchange(nullptr, currentThread))
{ {
OSYieldThread(); OSYieldThread();

View File

@ -464,6 +464,14 @@ namespace nn
return ipcCtx->Submit(std::move(ipcCtx)); return ipcCtx->Submit(std::move(ipcCtx));
} }
nnResult GetMyPlayingGame(iosu::fpd::GameKey* myPlayingGame)
{
FP_API_BASE();
auto ipcCtx = std::make_unique<FPIpcContext>(iosu::fpd::FPD_REQUEST_ID::GetMyPlayingGame);
ipcCtx->AddOutput(myPlayingGame, sizeof(iosu::fpd::GameKey));
return ipcCtx->Submit(std::move(ipcCtx));
}
nnResult GetMyPreference(iosu::fpd::FPDPreference* myPreference) nnResult GetMyPreference(iosu::fpd::FPDPreference* myPreference)
{ {
FP_API_BASE(); FP_API_BASE();
@ -472,6 +480,14 @@ namespace nn
return ipcCtx->Submit(std::move(ipcCtx)); return ipcCtx->Submit(std::move(ipcCtx));
} }
nnResult GetMyComment(uint16be* myComment)
{
FP_API_BASE();
auto ipcCtx = std::make_unique<FPIpcContext>(iosu::fpd::FPD_REQUEST_ID::GetMyComment);
ipcCtx->AddOutput(myComment, iosu::fpd::MY_COMMENT_LENGTH * sizeof(uint16be));
return ipcCtx->Submit(std::move(ipcCtx));
}
nnResult GetMyMii(FFLData_t* fflData) nnResult GetMyMii(FFLData_t* fflData)
{ {
FP_API_BASE(); FP_API_BASE();
@ -607,6 +623,20 @@ namespace nn
return resultBuf != 0 ? 1 : 0; return resultBuf != 0 ? 1 : 0;
} }
nnResult UpdateCommentAsync(uint16be* newComment, void* funcPtr, void* customParam)
{
FP_API_BASE();
auto ipcCtx = std::make_unique<FPIpcContext>(iosu::fpd::FPD_REQUEST_ID::UpdateCommentAsync);
uint32 commentLen = CafeStringHelpers::Length(newComment, iosu::fpd::MY_COMMENT_LENGTH-1);
if (commentLen >= iosu::fpd::MY_COMMENT_LENGTH-1)
{
cemuLog_log(LogType::Force, "UpdateCommentAsync: message too long");
return FPResult_InvalidIPCParam;
}
ipcCtx->AddInput(newComment, sizeof(uint16be) * commentLen + 2);
return ipcCtx->SubmitAsync(std::move(ipcCtx), funcPtr, customParam);
}
nnResult UpdatePreferenceAsync(iosu::fpd::FPDPreference* newPreference, void* funcPtr, void* customParam) nnResult UpdatePreferenceAsync(iosu::fpd::FPDPreference* newPreference, void* funcPtr, void* customParam)
{ {
FP_API_BASE(); FP_API_BASE();
@ -763,7 +793,9 @@ namespace nn
cafeExportRegisterFunc(GetMyAccountId, "nn_fp", "GetMyAccountId__Q2_2nn2fpFPc", LogType::NN_FP); cafeExportRegisterFunc(GetMyAccountId, "nn_fp", "GetMyAccountId__Q2_2nn2fpFPc", LogType::NN_FP);
cafeExportRegisterFunc(GetMyScreenName, "nn_fp", "GetMyScreenName__Q2_2nn2fpFPw", LogType::NN_FP); cafeExportRegisterFunc(GetMyScreenName, "nn_fp", "GetMyScreenName__Q2_2nn2fpFPw", LogType::NN_FP);
cafeExportRegisterFunc(GetMyMii, "nn_fp", "GetMyMii__Q2_2nn2fpFP12FFLStoreData", LogType::NN_FP); cafeExportRegisterFunc(GetMyMii, "nn_fp", "GetMyMii__Q2_2nn2fpFP12FFLStoreData", LogType::NN_FP);
cafeExportRegisterFunc(GetMyPlayingGame, "nn_fp", "GetMyPlayingGame__Q2_2nn2fpFPQ3_2nn2fp7GameKey", LogType::NN_FP);
cafeExportRegisterFunc(GetMyPreference, "nn_fp", "GetMyPreference__Q2_2nn2fpFPQ3_2nn2fp10Preference", LogType::NN_FP); cafeExportRegisterFunc(GetMyPreference, "nn_fp", "GetMyPreference__Q2_2nn2fpFPQ3_2nn2fp10Preference", LogType::NN_FP);
cafeExportRegisterFunc(GetMyComment, "nn_fp", "GetMyComment__Q2_2nn2fpFPQ3_2nn2fp7Comment", LogType::NN_FP);
cafeExportRegisterFunc(GetFriendAccountId, "nn_fp", "GetFriendAccountId__Q2_2nn2fpFPA17_cPCUiUi", LogType::NN_FP); cafeExportRegisterFunc(GetFriendAccountId, "nn_fp", "GetFriendAccountId__Q2_2nn2fpFPA17_cPCUiUi", LogType::NN_FP);
cafeExportRegisterFunc(GetFriendScreenName, "nn_fp", "GetFriendScreenName__Q2_2nn2fpFPA11_wPCUiUibPUc", LogType::NN_FP); cafeExportRegisterFunc(GetFriendScreenName, "nn_fp", "GetFriendScreenName__Q2_2nn2fpFPA11_wPCUiUibPUc", LogType::NN_FP);
@ -774,6 +806,7 @@ namespace nn
cafeExportRegisterFunc(CheckSettingStatusAsync, "nn_fp", "CheckSettingStatusAsync__Q2_2nn2fpFPUcPFQ2_2nn6ResultPv_vPv", LogType::NN_FP); cafeExportRegisterFunc(CheckSettingStatusAsync, "nn_fp", "CheckSettingStatusAsync__Q2_2nn2fpFPUcPFQ2_2nn6ResultPv_vPv", LogType::NN_FP);
cafeExportRegisterFunc(IsPreferenceValid, "nn_fp", "IsPreferenceValid__Q2_2nn2fpFv", LogType::NN_FP); cafeExportRegisterFunc(IsPreferenceValid, "nn_fp", "IsPreferenceValid__Q2_2nn2fpFv", LogType::NN_FP);
cafeExportRegisterFunc(UpdateCommentAsync, "nn_fp", "UpdateCommentAsync__Q2_2nn2fpFPCwPFQ2_2nn6ResultPv_vPv", LogType::NN_FP);
cafeExportRegisterFunc(UpdatePreferenceAsync, "nn_fp", "UpdatePreferenceAsync__Q2_2nn2fpFPCQ3_2nn2fp10PreferencePFQ2_2nn6ResultPv_vPv", LogType::NN_FP); cafeExportRegisterFunc(UpdatePreferenceAsync, "nn_fp", "UpdatePreferenceAsync__Q2_2nn2fpFPCQ3_2nn2fp10PreferencePFQ2_2nn6ResultPv_vPv", LogType::NN_FP);
cafeExportRegisterFunc(GetRequestBlockSettingAsync, "nn_fp", "GetRequestBlockSettingAsync__Q2_2nn2fpFPUcPCUiUiPFQ2_2nn6ResultPv_vPv", LogType::NN_FP); cafeExportRegisterFunc(GetRequestBlockSettingAsync, "nn_fp", "GetRequestBlockSettingAsync__Q2_2nn2fpFPUcPCUiUiPFQ2_2nn6ResultPv_vPv", LogType::NN_FP);

View File

@ -12,6 +12,7 @@
enum class KPAD_ERROR : sint32 enum class KPAD_ERROR : sint32
{ {
NONE = 0, NONE = 0,
NO_SAMPLE_DATA = -1,
NO_CONTROLLER = -2, NO_CONTROLLER = -2,
NOT_INITIALIZED = -5, NOT_INITIALIZED = -5,
}; };
@ -106,6 +107,9 @@ void padscoreExport_WPADProbe(PPCInterpreter_t* hCPU)
} }
else else
{ {
if(type)
*type = 253;
osLib_returnFromFunction(hCPU, WPAD_ERR_NO_CONTROLLER); osLib_returnFromFunction(hCPU, WPAD_ERR_NO_CONTROLLER);
} }
} }
@ -420,9 +424,12 @@ void padscoreExport_KPADSetConnectCallback(PPCInterpreter_t* hCPU)
osLib_returnFromFunction(hCPU, old_callback.GetMPTR()); osLib_returnFromFunction(hCPU, old_callback.GetMPTR());
} }
uint64 g_kpadLastRead[InputManager::kMaxWPADControllers] = {0};
bool g_kpadIsInited = true; bool g_kpadIsInited = true;
sint32 _KPADRead(uint32 channel, KPADStatus_t* samplingBufs, uint32 length, betype<KPAD_ERROR>* errResult) sint32 _KPADRead(uint32 channel, KPADStatus_t* samplingBufs, uint32 length, betype<KPAD_ERROR>* errResult)
{ {
if (channel >= InputManager::kMaxWPADControllers) if (channel >= InputManager::kMaxWPADControllers)
{ {
debugBreakpoint(); debugBreakpoint();
@ -446,6 +453,19 @@ sint32 _KPADRead(uint32 channel, KPADStatus_t* samplingBufs, uint32 length, bety
return 0; return 0;
} }
// On console new input samples are only received every few ms and calling KPADRead(Ex) clears the internal queue regardless of length value
// thus calling KPADRead(Ex) again too soon on the same channel will result in no data being returned
// Games that depend on this: Affordable Space Adventures
uint64 currentTime = coreinit::OSGetTime();
uint64 timeDif = currentTime - g_kpadLastRead[channel];
if(length == 0 || timeDif < coreinit::EspressoTime::ConvertNsToTimerTicks(1000000))
{
if (errResult)
*errResult = KPAD_ERROR::NO_SAMPLE_DATA;
return 0;
}
g_kpadLastRead[channel] = currentTime;
memset(samplingBufs, 0x00, sizeof(KPADStatus_t)); memset(samplingBufs, 0x00, sizeof(KPADStatus_t));
samplingBufs->wpadErr = WPAD_ERR_NONE; samplingBufs->wpadErr = WPAD_ERR_NONE;
samplingBufs->data_format = controller->get_data_format(); samplingBufs->data_format = controller->get_data_format();
@ -474,7 +494,6 @@ void padscoreExport_KPADReadEx(PPCInterpreter_t* hCPU)
osLib_returnFromFunction(hCPU, samplesRead); osLib_returnFromFunction(hCPU, samplesRead);
} }
bool debugUseDRC1 = true;
void padscoreExport_KPADRead(PPCInterpreter_t* hCPU) void padscoreExport_KPADRead(PPCInterpreter_t* hCPU)
{ {
ppcDefineParamU32(channel, 0); ppcDefineParamU32(channel, 0);
@ -726,7 +745,8 @@ namespace padscore
// call sampling callback // call sampling callback
for (auto i = 0; i < InputManager::kMaxWPADControllers; ++i) for (auto i = 0; i < InputManager::kMaxWPADControllers; ++i)
{ {
if (g_padscore.controller_data[i].sampling_callback) { if (g_padscore.controller_data[i].sampling_callback)
{
if (const auto controller = instance.get_wpad_controller(i)) if (const auto controller = instance.get_wpad_controller(i))
{ {
cemuLog_log(LogType::InputAPI, "Calling WPADsamplingCallback({})", i); cemuLog_log(LogType::InputAPI, "Calling WPADsamplingCallback({})", i);
@ -741,7 +761,7 @@ namespace padscore
{ {
OSCreateAlarm(&g_padscore.alarm); OSCreateAlarm(&g_padscore.alarm);
const uint64 start_tick = coreinit::coreinit_getOSTime(); const uint64 start_tick = coreinit::coreinit_getOSTime();
const uint64 period_tick = coreinit::EspressoTime::GetTimerClock(); // once a second const uint64 period_tick = coreinit::EspressoTime::GetTimerClock() / 200; // every 5ms
MPTR handler = PPCInterpreter_makeCallableExportDepr(TickFunction); MPTR handler = PPCInterpreter_makeCallableExportDepr(TickFunction);
OSSetPeriodicAlarm(&g_padscore.alarm, start_tick, period_tick, handler); OSSetPeriodicAlarm(&g_padscore.alarm, start_tick, period_tick, handler);
} }

View File

@ -50,7 +50,6 @@
extern bool isLaunchTypeELF; extern bool isLaunchTypeELF;
bool debugUseDRC = true;
VPADDir g_vpadGyroDirOverwrite[VPAD_MAX_CONTROLLERS] = VPADDir g_vpadGyroDirOverwrite[VPAD_MAX_CONTROLLERS] =
{ {
{{1.0f,0.0f,0.0f}, {0.0f,1.0f,0.0f}, {0.0f, 0.0f, 0.1f}}, {{1.0f,0.0f,0.0f}, {0.0f,1.0f,0.0f}, {0.0f, 0.0f, 0.1f}},
@ -240,19 +239,20 @@ namespace vpad
status->tpProcessed2.validity = VPAD_TP_VALIDITY_INVALID_XY; status->tpProcessed2.validity = VPAD_TP_VALIDITY_INVALID_XY;
const auto controller = InputManager::instance().get_vpad_controller(channel); const auto controller = InputManager::instance().get_vpad_controller(channel);
if (!controller || debugUseDRC == false) if (!controller)
{ {
// no controller // most games expect the Wii U GamePad to be connected, so even if the user has not set it up we should still return empty samples for channel 0
if(channel != 0)
{
if (error)
*error = VPAD_READ_ERR_NO_CONTROLLER;
if (length > 0)
status->vpadErr = -1;
return 0;
}
if (error) if (error)
*error = VPAD_READ_ERR_NONE; // VPAD_READ_ERR_NO_DATA; // VPAD_READ_ERR_NO_CONTROLLER; *error = VPAD_READ_ERR_NONE;
return 1; return 1;
//osLib_returnFromFunction(hCPU, 1); return;
}
if (channel != 0)
{
debugBreakpoint();
} }
const bool vpadDelayEnabled = ActiveSettings::VPADDelayEnabled(); const bool vpadDelayEnabled = ActiveSettings::VPADDelayEnabled();
@ -274,9 +274,7 @@ namespace vpad
// not ready yet // not ready yet
if (error) if (error)
*error = VPAD_READ_ERR_NONE; *error = VPAD_READ_ERR_NONE;
return 0; return 0;
//osLib_returnFromFunction(hCPU, 0); return;
} }
else if (dif <= ESPRESSO_TIMER_CLOCK) else if (dif <= ESPRESSO_TIMER_CLOCK)
{ {

View File

@ -277,7 +277,8 @@ void NexFriends::handleResponse_getAllInformation(nexServiceResponse_t* response
} }
NexFriends* session = (NexFriends*)nexFriends; NexFriends* session = (NexFriends*)nexFriends;
session->myPreference = nexPrincipalPreference(&response->data); session->myPreference = nexPrincipalPreference(&response->data);
nexComment comment(&response->data); auto comment = nexComment(&response->data);
session->myComment = comment;
if (response->data.hasReadOutOfBounds()) if (response->data.hasReadOutOfBounds())
return; return;
// acquire lock on lists // acquire lock on lists
@ -391,6 +392,28 @@ void NexFriends::getMyPreference(nexPrincipalPreference& preference)
preference = myPreference; preference = myPreference;
} }
bool NexFriends::updateCommentAsync(nexComment newComment, std::function<void(RpcErrorCode)> cb)
{
uint8 tempNexBufferArray[1024];
nexPacketBuffer packetBuffer(tempNexBufferArray, sizeof(tempNexBufferArray), true);
newComment.writeData(&packetBuffer);
nexCon->callMethod(
NEX_PROTOCOL_FRIENDS_WIIU, 15, &packetBuffer, [this, cb, newComment](nexServiceResponse_t* response) -> void {
if (!response->isSuccessful)
return cb(NexFriends::ERR_RPC_FAILED);
this->myComment = newComment;
return cb(NexFriends::ERR_NONE);
},
true);
// TEST
return true;
}
void NexFriends::getMyComment(nexComment& comment)
{
comment = myComment;
}
bool NexFriends::addProvisionalFriendByPidGuessed(uint32 principalId) bool NexFriends::addProvisionalFriendByPidGuessed(uint32 principalId)
{ {
uint8 tempNexBufferArray[512]; uint8 tempNexBufferArray[512];

View File

@ -297,7 +297,9 @@ public:
void writeData(nexPacketBuffer* pb) const override void writeData(nexPacketBuffer* pb) const override
{ {
cemu_assert_unimplemented(); pb->writeU8(ukn0);
pb->writeString(commentString.c_str());
pb->writeU64(ukn1);
} }
void readData(nexPacketBuffer* pb) override void readData(nexPacketBuffer* pb) override
@ -554,6 +556,7 @@ public:
bool getFriendRequestByMessageId(nexFriendRequest& friendRequestData, bool* isIncoming, uint64 messageId); bool getFriendRequestByMessageId(nexFriendRequest& friendRequestData, bool* isIncoming, uint64 messageId);
bool isOnline(); bool isOnline();
void getMyPreference(nexPrincipalPreference& preference); void getMyPreference(nexPrincipalPreference& preference);
void getMyComment(nexComment& comment);
// asynchronous API (data has to be requested) // asynchronous API (data has to be requested)
bool addProvisionalFriend(char* name, std::function<void(RpcErrorCode)> cb); bool addProvisionalFriend(char* name, std::function<void(RpcErrorCode)> cb);
@ -565,6 +568,7 @@ public:
void acceptFriendRequest(uint64 messageId, std::function<void(RpcErrorCode)> cb); void acceptFriendRequest(uint64 messageId, std::function<void(RpcErrorCode)> cb);
void deleteFriendRequest(uint64 messageId, std::function<void(RpcErrorCode)> cb); // rejecting incoming friend request (differs from blocking friend requests) void deleteFriendRequest(uint64 messageId, std::function<void(RpcErrorCode)> cb); // rejecting incoming friend request (differs from blocking friend requests)
bool updatePreferencesAsync(const nexPrincipalPreference newPreferences, std::function<void(RpcErrorCode)> cb); bool updatePreferencesAsync(const nexPrincipalPreference newPreferences, std::function<void(RpcErrorCode)> cb);
bool updateCommentAsync(const nexComment newComment, std::function<void(RpcErrorCode)> cb);
void updateMyPresence(nexPresenceV2& myPresence); void updateMyPresence(nexPresenceV2& myPresence);
void setNotificationHandler(void(*notificationHandler)(NOTIFICATION_TYPE notificationType, uint32 pid)); void setNotificationHandler(void(*notificationHandler)(NOTIFICATION_TYPE notificationType, uint32 pid));
@ -619,6 +623,7 @@ private:
// local friend state // local friend state
nexPresenceV2 myPresence; nexPresenceV2 myPresence;
nexPrincipalPreference myPreference; nexPrincipalPreference myPreference;
nexComment myComment;
std::recursive_mutex mtx_lists; std::recursive_mutex mtx_lists;
std::vector<nexFriend> list_friends; std::vector<nexFriend> list_friends;

View File

@ -1,36 +1,19 @@
#ifndef EMULATOR_NAME #ifndef EMULATOR_NAME
#define EMULATOR_NAME "Cemu" #define EMULATOR_NAME "Cemu"
#define EMULATOR_VERSION_LEAD 2
#define EMULATOR_VERSION_MAJOR 0
// the minor version is used for experimental builds to indicate the build index. Set by command line option from CI build script
// if zero, the version text will be constructed as LEAD.MAJOR, otherwise as LEAD.MAJOR-MINOR
#if defined(EMULATOR_VERSION_MINOR) && EMULATOR_VERSION_MINOR == 0
#define EMULATOR_VERSION_SUFFIX "" #define EMULATOR_VERSION_SUFFIX ""
#else
#define EMULATOR_VERSION_SUFFIX " (experimental)"
#endif
#ifndef EMULATOR_VERSION_MINOR
#define EMULATOR_VERSION_MINOR 0
#endif
#define _XSTRINGFY(s) _STRINGFY(s) #define _XSTRINGFY(s) _STRINGFY(s)
#define _STRINGFY(s) #s #define _STRINGFY(s) #s
#if EMULATOR_VERSION_MINOR != 0 #if EMULATOR_VERSION_MAJOR != 0
#if defined(EMULATOR_HASH) && EMULATOR_VERSION_MINOR == 999999 #define BUILD_VERSION_WITH_NAME_STRING (EMULATOR_NAME " " _XSTRINGFY(EMULATOR_VERSION_MAJOR) "." _XSTRINGFY(EMULATOR_VERSION_MINOR) EMULATOR_VERSION_SUFFIX)
#define BUILD_VERSION_WITH_NAME_STRING (EMULATOR_NAME " " _XSTRINGFY(EMULATOR_VERSION_LEAD) "." _XSTRINGFY(EMULATOR_VERSION_MAJOR) "-" _XSTRINGFY(EMULATOR_HASH) EMULATOR_VERSION_SUFFIX) #define BUILD_VERSION_STRING (_XSTRINGFY(EMULATOR_VERSION_MAJOR) "." _XSTRINGFY(EMULATOR_VERSION_MINOR) EMULATOR_VERSION_SUFFIX)
#define BUILD_VERSION_STRING (_XSTRINGFY(EMULATOR_VERSION_LEAD) "." _XSTRINGFY(EMULATOR_VERSION_MAJOR) "-" _XSTRINGFY(EMULATOR_HASH) EMULATOR_VERSION_SUFFIX)
#else #else
#define BUILD_VERSION_WITH_NAME_STRING (EMULATOR_NAME " " _XSTRINGFY(EMULATOR_VERSION_LEAD) "." _XSTRINGFY(EMULATOR_VERSION_MAJOR) "-" _XSTRINGFY(EMULATOR_VERSION_MINOR) EMULATOR_VERSION_SUFFIX) // no version provided. Only show commit hash
#define BUILD_VERSION_STRING (_XSTRINGFY(EMULATOR_VERSION_LEAD) "." _XSTRINGFY(EMULATOR_VERSION_MAJOR) "-" _XSTRINGFY(EMULATOR_VERSION_MINOR) EMULATOR_VERSION_SUFFIX) #define BUILD_VERSION_STRING (_XSTRINGFY(EMULATOR_HASH) EMULATOR_VERSION_SUFFIX)
#endif #define BUILD_VERSION_WITH_NAME_STRING (EMULATOR_NAME " " _XSTRINGFY(EMULATOR_HASH) EMULATOR_VERSION_SUFFIX)
#else
#define BUILD_VERSION_STRING (_XSTRINGFY(EMULATOR_VERSION_LEAD) "." _XSTRINGFY(EMULATOR_VERSION_MAJOR) EMULATOR_VERSION_SUFFIX)
#define BUILD_VERSION_WITH_NAME_STRING (EMULATOR_NAME " " _XSTRINGFY(EMULATOR_VERSION_LEAD) "." _XSTRINGFY(EMULATOR_VERSION_MAJOR) EMULATOR_VERSION_SUFFIX)
#endif #endif
#endif #endif

View File

@ -1,6 +1,12 @@
project(CemuAsm C) project(CemuAsm C)
if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)") if (CMAKE_OSX_ARCHITECTURES)
set(CEMU_ASM_ARCHITECTURE ${CMAKE_OSX_ARCHITECTURES})
else()
set(CEMU_ASM_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR})
endif()
if (CEMU_ASM_ARCHITECTURE MATCHES "(x86)|(X86)|(amd64)|(AMD64)")
if (WIN32) if (WIN32)
@ -40,8 +46,8 @@ if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)")
endif() endif()
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "(aarch64)|(AARCH64)") elseif(CEMU_ASM_ARCHITECTURE MATCHES "(aarch64)|(AARCH64)|(arm64)|(ARM64)")
add_library(CemuAsm stub.cpp) add_library(CemuAsm stub.cpp)
else() else()
message(STATUS "CemuAsm - Unsupported arch: ${CMAKE_SYSTEM_PROCESSOR}") message(STATUS "CemuAsm - Unsupported arch: ${CEMU_ASM_ARCHITECTURE}")
endif() endif()

View File

@ -38,6 +38,7 @@ void CemuConfig::Load(XMLConfigParser& parser)
fullscreen_menubar = parser.get("fullscreen_menubar", false); fullscreen_menubar = parser.get("fullscreen_menubar", false);
feral_gamemode = parser.get("feral_gamemode", false); feral_gamemode = parser.get("feral_gamemode", false);
check_update = parser.get("check_update", check_update); check_update = parser.get("check_update", check_update);
receive_untested_updates = parser.get("receive_untested_updates", check_update);
save_screenshot = parser.get("save_screenshot", save_screenshot); save_screenshot = parser.get("save_screenshot", save_screenshot);
did_show_vulkan_warning = parser.get("vk_warning", did_show_vulkan_warning); did_show_vulkan_warning = parser.get("vk_warning", did_show_vulkan_warning);
did_show_graphic_pack_download = parser.get("gp_download", did_show_graphic_pack_download); did_show_graphic_pack_download = parser.get("gp_download", did_show_graphic_pack_download);
@ -360,6 +361,7 @@ void CemuConfig::Save(XMLConfigParser& parser)
config.set<bool>("fullscreen_menubar", fullscreen_menubar); config.set<bool>("fullscreen_menubar", fullscreen_menubar);
config.set<bool>("feral_gamemode", feral_gamemode); config.set<bool>("feral_gamemode", feral_gamemode);
config.set<bool>("check_update", check_update); config.set<bool>("check_update", check_update);
config.set<bool>("receive_untested_updates", receive_untested_updates);
config.set<bool>("save_screenshot", save_screenshot); config.set<bool>("save_screenshot", save_screenshot);
config.set<bool>("vk_warning", did_show_vulkan_warning); config.set<bool>("vk_warning", did_show_vulkan_warning);
config.set<bool>("gp_download", did_show_graphic_pack_download); config.set<bool>("gp_download", did_show_graphic_pack_download);

View File

@ -414,7 +414,8 @@ struct CemuConfig
Vector2i pad_size{ -1,-1 }; Vector2i pad_size{ -1,-1 };
ConfigValue<bool> pad_maximized; ConfigValue<bool> pad_maximized;
ConfigValue<bool> check_update{false}; ConfigValue<bool> check_update{true};
ConfigValue<bool> receive_untested_updates{false};
ConfigValue<bool> save_screenshot{true}; ConfigValue<bool> save_screenshot{true};
ConfigValue<bool> did_show_vulkan_warning{false}; ConfigValue<bool> did_show_vulkan_warning{false};

View File

@ -112,10 +112,10 @@ bool LaunchSettings::HandleCommandline(const std::vector<std::wstring>& args)
{ {
requireConsole(); requireConsole();
std::string versionStr; std::string versionStr;
#if EMULATOR_VERSION_MINOR == 0 #if EMULATOR_VERSION_PATCH == 0
versionStr = fmt::format("{}.{}{}", EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_SUFFIX); versionStr = fmt::format("{}.{}{}", EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR, EMULATOR_VERSION_SUFFIX);
#else #else
versionStr = fmt::format("{}.{}-{}{}", EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR, EMULATOR_VERSION_SUFFIX); versionStr = fmt::format("{}.{}-{}{}", EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR, EMULATOR_VERSION_PATCH, EMULATOR_VERSION_SUFFIX);
#endif #endif
std::cout << versionStr << std::endl; std::cout << versionStr << std::endl;
return false; // exit in main return false; // exit in main

View File

@ -116,9 +116,11 @@ bool CemuUpdateWindow::QueryUpdateInfo(std::string& downloadUrlOut, std::string&
#elif BOOST_OS_MACOS #elif BOOST_OS_MACOS
urlStr.append("&platform=macos_bundle_x86"); urlStr.append("&platform=macos_bundle_x86");
#elif #elif
#error Name for current platform is missing #error Name for current platform is missing
#endif #endif
const auto& config = GetConfig();
if(config.receive_untested_updates)
urlStr.append("&allowNewUpdates=1");
curl_easy_setopt(curl, CURLOPT_URL, urlStr.c_str()); curl_easy_setopt(curl, CURLOPT_URL, urlStr.c_str());
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);

View File

@ -115,7 +115,7 @@ void DownloadGraphicPacksWindow::UpdateThread()
curlDownloadFileState_t tempDownloadState; curlDownloadFileState_t tempDownloadState;
std::string queryUrl("https://cemu.info/api2/query_graphicpack_url.php?"); std::string queryUrl("https://cemu.info/api2/query_graphicpack_url.php?");
char temp[64]; char temp[64];
sprintf(temp, "version=%d.%d.%d", EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR); sprintf(temp, "version=%d.%d.%d", EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR, EMULATOR_VERSION_PATCH);
queryUrl.append(temp); queryUrl.append(temp);
queryUrl.append("&"); queryUrl.append("&");
sprintf(temp, "t=%u", (uint32)std::chrono::seconds(std::time(NULL)).count()); // add a dynamic part to the url to bypass overly aggressive caching (like some proxies do) sprintf(temp, "t=%u", (uint32)std::chrono::seconds(std::time(NULL)).count()); // add a dynamic part to the url to bypass overly aggressive caching (like some proxies do)

View File

@ -141,49 +141,66 @@ wxPanel* GeneralSettings2::AddGeneralPage(wxNotebook* notebook)
second_row->SetFlexibleDirection(wxBOTH); second_row->SetFlexibleDirection(wxBOTH);
second_row->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED); second_row->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
sint32 checkboxCount = 0;
auto CountRowElement = [&]()
{
checkboxCount++;
if(checkboxCount != 2)
return;
second_row->AddSpacer(10);
checkboxCount = 0;
};
auto InsertEmptyRow = [&]()
{
while(checkboxCount != 0)
CountRowElement();
second_row->AddSpacer(10);
second_row->AddSpacer(10);
second_row->AddSpacer(10);
};
const int topflag = wxALIGN_CENTER_VERTICAL | wxALL; const int topflag = wxALIGN_CENTER_VERTICAL | wxALL;
m_save_window_position_size = new wxCheckBox(box, wxID_ANY, _("Remember main window position")); m_save_window_position_size = new wxCheckBox(box, wxID_ANY, _("Remember main window position"));
m_save_window_position_size->SetToolTip(_("Restores the last known window position and size when starting Cemu")); m_save_window_position_size->SetToolTip(_("Restores the last known window position and size when starting Cemu"));
second_row->Add(m_save_window_position_size, 0, topflag, 5); second_row->Add(m_save_window_position_size, 0, topflag, 5);
second_row->AddSpacer(10); CountRowElement();
//second_row->AddSpacer(10);
m_save_padwindow_position_size = new wxCheckBox(box, wxID_ANY, _("Remember pad window position")); m_save_padwindow_position_size = new wxCheckBox(box, wxID_ANY, _("Remember pad window position"));
m_save_padwindow_position_size->SetToolTip(_("Restores the last known pad window position and size when opening it")); m_save_padwindow_position_size->SetToolTip(_("Restores the last known pad window position and size when opening it"));
second_row->Add(m_save_padwindow_position_size, 0, topflag, 5); second_row->Add(m_save_padwindow_position_size, 0, topflag, 5);
CountRowElement();
const int botflag = wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT | wxBOTTOM; const int botflag = wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT | wxBOTTOM;
m_discord_presence = new wxCheckBox(box, wxID_ANY, _("Discord Presence")); m_discord_presence = new wxCheckBox(box, wxID_ANY, _("Discord Presence"));
m_discord_presence->SetToolTip(_("Enables the Discord Rich Presence feature\nYou will also need to enable it in the Discord settings itself!")); m_discord_presence->SetToolTip(_("Enables the Discord Rich Presence feature\nYou will also need to enable it in the Discord settings itself!"));
second_row->Add(m_discord_presence, 0, botflag, 5); second_row->Add(m_discord_presence, 0, botflag, 5);
CountRowElement();
#ifndef ENABLE_DISCORD_RPC #ifndef ENABLE_DISCORD_RPC
m_discord_presence->Disable(); m_discord_presence->Disable();
#endif #endif
second_row->AddSpacer(10); //second_row->AddSpacer(10);
m_fullscreen_menubar = new wxCheckBox(box, wxID_ANY, _("Fullscreen menu bar")); m_fullscreen_menubar = new wxCheckBox(box, wxID_ANY, _("Fullscreen menu bar"));
m_fullscreen_menubar->SetToolTip(_("Displays the menu bar when Cemu is running in fullscreen mode and the mouse cursor is moved to the top")); m_fullscreen_menubar->SetToolTip(_("Displays the menu bar when Cemu is running in fullscreen mode and the mouse cursor is moved to the top"));
second_row->Add(m_fullscreen_menubar, 0, botflag, 5); second_row->Add(m_fullscreen_menubar, 0, botflag, 5);
CountRowElement();
m_auto_update = new wxCheckBox(box, wxID_ANY, _("Automatically check for updates"));
m_auto_update->SetToolTip(_("Automatically checks for new cemu versions on startup"));
second_row->Add(m_auto_update, 0, botflag, 5);
#if BOOST_OS_LINUX
if (!std::getenv("APPIMAGE")) {
m_auto_update->Disable();
}
#endif
second_row->AddSpacer(10);
m_save_screenshot = new wxCheckBox(box, wxID_ANY, _("Save screenshot")); m_save_screenshot = new wxCheckBox(box, wxID_ANY, _("Save screenshot"));
m_save_screenshot->SetToolTip(_("Pressing the screenshot key (F12) will save a screenshot directly to the screenshots folder")); m_save_screenshot->SetToolTip(_("Pressing the screenshot key (F12) will save a screenshot directly to the screenshots folder"));
second_row->Add(m_save_screenshot, 0, botflag, 5); second_row->Add(m_save_screenshot, 0, botflag, 5);
CountRowElement();
m_disable_screensaver = new wxCheckBox(box, wxID_ANY, _("Disable screen saver")); m_disable_screensaver = new wxCheckBox(box, wxID_ANY, _("Disable screen saver"));
m_disable_screensaver->SetToolTip(_("Prevents the system from activating the screen saver or going to sleep while running a game.")); m_disable_screensaver->SetToolTip(_("Prevents the system from activating the screen saver or going to sleep while running a game."));
second_row->Add(m_disable_screensaver, 0, botflag, 5); second_row->Add(m_disable_screensaver, 0, botflag, 5);
CountRowElement();
// Enable/disable feral interactive gamemode // Enable/disable feral interactive gamemode
#if BOOST_OS_LINUX && defined(ENABLE_FERAL_GAMEMODE) #if BOOST_OS_LINUX && defined(ENABLE_FERAL_GAMEMODE)
m_feral_gamemode = new wxCheckBox(box, wxID_ANY, _("Enable Feral GameMode")); m_feral_gamemode = new wxCheckBox(box, wxID_ANY, _("Enable Feral GameMode"));
m_feral_gamemode->SetToolTip(_("Use FeralInteractive GameMode if installed.")); m_feral_gamemode->SetToolTip(_("Use FeralInteractive GameMode if installed."));
second_row->Add(m_feral_gamemode, 0, botflag, 5); second_row->Add(m_feral_gamemode, 0, botflag, 5);
CountRowElement();
#endif #endif
// temporary workaround because feature crashes on macOS // temporary workaround because feature crashes on macOS
@ -191,6 +208,22 @@ wxPanel* GeneralSettings2::AddGeneralPage(wxNotebook* notebook)
m_disable_screensaver->Enable(false); m_disable_screensaver->Enable(false);
#endif #endif
// InsertEmptyRow();
m_auto_update = new wxCheckBox(box, wxID_ANY, _("Automatically check for updates"));
m_auto_update->SetToolTip(_("Automatically checks for new cemu versions on startup"));
second_row->Add(m_auto_update, 0, botflag, 5);
CountRowElement();
m_receive_untested_releases = new wxCheckBox(box, wxID_ANY, _("Receive untested updates"));
m_receive_untested_releases->SetToolTip(_("When checking for updates, include brand new and untested releases. These may contain bugs!"));
second_row->Add(m_receive_untested_releases, 0, botflag, 5);
#if BOOST_OS_LINUX
if (!std::getenv("APPIMAGE")) {
m_auto_update->Disable();
}
#endif
box_sizer->Add(second_row, 0, wxEXPAND, 5); box_sizer->Add(second_row, 0, wxEXPAND, 5);
} }
@ -1538,6 +1571,7 @@ void GeneralSettings2::ApplyConfig()
m_fullscreen_menubar->SetValue(config.fullscreen_menubar); m_fullscreen_menubar->SetValue(config.fullscreen_menubar);
m_auto_update->SetValue(config.check_update); m_auto_update->SetValue(config.check_update);
m_receive_untested_releases->SetValue(config.receive_untested_updates);
m_save_screenshot->SetValue(config.save_screenshot); m_save_screenshot->SetValue(config.save_screenshot);
m_disable_screensaver->SetValue(config.disable_screensaver); m_disable_screensaver->SetValue(config.disable_screensaver);

View File

@ -41,7 +41,7 @@ private:
wxCheckBox* m_save_window_position_size; wxCheckBox* m_save_window_position_size;
wxCheckBox* m_save_padwindow_position_size; wxCheckBox* m_save_padwindow_position_size;
wxCheckBox* m_discord_presence, *m_fullscreen_menubar; wxCheckBox* m_discord_presence, *m_fullscreen_menubar;
wxCheckBox* m_auto_update, *m_save_screenshot; wxCheckBox* m_auto_update, *m_receive_untested_releases, *m_save_screenshot;
wxCheckBox* m_disable_screensaver; wxCheckBox* m_disable_screensaver;
#if BOOST_OS_LINUX && defined(ENABLE_FERAL_GAMEMODE) #if BOOST_OS_LINUX && defined(ENABLE_FERAL_GAMEMODE)
wxCheckBox* m_feral_gamemode; wxCheckBox* m_feral_gamemode;

View File

@ -458,10 +458,10 @@ void GraphicPacksWindow2::OnTreeSelectionChanged(wxTreeEvent& event)
m_shown_graphic_pack = gp; m_shown_graphic_pack = gp;
m_graphic_pack_name->Wrap(m_graphic_pack_name->GetParent()->GetClientSize().GetWidth() - 10); m_graphic_pack_name->Wrap(m_graphic_pack_name->GetParent()->GetClientSize().GetWidth() - 20);
m_graphic_pack_name->GetGrandParent()->Layout(); m_graphic_pack_name->GetGrandParent()->Layout();
m_graphic_pack_description->Wrap(m_graphic_pack_description->GetParent()->GetClientSize().GetWidth() - 10); m_graphic_pack_description->Wrap(m_graphic_pack_description->GetParent()->GetClientSize().GetWidth() - 20);
m_graphic_pack_description->GetGrandParent()->Layout(); m_graphic_pack_description->GetGrandParent()->Layout();
m_right_panel->FitInside(); m_right_panel->FitInside();

View File

@ -73,8 +73,8 @@ END
#define str(s) #s #define str(s) #s
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR, 0 FILEVERSION EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR, EMULATOR_VERSION_PATCH, 0
PRODUCTVERSION EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR, 0 PRODUCTVERSION EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR, EMULATOR_VERSION_PATCH, 0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -94,7 +94,7 @@ BEGIN
VALUE "LegalCopyright", "Team Cemu" VALUE "LegalCopyright", "Team Cemu"
VALUE "OriginalFilename", "Cemu.exe" VALUE "OriginalFilename", "Cemu.exe"
VALUE "ProductName", "Cemu" VALUE "ProductName", "Cemu"
VALUE "ProductVersion", xstr(EMULATOR_VERSION_LEAD) "." xstr(EMULATOR_VERSION_MAJOR) "." xstr(EMULATOR_VERSION_MINOR) EMULATOR_VERSION_SUFFIX "\0" VALUE "ProductVersion", xstr(EMULATOR_VERSION_MAJOR) "." xstr(EMULATOR_VERSION_MINOR) "." xstr(EMULATOR_VERSION_PATCH) EMULATOR_VERSION_SUFFIX "\0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"