Merge branch 'libretro-compat' into libretro

This commit is contained in:
刘皓 2025-02-21 23:56:52 -05:00
commit 8a8860912a
No known key found for this signature in database
GPG key ID: 7901753DB465B711
28 changed files with 2006 additions and 453 deletions

View file

@ -612,7 +612,14 @@ jobs:
echo "CMAKE_SHARED_LINKER_FLAGS_INIT = '-fuse-ld=lld'" | tee -a ${{ runner.temp }}/cross.ini
echo "CMAKE_STATIC_LINKER_FLAGS_INIT = '-fuse-ld=lld'" | tee -a ${{ runner.temp }}/cross.ini
echo '--------------------------------------------------------------------------------'
CLICOLOR_FORCE=1 meson setup build --cross-file ${{ runner.temp }}/cross.ini --buildtype release -Db_lto=true -Dlibretro=true
# If architecture is s390x and Clang version is older than 19.1.0, disable LTO due to https://github.com/llvm/llvm-project/issues/61101
if [ '${{ matrix.arch_mkxpz }}' = 's390x' ] && (echo "$(clang --version | head -n 1 | sed -e 's/.*clang version * \([0-9.]*\).*/\1/')\n19.1.0" | sort -CV)
then
lto=false
else
lto=true
fi
CLICOLOR_FORCE=1 meson setup build --cross-file ${{ runner.temp }}/cross.ini --buildtype release -Db_lto=$lto -Dlibretro=true
- name: Build core
run: |
@ -1061,6 +1068,22 @@ jobs:
apt remove -y meson cmake
pip install meson cmake
- name: Build and install wiiurpxtool
run: |
if command -v wiiurpxtool
then
echo 'wiiurpxtool already installed'
else
cd ~
git clone https://github.com/yawut/wiiurpxtool-ng
cd wiiurpxtool-ng
git checkout 682cc9f587dee507b400a307f5a0787efc5dcb72
git submodule update --init --recursive
cmake -G Ninja .
ninja -v
mv wiiurpxtool-ng /usr/local/bin/wiiurpxtool
fi
- id: short-sha
name: Get Git commit hash
uses: benjlevesque/short-sha@v2.2
@ -1242,7 +1265,6 @@ jobs:
cd retroarch
CLICOLOR_FORCE=1 make -f Makefile.libnx LIBRETRO=mkxp-z
mv retroarch_switch.nro ~/dist/mkxp-z_libretro.nro
mv retroarch_switch.elf ~/dist/mkxp-z_libretro.elf
- name: Upload artifact
uses: actions/upload-artifact@v4

View file

@ -28,6 +28,8 @@
# include <string.h>
#endif
#include <mkxp-retro-ruby-func-types.h>
#ifdef __cplusplus
extern "C" {
#endif

View file

@ -18,6 +18,7 @@ GIT ?= git
ZIP ?= zip
XXD ?= xxd
SED ?= sed
GREP ?= grep
CC ?= cc
CXX ?= c++
LD ?= ld
@ -91,6 +92,14 @@ $(OUTDIR)/sdl/include/SDL.h:
$(OUTDIR)/mkxp-retro-ruby/mkxp-retro-ruby.h $(OUTDIR)/mkxp-retro-ruby/mkxp-retro-ruby-impl.h $(OUTDIR)/mkxp-retro-ruby/mkxp-retro-ruby_0.c $(OUTDIR)/mkxp-retro-ruby/mkxp-retro-ruby_1.c $(OUTDIR)/mkxp-retro-ruby/mkxp-retro-ruby_2.c $(OUTDIR)/mkxp-retro-ruby/mkxp-retro-ruby_3.c $(OUTDIR)/mkxp-retro-ruby/mkxp-retro-ruby_4.c $(OUTDIR)/mkxp-retro-ruby/mkxp-retro-ruby_5.c $(OUTDIR)/mkxp-retro-ruby/mkxp-retro-ruby_6.c $(OUTDIR)/mkxp-retro-ruby/mkxp-retro-ruby_7.c &: $(LIBDIR)/mkxp-retro-dist/bin/ruby
mkdir -p $(OUTDIR)/mkxp-retro-ruby
$(WASM2C) $(LIBDIR)/mkxp-retro-dist/bin/ruby -n ruby --num-outputs=8 -o $(OUTDIR)/mkxp-retro-ruby/mkxp-retro-ruby.c
# Find all the function types declared using `FUNC_TYPE_DECL_EXTERN_T` and redeclare them as macros to fix the "initializer element is not constant" compilation error that occurs when using GCC versions earlier than 8.1.0
rm -f $(OUTDIR)/mkxp-retro-ruby/mkxp-retro-ruby-func-types.h
for func_type in $$($(GREP) -r 'FUNC_TYPE_DECL_EXTERN_T *([^()]*)' $(OUTDIR)/mkxp-retro-ruby/mkxp-retro-ruby-impl.h | $(GREP) -v '# *define' | $(SED) -e 's/FUNC_TYPE_DECL_EXTERN_T *( *\(.*\) *).*/\1/'); do \
echo "#define $$func_type \"$$($(XXD) -c 0 -l 32 -p /dev/urandom | $(SED) -e 's/.\{2\}/\\x&/g')\"" >> $(OUTDIR)/mkxp-retro-ruby/mkxp-retro-ruby-func-types.h; \
done
$(SED) -i 's/ *# *define * FUNC_TYPE_DECL_EXTERN_T *([^()]).*/#define FUNC_TYPE_DECL_EXTERN_T(x)/g' $(OUTDIR)/mkxp-retro-ruby/mkxp-retro-ruby-impl.h
$(SED) -i 's/ *# *define * FUNC_TYPE_EXTERN_T *([^()]).*/#define FUNC_TYPE_EXTERN_T(x) const char _mkxp_unused_##x[]/g' $(OUTDIR)/mkxp-retro-ruby/mkxp-retro-ruby-impl.h
$(SED) -i 's/ *# *define * FUNC_TYPE_T *([^()]).*/#define FUNC_TYPE_T(x) static const char _mkxp_unused_##x[]/g' $(OUTDIR)/mkxp-retro-ruby/mkxp-retro-ruby-impl.h
$(OUTDIR)/mkxp-retro-dist.zip.cpp: $(LIBDIR)/mkxp-retro-dist.zip
mkdir -p $(OUTDIR)

View file

@ -1,4 +1,4 @@
project('mkxp-z', 'c', 'cpp', version: '2.4.2', meson_version: '>=1.3.0', default_options: ['cpp_std=c++14', 'buildtype=release'])
project('mkxp-z', 'c', 'cpp', version: '2.4.2', meson_version: '>=1.3.0', default_options: ['cpp_std=c++14', 'buildtype=release', 'b_staticpic=false'])
host_system = host_machine.system()
host_endian = host_machine.endian()
@ -8,7 +8,7 @@ is_emscripten = host_system == 'emscripten'
core_is_static = is_emscripten or host_system == 'bare' or host_system == 'none'
if not is_libretro and host_system == 'darwin'
error('\nThis Meson project no longer supports macOS. Please use the Xcode project instead.')
error('This Meson project no longer supports macOS. Please use the Xcode project instead.')
endif
xxd = find_program('xxd', native: true)
@ -39,19 +39,6 @@ global_sources += vcs_tag(command: ['git', 'rev-parse', '--short', 'HEAD'], fall
if is_libretro
libretro_stage1_path = get_option('libretro_stage1_path')
libretro_defines = [
'-DMKXPZ_VERSION="@0@"'.format(meson.project_version()),
'-DMKXPZ_RETRO',
'-DSHARED_FLUID',
]
if host_endian == 'big'
libretro_defines += '-DMKXPZ_BIG_ENDIAN'
endif
if is_emscripten or not compilers['cpp'].compiles('struct E {}; int main() { throw E(); }', name: 'check if C++ exceptions are supported')
libretro_defines += '-DMKXPZ_NO_EXCEPTIONS'
libretro_defines += '-DBOOST_NO_EXCEPTIONS'
endif
libretro_link_args = []
libretro_cflags = []
libretro_cppflags = []
@ -85,32 +72,119 @@ if is_libretro
libretro_link_args += '-Wl,--version-script,' + meson.current_source_dir() / 'libretro/link.T'
endif
libretro_defines = [
'-DMKXPZ_VERSION="@0@"'.format(meson.project_version()),
'-DMKXPZ_RETRO',
'-DSHARED_FLUID',
'-D_FILE_OFFSET_BITS=64',
'-DMPG123_NO_LARGENAME',
]
if host_endian == 'big'
libretro_defines += '-DMKXPZ_BIG_ENDIAN'
endif
if is_emscripten or not compilers['cpp'].compiles('struct E {}; int main() { throw E(); }', name: 'C++ exceptions support check')
libretro_defines += '-DMKXPZ_NO_EXCEPTIONS'
libretro_defines += '-DBOOST_NO_EXCEPTIONS'
endif
if not compilers['cpp'].has_header_symbol('mutex', 'std::mutex')
libretro_defines += '-DMKXPZ_NO_STD_MUTEX'
endif
if not compilers['cpp'].has_header_symbol('mutex', 'std::recursive_mutex')
libretro_defines += '-DMKXPZ_NO_STD_RECURSIVE_MUTEX'
endif
if not compilers['cpp'].has_header_symbol('thread', 'std::this_thread::yield')
libretro_defines += '-DMKXPZ_NO_STD_THIS_THREAD_YIELD'
endif
if not compilers['cpp'].has_header('pthread.h') or not compilers['cpp'].compiles('''
#include <pthread.h>
int main() {
pthread_mutex_t mutex;
pthread_cond_t cond;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
pthread_cond_signal(&cond);
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
int result = pthread_self() != pthread_self();
pthread_mutex_unlock(&mutex);
pthread_cond_destroy(&cond);
pthread_mutex_destroy(&mutex);
return result;
}
''', name: 'pthread.h sanity check')
libretro_defines += '-DMKXPZ_NO_PTHREAD_H'
libretro_defines += '-DMKXPZ_NO_SEMAPHORE_H'
elif not compilers['cpp'].has_header('semaphore.h') or not compilers['cpp'].compiles('''
#include <semaphore.h>
int main() {
sem_t sem;
sem_init(&sem, 0, 0);
sem_post(&sem);
sem_wait(&sem);
sem_destroy(&sem);
return 0;
}
''', name: 'semaphore.h sanity check')
libretro_defines += '-DMKXPZ_NO_SEMAPHORE_H'
endif
# Enable integer-only mode in FLAC when building with Vita SDK. Otherwise, we get an internal compiler error in FLAC__window_triangle:
#
# ../subprojects/flac/src/libFLAC/window.c: In function 'FLAC__window_triangle':
# ../subprojects/flac/src/libFLAC/window.c:197:1: error: unrecognizable insn:
# 197 | }
# | ^
# (insn 191 190 192 21 (set (reg:V4SF 443)
# (mult:V4SF (reg:V4SF 443)
# (reg:V4SF 444))) "../subprojects/flac/src/libFLAC/window.c":189:43 -1
# (nil))
# during RTL pass: vregs
# ../subprojects/flac/src/libFLAC/window.c:197:1: internal compiler error: in extract_insn, at recog.c:2294
# Please submit a full bug report,
# with preprocessed source if appropriate.
# See <https://gcc.gnu.org/bugs/> for instructions.
if compilers['c'].has_header_symbol('sys/config.h', '__vita__')
libretro_defines += '-DFLAC__INTEGER_ONLY_LIBRARY'
endif
# Position-independent code is not supported on some platforms where we need to build a static library, e.g. https://github.com/vitasdk/vita-toolchain/issues/264
use_pic = is_emscripten or not core_is_static
if not use_pic and get_option('b_staticpic')
error('The `b_staticpic` option needs to be disabled when building for this platform.')
endif
subdir('shader')
cmake = import('cmake')
boost_options = cmake.subproject_options()
boost_options.add_cmake_defines({
'CMAKE_C_FLAGS': ' '.join(libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': get_option('b_staticpic'),
'CMAKE_C_FLAGS': ' '.join(libretro_defines + libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_defines + libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': use_pic,
'BUILD_TESTING': false,
})
zlib_options = cmake.subproject_options()
zlib_options.add_cmake_defines({
'CMAKE_C_FLAGS': ' '.join(libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': get_option('b_staticpic'),
'CMAKE_C_FLAGS': ' '.join(libretro_defines + libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_defines + libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': use_pic,
'BUILD_SHARED_LIBS': false,
'ZLIB_BUILD_EXAMPLES': false,
})
libzip_options = cmake.subproject_options()
libzip_options.add_cmake_defines({
'CMAKE_C_FLAGS': ' '.join(libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': get_option('b_staticpic'),
'CMAKE_C_FLAGS': ' '.join(libretro_defines + libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_defines + libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': use_pic,
'BUILD_SHARED_LIBS': false,
'LIBZIP_DO_INSTALL': false,
'BUILD_TOOLS': false,
@ -131,9 +205,9 @@ if is_libretro
physfs_options = cmake.subproject_options()
physfs_options.add_cmake_defines({
'CMAKE_C_FLAGS': ' '.join(libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': get_option('b_staticpic'),
'CMAKE_C_FLAGS': ' '.join(libretro_defines + libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_defines + libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': use_pic,
'PHYSFS_BUILD_STATIC': true,
'PHYSFS_BUILD_SHARED': false,
'PHYSFS_BUILD_TEST': false,
@ -142,9 +216,9 @@ if is_libretro
openal_options = cmake.subproject_options()
openal_options.add_cmake_defines({
'CMAKE_C_FLAGS': ' '.join(libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': get_option('b_staticpic'),
'CMAKE_C_FLAGS': ' '.join(libretro_defines + libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_defines + libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': use_pic,
'LIBTYPE': 'STATIC',
'ALSOFT_DLOPEN': false,
'ALSOFT_UTILS': false,
@ -175,18 +249,18 @@ if is_libretro
fluidlite_options = cmake.subproject_options()
fluidlite_options.add_cmake_defines({
'CMAKE_C_FLAGS': ' '.join(libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': get_option('b_staticpic'),
'CMAKE_C_FLAGS': ' '.join(libretro_defines + libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_defines + libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': use_pic,
'FLUIDLITE_BUILD_STATIC': true,
'FLUIDLITE_BUILD_SHARED': false,
})
ogg_options = cmake.subproject_options()
ogg_options.add_cmake_defines({
'CMAKE_C_FLAGS': ' '.join(libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': get_option('b_staticpic'),
'CMAKE_C_FLAGS': ' '.join(libretro_defines + libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_defines + libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': use_pic,
'BUILD_SHARED_LIBS': false,
'BUILD_TESTING': false,
'BUILD_FRAMEWORK': false,
@ -194,9 +268,9 @@ if is_libretro
vorbis_options = cmake.subproject_options()
vorbis_options.add_cmake_defines({
'CMAKE_C_FLAGS': ' '.join(libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': get_option('b_staticpic'),
'CMAKE_C_FLAGS': ' '.join(libretro_defines + libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_defines + libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': use_pic,
'BUILD_SHARED_LIBS': false,
'BUILD_TESTING': false,
'BUILD_FRAMEWORK': false,
@ -204,9 +278,9 @@ if is_libretro
flac_options = cmake.subproject_options()
flac_options.add_cmake_defines({
'CMAKE_C_FLAGS': ' '.join(libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': get_option('b_staticpic'),
'CMAKE_C_FLAGS': ' '.join(libretro_defines + libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_defines + libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': use_pic,
'BUILD_SHARED_LIBS': false,
'BUILD_CXXLIBS': false,
'BUILD_PROGRAMS': false,
@ -223,9 +297,9 @@ if is_libretro
opus_options = cmake.subproject_options()
opus_options.add_cmake_defines({
'CMAKE_C_FLAGS': ' '.join(libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': get_option('b_staticpic'),
'CMAKE_C_FLAGS': ' '.join(libretro_defines + libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_defines + libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': use_pic,
'BUILD_SHARED_LIBS': false,
'OPUS_BUILD_SHARED_LIBRARY': false,
'OPUS_BUILD_TESTING': false,
@ -241,9 +315,9 @@ if is_libretro
mpg123_options = cmake.subproject_options()
mpg123_options.add_cmake_defines({
'CMAKE_C_FLAGS': ' '.join(libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': get_option('b_staticpic'),
'CMAKE_C_FLAGS': ' '.join(libretro_defines + libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_defines + libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': use_pic,
'BUILD_SHARED_LIBS': false,
'BUILD_PROGRAMS': false,
'BUILD_LIBOUT123': false,
@ -253,9 +327,9 @@ if is_libretro
libsndfile_options = cmake.subproject_options()
libsndfile_options.add_cmake_defines({
'CMAKE_C_FLAGS': ' '.join(libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': get_option('b_staticpic'),
'CMAKE_C_FLAGS': ' '.join(libretro_defines + libretro_cflags),
'CMAKE_CXX_FLAGS': ' '.join(libretro_defines + libretro_cppflags),
'CMAKE_POSITION_INDEPENDENT_CODE': use_pic,
'BUILD_SHARED_LIBS': false,
'BUILD_PROGRAMS': false,
'BUILD_EXAMPLES': false,
@ -362,6 +436,7 @@ if is_libretro
],
sources: global_sources + [
'src/core.cpp',
'src/mkxp-threads.cpp',
'src/sharedstate.cpp',
'src/audio/alstream.cpp',
'src/audio/audio.cpp',

View file

@ -227,6 +227,7 @@ static bool init_sandbox() {
fluid_set_log_function(FLUID_DBG, fluid_log, NULL);
static fluid_fileapi_t fluid_fileapi = {
.data = NULL,
.free = [](fluid_fileapi_t *f) {
return 0;
},

View file

@ -423,7 +423,6 @@ struct BitmapPrivate
FBO::clear();
glState.clearColor.pop();
glState.scissorBox.pop();
glState.scissorTest.pop();
}

157
src/mkxp-threads.cpp Normal file
View file

@ -0,0 +1,157 @@
/*
** mkxp-threads.cpp
**
** This file is part of mkxp.
**
** Copyright (C) 2013 - 2021 Amaryllis Kulla <ancurio@mapleshrine.eu>
**
** mkxp is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 2 of the License, or
** (at your option) any later version.
**
** mkxp is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
*/
#include "mkxp-threads.h"
#include <cassert>
#if defined(MKXPZ_NO_SEMAPHORE_H) && !defined(MKXPZ_NO_PTHREAD_H)
struct mkxp_sem_private {
unsigned int value;
pthread_mutex_t mutex;
pthread_cond_t cond;
};
#endif
extern "C" mkxp_thread_t mkxp_thread_self() {
#ifndef MKXPZ_NO_PTHREAD_H
return pthread_self();
#else
return 42;
#endif
}
extern "C" int mkxp_mutex_init(mkxp_mutex_t *mutex, bool recursive) {
#ifndef MKXPZ_NO_PTHREAD_H
if (recursive) {
pthread_mutexattr_t attr;
if (pthread_mutexattr_init(&attr)) {
return -1;
}
if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) {
return -1;
}
return pthread_mutex_init(mutex, &attr);
} else {
return pthread_mutex_init(mutex, NULL);
}
#else
*mutex = 0;
return 0;
#endif
}
extern "C" int mkxp_mutex_destroy(mkxp_mutex_t *mutex) {
#ifndef MKXPZ_NO_PTHREAD_H
return pthread_mutex_destroy(mutex);
#else
assert(!*mutex);
return 0;
#endif
}
extern "C" int mkxp_mutex_lock(mkxp_mutex_t *mutex) {
#ifndef MKXPZ_NO_PTHREAD_H
return pthread_mutex_lock(mutex);
#else
++*mutex;
return 0;
#endif
}
extern "C" int mkxp_mutex_unlock(mkxp_mutex_t *mutex) {
#ifndef MKXPZ_NO_PTHREAD_H
return pthread_mutex_unlock(mutex);
#else
assert(*mutex);
--*mutex;
return 0;
#endif
}
extern "C" int mkxp_sem_init(mkxp_sem_t *sem, unsigned int value) {
#ifndef MKXPZ_NO_SEMAPHORE_H
return sem_init(sem, 0, value);
#elif !defined(MKXPZ_NO_PTHREAD_H)
*sem = (void *)new mkxp_sem_private;
int mutex_init_result = pthread_mutex_init(&((struct mkxp_sem_private *)*sem)->mutex, NULL);
if (mutex_init_result) {
return -1;
}
int cond_init_result = pthread_cond_init(&((struct mkxp_sem_private *)*sem)->cond, NULL);
if (cond_init_result) {
pthread_mutex_destroy(&((struct mkxp_sem_private *)*sem)->mutex);
return -1;
}
((struct mkxp_sem_private *)*sem)->value = value;
return 0;
#else
*sem = value;
return 0;
#endif
}
extern "C" int mkxp_sem_destroy(mkxp_sem_t *sem) {
#ifndef MKXPZ_NO_SEMAPHORE_H
return sem_destroy(sem);
#elif !defined(MKXPZ_NO_PTHREAD_H)
pthread_cond_destroy(&((struct mkxp_sem_private *)*sem)->cond);
pthread_mutex_destroy(&((struct mkxp_sem_private *)*sem)->mutex);
delete (struct mkxp_sem_private *)*sem;
return 0;
#else
return 0;
#endif
}
extern "C" int mkxp_sem_post(mkxp_sem_t *sem) {
#ifndef MKXPZ_NO_SEMAPHORE_H
return sem_post(sem);
#elif !defined(MKXPZ_NO_PTHREAD_H)
while (pthread_mutex_lock(&((struct mkxp_sem_private *)*sem)->mutex)) {}
++((struct mkxp_sem_private *)*sem)->value;
pthread_cond_signal(&((struct mkxp_sem_private *)*sem)->cond);
pthread_mutex_unlock(&((struct mkxp_sem_private *)*sem)->mutex);
return 0;
#else
++*sem;
return 0;
#endif
}
extern "C" int mkxp_sem_wait(mkxp_sem_t *sem) {
#ifndef MKXPZ_NO_SEMAPHORE_H
return sem_wait(sem);
#elif !defined(MKXPZ_NO_PTHREAD_H)
while (pthread_mutex_lock(&((struct mkxp_sem_private *)*sem)->mutex)) {}
for (;;) {
if (((struct mkxp_sem_private *)*sem)->value) {
--((struct mkxp_sem_private *)*sem)->value;
pthread_mutex_unlock(&((struct mkxp_sem_private *)*sem)->mutex);
return 0;
}
while (pthread_cond_wait(&((struct mkxp_sem_private *)*sem)->cond, &((struct mkxp_sem_private *)*sem)->mutex)) {}
}
#else
assert(*sem);
--*sem;
return 0;
#endif
}

154
src/mkxp-threads.h Normal file
View file

@ -0,0 +1,154 @@
/*
** mkxp-threads.h
**
** This file is part of mkxp.
**
** Copyright (C) 2013 - 2021 Amaryllis Kulla <ancurio@mapleshrine.eu>
**
** mkxp is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 2 of the License, or
** (at your option) any later version.
**
** mkxp is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MKXPZ_THREADS_H
#define MKXPZ_THREADS_H
#include <stdbool.h>
#include <stdlib.h>
#ifndef MKXPZ_NO_PTHREAD_H
# include <pthread.h>
#endif
#ifndef MKXPZ_NO_SEMAPHORE_H
# include <semaphore.h>
#endif
#ifdef __cplusplus
#include <mutex>
extern "C" {
#endif
#ifndef MKXPZ_NO_PTHREAD_H
typedef pthread_t mkxp_thread_t;
typedef pthread_mutex_t mkxp_mutex_t;
#else
typedef size_t mkxp_thread_t;
typedef unsigned int mkxp_mutex_t;
#endif
#ifndef MKXPZ_NO_SEMAPHORE_H
typedef sem_t mkxp_sem_t;
#elif !defined(MKXPZ_NO_PTHREAD_H)
typedef void *mkxp_sem_t;
#else
typedef unsigned int mkxp_sem_t;
#endif
mkxp_thread_t mkxp_thread_self(void);
int mkxp_mutex_init(mkxp_mutex_t *mutex, bool recursive);
int mkxp_mutex_destroy(mkxp_mutex_t *mutex);
int mkxp_mutex_lock(mkxp_mutex_t *mutex);
int mkxp_mutex_unlock(mkxp_mutex_t *mutex);
int mkxp_sem_init(mkxp_sem_t *sem, unsigned int value);
int mkxp_sem_destroy(mkxp_sem_t *sem);
int mkxp_sem_post(mkxp_sem_t *sem);
int mkxp_sem_wait(mkxp_sem_t *sem);
#ifdef __cplusplus
}
# ifdef MKXPZ_NO_STD_MUTEX
namespace std {
class mutex {
public:
typedef mkxp_mutex_t *native_handle_type;
mkxp_mutex_t inner;
inline mutex() noexcept {
if (mkxp_mutex_init(&inner, false)) {
abort();
}
}
inline ~mutex() noexcept {
mkxp_mutex_destroy(&inner);
}
inline void lock() noexcept {
if (mkxp_mutex_lock(&inner)) {
abort();
}
}
inline void unlock() noexcept {
if (mkxp_mutex_unlock(&inner)) {
abort();
}
}
inline native_handle_type native_handle() noexcept {
return &inner;
}
};
}
# endif
# ifdef MKXPZ_NO_STD_RECURSIVE_MUTEX
namespace std {
class recursive_mutex {
public:
typedef mkxp_mutex_t *native_handle_type;
mkxp_mutex_t inner;
inline recursive_mutex() noexcept {
if (mkxp_mutex_init(&inner, true)) {
abort();
}
}
inline ~recursive_mutex() noexcept {
mkxp_mutex_destroy(&inner);
}
inline void lock() noexcept {
if (mkxp_mutex_lock(&inner)) {
abort();
}
}
inline void unlock() noexcept {
if (mkxp_mutex_unlock(&inner)) {
abort();
}
}
inline native_handle_type native_handle() noexcept {
return &inner;
}
};
}
# endif
#endif
#endif // MKXPZ_THREADS_H

View file

@ -1,7 +1,7 @@
#pragma once
#include <atomic>
#include <memory>
#include <mutex>
#include "mkxp-threads.h"
#include <type_traits>
#include <utility>
#include <thread>
@ -348,7 +348,9 @@ struct spin_mutex {
void lock() noexcept {
while (true) {
while (!state.load(std::memory_order_relaxed)) {
#ifndef MKXPZ_NO_STD_THIS_THREAD_YIELD
std::this_thread::yield();
#endif
}
if (try_lock()) {

View file

@ -2,3 +2,4 @@
url = https://github.com/boostorg/asio
revision = boost-1.87.0
depth = 1
diff_files = boost_asio-counter.patch

View file

@ -4,4 +4,4 @@ url = https://github.com/madebr/mpg123
revision = 45fbaaeb00072d689b9c2ac4b7d109343f30abee
depth = 1
patch_directory = mpg123
diff_files = mpg123-compat-str.patch, mpg123-emscripten-endian.patch, mpg123-intrinsics.patch, mpg123-libsyn123.patch, mpg123-offset.patch, mpg123-signal.patch
diff_files = mpg123-emscripten-endian.patch, mpg123-intrinsics.patch, mpg123-libsyn123.patch, mpg123-offset.patch, mpg123-pic.patch, mpg123-signal.patch

View file

@ -2,4 +2,4 @@
url = https://github.com/kcat/openal-soft
revision = 1.24.2
depth = 1
diff_files = openal-soft-android-log.patch, openal-soft-atomic.patch, openal-soft-buildtype.patch, openal-soft-c11.patch, openal-soft-darwin-log.patch, openal-soft-devkitppc.patch, openal-soft-emscripten-pthread.patch, openal-soft-emscripten-setschedparam.patch, openal-soft-emscripten-symbol-conflict.patch, openal-soft-emscripten-tss.patch, openal-soft-event-thread.patch, openal-soft-flockfile.patch, openal-soft-int32.patch
diff_files = openal-soft-android-log.patch, openal-soft-atomic.patch, openal-soft-buildtype.patch, openal-soft-c11.patch, openal-soft-constexpr.patch, openal-soft-emscripten-pthread.patch, openal-soft-emscripten-setschedparam.patch, openal-soft-emscripten-symbol-conflict.patch, openal-soft-event-thread.patch, openal-soft-filesystem.patch, openal-soft-flockfile.patch, openal-soft-int32.patch, openal-soft-mkxp-threads.patch, openal-soft-null.patch, openal-soft-pic.patch, openal-soft-ps3.patch

View file

@ -0,0 +1,14 @@
# Makes the `BOOST_ASIO_CORO_YIELD` and `BOOST_ASIO_CORO_FORK` macros always use the `__COUNTER__` macro, even with non-MSVC compilers.
# Using `__LINE__` results in "duplicate case value" compilation errors when targeting PlayStation 3 due to some idiosyncrasy in how the __LINE__ macro is parsed in the really old GCC version it's using.
--- a/include/boost/asio/coroutine.hpp
+++ b/include/boost/asio/coroutine.hpp
@@ -319,7 +319,7 @@ private:
} \
else
-#if defined(_MSC_VER)
+#if true
# define BOOST_ASIO_CORO_YIELD BOOST_ASIO_CORO_YIELD_IMPL(__COUNTER__ + 1)
# define BOOST_ASIO_CORO_FORK BOOST_ASIO_CORO_FORK_IMPL(__COUNTER__ + 1)
#else // defined(_MSC_VER)

View file

@ -1,11 +0,0 @@
# Removes the duplicate inclusion of compat_str.c.
--- a/ports/cmake/src/compat/CMakeLists.txt
+++ b/ports/cmake/src/compat/CMakeLists.txt
@@ -8,6 +8,3 @@ add_library(${TARGET}_dl OBJECT
"${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/compat/compat_dl.c")
set_target_properties(${TARGET}_dl PROPERTIES POSITION_INDEPENDENT_CODE ON)
-add_library(${TARGET}_str OBJECT
- "${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/compat/compat_str.c")
-set_target_properties(${TARGET}_str PROPERTIES POSITION_INDEPENDENT_CODE ON)

View file

@ -1,16 +1,5 @@
# Fixes a problem where the size of off_t is miscalculated on certain platforms.
--- a/ports/cmake/src/CMakeLists.txt
+++ b/ports/cmake/src/CMakeLists.txt
@@ -71,7 +71,7 @@ check_function_exists(fork HAVE_FORK)
check_function_exists(execvp HAVE_EXECVP)
check_function_exists(ctermid HAVE_CTERMID)
check_function_exists(clock_gettime HAVE_CLOCK_GETTIME)
-
+set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} /D_FILE_OFFSET_BITS=64)
check_type_size(off_t SIZEOF_OFF_T)
if(SIZEOF_OFF_T LESS 8)
--- a/src/libmpg123/lfs_wrap.c
+++ b/src/libmpg123/lfs_wrap.c
@@ -48,18 +48,22 @@

View file

@ -0,0 +1,18 @@
# Prevents mpg123's build system from forcibly enabling position-independent code.
# Also removes the duplicate inclusion of compat_str.c. That causes duplicate symbol errors when linking mpg123 as whole archive.
--- a/ports/cmake/src/compat/CMakeLists.txt
+++ b/ports/cmake/src/compat/CMakeLists.txt
@@ -2,12 +2,6 @@ set(TARGET compat)
add_library(${TARGET} OBJECT
"${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/compat/compat.c"
"${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/compat/compat_str.c")
-set_target_properties(${TARGET} PROPERTIES POSITION_INDEPENDENT_CODE ON)
add_library(${TARGET}_dl OBJECT
"${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/compat/compat_dl.c")
-set_target_properties(${TARGET}_dl PROPERTIES POSITION_INDEPENDENT_CODE ON)
-
-add_library(${TARGET}_str OBJECT
- "${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/compat/compat_str.c")
-set_target_properties(${TARGET}_str PROPERTIES POSITION_INDEPENDENT_CODE ON)

View file

@ -0,0 +1,143 @@
# Removes all exception throwing and logging inside of functions marked `constexpr` since old versions of GCC don't support it.
# When building for PlayStation 3, we use an old enough version of GCC for this to be a problem.
--- a/al/auxeffectslot.cpp
+++ b/al/auxeffectslot.cpp
@@ -243,7 +243,7 @@ constexpr auto EffectSlotTypeFromEnum(ALenum type) noexcept -> EffectSlotType
case AL_EFFECT_DEDICATED_DIALOGUE: return EffectSlotType::Dedicated;
case AL_EFFECT_CONVOLUTION_SOFT: return EffectSlotType::Convolution;
}
- ERR("Unhandled effect enum: {:#04x}", as_unsigned(type));
+
return EffectSlotType::None;
}
--- a/al/buffer.cpp
+++ b/al/buffer.cpp
@@ -88,8 +88,8 @@ constexpr auto EnumFromAmbiLayout(AmbiLayout layout) -> ALenum
case AmbiLayout::FuMa: return AL_FUMA_SOFT;
case AmbiLayout::ACN: return AL_ACN_SOFT;
}
- throw std::runtime_error{fmt::format("Invalid AmbiLayout: {}",
- int{al::to_underlying(layout)})};
+
+ abort();
}
constexpr auto AmbiScalingFromEnum(ALenum scale) noexcept -> std::optional<AmbiScaling>
@@ -111,8 +111,8 @@ constexpr auto EnumFromAmbiScaling(AmbiScaling scale) -> ALenum
case AmbiScaling::N3D: return AL_N3D_SOFT;
case AmbiScaling::UHJ: break;
}
- throw std::runtime_error{fmt::format("Invalid AmbiScaling: {}",
- int{al::to_underlying(scale)})};
+
+ abort();
}
#if ALSOFT_EAX
--- a/al/debug.cpp
+++ b/al/debug.cpp
@@ -110,8 +110,8 @@ constexpr auto GetDebugSourceEnum(DebugSource source) -> ALenum
case DebugSource::Application: return AL_DEBUG_SOURCE_APPLICATION_EXT;
case DebugSource::Other: return AL_DEBUG_SOURCE_OTHER_EXT;
}
- throw std::runtime_error{fmt::format("Unexpected debug source value: {}",
- int{al::to_underlying(source)})};
+
+ abort();
}
constexpr auto GetDebugTypeEnum(DebugType type) -> ALenum
@@ -128,8 +128,8 @@ constexpr auto GetDebugTypeEnum(DebugType type) -> ALenum
case DebugType::PopGroup: return AL_DEBUG_TYPE_POP_GROUP_EXT;
case DebugType::Other: return AL_DEBUG_TYPE_OTHER_EXT;
}
- throw std::runtime_error{fmt::format("Unexpected debug type value: {}",
- int{al::to_underlying(type)})};
+
+ abort();
}
constexpr auto GetDebugSeverityEnum(DebugSeverity severity) -> ALenum
@@ -141,8 +141,8 @@ constexpr auto GetDebugSeverityEnum(DebugSeverity severity) -> ALenum
case DebugSeverity::Low: return AL_DEBUG_SEVERITY_LOW_EXT;
case DebugSeverity::Notification: return AL_DEBUG_SEVERITY_NOTIFICATION_EXT;
}
- throw std::runtime_error{fmt::format("Unexpected debug severity value: {}",
- int{al::to_underlying(severity)})};
+
+ abort();
}
--- a/al/effects/chorus.cpp
+++ b/al/effects/chorus.cpp
@@ -43,8 +43,8 @@ constexpr ALenum EnumFromWaveform(ChorusWaveform type)
case ChorusWaveform::Sinusoid: return AL_CHORUS_WAVEFORM_SINUSOID;
case ChorusWaveform::Triangle: return AL_CHORUS_WAVEFORM_TRIANGLE;
}
- throw std::runtime_error{fmt::format("Invalid chorus waveform: {}",
- int{al::to_underlying(type)})};
+
+ abort();
}
constexpr EffectProps genDefaultChorusProps() noexcept
--- a/al/effects/fshifter.cpp
+++ b/al/effects/fshifter.cpp
@@ -40,7 +40,7 @@ constexpr ALenum EnumFromDirection(FShifterDirection dir)
case FShifterDirection::Up: return AL_FREQUENCY_SHIFTER_DIRECTION_UP;
case FShifterDirection::Off: return AL_FREQUENCY_SHIFTER_DIRECTION_OFF;
}
- throw std::runtime_error{fmt::format("Invalid direction: {}", int{al::to_underlying(dir)})};
+ abort();
}
constexpr EffectProps genDefaultProps() noexcept
--- a/al/effects/modulator.cpp
+++ b/al/effects/modulator.cpp
@@ -40,8 +40,8 @@ constexpr ALenum EnumFromWaveform(ModulatorWaveform type)
case ModulatorWaveform::Sawtooth: return AL_RING_MODULATOR_SAWTOOTH;
case ModulatorWaveform::Square: return AL_RING_MODULATOR_SQUARE;
}
- throw std::runtime_error{fmt::format("Invalid modulator waveform: {}",
- int{al::to_underlying(type)})};
+
+ abort();
}
constexpr EffectProps genDefaultProps() noexcept
--- a/al/effects/vmorpher.cpp
+++ b/al/effects/vmorpher.cpp
@@ -97,7 +97,7 @@ constexpr ALenum EnumFromPhenome(VMorpherPhenome phenome)
HANDLE_PHENOME(V);
HANDLE_PHENOME(Z);
}
- throw std::runtime_error{fmt::format("Invalid phenome: {}", int{al::to_underlying(phenome)})};
+ abort();
#undef HANDLE_PHENOME
}
@@ -119,8 +119,8 @@ constexpr ALenum EnumFromWaveform(VMorpherWaveform type)
case VMorpherWaveform::Triangle: return AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE;
case VMorpherWaveform::Sawtooth: return AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH;
}
- throw std::runtime_error{fmt::format("Invalid vocal morpher waveform: {}",
- int{al::to_underlying(type)})};
+
+ abort();
}
constexpr EffectProps genDefaultProps() noexcept
--- a/al/state.cpp
+++ b/al/state.cpp
@@ -141,7 +141,7 @@ constexpr auto ALenumFromDistanceModel(DistanceModel model) -> ALenum
case DistanceModel::Exponent: return AL_EXPONENT_DISTANCE;
case DistanceModel::ExponentClamped: return AL_EXPONENT_DISTANCE_CLAMPED;
}
- throw std::runtime_error{"Unexpected distance model "+std::to_string(static_cast<int>(model))};
+ abort();
}
enum PropertyValue : ALenum {

View file

@ -1,26 +0,0 @@
# Removes the Apple-specific code from alconfig.cpp because we get missing symbol errors otherwise.
--- a/alc/alconfig.cpp
+++ b/alc/alconfig.cpp
@@ -419,21 +419,6 @@ void ReadALConfig()
}
}
-#ifdef __APPLE__
- CFBundleRef mainBundle = CFBundleGetMainBundle();
- if(mainBundle)
- {
- CFURLRef configURL{CFBundleCopyResourceURL(mainBundle, CFSTR(".alsoftrc"), CFSTR(""),
- nullptr)};
-
- std::array<unsigned char,PATH_MAX> fileName{};
- if(configURL && CFURLGetFileSystemRepresentation(configURL, true, fileName.data(), fileName.size()))
- {
- if(std::ifstream f{reinterpret_cast<char*>(fileName.data())}; f.is_open())
- LoadConfigFromFile(f);
- }
- }
-#endif
if(auto homedir = al::getenv("HOME"))
{

View file

@ -1,133 +0,0 @@
# devkitPPC does not provide POSIX semaphores, which OpenAL Soft needs.
# However, devkitPPC provides an alternative semaphore implementation in an external library, libogc.
# This patch makes OpenAL Soft use libogc semaphores if POSIX semaphores is not found.
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -174,6 +174,11 @@ if("${CMAKE_C_PLATFORM_ID}" STREQUAL "QNX")
set(INC_PATHS ${INC_PATHS} /usr/include)
set(LINKER_FLAGS ${LINKER_FLAGS} -L/usr/lib)
endif()
+check_symbol_exists(__DEVKITPPC__ "sys/config.h" DEVKITPPC)
+if(DEVKITPPC)
+ set(CPP_DEFS ${CPP_DEFS} MKXPZ_DEVKITPPC)
+ set(INC_PATHS ${INC_PATHS} "$ENV{DEVKITPRO}/libogc/include")
+endif()
# When the library is built for static linking, apps should define
# AL_LIBTYPE_STATIC when including the AL headers.
--- a/common/alsem.cpp
+++ b/common/alsem.cpp
@@ -55,8 +55,6 @@ void semaphore::post()
void semaphore::wait() noexcept
{ WaitForSingleObject(static_cast<HANDLE>(mSem), INFINITE); }
-bool semaphore::try_wait() noexcept
-{ return WaitForSingleObject(static_cast<HANDLE>(mSem), 0) == WAIT_OBJECT_0; }
} // namespace al
@@ -83,8 +81,6 @@ void semaphore::post()
void semaphore::wait() noexcept
{ dispatch_semaphore_wait(mSem, DISPATCH_TIME_FOREVER); }
-bool semaphore::try_wait() noexcept
-{ return dispatch_semaphore_wait(mSem, DISPATCH_TIME_NOW) == 0; }
} // namespace al
@@ -96,27 +92,41 @@ namespace al {
semaphore::semaphore(unsigned int initial)
{
+#ifdef MKXPZ_DEVKITPPC
+ if(LWP_SemInit(&mSem, initial, 0xffffffff) != 0)
+#else
if(sem_init(&mSem, 0, initial) != 0)
+#endif
throw std::system_error(std::make_error_code(std::errc::resource_unavailable_try_again));
}
semaphore::~semaphore()
+#ifdef MKXPZ_DEVKITPPC
+{ LWP_SemDestroy(mSem); }
+#else
{ sem_destroy(&mSem); }
+#endif
void semaphore::post()
{
+#ifdef MKXPZ_DEVKITPPC
+ if(LWP_SemPost(mSem) != 0)
+#else
if(sem_post(&mSem) != 0)
+#endif
throw std::system_error(std::make_error_code(std::errc::value_too_large));
}
void semaphore::wait() noexcept
{
+#ifdef MKXPZ_DEVKITPPC
+ LWP_SemWait(mSem);
+#else
while(sem_wait(&mSem) == -1 && errno == EINTR) {
}
+#endif
}
-bool semaphore::try_wait() noexcept
-{ return sem_trywait(&mSem) == 0; }
} // namespace al
--- a/common/alsem.h
+++ b/common/alsem.h
@@ -11,7 +11,11 @@
#include <semaphore.h> /* Fallback option for Apple without a working libdispatch */
#endif
#elif !defined(_WIN32)
-#include <semaphore.h>
+# ifdef MKXPZ_DEVKITPPC
+# include <ogc/semaphore.h>
+# else
+# include <semaphore.h>
+# endif
#endif
namespace al {
@@ -35,7 +39,6 @@ public:
void post();
void wait() noexcept;
- bool try_wait() noexcept;
};
} // namespace al
--- a/common/althrd_setname.cpp
+++ b/common/althrd_setname.cpp
@@ -55,13 +55,25 @@ using setname_t4 = int(*)(pthread_t, const char*, void*);
{ func(name); }
[[maybe_unused]] void setname_caller(setname_t2 func, const char *name)
+#ifdef MKXPZ_DEVKITPPC
+{ func(42, name); }
+#else
{ func(pthread_self(), name); }
+#endif
[[maybe_unused]] void setname_caller(setname_t3 func, const char *name)
+#ifdef MKXPZ_DEVKITPPC
+{ func(42, name); }
+#else
{ func(pthread_self(), name); }
+#endif
[[maybe_unused]] void setname_caller(setname_t4 func, const char *name)
+#ifdef MKXPZ_DEVKITPPC
+{ func(42, "%s", const_cast<char*>(name)); /* NOLINT(*-const-cast) */ }
+#else
{ func(pthread_self(), "%s", const_cast<char*>(name)); /* NOLINT(*-const-cast) */ }
+#endif
} // namespace

View file

@ -1,71 +0,0 @@
# Fixes a compilation error in althreads.h when targeting Emscripten without pthread support.
--- a/common/althreads.h
+++ b/common/althreads.h
@@ -13,7 +13,7 @@
#include <pthread.h>
-#else
+#elif (!defined(__EMSCRIPTEN__) || defined(__EMSCRIPTEN_PTHREADS__)) && !defined(__DEVKITPPC__) && !defined(__vita__)
#include <threads.h>
#endif
@@ -107,29 +107,57 @@ public:
#else
+#if (defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_PTHREADS__)) || defined(__DEVKITPPC__) || defined(__vita__)
+ void **mTss;
+#else
tss_t mTss{};
+#endif /* (defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_PTHREADS__)) || defined(__DEVKITPPC__) || defined(__vita__) */
public:
tss()
{
+#if (defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_PTHREADS__)) || defined(__DEVKITPPC__) || defined(__vita__)
+ if ((mTss = (void **)std::malloc(sizeof *mTss)) == NULL)
+ throw std::runtime_error{"al::tss::tss()"};
+ *mTss = nullptr;
+#else
if(int res{tss_create(&mTss, nullptr)}; res != thrd_success)
throw std::runtime_error{"al::tss::tss()"};
+#endif /* (defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_PTHREADS__)) || defined(__DEVKITPPC__) || defined(__vita__) */
}
explicit tss(const T &init) : tss{}
{
+#if (defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_PTHREADS__)) || defined(__DEVKITPPC__) || defined(__vita__)
+ if ((mTss = (void **)std::malloc(sizeof *mTss)) == NULL)
+ throw std::runtime_error{"al::tss::tss()"};
+ *mTss = to_ptr(init);
+#else
if(int res{tss_set(mTss, to_ptr(init))}; res != thrd_success)
throw std::runtime_error{"al::tss::tss(T)"};
+#endif /* (defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_PTHREADS__)) || defined(__DEVKITPPC__) || defined(__vita__) */
}
+#if (defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_PTHREADS__)) || defined(__DEVKITPPC__) || defined(__vita__)
+ ~tss() { std::free(mTss); }
+#else
~tss() { tss_delete(mTss); }
+#endif /* (defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_PTHREADS__)) || defined(__DEVKITPPC__) || defined(__vita__) */
void set(const T &value) const
{
+#if (defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_PTHREADS__)) || defined(__DEVKITPPC__) || defined(__vita__)
+ *mTss = to_ptr(value);
+#else
if(int res{tss_set(mTss, to_ptr(value))}; res != thrd_success)
throw std::runtime_error{"al::tss::set(T)"};
+#endif /* (defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_PTHREADS__)) || defined(__DEVKITPPC__) || defined(__vita__) */
}
[[nodiscard]]
+#if (defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_PTHREADS__)) || defined(__DEVKITPPC__) || defined(__vita__)
+ auto get() const noexcept -> T { return from_ptr(*mTss); }
+#else
auto get() const noexcept -> T { return from_ptr(tss_get(mTss)); }
+#endif /* (defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_PTHREADS__)) || defined(__DEVKITPPC__) || defined(__vita__) */
#endif /* _WIN32 */
tss(const tss&) = delete;

View file

@ -0,0 +1,627 @@
# Disables OpenAL Soft's dependency on both `ghc::filesystem` and `std::filesystem`. None of those work when building for PlayStation 3.
# As a side effect, also prevents OpenAL Soft from loading from its config file.
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -610,7 +610,7 @@ set(COMMON_OBJS
common/comptr.h
common/dynload.cpp
common/dynload.h
- common/filesystem.cpp
+
common/filesystem.h
common/flexarray.h
common/intrusive_ptr.h
@@ -673,7 +673,7 @@ set(CORE_OBJS
core/fpu_ctrl.cpp
core/fpu_ctrl.h
core/front_stablizer.h
- core/helpers.cpp
+
core/helpers.h
core/hrtf.cpp
core/hrtf.h
--- a/alc/alconfig.cpp
+++ b/alc/alconfig.cpp
@@ -46,7 +46,7 @@
#include "alstring.h"
#include "core/helpers.h"
#include "core/logging.h"
-#include "filesystem.h"
+
#include "strutils.h"
#if ALSOFT_UWP
@@ -332,156 +332,156 @@ auto GetConfigValue(const std::string_view devName, const std::string_view block
#ifdef _WIN32
void ReadALConfig()
{
- fs::path path;
-#if !defined(_GAMING_XBOX)
- {
-#if !ALSOFT_UWP
- std::unique_ptr<WCHAR,CoTaskMemDeleter> bufstore;
- const HRESULT hr{SHGetKnownFolderPath(FOLDERID_RoamingAppData, KF_FLAG_DONT_UNEXPAND,
- nullptr, al::out_ptr(bufstore))};
- if(SUCCEEDED(hr))
- {
- const std::wstring_view buffer{bufstore.get()};
-#else
- winrt::Windows::Storage::ApplicationDataContainer localSettings = winrt::Windows::Storage::ApplicationData::Current().LocalSettings();
- auto bufstore = Windows::Storage::ApplicationData::Current().RoamingFolder().Path();
- std::wstring_view buffer{bufstore};
- {
-#endif
- path = fs::path{buffer};
- path /= L"alsoft.ini";
- TRACE("Loading config {}...", al::u8_as_char(path.u8string()));
- if(fs::ifstream f{path}; f.is_open())
- LoadConfigFromFile(f);
- }
- }
-#endif
- path = fs::u8path(GetProcBinary().path);
- if(!path.empty())
- {
- path /= L"alsoft.ini";
- TRACE("Loading config {}...", al::u8_as_char(path.u8string()));
- if(fs::ifstream f{path}; f.is_open())
- LoadConfigFromFile(f);
- }
- if(auto confpath = al::getenv(L"ALSOFT_CONF"))
- {
- path = *confpath;
- TRACE("Loading config {}...", al::u8_as_char(path.u8string()));
- if(fs::ifstream f{path}; f.is_open())
- LoadConfigFromFile(f);
- }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
}
#else
void ReadALConfig()
{
- fs::path path{"/etc/openal/alsoft.conf"};
-
- TRACE("Loading config {}...", al::u8_as_char(path.u8string()));
- if(fs::ifstream f{path}; f.is_open())
- LoadConfigFromFile(f);
-
- std::string confpaths{al::getenv("XDG_CONFIG_DIRS").value_or("/etc/xdg")};
- /* Go through the list in reverse, since "the order of base directories
- * denotes their importance; the first directory listed is the most
- * important". Ergo, we need to load the settings from the later dirs
- * first so that the settings in the earlier dirs override them.
- */
- while(!confpaths.empty())
- {
- auto next = confpaths.rfind(':');
- if(next < confpaths.length())
- {
- path = fs::path{std::string_view{confpaths}.substr(next+1)}.lexically_normal();
- confpaths.erase(next);
- }
- else
- {
- path = fs::path{confpaths}.lexically_normal();
- confpaths.clear();
- }
- if(!path.is_absolute())
- WARN("Ignoring XDG config dir: {}", al::u8_as_char(path.u8string()));
- else
- {
- path /= "alsoft.conf";
- TRACE("Loading config {}...", al::u8_as_char(path.u8string()));
- if(fs::ifstream f{path}; f.is_open())
- LoadConfigFromFile(f);
- }
- }
-#ifdef __APPLE__
- CFBundleRef mainBundle = CFBundleGetMainBundle();
- if(mainBundle)
- {
- CFURLRef configURL{CFBundleCopyResourceURL(mainBundle, CFSTR(".alsoftrc"), CFSTR(""),
- nullptr)};
- std::array<unsigned char,PATH_MAX> fileName{};
- if(configURL && CFURLGetFileSystemRepresentation(configURL, true, fileName.data(), fileName.size()))
- {
- if(std::ifstream f{reinterpret_cast<char*>(fileName.data())}; f.is_open())
- LoadConfigFromFile(f);
- }
- }
-#endif
- if(auto homedir = al::getenv("HOME"))
- {
- path = *homedir;
- path /= ".alsoftrc";
- TRACE("Loading config {}...", al::u8_as_char(path.u8string()));
- if(std::ifstream f{path}; f.is_open())
- LoadConfigFromFile(f);
- }
- if(auto configdir = al::getenv("XDG_CONFIG_HOME"))
- {
- path = *configdir;
- path /= "alsoft.conf";
- }
- else
- {
- path.clear();
- if(auto homedir = al::getenv("HOME"))
- {
- path = *homedir;
- path /= ".config/alsoft.conf";
- }
- }
- if(!path.empty())
- {
- TRACE("Loading config {}...", al::u8_as_char(path.u8string()));
- if(std::ifstream f{path}; f.is_open())
- LoadConfigFromFile(f);
- }
- path = GetProcBinary().path;
- if(!path.empty())
- {
- path /= "alsoft.conf";
- TRACE("Loading config {}...", al::u8_as_char(path.u8string()));
- if(std::ifstream f{path}; f.is_open())
- LoadConfigFromFile(f);
- }
- if(auto confname = al::getenv("ALSOFT_CONF"))
- {
- TRACE("Loading config {}...", *confname);
- if(std::ifstream f{*confname}; f.is_open())
- LoadConfigFromFile(f);
- }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
}
#endif
--- a/core/ambdec.cpp
+++ b/core/ambdec.cpp
@@ -15,7 +15,7 @@
#include "albit.h"
#include "alspan.h"
-#include "filesystem.h"
+
#include "fmt/core.h"
@@ -60,231 +60,5 @@ AmbDecConf::~AmbDecConf() = default;
std::optional<std::string> AmbDecConf::load(const char *fname) noexcept
{
- fs::ifstream f{fs::u8path(fname)};
- if(!f.is_open())
- return std::string("Failed to open file \"")+fname+"\"";
-
- ReaderScope scope{ReaderScope::Global};
- size_t speaker_pos{0};
- size_t lfmatrix_pos{0};
- size_t hfmatrix_pos{0};
- size_t linenum{0};
-
- std::string buffer;
- while(f.good() && std::getline(f, buffer))
- {
- ++linenum;
-
- std::istringstream istr{buffer};
- std::string command{read_word(istr)};
- if(command.empty() || command[0] == '#')
- continue;
-
- if(command == "/}")
- {
- if(scope == ReaderScope::Global)
- return make_error(linenum, "Unexpected /}} in global scope");
- scope = ReaderScope::Global;
- continue;
- }
-
- if(scope == ReaderScope::Speakers)
- {
- if(command == "add_spkr")
- {
- if(speaker_pos == Speakers.size())
- return make_error(linenum, "Too many speakers specified");
-
- AmbDecConf::SpeakerConf &spkr = Speakers[speaker_pos++];
- istr >> spkr.Name;
- istr >> spkr.Distance;
- istr >> spkr.Azimuth;
- istr >> spkr.Elevation;
- istr >> spkr.Connection;
- }
- else
- return make_error(linenum, "Unexpected speakers command: {}", command);
- }
- else if(scope == ReaderScope::LFMatrix || scope == ReaderScope::HFMatrix)
- {
- auto &gains = (scope == ReaderScope::LFMatrix) ? LFOrderGain : HFOrderGain;
- auto matrix = (scope == ReaderScope::LFMatrix) ? LFMatrix : HFMatrix;
- auto &pos = (scope == ReaderScope::LFMatrix) ? lfmatrix_pos : hfmatrix_pos;
-
- if(command == "order_gain")
- {
- size_t toread{(ChanMask > Ambi3OrderMask) ? 5u : 4u};
- std::size_t curgain{0u};
- float value{};
- while(toread)
- {
- --toread;
- istr >> value;
- if(curgain < std::size(gains))
- gains[curgain++] = value;
- }
- }
- else if(command == "add_row")
- {
- if(pos == Speakers.size())
- return make_error(linenum, "Too many matrix rows specified");
-
- unsigned int mask{ChanMask};
-
- AmbDecConf::CoeffArray &mtxrow = matrix[pos++];
- mtxrow.fill(0.0f);
-
- float value{};
- while(mask)
- {
- auto idx = static_cast<unsigned>(al::countr_zero(mask));
- mask &= ~(1u << idx);
-
- istr >> value;
- if(idx < mtxrow.size())
- mtxrow[idx] = value;
- }
- }
- else
- return make_error(linenum, "Unexpected matrix command: {}", command);
- }
- // Global scope commands
- else if(command == "/description")
- {
- while(istr.good() && std::isspace(istr.peek()))
- istr.ignore();
- std::getline(istr, Description);
- while(!Description.empty() && std::isspace(Description.back()))
- Description.pop_back();
- }
- else if(command == "/version")
- {
- if(Version)
- return make_error(linenum, "Duplicate version definition");
- istr >> Version;
- if(Version != 3)
- return make_error(linenum, "Unsupported version: {}", Version);
- }
- else if(command == "/dec/chan_mask")
- {
- if(ChanMask)
- return make_error(linenum, "Duplicate chan_mask definition");
- istr >> std::hex >> ChanMask >> std::dec;
-
- if(!ChanMask || ChanMask > Ambi4OrderMask)
- return make_error(linenum, "Invalid chan_mask: {:#x}", ChanMask);
- if(ChanMask > Ambi3OrderMask && CoeffScale == AmbDecScale::FuMa)
- return make_error(linenum, "FuMa not compatible with over third-order");
- }
- else if(command == "/dec/freq_bands")
- {
- if(FreqBands)
- return make_error(linenum, "Duplicate freq_bands");
- istr >> FreqBands;
- if(FreqBands != 1 && FreqBands != 2)
- return make_error(linenum, "Invalid freq_bands: {}", FreqBands);
- }
- else if(command == "/dec/speakers")
- {
- if(!Speakers.empty())
- return make_error(linenum, "Duplicate speakers");
- size_t numspeakers{};
- istr >> numspeakers;
- if(!numspeakers)
- return make_error(linenum, "Invalid speakers: {}", numspeakers);
- Speakers.resize(numspeakers);
- }
- else if(command == "/dec/coeff_scale")
- {
- if(CoeffScale != AmbDecScale::Unset)
- return make_error(linenum, "Duplicate coeff_scale");
-
- std::string scale{read_word(istr)};
- if(scale == "n3d") CoeffScale = AmbDecScale::N3D;
- else if(scale == "sn3d") CoeffScale = AmbDecScale::SN3D;
- else if(scale == "fuma") CoeffScale = AmbDecScale::FuMa;
- else
- return make_error(linenum, "Unexpected coeff_scale: {}", scale);
-
- if(ChanMask > Ambi3OrderMask && CoeffScale == AmbDecScale::FuMa)
- return make_error(linenum, "FuMa not compatible with over third-order");
- }
- else if(command == "/opt/xover_freq")
- {
- istr >> XOverFreq;
- }
- else if(command == "/opt/xover_ratio")
- {
- istr >> XOverRatio;
- }
- else if(command == "/opt/input_scale" || command == "/opt/nfeff_comp"
- || command == "/opt/delay_comp" || command == "/opt/level_comp")
- {
- /* Unused */
- read_word(istr);
- }
- else if(command == "/speakers/{")
- {
- if(Speakers.empty())
- return make_error(linenum, "Speakers defined without a count");
- scope = ReaderScope::Speakers;
- }
- else if(command == "/lfmatrix/{" || command == "/hfmatrix/{" || command == "/matrix/{")
- {
- if(Speakers.empty())
- return make_error(linenum, "Matrix defined without a speaker count");
- if(!ChanMask)
- return make_error(linenum, "Matrix defined without a channel mask");
-
- if(Matrix.empty())
- {
- Matrix.resize(Speakers.size() * FreqBands);
- LFMatrix = al::span{Matrix}.first(Speakers.size());
- HFMatrix = al::span{Matrix}.subspan(Speakers.size()*(FreqBands-1));
- }
-
- if(FreqBands == 1)
- {
- if(command != "/matrix/{")
- return make_error(linenum, "Unexpected \"{}\" for a single-band decoder",
- command);
- scope = ReaderScope::HFMatrix;
- }
- else
- {
- if(command == "/lfmatrix/{")
- scope = ReaderScope::LFMatrix;
- else if(command == "/hfmatrix/{")
- scope = ReaderScope::HFMatrix;
- else
- return make_error(linenum, "Unexpected \"{}\" for a dual-band decoder",
- command);
- }
- }
- else if(command == "/end")
- {
- const auto endpos = static_cast<std::size_t>(istr.tellg());
- if(!is_at_end(buffer, endpos))
- return make_error(linenum, "Extra junk on end: {}",
- std::string_view{buffer}.substr(endpos));
-
- if(speaker_pos < Speakers.size() || hfmatrix_pos < Speakers.size()
- || (FreqBands == 2 && lfmatrix_pos < Speakers.size()))
- return make_error(linenum, "Incomplete decoder definition");
- if(CoeffScale == AmbDecScale::Unset)
- return make_error(linenum, "No coefficient scaling defined");
-
- return std::nullopt;
- }
- else
- return make_error(linenum, "Unexpected command: {}", command);
-
- istr.clear();
- const auto endpos = static_cast<std::size_t>(istr.tellg());
- if(!is_at_end(buffer, endpos))
- return make_error(linenum, "Extra junk on line: {}",
- std::string_view{buffer}.substr(endpos));
- buffer.clear();
- }
- return make_error(linenum, "Unexpected end of file");
+ return std::string("OpenAL Soft's Ambisonics config loader is disabled by mkxp-z");
}
--- a/core/hrtf.cpp
+++ b/core/hrtf.cpp
@@ -30,7 +30,7 @@
#include "alspan.h"
#include "alstring.h"
#include "ambidefs.h"
-#include "filesystem.h"
+
#include "filters/splitter.h"
#include "fmt/core.h"
#include "helpers.h"
@@ -1202,8 +1202,8 @@ std::vector<std::string> EnumerateHrtf(std::optional<std::string> pathopt)
std::lock_guard<std::mutex> enumlock{EnumeratedHrtfLock};
EnumeratedHrtfs.clear();
- for(const auto &fname : SearchDataFiles(".mhr"sv))
- AddFileEntry(fname);
+
+
bool usedefaults{true};
if(pathopt)
@@ -1230,16 +1230,16 @@ std::vector<std::string> EnumerateHrtf(std::optional<std::string> pathopt)
entry.remove_suffix(1);
if(!entry.empty())
{
- for(const auto &fname : SearchDataFiles(".mhr"sv, entry))
- AddFileEntry(fname);
+
+
}
}
}
if(usedefaults)
{
- for(const auto &fname : SearchDataFiles(".mhr"sv, "openal/hrtf"sv))
- AddFileEntry(fname);
+
+
if(!GetResource(IDR_DEFAULT_HRTF_MHR).empty())
AddBuiltInEntry("Built-In HRTF", IDR_DEFAULT_HRTF_MHR);
@@ -1303,14 +1303,14 @@ try {
else
{
TRACE("Loading {}...", fname);
- auto fstr = std::make_unique<fs::ifstream>(fs::u8path(fname),
- std::ios::binary);
- if(!fstr->is_open())
+
+ ERR("OpenAL Soft's HRTF loader is disabled by mkxp-z");
+ if(true)
{
ERR("Could not open {}", fname);
return nullptr;
}
- stream = std::move(fstr);
+
}
auto hrtf = std::unique_ptr<HrtfStore>{};

View file

@ -0,0 +1,547 @@
# This patch makes OpenAL Soft use mkxp-threads.cpp instead of POSIX threads and `std::mutex` for portability reasons.
--- a/al/auxeffectslot.cpp
+++ b/al/auxeffectslot.cpp
@@ -28,7 +28,7 @@
#include <functional>
#include <iterator>
#include <memory>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <numeric>
#include <stdexcept>
#include <tuple>
--- a/al/buffer.cpp
+++ b/al/buffer.cpp
@@ -32,7 +32,7 @@
#include <iterator>
#include <limits>
#include <memory>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <numeric>
#include <optional>
#include <stdexcept>
--- a/al/debug.cpp
+++ b/al/debug.cpp
@@ -7,7 +7,7 @@
#include <atomic>
#include <cstring>
#include <deque>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <optional>
#include <stdexcept>
#include <string>
--- a/al/effect.cpp
+++ b/al/effect.cpp
@@ -27,7 +27,7 @@
#include <cstring>
#include <iterator>
#include <memory>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <numeric>
#include <string>
#include <type_traits>
--- a/al/event.cpp
+++ b/al/event.cpp
@@ -7,7 +7,7 @@
#include <bitset>
#include <exception>
#include <memory>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <new>
#include <optional>
#include <string>
--- a/al/filter.cpp
+++ b/al/filter.cpp
@@ -28,7 +28,7 @@
#include <cstdio>
#include <iterator>
#include <memory>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <numeric>
#include <unordered_map>
#include <vector>
--- a/al/listener.cpp
+++ b/al/listener.cpp
@@ -24,7 +24,7 @@
#include <algorithm>
#include <cmath>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include "AL/al.h"
#include "AL/alc.h"
--- a/al/source.cpp
+++ b/al/source.cpp
@@ -34,7 +34,7 @@
#include <iterator>
#include <limits>
#include <memory>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <numeric>
#include <optional>
#include <stdexcept>
--- a/al/state.cpp
+++ b/al/state.cpp
@@ -26,7 +26,7 @@
#include <atomic>
#include <cmath>
#include <deque>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <optional>
#include <stdexcept>
#include <string>
--- a/alc/alc.cpp
+++ b/alc/alc.cpp
@@ -48,7 +48,7 @@
#include <iterator>
#include <limits>
#include <memory>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <new>
#include <optional>
#include <stdexcept>
@@ -314,7 +314,7 @@ std::atomic<ALCenum> LastNullDeviceError{ALC_NO_ERROR};
bool TrapALCError{false};
/* One-time configuration init control */
-std::once_flag alc_config_once{};
+
/* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
* updates.
@@ -743,7 +743,7 @@ void alc_initconfig()
#endif // ALSOFT_EAX
}
inline void InitConfig()
-{ std::call_once(alc_config_once, [](){alc_initconfig();}); }
+{ alc_initconfig(); }
/************************************************
--- a/alc/backends/alsa.cpp
+++ b/alc/backends/alsa.cpp
@@ -30,7 +30,7 @@
#include <cstring>
#include <exception>
#include <memory>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <string>
#include <string_view>
#include <thread>
--- a/alc/backends/jack.cpp
+++ b/alc/backends/jack.cpp
@@ -27,7 +27,7 @@
#include <cstdio>
#include <cstring>
#include <memory.h>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <thread>
#include <vector>
--- a/alc/backends/opensl.cpp
+++ b/alc/backends/opensl.cpp
@@ -28,7 +28,7 @@
#include <array>
#include <cstdlib>
#include <cstring>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <new>
#include <thread>
#include <functional>
--- a/alc/backends/otherio.cpp
+++ b/alc/backends/otherio.cpp
@@ -49,7 +49,7 @@
#include <cstring>
#include <deque>
#include <future>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <string>
#include <string_view>
#include <thread>
--- a/alc/backends/pipewire.cpp
+++ b/alc/backends/pipewire.cpp
@@ -37,7 +37,7 @@
#include <ctime>
#include <iterator>
#include <memory>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <optional>
#include <string_view>
#include <thread>
--- a/alc/backends/pulseaudio.cpp
+++ b/alc/backends/pulseaudio.cpp
@@ -33,7 +33,7 @@
#include <cstdint>
#include <cstring>
#include <limits>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <optional>
#include <string>
#include <string_view>
--- a/alc/backends/wasapi.cpp
+++ b/alc/backends/wasapi.cpp
@@ -52,7 +52,7 @@
#include <condition_variable>
#include <cstring>
#include <future>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <string>
#include <string_view>
#include <thread>
--- a/alc/context.h
+++ b/alc/context.h
@@ -8,7 +8,7 @@
#include <cstdint>
#include <deque>
#include <memory>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <string>
#include <string_view>
#include <unordered_map>
--- a/alc/device.h
+++ b/alc/device.h
@@ -5,7 +5,7 @@
#include <atomic>
#include <memory>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <optional>
#include <string>
#include <unordered_map>
--- a/alc/events.h
+++ b/alc/events.h
@@ -5,7 +5,7 @@
#include "opthelpers.h"
#include <bitset>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <optional>
#include <string_view>
--- a/common/alsem.cpp
+++ b/common/alsem.cpp
@@ -55,8 +55,6 @@ void semaphore::post()
void semaphore::wait() noexcept
{ WaitForSingleObject(static_cast<HANDLE>(mSem), INFINITE); }
-bool semaphore::try_wait() noexcept
-{ return WaitForSingleObject(static_cast<HANDLE>(mSem), 0) == WAIT_OBJECT_0; }
} // namespace al
@@ -83,8 +81,6 @@ void semaphore::post()
void semaphore::wait() noexcept
{ dispatch_semaphore_wait(mSem, DISPATCH_TIME_FOREVER); }
-bool semaphore::try_wait() noexcept
-{ return dispatch_semaphore_wait(mSem, DISPATCH_TIME_NOW) == 0; }
} // namespace al
@@ -96,27 +92,25 @@ namespace al {
semaphore::semaphore(unsigned int initial)
{
- if(sem_init(&mSem, 0, initial) != 0)
- throw std::system_error(std::make_error_code(std::errc::resource_unavailable_try_again));
+ if(mkxp_sem_init(&mSem, initial) != 0)
+ abort();
}
semaphore::~semaphore()
-{ sem_destroy(&mSem); }
+{ mkxp_sem_destroy(&mSem); }
void semaphore::post()
{
- if(sem_post(&mSem) != 0)
- throw std::system_error(std::make_error_code(std::errc::value_too_large));
+ if(mkxp_sem_post(&mSem) != 0)
+ abort();
}
void semaphore::wait() noexcept
{
- while(sem_wait(&mSem) == -1 && errno == EINTR) {
+ while(mkxp_sem_wait(&mSem) == -1 && errno == EINTR) {
}
}
-bool semaphore::try_wait() noexcept
-{ return sem_trywait(&mSem) == 0; }
} // namespace al
--- a/common/alsem.h
+++ b/common/alsem.h
@@ -11,7 +11,7 @@
#include <semaphore.h> /* Fallback option for Apple without a working libdispatch */
#endif
#elif !defined(_WIN32)
-#include <semaphore.h>
+#include "../../src/mkxp-threads.h"
#endif
namespace al {
@@ -22,7 +22,7 @@ class semaphore {
#elif defined(AL_APPLE_HAVE_DISPATCH)
using native_type = dispatch_semaphore_t;
#else
- using native_type = sem_t;
+ using native_type = mkxp_sem_t;
#endif
native_type mSem{};
@@ -35,7 +35,6 @@ public:
void post();
void wait() noexcept;
- bool try_wait() noexcept;
};
} // namespace al
--- a/common/althrd_setname.cpp
+++ b/common/althrd_setname.cpp
@@ -39,39 +39,39 @@ void althrd_setname(const char *name [[maybe_unused]])
#else
-#include <pthread.h>
-#ifdef HAVE_PTHREAD_NP_H
-#include <pthread_np.h>
-#endif
+#include "../../src/mkxp-threads.h"
+
+
+
+
namespace {
using setname_t1 = int(*)(const char*);
-using setname_t2 = int(*)(pthread_t, const char*);
-using setname_t3 = void(*)(pthread_t, const char*);
-using setname_t4 = int(*)(pthread_t, const char*, void*);
+using setname_t2 = int(*)(mkxp_thread_t, const char*);
+using setname_t3 = void(*)(mkxp_thread_t, const char*);
+using setname_t4 = int(*)(mkxp_thread_t, const char*, void*);
[[maybe_unused]] void setname_caller(setname_t1 func, const char *name)
{ func(name); }
[[maybe_unused]] void setname_caller(setname_t2 func, const char *name)
-{ func(pthread_self(), name); }
+{ func(mkxp_thread_self(), name); }
[[maybe_unused]] void setname_caller(setname_t3 func, const char *name)
-{ func(pthread_self(), name); }
+{ func(mkxp_thread_self(), name); }
[[maybe_unused]] void setname_caller(setname_t4 func, const char *name)
-{ func(pthread_self(), "%s", const_cast<char*>(name)); /* NOLINT(*-const-cast) */ }
+{ func(mkxp_thread_self(), "%s", const_cast<char*>(name)); /* NOLINT(*-const-cast) */ }
} // namespace
void althrd_setname(const char *name [[maybe_unused]])
{
-#if defined(HAVE_PTHREAD_SET_NAME_NP)
- setname_caller(pthread_set_name_np, name);
-#elif defined(HAVE_PTHREAD_SETNAME_NP)
- setname_caller(pthread_setname_np, name);
-#endif
-}
+
+
+
+
+}
#endif
--- a/common/althreads.h
+++ b/common/althreads.h
@@ -5,7 +5,7 @@
#include <stdexcept>
#include <type_traits>
-#ifdef _WIN32
+#if false
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
@@ -13,7 +13,7 @@
#include <pthread.h>
-#else
+#elif false
#include <threads.h>
#endif
@@ -54,7 +54,7 @@ class tss {
return static_cast<T>(al::bit_cast<std::uintptr_t>(ptr));
}
-#ifdef _WIN32
+#if false
DWORD mTss{TLS_OUT_OF_INDEXES};
public:
@@ -107,29 +107,30 @@ public:
#else
- tss_t mTss{};
+ void **mTss;
public:
tss()
{
- if(int res{tss_create(&mTss, nullptr)}; res != thrd_success)
+ if ((mTss = (void **)std::malloc(sizeof *mTss)) == NULL)
throw std::runtime_error{"al::tss::tss()"};
+ *mTss = nullptr;
}
explicit tss(const T &init) : tss{}
{
- if(int res{tss_set(mTss, to_ptr(init))}; res != thrd_success)
- throw std::runtime_error{"al::tss::tss(T)"};
+ if ((mTss = (void **)std::malloc(sizeof *mTss)) == NULL)
+ throw std::runtime_error{"al::tss::tss()"};
+ *mTss = to_ptr(init);
}
- ~tss() { tss_delete(mTss); }
+ ~tss() { std::free(mTss); }
void set(const T &value) const
{
- if(int res{tss_set(mTss, to_ptr(value))}; res != thrd_success)
- throw std::runtime_error{"al::tss::set(T)"};
+ *mTss = to_ptr(value);
}
[[nodiscard]]
- auto get() const noexcept -> T { return from_ptr(tss_get(mTss)); }
+ auto get() const noexcept -> T { return from_ptr(*mTss); }
#endif /* _WIN32 */
tss(const tss&) = delete;
--- a/core/context.h
+++ b/core/context.h
@@ -140,7 +140,7 @@ struct ContextBase {
*/
al::atomic_unique_ptr<EffectSlotArray> mActiveAuxSlots;
- std::thread mEventThread;
+
al::semaphore mEventSem;
std::unique_ptr<RingBuffer> mAsyncEvents;
using AsyncEventBitset = std::bitset<al::to_underlying(AsyncEnableBits::Count)>;
--- a/core/dbus_wrap.cpp
+++ b/core/dbus_wrap.cpp
@@ -5,7 +5,7 @@
#if HAVE_DYNLOAD
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <type_traits>
#include "logging.h"
--- a/core/dbus_wrap.h
+++ b/core/dbus_wrap.h
@@ -9,7 +9,7 @@
#if HAVE_DYNLOAD
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#define DBUS_FUNCTIONS(MAGIC) \
MAGIC(dbus_error_init) \
--- a/core/helpers.cpp
+++ b/core/helpers.cpp
@@ -12,7 +12,7 @@
#include <cstdlib>
#include <cstring>
#include <limits>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <optional>
#include <string>
#include <string_view>
--- a/core/hrtf.cpp
+++ b/core/hrtf.cpp
@@ -15,7 +15,7 @@
#include <fstream>
#include <iterator>
#include <memory>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <numeric>
#include <optional>
#include <tuple>
--- a/core/logging.cpp
+++ b/core/logging.cpp
@@ -7,7 +7,7 @@
#include <cstdarg>
#include <cstdio>
#include <cstring>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <optional>
#include <string>
#include <string_view>
--- a/examples/alffplay.cpp
+++ b/examples/alffplay.cpp
@@ -20,7 +20,7 @@
#include <functional>
#include <future>
#include <memory>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <ratio>
#include <string>
#include <string_view>
--- a/router/alc.cpp
+++ b/router/alc.cpp
@@ -7,7 +7,7 @@
#include <cstdlib>
#include <cstring>
#include <cstdio>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <optional>
#include <string_view>
#include <tuple>
--- a/router/router.h
+++ b/router/router.h
@@ -8,7 +8,7 @@
#include <atomic>
#include <cstdio>
#include <memory>
-#include <mutex>
+#include "../../src/mkxp-threads.h"
#include <string>
#include <utility>
#include <vector>

View file

@ -0,0 +1,33 @@
# Disables OpenAL Soft's null backend since it fails to compile for PlayStation 3. Don't worry, we don't need the null backend.
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -897,7 +897,7 @@ set(ALC_OBJS ${ALC_OBJS}
# Default backends, always available
alc/backends/loopback.cpp
alc/backends/loopback.h
- alc/backends/null.cpp
+
alc/backends/null.h
)
--- a/alc/alc.cpp
+++ b/alc/alc.cpp
@@ -216,7 +216,7 @@ struct BackendInfo {
BackendFactory& (*getFactory)();
};
-std::array BackendList{
+std::array<BackendInfo, 0> BackendList{
#if HAVE_PIPEWIRE
BackendInfo{"pipewire", PipeWireBackendFactory::getFactory},
#endif
@@ -269,7 +269,7 @@ std::array BackendList{
BackendInfo{"otherio", OtherIOBackendFactory::getFactory},
#endif
- BackendInfo{"null", NullBackendFactory::getFactory},
+
#if HAVE_WAVE
BackendInfo{"wave", WaveBackendFactory::getFactory},
#endif

View file

@ -0,0 +1,24 @@
# Prevents OpenAL Soft's build system from forcibly enabling position-independent code.
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1377,7 +1377,7 @@ target_compile_definitions(alsoft.common PRIVATE ${CPP_DEFS})
target_compile_options(alsoft.common PRIVATE ${C_FLAGS})
target_link_libraries(alsoft.common PRIVATE alsoft::fmt)
set_target_properties(alsoft.common PROPERTIES ${ALSOFT_STD_VERSION_PROPS}
- POSITION_INDEPENDENT_CODE TRUE)
+ )
unset(HAS_ROUTER)
--- a/fmt-11.1.1/CMakeLists.txt
+++ b/fmt-11.1.1/CMakeLists.txt
@@ -73,7 +73,7 @@ target_include_directories(alsoft.fmt PUBLIC
set_target_properties(alsoft.fmt PROPERTIES ${ALSOFT_STD_VERSION_PROPS}
VERSION ${FMT_VERSION} SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR}
DEBUG_POSTFIX "${ALSOFT_FMT_DEBUG_POSTFIX}"
- POSITION_INDEPENDENT_CODE TRUE
+
C_VISIBILITY_PRESET hidden
CXX_VISIBILITY_PRESET hidden
EXCLUDE_FROM_ALL TRUE)

View file

@ -0,0 +1,24 @@
# The PlayStation 3 toolchain appears to be missing some functions from the C++ standard library. This replaces the missing functions with other ones that are available.
--- a/alc/alu.cpp
+++ b/alc/alu.cpp
@@ -2155,7 +2155,7 @@ void Write(const al::span<const FloatBufferLine> InBuffer, void *OutBuffer, cons
out[c] = SampleConv<T>(s);
out += ptrdiff_t(FrameStep);
};
- std::for_each_n(inbuf.cbegin(), SamplesToDo, conv_sample);
+ std::for_each(inbuf.cbegin(), inbuf.cbegin() + SamplesToDo, conv_sample);
++c;
}
if(const size_t extra{FrameStep - c})
--- a/alc/effects/reverb.cpp
+++ b/alc/effects/reverb.cpp
@@ -931,7 +931,7 @@ void EarlyReflections::updateLines(const float density_mult, const float diffusi
/* Calculate the gain (coefficient) for the secondary reflections based on
* the average delay and decay time.
*/
- const auto length = std::reduce(EARLY_LINE_LENGTHS.begin(), EARLY_LINE_LENGTHS.end(), 0.0f)
+ const auto length = std::accumulate(EARLY_LINE_LENGTHS.begin(), EARLY_LINE_LENGTHS.end(), 0.0f)
/ float{EARLY_LINE_LENGTHS.size()} * density_mult;
Coeff = CalcDecayCoeff(length, decayTime);

View file

@ -1,143 +0,0 @@
# devkitPPC does not provide POSIX semaphores, which OpenAL Soft needs.
# However, devkitPPC provides an alternative semaphore implementation in an external library, libogc.
# This patch makes PhysFS use libogc semaphores if POSIX semaphores is not found.
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -172,11 +172,20 @@ if(PHYSFS_BUILD_STATIC)
set_target_properties(physfs-static PROPERTIES VS_WINRT_COMPONENT True)
set_target_properties(physfs-static PROPERTIES STATIC_LIBRARY_FLAGS "/ignore:4264")
endif()
+ set(CPP_DEFS)
+ set(INC_PATHS)
+ include(CheckSymbolExists)
+ check_symbol_exists(__DEVKITPPC__ "sys/config.h" DEVKITPPC)
+ if(DEVKITPPC)
+ set(CPP_DEFS ${CPP_DEFS} MKXPZ_DEVKITPPC)
+ set(INC_PATHS ${INC_PATHS} "$ENV{DEVKITPRO}/libogc/include")
+ endif()
if(WIN32 OR WINRT OR OS2)
# no dll exports from the static library
- target_compile_definitions(physfs-static PRIVATE "PHYSFS_STATIC")
+ set(CPP_DEFS ${CPP_DEFS} "PHYSFS_STATIC")
endif()
- target_include_directories(physfs-static PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>")
+ target_compile_definitions(physfs-static PRIVATE ${CPP_DEFS})
+ target_include_directories(physfs-static PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>" ${INC_PATHS})
target_link_libraries(physfs-static PRIVATE ${OPTIONAL_LIBRARY_LIBS} ${OTHER_LDFLAGS})
set(PHYSFS_LIB_TARGET physfs-static)
list(APPEND PHYSFS_INSTALL_TARGETS "physfs-static")
--- a/src/physfs_platform_posix.c
+++ b/src/physfs_platform_posix.c
@@ -19,7 +19,11 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
-#include <pthread.h>
+#ifdef MKXPZ_DEVKITPPC
+# include <ogc/mutex.h>
+#else
+# include <pthread.h>
+#endif
#include "physfs_internal.h"
@@ -369,15 +373,23 @@ int __PHYSFS_platformStat(const char *fname, PHYSFS_Stat *st, const int follow)
typedef struct
{
+#ifdef MKXPZ_DEVKITPPC
+ mutex_t mutex;
+#else
pthread_mutex_t mutex;
pthread_t owner;
+#endif
PHYSFS_uint32 count;
} PthreadMutex;
void *__PHYSFS_platformGetThreadID(void)
{
+#ifdef MKXPZ_DEVKITPPC
+ return (void *)42;
+#else
return ( (void *) ((size_t) pthread_self()) );
+#endif
} /* __PHYSFS_platformGetThreadID */
@@ -386,7 +398,11 @@ void *__PHYSFS_platformCreateMutex(void)
int rc;
PthreadMutex *m = (PthreadMutex *) allocator.Malloc(sizeof (PthreadMutex));
BAIL_IF(!m, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
+#ifdef MKXPZ_DEVKITPPC
+ rc = LWP_MutexInit(&m->mutex, false);
+#else
rc = pthread_mutex_init(&m->mutex, NULL);
+#endif
if (rc != 0)
{
allocator.Free(m);
@@ -394,7 +410,9 @@ void *__PHYSFS_platformCreateMutex(void)
} /* if */
m->count = 0;
+#ifndef MKXPZ_DEVKITPPC
m->owner = (pthread_t) 0xDEADBEEF;
+#endif
return ((void *) m);
} /* __PHYSFS_platformCreateMutex */
@@ -403,11 +421,15 @@ void __PHYSFS_platformDestroyMutex(void *mutex)
{
PthreadMutex *m = (PthreadMutex *) mutex;
+#ifdef MKXPZ_DEVKITPPC
+ LWP_MutexDestroy(m->mutex);
+#else
/* Destroying a locked mutex is a bug, but we'll try to be helpful. */
if ((m->owner == pthread_self()) && (m->count > 0))
pthread_mutex_unlock(&m->mutex);
pthread_mutex_destroy(&m->mutex);
+#endif
allocator.Free(m);
} /* __PHYSFS_platformDestroyMutex */
@@ -415,6 +437,10 @@ void __PHYSFS_platformDestroyMutex(void *mutex)
int __PHYSFS_platformGrabMutex(void *mutex)
{
PthreadMutex *m = (PthreadMutex *) mutex;
+#ifdef MKXPZ_DEVKITPPC
+ if (LWP_MutexLock(m->mutex) != 0)
+ return 0;
+#else
pthread_t tid = pthread_self();
if (m->owner != tid)
{
@@ -422,6 +448,7 @@ int __PHYSFS_platformGrabMutex(void *mutex)
return 0;
m->owner = tid;
} /* if */
+#endif
m->count++;
return 1;
@@ -431,6 +458,9 @@ int __PHYSFS_platformGrabMutex(void *mutex)
void __PHYSFS_platformReleaseMutex(void *mutex)
{
PthreadMutex *m = (PthreadMutex *) mutex;
+#ifdef MKXPZ_DEVKITPPC
+ LWP_MutexUnlock(m->mutex);
+#else
assert(m->owner == pthread_self()); /* catch programming errors. */
assert(m->count > 0); /* catch programming errors. */
if (m->owner == pthread_self())
@@ -441,6 +471,7 @@ void __PHYSFS_platformReleaseMutex(void *mutex)
pthread_mutex_unlock(&m->mutex);
} /* if */
} /* if */
+#endif
} /* __PHYSFS_platformReleaseMutex */
#endif /* PHYSFS_PLATFORM_POSIX */

View file

@ -0,0 +1,96 @@
# This patch makes PhysFS use mkxp-threads.cpp instead of POSIX threads for portability reasons.
--- a/src/physfs_platform_posix.c
+++ b/src/physfs_platform_posix.c
@@ -19,7 +19,7 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
-#include <pthread.h>
+#include "../../src/mkxp-threads.h"
#include "physfs_internal.h"
@@ -369,15 +369,15 @@ int __PHYSFS_platformStat(const char *fname, PHYSFS_Stat *st, const int follow)
typedef struct
{
- pthread_mutex_t mutex;
- pthread_t owner;
+ mkxp_mutex_t mutex;
+ mkxp_thread_t owner;
PHYSFS_uint32 count;
} PthreadMutex;
void *__PHYSFS_platformGetThreadID(void)
{
- return ( (void *) ((size_t) pthread_self()) );
+ return ( (void *) ((size_t) mkxp_thread_self()) );
} /* __PHYSFS_platformGetThreadID */
@@ -386,7 +386,7 @@ void *__PHYSFS_platformCreateMutex(void)
int rc;
PthreadMutex *m = (PthreadMutex *) allocator.Malloc(sizeof (PthreadMutex));
BAIL_IF(!m, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
- rc = pthread_mutex_init(&m->mutex, NULL);
+ rc = mkxp_mutex_init(&m->mutex, false);
if (rc != 0)
{
allocator.Free(m);
@@ -394,7 +394,7 @@ void *__PHYSFS_platformCreateMutex(void)
} /* if */
m->count = 0;
- m->owner = (pthread_t) 0xDEADBEEF;
+ m->owner = (mkxp_thread_t) 0xDEADBEEF;
return ((void *) m);
} /* __PHYSFS_platformCreateMutex */
@@ -404,10 +404,10 @@ void __PHYSFS_platformDestroyMutex(void *mutex)
PthreadMutex *m = (PthreadMutex *) mutex;
/* Destroying a locked mutex is a bug, but we'll try to be helpful. */
- if ((m->owner == pthread_self()) && (m->count > 0))
- pthread_mutex_unlock(&m->mutex);
+ if ((m->owner == mkxp_thread_self()) && (m->count > 0))
+ mkxp_mutex_unlock(&m->mutex);
- pthread_mutex_destroy(&m->mutex);
+ mkxp_mutex_destroy(&m->mutex);
allocator.Free(m);
} /* __PHYSFS_platformDestroyMutex */
@@ -415,10 +415,10 @@ void __PHYSFS_platformDestroyMutex(void *mutex)
int __PHYSFS_platformGrabMutex(void *mutex)
{
PthreadMutex *m = (PthreadMutex *) mutex;
- pthread_t tid = pthread_self();
+ mkxp_thread_t tid = mkxp_thread_self();
if (m->owner != tid)
{
- if (pthread_mutex_lock(&m->mutex) != 0)
+ if (mkxp_mutex_lock(&m->mutex) != 0)
return 0;
m->owner = tid;
} /* if */
@@ -431,14 +431,14 @@ int __PHYSFS_platformGrabMutex(void *mutex)
void __PHYSFS_platformReleaseMutex(void *mutex)
{
PthreadMutex *m = (PthreadMutex *) mutex;
- assert(m->owner == pthread_self()); /* catch programming errors. */
+ assert(m->owner == mkxp_thread_self()); /* catch programming errors. */
assert(m->count > 0); /* catch programming errors. */
- if (m->owner == pthread_self())
+ if (m->owner == mkxp_thread_self())
{
if (--m->count == 0)
{
- m->owner = (pthread_t) 0xDEADBEEF;
- pthread_mutex_unlock(&m->mutex);
+ m->owner = (mkxp_thread_t) 0xDEADBEEF;
+ mkxp_mutex_unlock(&m->mutex);
} /* if */
} /* if */
} /* __PHYSFS_platformReleaseMutex */

View file

@ -2,4 +2,4 @@
url = https://github.com/icculus/physfs
revision = release-3.2.0
depth = 1
diff_files = physfs-darwin.patch, physfs-devkitppc.patch, physfs-dir.patch, physfs-unknown-platform.patch
diff_files = physfs-darwin.patch, physfs-dir.patch, physfs-mkxp-threads.patch, physfs-unknown-platform.patch