mirror of
https://github.com/libretro/RetroArch
synced 2025-01-30 03:32:46 +00:00
commit
7fedabee4b
58
.github/ISSUE_TEMPLATE.md
vendored
58
.github/ISSUE_TEMPLATE.md
vendored
@ -2,34 +2,34 @@
|
||||
- Only RetroArch bugs should be filed here. Not core bugs or game bugs
|
||||
- This is not a forum or a help section, this is strictly developer oriented
|
||||
|
||||
## Description
|
||||
|
||||
[Description of the bug]
|
||||
|
||||
### Expected behavior
|
||||
|
||||
[What you expected to happen]
|
||||
|
||||
### Actual behavior
|
||||
|
||||
[What is actually happening]
|
||||
|
||||
### Steps to reproduce the bug
|
||||
|
||||
1. [First step]
|
||||
2. [Second step]
|
||||
3. [and so on...]
|
||||
|
||||
### Bisect Results
|
||||
## Description
|
||||
|
||||
[Description of the bug]
|
||||
|
||||
### Expected behavior
|
||||
|
||||
[What you expected to happen]
|
||||
|
||||
### Actual behavior
|
||||
|
||||
[What is actually happening]
|
||||
|
||||
### Steps to reproduce the bug
|
||||
|
||||
1. [First step]
|
||||
2. [Second step]
|
||||
3. [and so on...]
|
||||
|
||||
### Bisect Results
|
||||
|
||||
[Try to bisect and tell us when this started happening]
|
||||
|
||||
### Version/Commit
|
||||
You can find this information under Information/System Information
|
||||
|
||||
- RetroArch: [version/commit]
|
||||
|
||||
### Environment information
|
||||
|
||||
[Try to bisect and tell us when this started happening]
|
||||
|
||||
### Version/Commit
|
||||
You can find this information under Information/System Information
|
||||
|
||||
- RetroArch: [version/commit]
|
||||
|
||||
### Environment information
|
||||
|
||||
- OS: [The operating system you're running]
|
||||
- Compiler: [In case you are running local builds]
|
||||
- Compiler: [In case you are running local builds]
|
||||
|
1
.github/PULL_REQUEST_TEMPLATE.md
vendored
1
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -4,7 +4,6 @@
|
||||
2. If you are sending several unrelated fixes or features, use a branch and a separate pull request for each
|
||||
3. If possible try squashing everything in a single commit. This is particularly beneficial in the case of feature merges since it allows easy bisecting when a problem arises
|
||||
|
||||
|
||||
## Description
|
||||
|
||||
[Description of the pull request, detail any issues you are fixing or any features you are implementing]
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -87,7 +87,6 @@ wiiu/wut/elf2rpl/elf2rpl
|
||||
/pkg/wiiu/rpx
|
||||
/wiiu-devel.properties
|
||||
|
||||
|
||||
# 3ds
|
||||
/.lst
|
||||
*.3dsx
|
||||
|
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@ -24,7 +24,7 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
{
|
||||
"name": "(gdb) Attach",
|
||||
"type": "cppdbg",
|
||||
"request": "attach",
|
||||
|
2
.vscode/tasks.json
vendored
2
.vscode/tasks.json
vendored
@ -45,7 +45,7 @@
|
||||
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
"isDefault": true
|
||||
},
|
||||
|
||||
"command": "./configure; make -j2",
|
||||
|
@ -48,7 +48,7 @@ index b90a8e40c3..e57c4df194 100644
|
||||
+#endif
|
||||
+
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(HAVE_OPENGL)
|
||||
@@ -313,6 +354,43 @@ static void create_gl_context(HWND hwnd, bool *quit)
|
||||
RARCH_LOG("[WGL]: Adaptive VSync supported.\n");
|
||||
|
114
CONTRIBUTING.md
114
CONTRIBUTING.md
@ -1,58 +1,58 @@
|
||||
# Contributing to RetroArch
|
||||
|
||||
If you are a developer and want to contribute to the development of RetroArch, please read this.
|
||||
If you have found a bug and want to submit a minor patch or a bug report, please read this as well.
|
||||
|
||||
# Submitting a bug report
|
||||
When submitting a bug report, make sure that the bug is local to RetroArch.
|
||||
A bug in a libretro core or something deemed to be external is likely to be closed very fast.
|
||||
If you still suspect a bug in RetroArch, make sure to test with several cores to make sure.
|
||||
|
||||
If you have troubles building RetroArch on Linux/BSD/OSX, make sure to paste shell output of ./configure,
|
||||
as well as config.log and shell output of make. If building on Windows, just paste shell output of make.
|
||||
|
||||
If the issue occurs during runtime, make sure to paste RetroArch's verbose log.
|
||||
If using Phoenix frontend, you can find log in (File -> Show Log) after running.
|
||||
In console, make sure to run with verbose (-v) flag.
|
||||
|
||||
# Pull Requests
|
||||
Outside contributions are generally only accepted in the form of a pull request. The process is very simple.
|
||||
Fork RetroArch, make your changes, and issue a pull request on GitHub. This can all be done within the browser.
|
||||
The changes are reviewed, and might be merged in. If the pull request isn't acceptable at the time,
|
||||
note that it's possible to continue pushing up commits to your branch.
|
||||
|
||||
If you want to develop a larger feature,
|
||||
we'd like to discuss this first (ideally on IRC) so that you don't risk developing something
|
||||
that won't be merged. A pull request with a proof-of-concept is fine, but please indicate so.
|
||||
|
||||
## libretro API
|
||||
If you wish to add functionality to libretro's API, it can take some time to merge in, because changes
|
||||
to libretro API will affect other projects as well, and we highly value API/ABI stability.
|
||||
Features will only be added when deemed *necessary* for a concrete libretro core to function properly.
|
||||
Features will not be added on basis of hypothetical libretro implementations.
|
||||
|
||||
# Coding style
|
||||
Having a consistent code style throughout the code base is highly valued.
|
||||
Please look through the code to get a feel for the coding style.
|
||||
A pull request may be asked to fix the coding style before submission.
|
||||
In other cases, a pull request may be followed up with a "style nit commit".
|
||||
|
||||
## Non-obvious things:
|
||||
- Code should be both ISO C99 and ISO C++ compatible. This dual requirement is for XBox360 and MSVC in general. Think of it as a C++ compatible subset of C99.
|
||||
- Warnings are not allowed (-Wall). Make sure your code is warning-free. Note that warning sensitivity differs a bit across compiler versions.
|
||||
- Using deprecated APIs is discouraged.
|
||||
|
||||
# Copyright Headers and AUTHORS
|
||||
If you have contributed to a part of a source file (a chunk of code that's written by you),
|
||||
you should add yourself to the copyright header in that file.
|
||||
If you have contributed significantly
|
||||
(a feature, a contribution you can "name", e.g. "Added audio driver foo"), you should add yourself to AUTHORS file.
|
||||
We'd like your full name and email, and which features you have been part of.
|
||||
|
||||
# IRC
|
||||
Active development happens on IRC. (#retroarch @ irc.freenode.org)
|
||||
We value discussing things in "real-time".
|
||||
|
||||
# Commit Access
|
||||
Contributors who show a track record of making good pull requests over time will eventually get commit access to the repo.
|
||||
# Contributing to RetroArch
|
||||
|
||||
If you are a developer and want to contribute to the development of RetroArch, please read this.
|
||||
If you have found a bug and want to submit a minor patch or a bug report, please read this as well.
|
||||
|
||||
# Submitting a bug report
|
||||
When submitting a bug report, make sure that the bug is local to RetroArch.
|
||||
A bug in a libretro core or something deemed to be external is likely to be closed very fast.
|
||||
If you still suspect a bug in RetroArch, make sure to test with several cores to make sure.
|
||||
|
||||
If you have troubles building RetroArch on Linux/BSD/OSX, make sure to paste shell output of ./configure,
|
||||
as well as config.log and shell output of make. If building on Windows, just paste shell output of make.
|
||||
|
||||
If the issue occurs during runtime, make sure to paste RetroArch's verbose log.
|
||||
If using Phoenix frontend, you can find log in (File -> Show Log) after running.
|
||||
In console, make sure to run with verbose (-v) flag.
|
||||
|
||||
# Pull Requests
|
||||
Outside contributions are generally only accepted in the form of a pull request. The process is very simple.
|
||||
Fork RetroArch, make your changes, and issue a pull request on GitHub. This can all be done within the browser.
|
||||
The changes are reviewed, and might be merged in. If the pull request isn't acceptable at the time,
|
||||
note that it's possible to continue pushing up commits to your branch.
|
||||
|
||||
If you want to develop a larger feature,
|
||||
we'd like to discuss this first (ideally on IRC) so that you don't risk developing something
|
||||
that won't be merged. A pull request with a proof-of-concept is fine, but please indicate so.
|
||||
|
||||
## libretro API
|
||||
If you wish to add functionality to libretro's API, it can take some time to merge in, because changes
|
||||
to libretro API will affect other projects as well, and we highly value API/ABI stability.
|
||||
Features will only be added when deemed *necessary* for a concrete libretro core to function properly.
|
||||
Features will not be added on basis of hypothetical libretro implementations.
|
||||
|
||||
# Coding style
|
||||
Having a consistent code style throughout the code base is highly valued.
|
||||
Please look through the code to get a feel for the coding style.
|
||||
A pull request may be asked to fix the coding style before submission.
|
||||
In other cases, a pull request may be followed up with a "style nit commit".
|
||||
|
||||
## Non-obvious things:
|
||||
- Code should be both ISO C99 and ISO C++ compatible. This dual requirement is for XBox360 and MSVC in general. Think of it as a C++ compatible subset of C99.
|
||||
- Warnings are not allowed (-Wall). Make sure your code is warning-free. Note that warning sensitivity differs a bit across compiler versions.
|
||||
- Using deprecated APIs is discouraged.
|
||||
|
||||
# Copyright Headers and AUTHORS
|
||||
If you have contributed to a part of a source file (a chunk of code that's written by you),
|
||||
you should add yourself to the copyright header in that file.
|
||||
If you have contributed significantly
|
||||
(a feature, a contribution you can "name", e.g. "Added audio driver foo"), you should add yourself to AUTHORS file.
|
||||
We'd like your full name and email, and which features you have been part of.
|
||||
|
||||
# IRC
|
||||
Active development happens on IRC. (#retroarch @ irc.freenode.org)
|
||||
We value discussing things in "real-time".
|
||||
|
||||
# Commit Access
|
||||
Contributors who show a track record of making good pull requests over time will eventually get commit access to the repo.
|
||||
This typically happens when the "overhead" of looking through pull requests over time becomes a burden.
|
@ -19,6 +19,6 @@ $(foreach x,$(join $(addsuffix :,$(MOC_SRC)),$(MOC_HEADERS)),$(eval $x))
|
||||
|
||||
generate: $(MOC_SRC)
|
||||
@echo $(MOC_SRC)
|
||||
|
||||
|
||||
print-%:
|
||||
@echo '$*=$($*)'
|
||||
@echo '$*=$($*)'
|
||||
|
@ -1,7 +1,7 @@
|
||||
# This build was put together and is maintained by ModMyClassic.com for Libretro.
|
||||
# The purpose is to give Libretro a proper "official" build platform for classic consoles.
|
||||
# If you need any help in building for the classics or have any questions then please visit
|
||||
# https://modmyclassic.com/comp and we will help in any way possible!
|
||||
# https://modmyclassic.com/comp and we will help in any way possible!
|
||||
|
||||
# Building Prerequisites ##############
|
||||
# arm-linux-gnueabihf-gcc-8
|
||||
@ -79,7 +79,7 @@ retroarch:
|
||||
rm -fr /tmp/$(HAKCHI_DIR) #clean up tmp
|
||||
|
||||
#COMMODORE 64 MINI BUILD (WIP)
|
||||
|
||||
|
||||
#Clean down dirty files
|
||||
rm -f version.all version.dtd
|
||||
mv version_BACKUP.all version.all && mv version_BACKUP.dtd version.dtd
|
||||
|
@ -510,7 +510,6 @@ endif
|
||||
|
||||
# Audio
|
||||
|
||||
|
||||
ifeq ($(HAVE_COREAUDIO), 1)
|
||||
OBJ += audio/drivers/coreaudio.o
|
||||
HAVE_COREAUDIO_LIBS = 1
|
||||
@ -681,7 +680,7 @@ ifeq ($(HW_CONTEXT_MENU_DRIVERS), 1)
|
||||
ifeq ($(HAVE_XMB),)
|
||||
HAVE_XMB = 1
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(HAVE_STRIPES),)
|
||||
HAVE_STRIPES = 0
|
||||
endif
|
||||
@ -1535,8 +1534,6 @@ ifeq ($(HAVE_CHD), 1)
|
||||
$(LIBRETRO_COMM_DIR)/formats/libchdr/libchdr_chd.o \
|
||||
$(LIBRETRO_COMM_DIR)/formats/libchdr/libchdr_huffman.o \
|
||||
$(LIBRETRO_COMM_DIR)/streams/chd_stream.o
|
||||
|
||||
|
||||
|
||||
OBJ += $(LIBRETRO_COMM_DIR)/formats/libchdr/libchdr_zlib.o
|
||||
ifeq ($(HAVE_FLAC),1)
|
||||
|
@ -40,7 +40,7 @@ OBJ := ctr/ctr_system.o \
|
||||
libretro-common/hash/rhash.o \
|
||||
file_path_str.o \
|
||||
verbosity.o
|
||||
|
||||
|
||||
OBJ += ctr/exec-3dsx/exec_cia.o \
|
||||
ctr/exec-3dsx/exec_3dsx.o \
|
||||
ctr/exec-3dsx/mini-hb-menu/launch.o \
|
||||
|
@ -112,7 +112,7 @@ else ifeq ($(libogc_platform), 1)
|
||||
EXT_INTER_TARGET := $(TARGET_NAME)_$(platform).elf
|
||||
|
||||
INCLUDE += -I. -I$(DEVKITPRO)/libogc/include -Ideps/libz -Iwii/libogc/include
|
||||
|
||||
|
||||
ifeq ($(EXTERNAL_LIBOGC), 1)
|
||||
CFLAGS += -DEXTERNAL_LIBOGC
|
||||
CXXFLAGS += -DEXTERNAL_LIBOGC
|
||||
@ -384,7 +384,7 @@ else ifeq ($(platform), windows_msvc2003_x86)
|
||||
|
||||
PLATCFLAGS += -D_WIN32 -DWINVER=0x0400 -D_WIN32_WINNT=0x0400 -D__STDC_CONSTANT_MACROS -D_MBCS -D_VC80_UPGRADE=0x0710
|
||||
LDFLAGS += shell32.lib user32.lib gdi32.lib comdlg32.lib winmm.lib ole32.lib
|
||||
|
||||
|
||||
PATH := $(shell IFS=$$'\n'; cygpath "$(VS71COMNTOOLS)../../Vc7/bin"):$(PATH)
|
||||
PATH := $(PATH):$(shell IFS=$$'\n'; cygpath "$(VS71COMNTOOLS)../IDE")
|
||||
INCLUDE := $(shell IFS=$$'\n'; cygpath -w "$(VS71COMNTOOLS)../../Vc7/include")
|
||||
@ -432,7 +432,7 @@ else ifeq ($(platform), windows_msvc2005_x86)
|
||||
|
||||
PLATCFLAGS += -D_WIN32 -D_WIN32_WINNT=0x0410 -D__STDC_CONSTANT_MACROS -D_MBCS -DHAVE_EASTEREGG
|
||||
LDFLAGS += shell32.lib user32.lib gdi32.lib comdlg32.lib winmm.lib ole32.lib msimg32.lib
|
||||
|
||||
|
||||
PATH := $(shell IFS=$$'\n'; cygpath "$(VS80COMNTOOLS)../../VC/bin"):$(PATH)
|
||||
PATH := $(PATH):$(shell IFS=$$'\n'; cygpath "$(VS80COMNTOOLS)../IDE")
|
||||
INCLUDE := $(shell IFS=$$'\n'; cygpath -w "$(VS80COMNTOOLS)../../VC/include")
|
||||
@ -766,7 +766,7 @@ else
|
||||
CFLAGS += -Wall -std=gnu99 $(MACHDEP) $(PLATCFLAGS) $(INCLUDE)
|
||||
INCLUDE += -I./libretro-common/include \
|
||||
-Ideps \
|
||||
-Ideps/stb
|
||||
-Ideps/stb
|
||||
endif
|
||||
|
||||
OBJ = griffin/griffin.o $(PLATOBJS)
|
||||
@ -973,8 +973,8 @@ ifneq (,$(findstring msvc,$(platform)))
|
||||
LINKOUT = -out:
|
||||
LINK = link.exe
|
||||
else
|
||||
OBJOUT = -o
|
||||
LINKOUT = -o
|
||||
OBJOUT = -o
|
||||
LINKOUT = -o
|
||||
LINK = $(CXX)
|
||||
endif
|
||||
|
||||
|
@ -17,9 +17,9 @@ DEBUG ?= 0
|
||||
WHOLE_ARCHIVE_LINK = 0
|
||||
GRIFFIN_BUILD = 0
|
||||
|
||||
OBJ :=
|
||||
OBJ :=
|
||||
|
||||
# For threading we need to overwrite some vars with global defines because devkitPro's includes
|
||||
# For threading we need to overwrite some vars with global defines because devkitPro's includes
|
||||
# make it hard for us. This works for the pthread wrapper
|
||||
DEFINES_THREAD := -Dpthread_t=Thread -Dpthread_mutex_t=Mutex -Dpthread_mutexattr_t='void*' -Dpthread_attr_t=int -Dpthread_cond_t=CondVar -Dpthread_condattr_t='int' -D_SYS__PTHREADTYPES_H_
|
||||
DEFINES := -D__SWITCH__=1 -U__linux__ -U__linux -DGLM_FORCE_PURE=1 -DRARCH_CONSOLE -DRARCH_INTERNAL -DGLOBAL_CONFIG_DIR='"/switch"' $(DEFINES_THREAD) -DHAVE_STB_VORBIS
|
||||
|
@ -29,7 +29,7 @@ ifneq (,$(findstring Darwin,$(UNAME_S)))
|
||||
endif
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# path to tools
|
||||
# path to tools
|
||||
#---------------------------------------------------------------------------------
|
||||
export PORTLIBS := $(DEVKITPRO)/portlibs/ppc
|
||||
export PATH := $(DEVKITPPC)/bin:$(PORTLIBS)/bin:$(PATH)
|
||||
@ -56,7 +56,7 @@ ISVC=$(or $(VCBUILDHELPER_COMMAND),$(MSBUILDEXTENSIONSPATH32),$(MSBUILDEXTENSION
|
||||
#---------------------------------------------------------------------------------
|
||||
%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c $< -o $@
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
@ -117,12 +117,12 @@ ifeq ($(WHOLE_ARCHIVE_LINK), 1)
|
||||
WHOLE_START := -Wl,--whole-archive
|
||||
WHOLE_END := -Wl,--no-whole-archive
|
||||
endif
|
||||
CXXFLAGS := $(CFLAGS)
|
||||
CXXFLAGS := $(CFLAGS)
|
||||
|
||||
PS4_LIBS := -lps4link -ldebugnet -lorbisFile -lelfloader -lorbisKeyboard -lorbis2d -lpng -lz -lorbisGl -lorbisPad -lorbisAudio -lmod -lorbisFileBrowser -lorbisXbmFont -lSceNet_stub -lScePigletv2VSH_stub -lSceSystemService_stub -lSceUserService_stub -lScePad_stub -lSceAudioOut_stub -lSceIme_stub -lSceSysmodule_stub \
|
||||
-lPs4_extension_kernel_call_standard -lPs4_extension_kernel_execute_dynlib_prepare_dlclose -lPs4_common_kernel -lPs4_common_user -lPs4_common_generic -lPs4LibCInternalAdaptive_stub -lPs4LibKernelAdaptive_stub -lSceLibcInternal_stub -lkernel_stub -lps4Kernel_stub -lPs4_base_stub_resolve_minimal -lPs4_base_kernel_dlsym_standard -lPs4_base_kernel_seek_elf_address_standard -lPs4_base_assembler_register_parameter_standard -lPs4_base_assembler_system_call_standard
|
||||
|
||||
LIBS := $(WHOLE_START) -lretro_orbis $(WHOLE_END) $(PS4_LIBS)
|
||||
LIBS := $(WHOLE_START) -lretro_orbis $(WHOLE_END) $(PS4_LIBS)
|
||||
|
||||
TARGETS := $(TARGET).elf
|
||||
|
||||
@ -157,10 +157,10 @@ $(TARGET).elf: $(OBJ) libretro_orbis.a
|
||||
$(LD) $(CRTFILE) $(OBJ) $(LDFLAGS) $(LIBDIRS) $(LIBS) -o $@
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ) $(TARGET).elf
|
||||
rm -f $(OBJ) $(TARGET).elf
|
||||
rm -f $(OBJ:.o=.depend)
|
||||
|
||||
.PHONY: clean all
|
||||
.PHONY: clean all
|
||||
.PRECIOUS: %.depend
|
||||
|
||||
-include $(OBJ:.o=.depend)
|
||||
|
@ -36,7 +36,7 @@ retroarch.pnd: install
|
||||
pnd_make -c -p retroarch.pnd -d $(PNDDIR)/ -x $(PNDDIR)/PXML.xml -i $(PNDDIR)/icon.png
|
||||
|
||||
clean:
|
||||
rm -f *.o
|
||||
rm -f *.o
|
||||
rm -f audio/*.o
|
||||
rm -f conf/*.o
|
||||
rm -f gfx/*.o
|
||||
|
@ -77,7 +77,7 @@ EE_LDFLAGS = $(LDFLAGS)
|
||||
EE_LIBS = $(LIBS)
|
||||
EE_ASFLAGS = $(ASFLAGS)
|
||||
EE_INCS = $(INCDIR)
|
||||
EE_IRX_OBJ = $(IRX_OBJ)
|
||||
EE_IRX_OBJ = $(IRX_OBJ)
|
||||
EE_BIN = $(TARGET)
|
||||
EE_GPVAL = $(GPVAL)
|
||||
|
||||
@ -105,7 +105,7 @@ $(EE_IRX_OBJ):
|
||||
$(EE_BIN2O) $(EE_GPVAL) $(IRX_DIR)/$(@:.o=.irx) $@ $(@:.o=_irx)
|
||||
|
||||
#Include preferences
|
||||
include $(PS2SDK)/samples/Makefile.pref
|
||||
include $(PS2SDK)/samples/Makefile.pref
|
||||
include $(PS2SDK)/samples/Makefile.eeglobal
|
||||
|
||||
#Linking with C++
|
||||
|
@ -159,7 +159,7 @@ create-core:
|
||||
|
||||
create-npdrm-salamander:
|
||||
$(MAKE_FSELF_NPDRM) $(SALAMANDER_TARGET) $(EBOOT_PATH)
|
||||
|
||||
|
||||
create-salamander:
|
||||
$(MAKE_SELF) $(SALAMANDER_TARGET) $(EBOOT_PATH) $(CONTENT_ID_FULL)
|
||||
|
||||
|
@ -155,7 +155,7 @@ create-core:
|
||||
|
||||
create-npdrm-salamander:
|
||||
$(MAKE_FSELF_NPDRM) $(SALAMANDER_TARGET) $(EBOOT_PATH)
|
||||
|
||||
|
||||
create-salamander:
|
||||
$(MAKE_SELF) $(SALAMANDER_TARGET) $(EBOOT_PATH) $(CONTENT_ID_FULL)
|
||||
|
||||
|
@ -1,91 +1,91 @@
|
||||
CELL_BUILD_TOOLS = GCC
|
||||
CELL_SDK ?= /usr/local/cell
|
||||
HAVE_LOGGER = 0
|
||||
CELL_MK_DIR ?= $(CELL_SDK)/samples/mk
|
||||
|
||||
include $(CELL_MK_DIR)/sdk.makedef.mk
|
||||
|
||||
# system platform
|
||||
system_platform = unix
|
||||
ifeq ($(shell uname -a),)
|
||||
EXE_EXT = .exe
|
||||
system_platform = win
|
||||
else ifneq ($(findstring Darwin,$(shell uname -a)),)
|
||||
system_platform = osx
|
||||
else ifneq ($(findstring MINGW,$(shell uname -a)),)
|
||||
system_platform = win
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
PPU_OPTIMIZE_LV := -O0 -g
|
||||
else
|
||||
PPU_OPTIMIZE_LV := -O2 -DNDEBUG
|
||||
endif
|
||||
|
||||
STRIP = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-strip.exe
|
||||
|
||||
INCFLAGS = -I. -Idefines -Ilibretro-common/include -Ideps/libz
|
||||
DEFINES = -D__CELLOS_LV2__ -DIS_SALAMANDER -DRARCH_CONSOLE -DHAVE_SYSUTILS -DHAVE_SYSMODULES -DHAVE_RARCH_EXEC
|
||||
|
||||
ifeq ($(DEX_BUILD), 1)
|
||||
DEFINES += -DDEX_BUILD
|
||||
endif
|
||||
|
||||
ifeq ($(CEX_BUILD), 1)
|
||||
DEFINES += -DCEX_BUILD
|
||||
endif
|
||||
|
||||
ifeq ($(ODE_BUILD), 1)
|
||||
DEFINES += -DODE_BUILD
|
||||
endif
|
||||
|
||||
PPU_CFLAGS := $(PPU_OPTIMIZE_LV) $(INCFLAGS) $(DEFINES)
|
||||
PPU_CXXFLAGS := $(PPU_OPTIMIZE_LV) $(INCFLAGS) $(DEFINES)
|
||||
|
||||
PPU_SRCS = frontend/frontend_salamander.c \
|
||||
frontend/frontend_driver.c \
|
||||
frontend/drivers/platform_ps3.c \
|
||||
frontend/drivers/platform_null.c \
|
||||
libretro-common/file/file_path.c \
|
||||
libretro-common/lists/dir_list.c \
|
||||
libretro-common/lists/string_list.c \
|
||||
libretro-common/file/retro_dirent.c \
|
||||
libretro-common/hash/rhash.c \
|
||||
libretro-common/string/stdstring.c \
|
||||
libretro-common/encodings/encoding_utf.c \
|
||||
libretro-common/compat/compat_strl.c \
|
||||
libretro-common/compat/compat_strcasestr.c \
|
||||
libretro-common/compat/fopen_utf8.c \
|
||||
libretro-common/streams/file_stream.c \
|
||||
libretro-common/vfs/vfs_implementation.c \
|
||||
libretro-common/file/config_file.c \
|
||||
file_path_str.c \
|
||||
verbosity.c
|
||||
|
||||
ifeq ($(HAVE_LOGGER), 1)
|
||||
PPU_CFLAGS += -DHAVE_LOGGER
|
||||
PPU_SRCS += network/net_logger.c \
|
||||
libretro-common/net/net_compat.c \
|
||||
libretro-common/net/net_socket.c
|
||||
endif
|
||||
|
||||
PPU_TARGET = retroarch-salamander_ps3.elf
|
||||
|
||||
ifeq ($(CELL_BUILD_TOOLS),SNC)
|
||||
PPU_CFLAGS += -Xbranchless=1 -Xfastmath=1 -Xassumecorrectsign=1 -Xassumecorrectalignment=1 -Xunroll=1 -Xautovecreg=1
|
||||
PPU_CXXFLAGS += -Xbranchless=1 -Xfastmath=1 -Xassumecorrectsign=1 -Xassumecorrectalignment=1 -Xunroll=1 -Xautovecreg=1
|
||||
PPU_CXXLD = $(CELL_SDK)/host-win32/sn/bin/ps3ppuld.exe
|
||||
PPU_CLD = $(CELL_SDK)/host-win32/sn/bin/ps3ppuld.exe
|
||||
PPU_CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe
|
||||
else
|
||||
PPU_CFLAGS += -std=gnu99
|
||||
PPU_CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe
|
||||
PPU_CLD = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ld.exe
|
||||
PPU_CXXLD = $(CELL_SDK)/host-win32/sn/bin/ps3ppuld.exe
|
||||
endif
|
||||
|
||||
PPU_LDLIBS += -lm -lnet_stub -lnetctl_stub -lio_stub -lsysmodule_stub -lsysutil_stub -lsysutil_game_stub -lfs_stub -lsysutil_np_stub
|
||||
|
||||
MAKE_FSELF = $(CELL_SDK)/host-win32/bin/make_fself.exe
|
||||
|
||||
include $(CELL_MK_DIR)/sdk.target.mk
|
||||
CELL_BUILD_TOOLS = GCC
|
||||
CELL_SDK ?= /usr/local/cell
|
||||
HAVE_LOGGER = 0
|
||||
CELL_MK_DIR ?= $(CELL_SDK)/samples/mk
|
||||
|
||||
include $(CELL_MK_DIR)/sdk.makedef.mk
|
||||
|
||||
# system platform
|
||||
system_platform = unix
|
||||
ifeq ($(shell uname -a),)
|
||||
EXE_EXT = .exe
|
||||
system_platform = win
|
||||
else ifneq ($(findstring Darwin,$(shell uname -a)),)
|
||||
system_platform = osx
|
||||
else ifneq ($(findstring MINGW,$(shell uname -a)),)
|
||||
system_platform = win
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
PPU_OPTIMIZE_LV := -O0 -g
|
||||
else
|
||||
PPU_OPTIMIZE_LV := -O2 -DNDEBUG
|
||||
endif
|
||||
|
||||
STRIP = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-strip.exe
|
||||
|
||||
INCFLAGS = -I. -Idefines -Ilibretro-common/include -Ideps/libz
|
||||
DEFINES = -D__CELLOS_LV2__ -DIS_SALAMANDER -DRARCH_CONSOLE -DHAVE_SYSUTILS -DHAVE_SYSMODULES -DHAVE_RARCH_EXEC
|
||||
|
||||
ifeq ($(DEX_BUILD), 1)
|
||||
DEFINES += -DDEX_BUILD
|
||||
endif
|
||||
|
||||
ifeq ($(CEX_BUILD), 1)
|
||||
DEFINES += -DCEX_BUILD
|
||||
endif
|
||||
|
||||
ifeq ($(ODE_BUILD), 1)
|
||||
DEFINES += -DODE_BUILD
|
||||
endif
|
||||
|
||||
PPU_CFLAGS := $(PPU_OPTIMIZE_LV) $(INCFLAGS) $(DEFINES)
|
||||
PPU_CXXFLAGS := $(PPU_OPTIMIZE_LV) $(INCFLAGS) $(DEFINES)
|
||||
|
||||
PPU_SRCS = frontend/frontend_salamander.c \
|
||||
frontend/frontend_driver.c \
|
||||
frontend/drivers/platform_ps3.c \
|
||||
frontend/drivers/platform_null.c \
|
||||
libretro-common/file/file_path.c \
|
||||
libretro-common/lists/dir_list.c \
|
||||
libretro-common/lists/string_list.c \
|
||||
libretro-common/file/retro_dirent.c \
|
||||
libretro-common/hash/rhash.c \
|
||||
libretro-common/string/stdstring.c \
|
||||
libretro-common/encodings/encoding_utf.c \
|
||||
libretro-common/compat/compat_strl.c \
|
||||
libretro-common/compat/compat_strcasestr.c \
|
||||
libretro-common/compat/fopen_utf8.c \
|
||||
libretro-common/streams/file_stream.c \
|
||||
libretro-common/vfs/vfs_implementation.c \
|
||||
libretro-common/file/config_file.c \
|
||||
file_path_str.c \
|
||||
verbosity.c
|
||||
|
||||
ifeq ($(HAVE_LOGGER), 1)
|
||||
PPU_CFLAGS += -DHAVE_LOGGER
|
||||
PPU_SRCS += network/net_logger.c \
|
||||
libretro-common/net/net_compat.c \
|
||||
libretro-common/net/net_socket.c
|
||||
endif
|
||||
|
||||
PPU_TARGET = retroarch-salamander_ps3.elf
|
||||
|
||||
ifeq ($(CELL_BUILD_TOOLS),SNC)
|
||||
PPU_CFLAGS += -Xbranchless=1 -Xfastmath=1 -Xassumecorrectsign=1 -Xassumecorrectalignment=1 -Xunroll=1 -Xautovecreg=1
|
||||
PPU_CXXFLAGS += -Xbranchless=1 -Xfastmath=1 -Xassumecorrectsign=1 -Xassumecorrectalignment=1 -Xunroll=1 -Xautovecreg=1
|
||||
PPU_CXXLD = $(CELL_SDK)/host-win32/sn/bin/ps3ppuld.exe
|
||||
PPU_CLD = $(CELL_SDK)/host-win32/sn/bin/ps3ppuld.exe
|
||||
PPU_CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe
|
||||
else
|
||||
PPU_CFLAGS += -std=gnu99
|
||||
PPU_CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe
|
||||
PPU_CLD = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ld.exe
|
||||
PPU_CXXLD = $(CELL_SDK)/host-win32/sn/bin/ps3ppuld.exe
|
||||
endif
|
||||
|
||||
PPU_LDLIBS += -lm -lnet_stub -lnetctl_stub -lio_stub -lsysmodule_stub -lsysutil_stub -lsysutil_game_stub -lfs_stub -lsysutil_np_stub
|
||||
|
||||
MAKE_FSELF = $(CELL_SDK)/host-win32/bin/make_fself.exe
|
||||
|
||||
include $(CELL_MK_DIR)/sdk.target.mk
|
||||
|
@ -96,7 +96,7 @@ CXXFLAGS += $(SHARED_FLAGS)
|
||||
ifeq ($(DEBUG), 1)
|
||||
CFLAGS += -O0 -g
|
||||
else
|
||||
CFLAGS += -O3 -g
|
||||
CFLAGS += -O3 -g
|
||||
CXXFLAGS += -03 -g
|
||||
endif
|
||||
|
||||
|
@ -25,7 +25,7 @@ ifeq ($(HAVE_FILE_LOGGER), 1)
|
||||
CFLAGS += -DHAVE_FILE_LOGGER
|
||||
endif
|
||||
|
||||
CFLAGS += $(RARCH_DEFINES)
|
||||
CFLAGS += $(RARCH_DEFINES)
|
||||
|
||||
EXTRA_TARGETS = EBOOT.PBP
|
||||
PSP_EBOOT_TITLE = RetroArch
|
||||
@ -51,7 +51,7 @@ OBJS = frontend/frontend_salamander.o \
|
||||
libretro-common/hash/rhash.o \
|
||||
file_path_str.o \
|
||||
verbosity.o \
|
||||
bootstrap/psp1/kernel_functions.o
|
||||
bootstrap/psp1/kernel_functions.o
|
||||
|
||||
PSPSDK=$(shell psp-config --pspsdk-path)
|
||||
include $(PSPSDK)/lib/build.mak
|
||||
|
@ -32,10 +32,10 @@ ELF_TARGET := retroarch-salamander_wii.elf
|
||||
|
||||
INCLUDE := -I. -Ilibretro-common/include -Ideps/libz
|
||||
ifeq ($(EXTERNAL_LIBOGC), 1)
|
||||
INCLUDE += -I$(DEVKITPRO)/libogc/include
|
||||
INCLUDE += -I$(DEVKITPRO)/libogc/include
|
||||
LIBDIRS := -L$(DEVKITPRO)/libogc/lib/wii -L.
|
||||
else
|
||||
INCLUDE += -Iwii/libogc/include
|
||||
INCLUDE += -Iwii/libogc/include
|
||||
LIBDIRS := -Lwii/libogc/libs/wii -L.
|
||||
endif
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
USAGE NOTES
|
||||
===========
|
||||
|
||||
This driver is meant for devices with Allwinner SoCs with Mali400 3D block and a
|
||||
This driver is meant for devices with Allwinner SoCs with Mali400 3D block and a
|
||||
good fbdev implementation. It is derived from the old Android GLES driver.
|
||||
|
||||
It was meant to be used on Cubieboard/Cubieboard2/Cubietruck, but it should not
|
||||
@ -19,7 +19,7 @@ First we will clone and build the kernel:
|
||||
git clone https://github.com/mireq/linux-sunxi.git -b sunxi-3.4 --depth 1
|
||||
|
||||
Now we edit drivers/video/sunxi/disp/dev_fb.c, and uncomment the line 1074:
|
||||
// Fb_wait_for_vsync(info);
|
||||
// Fb_wait_for_vsync(info);
|
||||
|
||||
It is assumed you have a cross-compiler installed, so we configure and build the kernel and modules:
|
||||
|
||||
@ -50,7 +50,7 @@ Now we need the headers. We can get them from here:
|
||||
|
||||
http://malideveloper.arm.com/develop-for-mali/sdks/opengl-es-sdk-for-linux/#opengl-es-sdk-for-linux-download
|
||||
|
||||
Download whatever version you want. We just get the headers from here, not machine-dependant compiled code.
|
||||
Download whatever version you want. We just get the headers from here, not machine-dependant compiled code.
|
||||
|
||||
Extract the files and copy the directories inside inc to /usr/include .
|
||||
|
||||
@ -60,20 +60,20 @@ In the end you should have this on your system:
|
||||
|
||||
/usr/include/EGL/
|
||||
eglext.h
|
||||
egl.h
|
||||
eglplatform.h
|
||||
egl.h
|
||||
eglplatform.h
|
||||
fbdev_window.h
|
||||
/usr/include/GLES/
|
||||
glext.h
|
||||
gl.h
|
||||
gl.h
|
||||
glplatform.h
|
||||
/usr/include/GLES2
|
||||
gl2ext.h
|
||||
gl2.h
|
||||
gl2.h
|
||||
gl2platform.h
|
||||
/usr/include/GLES3
|
||||
gl3ext.h
|
||||
gl3.h
|
||||
gl3.h
|
||||
gl3platform.h
|
||||
|
||||
To enable mali_fbdev you must configure RetroArch with --enable-gles and --enable-mali_fbdev.
|
||||
|
@ -148,7 +148,7 @@ Instructions for compiling and installing RetroArch can be found in the [Libretr
|
||||
|
||||
## CRT 15Khz Resolution Switching
|
||||
|
||||
CRT SwitchRes will turn on, on the fly. However, you will need to restart RetroArch to disable it. With CRT SwitchRes enable RetroArch will start in 2560 x 480 @ 60.
|
||||
CRT SwitchRes will turn on, on the fly. However, you will need to restart RetroArch to disable it. With CRT SwitchRes enable RetroArch will start in 2560 x 480 @ 60.
|
||||
|
||||
If you are running Windows, before enabling the CRT SwitchRes options please make sure you have installed CRTEmudriver and installed some modelines. The minimum modelines for all games to switch correctly are:
|
||||
|
||||
|
@ -278,12 +278,12 @@ bool compute_audio_buffer_statistics(audio_statistics_t *stats)
|
||||
stats->samples = (unsigned)audio_driver_free_samples_count;
|
||||
|
||||
#ifdef WARPUP
|
||||
/* uint64 to double not implemented, fair chance
|
||||
/* uint64 to double not implemented, fair chance
|
||||
* signed int64 to double doesn't exist either */
|
||||
/* https://forums.libretro.com/t/unsupported-platform-help/13903/ */
|
||||
(void)stddev;
|
||||
#elif defined(_MSC_VER) && _MSC_VER <= 1200
|
||||
/* FIXME: error C2520: conversion from unsigned __int64
|
||||
/* FIXME: error C2520: conversion from unsigned __int64
|
||||
* to double not implemented, use signed __int64 */
|
||||
(void)stddev;
|
||||
#else
|
||||
@ -301,9 +301,9 @@ bool compute_audio_buffer_statistics(audio_statistics_t *stats)
|
||||
stddev = (unsigned)
|
||||
sqrt((double)accum_var / (samples - 2));
|
||||
|
||||
stats->average_buffer_saturation = (1.0f - (float)avg
|
||||
stats->average_buffer_saturation = (1.0f - (float)avg
|
||||
/ audio_driver_buffer_size) * 100.0;
|
||||
stats->std_deviation_percentage = ((float)stddev
|
||||
stats->std_deviation_percentage = ((float)stddev
|
||||
/ audio_driver_buffer_size) * 100.0;
|
||||
#endif
|
||||
|
||||
@ -975,7 +975,7 @@ void audio_driver_monitor_adjust_system_rates(void)
|
||||
float video_refresh_rate = settings->floats.video_refresh_rate;
|
||||
float max_timing_skew = settings->floats.audio_max_timing_skew;
|
||||
struct retro_system_av_info *av_info = video_viewport_get_system_av_info();
|
||||
const struct retro_system_timing *info =
|
||||
const struct retro_system_timing *info =
|
||||
(const struct retro_system_timing*)&av_info->timing;
|
||||
|
||||
if (info->sample_rate <= 0.0)
|
||||
@ -1281,7 +1281,7 @@ bool audio_driver_mixer_add_stream(audio_mixer_stream_params_t *params)
|
||||
|
||||
if (params->stream_type == AUDIO_STREAM_TYPE_NONE)
|
||||
return false;
|
||||
|
||||
|
||||
switch (params->slot_selection_type)
|
||||
{
|
||||
case AUDIO_MIXER_SLOT_SELECTION_MANUAL:
|
||||
|
@ -1,382 +1,382 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2019 - Stuart Carnie
|
||||
*
|
||||
* RetroArch 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 Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch 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 RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <AudioToolbox/AudioToolbox.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
|
||||
#include "../audio_driver.h"
|
||||
|
||||
#pragma mark - ringbuffer
|
||||
|
||||
typedef struct ringbuffer
|
||||
{
|
||||
float *buffer;
|
||||
size_t cap;
|
||||
atomic_int len;
|
||||
size_t writePtr;
|
||||
size_t readPtr;
|
||||
} ringbuffer_t;
|
||||
|
||||
typedef ringbuffer_t * ringbuffer_h;
|
||||
|
||||
static inline size_t rb_len(ringbuffer_h r)
|
||||
{
|
||||
return atomic_load_explicit(&r->len, memory_order_relaxed);
|
||||
}
|
||||
|
||||
static inline size_t rb_cap(ringbuffer_h r)
|
||||
{
|
||||
return (r->readPtr + r->cap - r->writePtr) % r->cap;
|
||||
}
|
||||
|
||||
static inline size_t rb_avail(ringbuffer_h r)
|
||||
{
|
||||
return r->cap - rb_len(r);
|
||||
}
|
||||
|
||||
static inline void rb_advance_write(ringbuffer_h r)
|
||||
{
|
||||
r->writePtr = (r->writePtr + 1) % r->cap;
|
||||
}
|
||||
|
||||
static inline void rb_advance_write_n(ringbuffer_h r, size_t n)
|
||||
{
|
||||
r->writePtr = (r->writePtr + n) % r->cap;
|
||||
}
|
||||
|
||||
static inline void rb_advance_read(ringbuffer_h r)
|
||||
{
|
||||
r->readPtr = (r->readPtr + 1) % r->cap;
|
||||
}
|
||||
|
||||
static inline void rb_len_add(ringbuffer_h r, int n)
|
||||
{
|
||||
atomic_fetch_add(&r->len, n);
|
||||
}
|
||||
|
||||
static inline void rb_len_sub(ringbuffer_h r, int n)
|
||||
{
|
||||
atomic_fetch_sub(&r->len, n);
|
||||
}
|
||||
|
||||
static void rb_init(ringbuffer_h r, size_t cap)
|
||||
{
|
||||
r->buffer = malloc(cap * sizeof(float));
|
||||
r->cap = cap;
|
||||
atomic_init(&r->len, 0);
|
||||
r->writePtr = 0;
|
||||
r->readPtr = 0;
|
||||
}
|
||||
|
||||
static void rb_free(ringbuffer_h r)
|
||||
{
|
||||
free(r->buffer);
|
||||
bzero(r, sizeof(*r));
|
||||
}
|
||||
|
||||
#define UNLIKELY(x) __builtin_expect((x), 0)
|
||||
#define LIKELY(x) __builtin_expect((x), 1)
|
||||
|
||||
static void rb_write_data(ringbuffer_h r, const float *data, size_t len)
|
||||
{
|
||||
size_t avail = rb_avail(r);
|
||||
size_t n = MIN(len, avail);
|
||||
size_t first_write = n;
|
||||
size_t rest_write = 0;
|
||||
|
||||
if (r->writePtr + n > r->cap)
|
||||
{
|
||||
first_write = r->cap - r->writePtr;
|
||||
rest_write = n - first_write;
|
||||
}
|
||||
|
||||
memcpy(r->buffer + r->writePtr, data, first_write*sizeof(float));
|
||||
memcpy(r->buffer, data + first_write, rest_write*sizeof(float));
|
||||
|
||||
rb_advance_write_n(r, n);
|
||||
rb_len_add(r, (int)n);
|
||||
}
|
||||
|
||||
static void rb_read_data(ringbuffer_h r, float *d0, float *d1, size_t len)
|
||||
{
|
||||
size_t need = len*2;
|
||||
|
||||
do {
|
||||
size_t have = rb_len(r);
|
||||
size_t n = MIN(have, need);
|
||||
int i = 0;
|
||||
for (; i < n/2; i++)
|
||||
{
|
||||
d0[i] = r->buffer[r->readPtr];
|
||||
rb_advance_read(r);
|
||||
d1[i] = r->buffer[r->readPtr];
|
||||
rb_advance_read(r);
|
||||
}
|
||||
|
||||
need -= n;
|
||||
rb_len_sub(r, (int)n);
|
||||
|
||||
if (UNLIKELY(need > 0))
|
||||
{
|
||||
/* we got more data */
|
||||
if (rb_len(r) > 0)
|
||||
continue;
|
||||
|
||||
// underflow
|
||||
const float quiet = 0.0f;
|
||||
size_t fill = (need/2)*sizeof(float);
|
||||
memset_pattern4(&d0[i], &quiet, fill);
|
||||
memset_pattern4(&d1[i], &quiet, fill);
|
||||
}
|
||||
} while (0);
|
||||
}
|
||||
|
||||
#pragma mark - CoreAudio3
|
||||
|
||||
static bool g_interrupted;
|
||||
|
||||
@interface CoreAudio3 : NSObject {
|
||||
ringbuffer_t _rb;
|
||||
dispatch_semaphore_t _sema;
|
||||
AUAudioUnit *_au;
|
||||
size_t _bufferSize;
|
||||
BOOL _nonBlock;
|
||||
}
|
||||
|
||||
@property (nonatomic, readwrite) BOOL nonBlock;
|
||||
@property (nonatomic, readonly) BOOL paused;
|
||||
@property (nonatomic, readonly) size_t writeAvailableInBytes;
|
||||
@property (nonatomic, readonly) size_t bufferSizeInBytes;
|
||||
|
||||
- (instancetype)initWithRate:(NSUInteger)rate
|
||||
latency:(NSUInteger)latency;
|
||||
- (ssize_t)writeFloat:(const float *)data samples:(size_t)samples;
|
||||
- (void)start;
|
||||
- (void)stop;
|
||||
|
||||
@end
|
||||
|
||||
@implementation CoreAudio3
|
||||
|
||||
- (instancetype)initWithRate:(NSUInteger)rate
|
||||
latency:(NSUInteger)latency {
|
||||
if (self = [super init])
|
||||
{
|
||||
_sema = dispatch_semaphore_create(0);
|
||||
|
||||
_bufferSize = (latency * rate) / 1000;
|
||||
_bufferSize *= 2; // stereo
|
||||
rb_init(&_rb, _bufferSize);
|
||||
|
||||
AudioComponentDescription desc = {
|
||||
.componentType = kAudioUnitType_Output,
|
||||
.componentSubType = kAudioUnitSubType_DefaultOutput,
|
||||
.componentManufacturer = kAudioUnitManufacturer_Apple,
|
||||
};
|
||||
|
||||
NSError *err;
|
||||
AUAudioUnit *au = [[AUAudioUnit alloc] initWithComponentDescription:desc error:&err];
|
||||
if (err != nil)
|
||||
return nil;
|
||||
|
||||
AVAudioFormat *format = au.outputBusses[0].format;
|
||||
if (format.channelCount != 2)
|
||||
return nil;
|
||||
|
||||
AVAudioFormat *renderFormat = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:rate channels:2];
|
||||
[au.inputBusses[0] setFormat:renderFormat error:&err];
|
||||
if (err != nil)
|
||||
return nil;
|
||||
|
||||
ringbuffer_h rb = &_rb;
|
||||
__block dispatch_semaphore_t sema = _sema;
|
||||
au.outputProvider = ^AUAudioUnitStatus(AudioUnitRenderActionFlags * actionFlags, const AudioTimeStamp * timestamp, AUAudioFrameCount frameCount, NSInteger inputBusNumber, AudioBufferList * inputData) {
|
||||
rb_read_data(rb, inputData->mBuffers[0].mData, inputData->mBuffers[1].mData, frameCount);
|
||||
dispatch_semaphore_signal(sema);
|
||||
return 0;
|
||||
};
|
||||
|
||||
[au allocateRenderResourcesAndReturnError:&err];
|
||||
if (err != nil)
|
||||
return nil;
|
||||
|
||||
_au = au;
|
||||
|
||||
RARCH_LOG("[CoreAudio3]: Using buffer size of %u bytes: (latency = %u ms)\n", (unsigned)self.bufferSizeInBytes, latency);
|
||||
|
||||
[self start];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
rb_free(&_rb);
|
||||
}
|
||||
|
||||
- (BOOL)paused {
|
||||
return !_au.running;
|
||||
}
|
||||
|
||||
- (size_t)bufferSizeInBytes {
|
||||
return _bufferSize * sizeof(float);
|
||||
}
|
||||
|
||||
- (size_t)writeAvailableInBytes {
|
||||
return rb_avail(&_rb) * sizeof(float);
|
||||
}
|
||||
|
||||
- (void)start {
|
||||
NSError *err;
|
||||
[_au startHardwareAndReturnError:&err];
|
||||
}
|
||||
|
||||
- (void)stop {
|
||||
[_au stopHardware];
|
||||
}
|
||||
|
||||
- (ssize_t)writeFloat:(const float *)data samples:(size_t)samples {
|
||||
size_t written = 0;
|
||||
while (!g_interrupted && samples > 0)
|
||||
{
|
||||
size_t write_avail = rb_avail(&_rb);
|
||||
if (write_avail > samples)
|
||||
write_avail = samples;
|
||||
|
||||
rb_write_data(&_rb, data, write_avail);
|
||||
data += write_avail;
|
||||
written += write_avail;
|
||||
samples -= write_avail;
|
||||
|
||||
if (_nonBlock)
|
||||
break;
|
||||
|
||||
if (write_avail == 0)
|
||||
dispatch_semaphore_wait(_sema, DISPATCH_TIME_FOREVER);
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
static void coreaudio3_free(void *data)
|
||||
{
|
||||
CoreAudio3 *dev = (__bridge_transfer CoreAudio3 *)data;
|
||||
if (dev == nil)
|
||||
return;
|
||||
|
||||
[dev stop];
|
||||
dev = nil;
|
||||
}
|
||||
|
||||
static void *coreaudio3_init(const char *device,
|
||||
unsigned rate, unsigned latency,
|
||||
unsigned block_frames,
|
||||
unsigned *new_rate)
|
||||
{
|
||||
CoreAudio3 *dev = [[CoreAudio3 alloc] initWithRate:rate
|
||||
latency:latency];
|
||||
|
||||
*new_rate = rate;
|
||||
|
||||
return (__bridge_retained void *)dev;
|
||||
}
|
||||
|
||||
static ssize_t coreaudio3_write(void *data, const void *buf_, size_t size)
|
||||
{
|
||||
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
|
||||
return [dev writeFloat:(const float *)buf_ samples:size/sizeof(float)] * sizeof(float);
|
||||
}
|
||||
|
||||
static void coreaudio3_set_nonblock_state(void *data, bool state)
|
||||
{
|
||||
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
|
||||
if (dev == nil)
|
||||
return;
|
||||
|
||||
dev.nonBlock = state;
|
||||
}
|
||||
|
||||
static bool coreaudio3_alive(void *data)
|
||||
{
|
||||
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
|
||||
if (dev == nil)
|
||||
return NO;
|
||||
|
||||
return !dev.paused;
|
||||
}
|
||||
|
||||
static bool coreaudio3_stop(void *data)
|
||||
{
|
||||
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
|
||||
if (dev == nil)
|
||||
return NO;
|
||||
|
||||
[dev stop];
|
||||
return dev.paused;
|
||||
}
|
||||
|
||||
static bool coreaudio3_start(void *data, bool is_shutdown)
|
||||
{
|
||||
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
|
||||
if (dev == nil)
|
||||
return NO;
|
||||
|
||||
[dev start];
|
||||
return !dev.paused;
|
||||
}
|
||||
|
||||
static bool coreaudio3_use_float(void *data)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
static size_t coreaudio3_write_avail(void *data)
|
||||
{
|
||||
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
|
||||
if (dev == nil)
|
||||
return 0;
|
||||
|
||||
return dev.writeAvailableInBytes;
|
||||
}
|
||||
|
||||
static size_t coreaudio3_buffer_size(void *data)
|
||||
{
|
||||
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
|
||||
if (dev == nil)
|
||||
return 0;
|
||||
|
||||
return dev.bufferSizeInBytes;
|
||||
}
|
||||
|
||||
audio_driver_t audio_coreaudio3 = {
|
||||
coreaudio3_init,
|
||||
coreaudio3_write,
|
||||
coreaudio3_stop,
|
||||
coreaudio3_start,
|
||||
coreaudio3_alive,
|
||||
coreaudio3_set_nonblock_state,
|
||||
coreaudio3_free,
|
||||
coreaudio3_use_float,
|
||||
"coreaudio3",
|
||||
coreaudio3_write_avail,
|
||||
coreaudio3_buffer_size,
|
||||
};
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2019 - Stuart Carnie
|
||||
*
|
||||
* RetroArch 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 Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch 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 RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <AudioToolbox/AudioToolbox.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
|
||||
#include "../audio_driver.h"
|
||||
|
||||
#pragma mark - ringbuffer
|
||||
|
||||
typedef struct ringbuffer
|
||||
{
|
||||
float *buffer;
|
||||
size_t cap;
|
||||
atomic_int len;
|
||||
size_t writePtr;
|
||||
size_t readPtr;
|
||||
} ringbuffer_t;
|
||||
|
||||
typedef ringbuffer_t * ringbuffer_h;
|
||||
|
||||
static inline size_t rb_len(ringbuffer_h r)
|
||||
{
|
||||
return atomic_load_explicit(&r->len, memory_order_relaxed);
|
||||
}
|
||||
|
||||
static inline size_t rb_cap(ringbuffer_h r)
|
||||
{
|
||||
return (r->readPtr + r->cap - r->writePtr) % r->cap;
|
||||
}
|
||||
|
||||
static inline size_t rb_avail(ringbuffer_h r)
|
||||
{
|
||||
return r->cap - rb_len(r);
|
||||
}
|
||||
|
||||
static inline void rb_advance_write(ringbuffer_h r)
|
||||
{
|
||||
r->writePtr = (r->writePtr + 1) % r->cap;
|
||||
}
|
||||
|
||||
static inline void rb_advance_write_n(ringbuffer_h r, size_t n)
|
||||
{
|
||||
r->writePtr = (r->writePtr + n) % r->cap;
|
||||
}
|
||||
|
||||
static inline void rb_advance_read(ringbuffer_h r)
|
||||
{
|
||||
r->readPtr = (r->readPtr + 1) % r->cap;
|
||||
}
|
||||
|
||||
static inline void rb_len_add(ringbuffer_h r, int n)
|
||||
{
|
||||
atomic_fetch_add(&r->len, n);
|
||||
}
|
||||
|
||||
static inline void rb_len_sub(ringbuffer_h r, int n)
|
||||
{
|
||||
atomic_fetch_sub(&r->len, n);
|
||||
}
|
||||
|
||||
static void rb_init(ringbuffer_h r, size_t cap)
|
||||
{
|
||||
r->buffer = malloc(cap * sizeof(float));
|
||||
r->cap = cap;
|
||||
atomic_init(&r->len, 0);
|
||||
r->writePtr = 0;
|
||||
r->readPtr = 0;
|
||||
}
|
||||
|
||||
static void rb_free(ringbuffer_h r)
|
||||
{
|
||||
free(r->buffer);
|
||||
bzero(r, sizeof(*r));
|
||||
}
|
||||
|
||||
#define UNLIKELY(x) __builtin_expect((x), 0)
|
||||
#define LIKELY(x) __builtin_expect((x), 1)
|
||||
|
||||
static void rb_write_data(ringbuffer_h r, const float *data, size_t len)
|
||||
{
|
||||
size_t avail = rb_avail(r);
|
||||
size_t n = MIN(len, avail);
|
||||
size_t first_write = n;
|
||||
size_t rest_write = 0;
|
||||
|
||||
if (r->writePtr + n > r->cap)
|
||||
{
|
||||
first_write = r->cap - r->writePtr;
|
||||
rest_write = n - first_write;
|
||||
}
|
||||
|
||||
memcpy(r->buffer + r->writePtr, data, first_write*sizeof(float));
|
||||
memcpy(r->buffer, data + first_write, rest_write*sizeof(float));
|
||||
|
||||
rb_advance_write_n(r, n);
|
||||
rb_len_add(r, (int)n);
|
||||
}
|
||||
|
||||
static void rb_read_data(ringbuffer_h r, float *d0, float *d1, size_t len)
|
||||
{
|
||||
size_t need = len*2;
|
||||
|
||||
do {
|
||||
size_t have = rb_len(r);
|
||||
size_t n = MIN(have, need);
|
||||
int i = 0;
|
||||
for (; i < n/2; i++)
|
||||
{
|
||||
d0[i] = r->buffer[r->readPtr];
|
||||
rb_advance_read(r);
|
||||
d1[i] = r->buffer[r->readPtr];
|
||||
rb_advance_read(r);
|
||||
}
|
||||
|
||||
need -= n;
|
||||
rb_len_sub(r, (int)n);
|
||||
|
||||
if (UNLIKELY(need > 0))
|
||||
{
|
||||
/* we got more data */
|
||||
if (rb_len(r) > 0)
|
||||
continue;
|
||||
|
||||
// underflow
|
||||
const float quiet = 0.0f;
|
||||
size_t fill = (need/2)*sizeof(float);
|
||||
memset_pattern4(&d0[i], &quiet, fill);
|
||||
memset_pattern4(&d1[i], &quiet, fill);
|
||||
}
|
||||
} while (0);
|
||||
}
|
||||
|
||||
#pragma mark - CoreAudio3
|
||||
|
||||
static bool g_interrupted;
|
||||
|
||||
@interface CoreAudio3 : NSObject {
|
||||
ringbuffer_t _rb;
|
||||
dispatch_semaphore_t _sema;
|
||||
AUAudioUnit *_au;
|
||||
size_t _bufferSize;
|
||||
BOOL _nonBlock;
|
||||
}
|
||||
|
||||
@property (nonatomic, readwrite) BOOL nonBlock;
|
||||
@property (nonatomic, readonly) BOOL paused;
|
||||
@property (nonatomic, readonly) size_t writeAvailableInBytes;
|
||||
@property (nonatomic, readonly) size_t bufferSizeInBytes;
|
||||
|
||||
- (instancetype)initWithRate:(NSUInteger)rate
|
||||
latency:(NSUInteger)latency;
|
||||
- (ssize_t)writeFloat:(const float *)data samples:(size_t)samples;
|
||||
- (void)start;
|
||||
- (void)stop;
|
||||
|
||||
@end
|
||||
|
||||
@implementation CoreAudio3
|
||||
|
||||
- (instancetype)initWithRate:(NSUInteger)rate
|
||||
latency:(NSUInteger)latency {
|
||||
if (self = [super init])
|
||||
{
|
||||
_sema = dispatch_semaphore_create(0);
|
||||
|
||||
_bufferSize = (latency * rate) / 1000;
|
||||
_bufferSize *= 2; // stereo
|
||||
rb_init(&_rb, _bufferSize);
|
||||
|
||||
AudioComponentDescription desc = {
|
||||
.componentType = kAudioUnitType_Output,
|
||||
.componentSubType = kAudioUnitSubType_DefaultOutput,
|
||||
.componentManufacturer = kAudioUnitManufacturer_Apple,
|
||||
};
|
||||
|
||||
NSError *err;
|
||||
AUAudioUnit *au = [[AUAudioUnit alloc] initWithComponentDescription:desc error:&err];
|
||||
if (err != nil)
|
||||
return nil;
|
||||
|
||||
AVAudioFormat *format = au.outputBusses[0].format;
|
||||
if (format.channelCount != 2)
|
||||
return nil;
|
||||
|
||||
AVAudioFormat *renderFormat = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:rate channels:2];
|
||||
[au.inputBusses[0] setFormat:renderFormat error:&err];
|
||||
if (err != nil)
|
||||
return nil;
|
||||
|
||||
ringbuffer_h rb = &_rb;
|
||||
__block dispatch_semaphore_t sema = _sema;
|
||||
au.outputProvider = ^AUAudioUnitStatus(AudioUnitRenderActionFlags * actionFlags, const AudioTimeStamp * timestamp, AUAudioFrameCount frameCount, NSInteger inputBusNumber, AudioBufferList * inputData) {
|
||||
rb_read_data(rb, inputData->mBuffers[0].mData, inputData->mBuffers[1].mData, frameCount);
|
||||
dispatch_semaphore_signal(sema);
|
||||
return 0;
|
||||
};
|
||||
|
||||
[au allocateRenderResourcesAndReturnError:&err];
|
||||
if (err != nil)
|
||||
return nil;
|
||||
|
||||
_au = au;
|
||||
|
||||
RARCH_LOG("[CoreAudio3]: Using buffer size of %u bytes: (latency = %u ms)\n", (unsigned)self.bufferSizeInBytes, latency);
|
||||
|
||||
[self start];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
rb_free(&_rb);
|
||||
}
|
||||
|
||||
- (BOOL)paused {
|
||||
return !_au.running;
|
||||
}
|
||||
|
||||
- (size_t)bufferSizeInBytes {
|
||||
return _bufferSize * sizeof(float);
|
||||
}
|
||||
|
||||
- (size_t)writeAvailableInBytes {
|
||||
return rb_avail(&_rb) * sizeof(float);
|
||||
}
|
||||
|
||||
- (void)start {
|
||||
NSError *err;
|
||||
[_au startHardwareAndReturnError:&err];
|
||||
}
|
||||
|
||||
- (void)stop {
|
||||
[_au stopHardware];
|
||||
}
|
||||
|
||||
- (ssize_t)writeFloat:(const float *)data samples:(size_t)samples {
|
||||
size_t written = 0;
|
||||
while (!g_interrupted && samples > 0)
|
||||
{
|
||||
size_t write_avail = rb_avail(&_rb);
|
||||
if (write_avail > samples)
|
||||
write_avail = samples;
|
||||
|
||||
rb_write_data(&_rb, data, write_avail);
|
||||
data += write_avail;
|
||||
written += write_avail;
|
||||
samples -= write_avail;
|
||||
|
||||
if (_nonBlock)
|
||||
break;
|
||||
|
||||
if (write_avail == 0)
|
||||
dispatch_semaphore_wait(_sema, DISPATCH_TIME_FOREVER);
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
static void coreaudio3_free(void *data)
|
||||
{
|
||||
CoreAudio3 *dev = (__bridge_transfer CoreAudio3 *)data;
|
||||
if (dev == nil)
|
||||
return;
|
||||
|
||||
[dev stop];
|
||||
dev = nil;
|
||||
}
|
||||
|
||||
static void *coreaudio3_init(const char *device,
|
||||
unsigned rate, unsigned latency,
|
||||
unsigned block_frames,
|
||||
unsigned *new_rate)
|
||||
{
|
||||
CoreAudio3 *dev = [[CoreAudio3 alloc] initWithRate:rate
|
||||
latency:latency];
|
||||
|
||||
*new_rate = rate;
|
||||
|
||||
return (__bridge_retained void *)dev;
|
||||
}
|
||||
|
||||
static ssize_t coreaudio3_write(void *data, const void *buf_, size_t size)
|
||||
{
|
||||
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
|
||||
return [dev writeFloat:(const float *)buf_ samples:size/sizeof(float)] * sizeof(float);
|
||||
}
|
||||
|
||||
static void coreaudio3_set_nonblock_state(void *data, bool state)
|
||||
{
|
||||
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
|
||||
if (dev == nil)
|
||||
return;
|
||||
|
||||
dev.nonBlock = state;
|
||||
}
|
||||
|
||||
static bool coreaudio3_alive(void *data)
|
||||
{
|
||||
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
|
||||
if (dev == nil)
|
||||
return NO;
|
||||
|
||||
return !dev.paused;
|
||||
}
|
||||
|
||||
static bool coreaudio3_stop(void *data)
|
||||
{
|
||||
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
|
||||
if (dev == nil)
|
||||
return NO;
|
||||
|
||||
[dev stop];
|
||||
return dev.paused;
|
||||
}
|
||||
|
||||
static bool coreaudio3_start(void *data, bool is_shutdown)
|
||||
{
|
||||
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
|
||||
if (dev == nil)
|
||||
return NO;
|
||||
|
||||
[dev start];
|
||||
return !dev.paused;
|
||||
}
|
||||
|
||||
static bool coreaudio3_use_float(void *data)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
static size_t coreaudio3_write_avail(void *data)
|
||||
{
|
||||
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
|
||||
if (dev == nil)
|
||||
return 0;
|
||||
|
||||
return dev.writeAvailableInBytes;
|
||||
}
|
||||
|
||||
static size_t coreaudio3_buffer_size(void *data)
|
||||
{
|
||||
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
|
||||
if (dev == nil)
|
||||
return 0;
|
||||
|
||||
return dev.bufferSizeInBytes;
|
||||
}
|
||||
|
||||
audio_driver_t audio_coreaudio3 = {
|
||||
coreaudio3_init,
|
||||
coreaudio3_write,
|
||||
coreaudio3_stop,
|
||||
coreaudio3_start,
|
||||
coreaudio3_alive,
|
||||
coreaudio3_set_nonblock_state,
|
||||
coreaudio3_free,
|
||||
coreaudio3_use_float,
|
||||
"coreaudio3",
|
||||
coreaudio3_write_avail,
|
||||
coreaudio3_buffer_size,
|
||||
};
|
||||
|
@ -53,7 +53,7 @@ static void audioMainLoop(void *data)
|
||||
size_t size;
|
||||
|
||||
WaitSema(ps2->lock);
|
||||
size = MIN(fifo_read_avail(ps2->buffer), sizeof(out_tmp));
|
||||
size = MIN(fifo_read_avail(ps2->buffer), sizeof(out_tmp));
|
||||
fifo_read(ps2->buffer, out_tmp, size);
|
||||
iSignalSema(ps2->lock);
|
||||
iSignalSema(ps2->cond_lock);
|
||||
@ -262,7 +262,7 @@ static size_t ps2_audio_write_avail(void *data)
|
||||
{
|
||||
size_t size;
|
||||
WaitSema(ps2->lock);
|
||||
size = AUDIO_BUFFER - fifo_read_avail(ps2->buffer);
|
||||
size = AUDIO_BUFFER - fifo_read_avail(ps2->buffer);
|
||||
iSignalSema(ps2->lock);
|
||||
return size;
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ static void psp_audio_free(void *data)
|
||||
psp->running = false;
|
||||
sthread_join(psp->worker_thread);
|
||||
}
|
||||
|
||||
|
||||
if (psp->cond)
|
||||
scond_free(psp->cond);
|
||||
if (psp->fifo_lock)
|
||||
@ -205,7 +205,7 @@ static ssize_t psp_audio_write(void *data, const void *buf, size_t size)
|
||||
psp_audio_t* psp = (psp_audio_t*)data;
|
||||
uint16_t write_pos = psp->write_pos;
|
||||
uint16_t sampleCount = size / sizeof(uint32_t);
|
||||
|
||||
|
||||
if (!psp->running)
|
||||
return -1;
|
||||
|
||||
@ -241,7 +241,6 @@ static ssize_t psp_audio_write(void *data, const void *buf, size_t size)
|
||||
slock_unlock(psp->fifo_lock);
|
||||
return size;
|
||||
|
||||
|
||||
}
|
||||
|
||||
static bool psp_audio_alive(void *data)
|
||||
|
@ -120,7 +120,7 @@ static ssize_t switch_audio_write(void *data, const void *buf, size_t size)
|
||||
|
||||
if (to_write > switch_audio_buffer_size(NULL) - swa->current_buffer->data_size)
|
||||
to_write = switch_audio_buffer_size(NULL) - swa->current_buffer->data_size;
|
||||
|
||||
|
||||
#ifndef HAVE_LIBNX
|
||||
memcpy(((uint8_t*) swa->current_buffer->sample_data) + swa->current_buffer->data_size, buf, to_write);
|
||||
#else
|
||||
@ -137,7 +137,7 @@ static ssize_t switch_audio_write(void *data, const void *buf, size_t size)
|
||||
}
|
||||
|
||||
swa->last_append = svcGetSystemTick();
|
||||
|
||||
|
||||
return to_write;
|
||||
}
|
||||
|
||||
@ -328,7 +328,7 @@ static void *switch_audio_init(const char *device,
|
||||
swa->is_paused = true;
|
||||
|
||||
RARCH_LOG("[Audio]: Audio initialized\n");
|
||||
|
||||
|
||||
return swa;
|
||||
|
||||
fail_audio_output:
|
||||
|
@ -237,7 +237,7 @@ static void *switch_thread_audio_init(const char *device, unsigned rate, unsigne
|
||||
if (switch_audio_ipc_output_append_buffer(swa, &swa->buffers[i]) != 0)
|
||||
goto fail_audio_output;
|
||||
}
|
||||
|
||||
|
||||
compat_mutex_create(&swa->fifoLock);
|
||||
swa->fifo = fifo_new(swa->fifoSize);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -149,7 +149,7 @@ done:
|
||||
}
|
||||
|
||||
static void *resampler_CC_init(const struct resampler_config *config,
|
||||
double bandwidth_mod,
|
||||
double bandwidth_mod,
|
||||
enum resampler_quality quality,
|
||||
resampler_simd_mask_t mask)
|
||||
{
|
||||
@ -488,7 +488,7 @@ static void resampler_CC_process(void *re_, struct resampler_data *data)
|
||||
}
|
||||
|
||||
static void *resampler_CC_init(const struct resampler_config *config,
|
||||
double bandwidth_mod,
|
||||
double bandwidth_mod,
|
||||
enum resampler_quality quality,
|
||||
resampler_simd_mask_t mask)
|
||||
{
|
||||
|
@ -78,7 +78,6 @@
|
||||
# d23: (temp) # d31: buffer[6]
|
||||
# (temp) # buffer[7]
|
||||
|
||||
|
||||
resampler_CC_downsample_neon:
|
||||
_resampler_CC_downsample_neon:
|
||||
|
||||
@ -89,7 +88,6 @@ push {r4}
|
||||
|
||||
mov r4, r0
|
||||
|
||||
|
||||
veor q0, q0, q0
|
||||
vmov.f32 s1, #1.0
|
||||
vmov.f32 s2, #2.0
|
||||
@ -102,18 +100,15 @@ vmov.f32 q5, #1.0
|
||||
vmov.f32 q6, #3.0
|
||||
vmov.f32 q7, #0.25
|
||||
|
||||
|
||||
vldr s5, [r2, #32]
|
||||
vdiv.f32 s6, s20, s4
|
||||
vadd.f32 s7, s6, s8
|
||||
vdup.f32 q4, d2[0]
|
||||
vmin.f32 q4, q4, q5
|
||||
|
||||
|
||||
lsl r3, #3
|
||||
add r3, r3, r1
|
||||
|
||||
|
||||
cmp r3, r1
|
||||
beq 3f
|
||||
1:
|
||||
@ -199,7 +194,6 @@ vpop {q4,q5,q6,q7}
|
||||
|
||||
bx lr
|
||||
|
||||
|
||||
.align 4
|
||||
.globl resampler_CC_upsample_neon
|
||||
#ifndef __MACH__
|
||||
@ -256,7 +250,6 @@ bx lr
|
||||
# d23: (temp) # d31: buffer[6]
|
||||
# (temp) # buffer[7]
|
||||
|
||||
|
||||
resampler_CC_upsample_neon:
|
||||
_resampler_CC_upsample_neon:
|
||||
|
||||
@ -267,7 +260,6 @@ push {r4}
|
||||
|
||||
mov r4, r0
|
||||
|
||||
|
||||
veor q0, q0, q0
|
||||
vmov.f32 s0, #1.0
|
||||
vmov.f32 s2, #-1.0
|
||||
@ -280,18 +272,15 @@ vmov.f32 q5, #1.0
|
||||
vmov.f32 q6, #3.0
|
||||
vmov.f32 q7, #0.25
|
||||
|
||||
|
||||
vldr s5, [r2, #32]
|
||||
vdiv.f32 s6, s20, s4
|
||||
vadd.f32 s7, s6, s8
|
||||
vdup.f32 q4, d2[0]
|
||||
vmin.f32 q4, q4, q5
|
||||
|
||||
|
||||
lsl r3, #3
|
||||
add r3, r3, r1
|
||||
|
||||
|
||||
cmp r3, r1
|
||||
beq 4f
|
||||
1:
|
||||
@ -356,7 +345,6 @@ vst1.f32 d20, [r4, :64]!
|
||||
|
||||
vadd.f32 s5, s5, s6
|
||||
|
||||
|
||||
vcmpe.f32 s5, s20
|
||||
vmrs APSR_nzcv, fpscr
|
||||
blt 2b
|
||||
@ -368,7 +356,6 @@ vsub.f32 s5, s5, s20
|
||||
cmp r3, r1
|
||||
bne 1b
|
||||
|
||||
|
||||
4:
|
||||
vst1.f32 {q14-q15}, [r2, :256]
|
||||
vstr s5, [r2, #32]
|
||||
|
@ -86,7 +86,7 @@ SECTIONS
|
||||
KEEP (*(.fini))
|
||||
. = ALIGN(32); /* REQUIRED. LD is flaky without it. */
|
||||
} = 0
|
||||
|
||||
|
||||
PROVIDE (__etext = .);
|
||||
PROVIDE (_etext = .);
|
||||
PROVIDE (etext = .);
|
||||
@ -167,7 +167,6 @@ SECTIONS
|
||||
.jcr : { KEEP (*(.jcr)) }
|
||||
.got : { *(.got.plt) *(.got) }
|
||||
|
||||
|
||||
/* We want the small data sections together, so single-instruction offsets
|
||||
can access them all, and initialized data all before uninitialized, so
|
||||
we can shorten the on-disk segment size. */
|
||||
@ -182,7 +181,7 @@ SECTIONS
|
||||
|
||||
_edata = .;
|
||||
PROVIDE (edata = .);
|
||||
|
||||
|
||||
.sbss :
|
||||
{
|
||||
__sbss_start = .;
|
||||
|
@ -97,7 +97,7 @@ SECTIONS
|
||||
KEEP (*(.fini))
|
||||
. = ALIGN(32); /* REQUIRED. LD is flaky without it. */
|
||||
} = 0
|
||||
|
||||
|
||||
PROVIDE (__etext = .);
|
||||
PROVIDE (_etext = .);
|
||||
PROVIDE (etext = .);
|
||||
@ -178,7 +178,6 @@ SECTIONS
|
||||
.jcr : { KEEP (*(.jcr)) }
|
||||
.got : { *(.got.plt) *(.got) }
|
||||
|
||||
|
||||
/* We want the small data sections together, so single-instruction offsets
|
||||
can access them all, and initialized data all before uninitialized, so
|
||||
we can shorten the on-disk segment size. */
|
||||
@ -193,7 +192,7 @@ SECTIONS
|
||||
|
||||
_edata = .;
|
||||
PROVIDE (edata = .);
|
||||
|
||||
|
||||
.sbss :
|
||||
{
|
||||
__sbss_start = .;
|
||||
|
@ -56,7 +56,7 @@ void exitspawn_kernel(const char *fileName, SceSize args, void *argp)
|
||||
game_param.unk5 = 0x10000;
|
||||
|
||||
int k1 = pspSdkSetK1(0);
|
||||
//sceKernelSuspendAllUserThreads();
|
||||
//sceKernelSuspendAllUserThreads();
|
||||
int ret = sceKernelLoadExecVSHMs2(fileName, &game_param);
|
||||
pspSdkSetK1(k1);
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ typedef struct
|
||||
#endif
|
||||
|
||||
bool core_supports;
|
||||
|
||||
|
||||
cheevos_rapatchdata_t patchdata;
|
||||
cheevos_cheevo_t* core;
|
||||
cheevos_cheevo_t* unofficial;
|
||||
@ -289,7 +289,7 @@ static int cheevos_parse(const char* json)
|
||||
cheevos_racheevo_t* rac = NULL;
|
||||
|
||||
cheevos_fixup_init(&cheevos_locals.fixups);
|
||||
|
||||
|
||||
res = cheevos_get_patchdata(json, &cheevos_locals.patchdata);
|
||||
|
||||
if (res != 0)
|
||||
@ -312,13 +312,13 @@ static int cheevos_parse(const char* json)
|
||||
/* Allocate memory. */
|
||||
cheevos_locals.core = (cheevos_cheevo_t*)
|
||||
calloc(cheevos_locals.patchdata.core_count, sizeof(cheevos_cheevo_t));
|
||||
|
||||
|
||||
cheevos_locals.unofficial = (cheevos_cheevo_t*)
|
||||
calloc(cheevos_locals.patchdata.unofficial_count, sizeof(cheevos_cheevo_t));
|
||||
|
||||
cheevos_locals.lboards = (cheevos_lboard_t*)
|
||||
calloc(cheevos_locals.patchdata.lboard_count, sizeof(cheevos_lboard_t));
|
||||
|
||||
|
||||
if ( !cheevos_locals.core
|
||||
|| !cheevos_locals.unofficial
|
||||
|| !cheevos_locals.lboards)
|
||||
@ -726,7 +726,7 @@ void cheevos_populate_menu(void* data)
|
||||
cheevos_cheevo_t* cheevo = NULL;
|
||||
|
||||
if ( settings->bools.cheevos_enable
|
||||
&& settings->bools.cheevos_hardcore_mode_enable
|
||||
&& settings->bools.cheevos_hardcore_mode_enable
|
||||
&& cheevos_loaded)
|
||||
{
|
||||
if (!cheevos_hardcore_paused)
|
||||
@ -773,7 +773,7 @@ void cheevos_populate_menu(void* data)
|
||||
cheevo->info->description,
|
||||
MENU_ENUM_LABEL_CHEEVOS_LOCKED_ENTRY,
|
||||
MENU_SETTINGS_CHEEVOS_START + i, 0, 0);
|
||||
|
||||
|
||||
set_badge_info(&badges_ctx, i, cheevo->info->badge,
|
||||
(cheevo->active & CHEEVOS_ACTIVE_SOFTCORE));
|
||||
}
|
||||
@ -811,7 +811,7 @@ void cheevos_populate_menu(void* data)
|
||||
cheevo->info->description,
|
||||
MENU_ENUM_LABEL_CHEEVOS_LOCKED_ENTRY,
|
||||
MENU_SETTINGS_CHEEVOS_START + i, 0, 0);
|
||||
|
||||
|
||||
set_badge_info(&badges_ctx, i, cheevo->info->badge,
|
||||
(cheevo->active & CHEEVOS_ACTIVE_SOFTCORE));
|
||||
}
|
||||
@ -979,7 +979,7 @@ void cheevos_test(void)
|
||||
{
|
||||
if (settings->bools.cheevos_test_unofficial)
|
||||
cheevos_test_cheevo_set(false);
|
||||
|
||||
|
||||
if (settings->bools.cheevos_hardcore_mode_enable &&
|
||||
settings->bools.cheevos_leaderboards_enable &&
|
||||
!cheevos_hardcore_paused)
|
||||
@ -1671,7 +1671,7 @@ found:
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
if (!(
|
||||
string_is_equal(settings->arrays.menu_driver, "xmb") ||
|
||||
string_is_equal(settings->arrays.menu_driver, "xmb") ||
|
||||
string_is_equal(settings->arrays.menu_driver, "ozone")
|
||||
) ||
|
||||
!settings->bools.cheevos_badges_enable)
|
||||
|
@ -197,7 +197,7 @@ const uint8_t* cheevos_patch_address(unsigned address, int console)
|
||||
{
|
||||
unsigned addr = address;
|
||||
pointer = desc->core.ptr;
|
||||
|
||||
|
||||
address = (unsigned)cheevos_var_reduce(
|
||||
(addr - desc->core.start) & desc->disconnect_mask,
|
||||
desc->core.disconnect);
|
||||
|
@ -148,7 +148,7 @@ int cheevos_get_token(const char* json, char* token, size_t length)
|
||||
|
||||
if (!string_is_empty(token))
|
||||
return -1;
|
||||
|
||||
|
||||
return cheevos_get_value(json, CHEEVOS_JSON_KEY_TOKEN, token, length);
|
||||
}
|
||||
|
||||
|
@ -1,171 +1,171 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2018 - Andre Leiradella
|
||||
*
|
||||
* RetroArch 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 Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch 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 RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __RARCH_CHEEVOS_OLD_H
|
||||
#define __RARCH_CHEEVOS_OLD_H
|
||||
|
||||
#ifdef HAVE_NEW_CHEEVOS
|
||||
#include "../cheevos-new/cheevos.h"
|
||||
#else
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <boolean.h>
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
/*****************************************************************************
|
||||
Setup - mainly for debugging
|
||||
*****************************************************************************/
|
||||
|
||||
/* Define this macro to get extra-verbose log for cheevos. */
|
||||
#undef CHEEVOS_VERBOSE
|
||||
|
||||
/*****************************************************************************
|
||||
End of setup
|
||||
*****************************************************************************/
|
||||
|
||||
#define CHEEVOS_TAG "[CHEEVOS]: "
|
||||
|
||||
#ifdef CHEEVOS_VERBOSE
|
||||
|
||||
#define CHEEVOS_LOG RARCH_LOG
|
||||
#define CHEEVOS_ERR RARCH_ERR
|
||||
|
||||
#else
|
||||
|
||||
void cheevos_log(const char *fmt, ...);
|
||||
|
||||
#define CHEEVOS_LOG cheevos_log
|
||||
#define CHEEVOS_ERR cheevos_log
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct cheevos_ctx_desc
|
||||
{
|
||||
unsigned idx;
|
||||
char *s;
|
||||
size_t len;
|
||||
} cheevos_ctx_desc_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CHEEVOS_CONSOLE_NONE = 0,
|
||||
/* Don't change those, the values match the console IDs
|
||||
* at retroachievements.org. */
|
||||
CHEEVOS_CONSOLE_MEGA_DRIVE = 1,
|
||||
CHEEVOS_CONSOLE_NINTENDO_64 = 2,
|
||||
CHEEVOS_CONSOLE_SUPER_NINTENDO = 3,
|
||||
CHEEVOS_CONSOLE_GAMEBOY = 4,
|
||||
CHEEVOS_CONSOLE_GAMEBOY_ADVANCE = 5,
|
||||
CHEEVOS_CONSOLE_GAMEBOY_COLOR = 6,
|
||||
CHEEVOS_CONSOLE_NINTENDO = 7,
|
||||
CHEEVOS_CONSOLE_PC_ENGINE = 8,
|
||||
CHEEVOS_CONSOLE_SEGA_CD = 9,
|
||||
CHEEVOS_CONSOLE_SEGA_32X = 10,
|
||||
CHEEVOS_CONSOLE_MASTER_SYSTEM = 11,
|
||||
CHEEVOS_CONSOLE_PLAYSTATION = 12,
|
||||
CHEEVOS_CONSOLE_ATARI_LYNX = 13,
|
||||
CHEEVOS_CONSOLE_NEOGEO_POCKET = 14,
|
||||
CHEEVOS_CONSOLE_GAME_GEAR = 15,
|
||||
CHEEVOS_CONSOLE_GAMECUBE = 16,
|
||||
CHEEVOS_CONSOLE_ATARI_JAGUAR = 17,
|
||||
CHEEVOS_CONSOLE_NINTENDO_DS = 18,
|
||||
CHEEVOS_CONSOLE_WII = 19,
|
||||
CHEEVOS_CONSOLE_WII_U = 20,
|
||||
CHEEVOS_CONSOLE_PLAYSTATION_2 = 21,
|
||||
CHEEVOS_CONSOLE_XBOX = 22,
|
||||
CHEEVOS_CONSOLE_SKYNET = 23,
|
||||
CHEEVOS_CONSOLE_XBOX_ONE = 24,
|
||||
CHEEVOS_CONSOLE_ATARI_2600 = 25,
|
||||
CHEEVOS_CONSOLE_MS_DOS = 26,
|
||||
CHEEVOS_CONSOLE_ARCADE = 27,
|
||||
CHEEVOS_CONSOLE_VIRTUAL_BOY = 28,
|
||||
CHEEVOS_CONSOLE_MSX = 29,
|
||||
CHEEVOS_CONSOLE_COMMODORE_64 = 30,
|
||||
CHEEVOS_CONSOLE_ZX81 = 31,
|
||||
CHEEVOS_CONSOLE_ATARI_7800 = 51
|
||||
} cheevos_console_t;
|
||||
|
||||
enum
|
||||
{
|
||||
CHEEVOS_DIRTY_TITLE = 1 << 0,
|
||||
CHEEVOS_DIRTY_DESC = 1 << 1,
|
||||
CHEEVOS_DIRTY_POINTS = 1 << 2,
|
||||
CHEEVOS_DIRTY_AUTHOR = 1 << 3,
|
||||
CHEEVOS_DIRTY_ID = 1 << 4,
|
||||
CHEEVOS_DIRTY_BADGE = 1 << 5,
|
||||
CHEEVOS_DIRTY_CONDITIONS = 1 << 6,
|
||||
CHEEVOS_DIRTY_VOTES = 1 << 7,
|
||||
CHEEVOS_DIRTY_DESCRIPTION = 1 << 8,
|
||||
|
||||
CHEEVOS_DIRTY_ALL = (1 << 9) - 1
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CHEEVOS_ACTIVE_SOFTCORE = 1 << 0,
|
||||
CHEEVOS_ACTIVE_HARDCORE = 1 << 1
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CHEEVOS_FORMAT_FRAMES = 0,
|
||||
CHEEVOS_FORMAT_SECS,
|
||||
CHEEVOS_FORMAT_MILLIS,
|
||||
CHEEVOS_FORMAT_SCORE,
|
||||
CHEEVOS_FORMAT_VALUE,
|
||||
CHEEVOS_FORMAT_OTHER
|
||||
};
|
||||
|
||||
bool cheevos_load(const void *data);
|
||||
|
||||
void cheevos_reset_game(void);
|
||||
|
||||
void cheevos_populate_menu(void *data);
|
||||
|
||||
bool cheevos_get_description(cheevos_ctx_desc_t *desc);
|
||||
|
||||
bool cheevos_apply_cheats(bool *data_bool);
|
||||
|
||||
bool cheevos_unload(void);
|
||||
|
||||
bool cheevos_toggle_hardcore_mode(void);
|
||||
|
||||
void cheevos_test(void);
|
||||
|
||||
bool cheevos_set_cheats(void);
|
||||
|
||||
void cheevos_set_support_cheevos(bool state);
|
||||
|
||||
bool cheevos_get_support_cheevos(void);
|
||||
|
||||
cheevos_console_t cheevos_get_console(void);
|
||||
|
||||
extern bool cheevos_loaded;
|
||||
extern bool cheevos_hardcore_active;
|
||||
extern bool cheevos_hardcore_paused;
|
||||
extern bool cheevos_state_loaded_flag;
|
||||
extern int cheats_are_enabled;
|
||||
extern int cheats_were_enabled;
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __RARCH_CHEEVOS_H */
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2018 - Andre Leiradella
|
||||
*
|
||||
* RetroArch 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 Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch 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 RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __RARCH_CHEEVOS_OLD_H
|
||||
#define __RARCH_CHEEVOS_OLD_H
|
||||
|
||||
#ifdef HAVE_NEW_CHEEVOS
|
||||
#include "../cheevos-new/cheevos.h"
|
||||
#else
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <boolean.h>
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
/*****************************************************************************
|
||||
Setup - mainly for debugging
|
||||
*****************************************************************************/
|
||||
|
||||
/* Define this macro to get extra-verbose log for cheevos. */
|
||||
#undef CHEEVOS_VERBOSE
|
||||
|
||||
/*****************************************************************************
|
||||
End of setup
|
||||
*****************************************************************************/
|
||||
|
||||
#define CHEEVOS_TAG "[CHEEVOS]: "
|
||||
|
||||
#ifdef CHEEVOS_VERBOSE
|
||||
|
||||
#define CHEEVOS_LOG RARCH_LOG
|
||||
#define CHEEVOS_ERR RARCH_ERR
|
||||
|
||||
#else
|
||||
|
||||
void cheevos_log(const char *fmt, ...);
|
||||
|
||||
#define CHEEVOS_LOG cheevos_log
|
||||
#define CHEEVOS_ERR cheevos_log
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct cheevos_ctx_desc
|
||||
{
|
||||
unsigned idx;
|
||||
char *s;
|
||||
size_t len;
|
||||
} cheevos_ctx_desc_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CHEEVOS_CONSOLE_NONE = 0,
|
||||
/* Don't change those, the values match the console IDs
|
||||
* at retroachievements.org. */
|
||||
CHEEVOS_CONSOLE_MEGA_DRIVE = 1,
|
||||
CHEEVOS_CONSOLE_NINTENDO_64 = 2,
|
||||
CHEEVOS_CONSOLE_SUPER_NINTENDO = 3,
|
||||
CHEEVOS_CONSOLE_GAMEBOY = 4,
|
||||
CHEEVOS_CONSOLE_GAMEBOY_ADVANCE = 5,
|
||||
CHEEVOS_CONSOLE_GAMEBOY_COLOR = 6,
|
||||
CHEEVOS_CONSOLE_NINTENDO = 7,
|
||||
CHEEVOS_CONSOLE_PC_ENGINE = 8,
|
||||
CHEEVOS_CONSOLE_SEGA_CD = 9,
|
||||
CHEEVOS_CONSOLE_SEGA_32X = 10,
|
||||
CHEEVOS_CONSOLE_MASTER_SYSTEM = 11,
|
||||
CHEEVOS_CONSOLE_PLAYSTATION = 12,
|
||||
CHEEVOS_CONSOLE_ATARI_LYNX = 13,
|
||||
CHEEVOS_CONSOLE_NEOGEO_POCKET = 14,
|
||||
CHEEVOS_CONSOLE_GAME_GEAR = 15,
|
||||
CHEEVOS_CONSOLE_GAMECUBE = 16,
|
||||
CHEEVOS_CONSOLE_ATARI_JAGUAR = 17,
|
||||
CHEEVOS_CONSOLE_NINTENDO_DS = 18,
|
||||
CHEEVOS_CONSOLE_WII = 19,
|
||||
CHEEVOS_CONSOLE_WII_U = 20,
|
||||
CHEEVOS_CONSOLE_PLAYSTATION_2 = 21,
|
||||
CHEEVOS_CONSOLE_XBOX = 22,
|
||||
CHEEVOS_CONSOLE_SKYNET = 23,
|
||||
CHEEVOS_CONSOLE_XBOX_ONE = 24,
|
||||
CHEEVOS_CONSOLE_ATARI_2600 = 25,
|
||||
CHEEVOS_CONSOLE_MS_DOS = 26,
|
||||
CHEEVOS_CONSOLE_ARCADE = 27,
|
||||
CHEEVOS_CONSOLE_VIRTUAL_BOY = 28,
|
||||
CHEEVOS_CONSOLE_MSX = 29,
|
||||
CHEEVOS_CONSOLE_COMMODORE_64 = 30,
|
||||
CHEEVOS_CONSOLE_ZX81 = 31,
|
||||
CHEEVOS_CONSOLE_ATARI_7800 = 51
|
||||
} cheevos_console_t;
|
||||
|
||||
enum
|
||||
{
|
||||
CHEEVOS_DIRTY_TITLE = 1 << 0,
|
||||
CHEEVOS_DIRTY_DESC = 1 << 1,
|
||||
CHEEVOS_DIRTY_POINTS = 1 << 2,
|
||||
CHEEVOS_DIRTY_AUTHOR = 1 << 3,
|
||||
CHEEVOS_DIRTY_ID = 1 << 4,
|
||||
CHEEVOS_DIRTY_BADGE = 1 << 5,
|
||||
CHEEVOS_DIRTY_CONDITIONS = 1 << 6,
|
||||
CHEEVOS_DIRTY_VOTES = 1 << 7,
|
||||
CHEEVOS_DIRTY_DESCRIPTION = 1 << 8,
|
||||
|
||||
CHEEVOS_DIRTY_ALL = (1 << 9) - 1
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CHEEVOS_ACTIVE_SOFTCORE = 1 << 0,
|
||||
CHEEVOS_ACTIVE_HARDCORE = 1 << 1
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CHEEVOS_FORMAT_FRAMES = 0,
|
||||
CHEEVOS_FORMAT_SECS,
|
||||
CHEEVOS_FORMAT_MILLIS,
|
||||
CHEEVOS_FORMAT_SCORE,
|
||||
CHEEVOS_FORMAT_VALUE,
|
||||
CHEEVOS_FORMAT_OTHER
|
||||
};
|
||||
|
||||
bool cheevos_load(const void *data);
|
||||
|
||||
void cheevos_reset_game(void);
|
||||
|
||||
void cheevos_populate_menu(void *data);
|
||||
|
||||
bool cheevos_get_description(cheevos_ctx_desc_t *desc);
|
||||
|
||||
bool cheevos_apply_cheats(bool *data_bool);
|
||||
|
||||
bool cheevos_unload(void);
|
||||
|
||||
bool cheevos_toggle_hardcore_mode(void);
|
||||
|
||||
void cheevos_test(void);
|
||||
|
||||
bool cheevos_set_cheats(void);
|
||||
|
||||
void cheevos_set_support_cheevos(bool state);
|
||||
|
||||
bool cheevos_get_support_cheevos(void);
|
||||
|
||||
cheevos_console_t cheevos_get_console(void);
|
||||
|
||||
extern bool cheevos_loaded;
|
||||
extern bool cheevos_hardcore_active;
|
||||
extern bool cheevos_hardcore_paused;
|
||||
extern bool cheevos_state_loaded_flag;
|
||||
extern int cheats_are_enabled;
|
||||
extern int cheats_were_enabled;
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __RARCH_CHEEVOS_H */
|
||||
|
378
cheevos/cond.c
378
cheevos/cond.c
@ -1,189 +1,189 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2017 - Andre Leiradella
|
||||
*
|
||||
* RetroArch 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 Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch 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 RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "cond.h"
|
||||
#include "var.h"
|
||||
|
||||
#include "../retroarch.h"
|
||||
#include "../verbosity.h"
|
||||
|
||||
/*****************************************************************************
|
||||
Parsing
|
||||
*****************************************************************************/
|
||||
|
||||
static cheevos_cond_op_t cheevos_cond_parse_operator(const char** memaddr)
|
||||
{
|
||||
const char *str = *memaddr;
|
||||
cheevos_cond_op_t op;
|
||||
|
||||
if (*str == '=' && str[1] == '=')
|
||||
{
|
||||
op = CHEEVOS_COND_OP_EQUALS;
|
||||
str += 2;
|
||||
}
|
||||
else if (*str == '=')
|
||||
{
|
||||
op = CHEEVOS_COND_OP_EQUALS;
|
||||
str++;
|
||||
}
|
||||
else if (*str == '!' && str[1] == '=')
|
||||
{
|
||||
op = CHEEVOS_COND_OP_NOT_EQUAL_TO;
|
||||
str += 2;
|
||||
}
|
||||
else if (*str == '<' && str[1] == '=')
|
||||
{
|
||||
op = CHEEVOS_COND_OP_LESS_THAN_OR_EQUAL;
|
||||
str += 2;
|
||||
}
|
||||
else if (*str == '<')
|
||||
{
|
||||
op = CHEEVOS_COND_OP_LESS_THAN;
|
||||
str++;
|
||||
}
|
||||
else if (*str == '>' && str[1] == '=')
|
||||
{
|
||||
op = CHEEVOS_COND_OP_GREATER_THAN_OR_EQUAL;
|
||||
str += 2;
|
||||
}
|
||||
else if (*str == '>')
|
||||
{
|
||||
op = CHEEVOS_COND_OP_GREATER_THAN;
|
||||
str++;
|
||||
}
|
||||
else
|
||||
{
|
||||
CHEEVOS_ERR(CHEEVOS_TAG "unknown operator %c\n.", *str);
|
||||
op = CHEEVOS_COND_OP_EQUALS;
|
||||
}
|
||||
|
||||
*memaddr = str;
|
||||
return op;
|
||||
}
|
||||
|
||||
void cheevos_cond_parse(cheevos_cond_t* cond, const char** memaddr)
|
||||
{
|
||||
const char* str = *memaddr;
|
||||
cond->type = CHEEVOS_COND_TYPE_STANDARD;
|
||||
|
||||
if (*str != 0 && str[1] == ':')
|
||||
{
|
||||
int skip = 2;
|
||||
|
||||
switch (*str)
|
||||
{
|
||||
case 'R':
|
||||
cond->type = CHEEVOS_COND_TYPE_RESET_IF;
|
||||
break;
|
||||
case 'P':
|
||||
cond->type = CHEEVOS_COND_TYPE_PAUSE_IF;
|
||||
break;
|
||||
case 'A':
|
||||
cond->type = CHEEVOS_COND_TYPE_ADD_SOURCE;
|
||||
break;
|
||||
case 'B':
|
||||
cond->type = CHEEVOS_COND_TYPE_SUB_SOURCE;
|
||||
break;
|
||||
case 'C':
|
||||
cond->type = CHEEVOS_COND_TYPE_ADD_HITS;
|
||||
break;
|
||||
default:
|
||||
skip = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
str += skip;
|
||||
}
|
||||
|
||||
cheevos_var_parse(&cond->source, &str);
|
||||
cond->op = cheevos_cond_parse_operator(&str);
|
||||
cheevos_var_parse(&cond->target, &str);
|
||||
cond->curr_hits = 0;
|
||||
|
||||
if (*str == '(' || *str == '.')
|
||||
{
|
||||
char* end;
|
||||
cond->req_hits = (unsigned)strtol(str + 1, &end, 10);
|
||||
str = end + (*end == ')' || *end == '.');
|
||||
}
|
||||
else
|
||||
cond->req_hits = 0;
|
||||
|
||||
*memaddr = str;
|
||||
}
|
||||
|
||||
unsigned cheevos_cond_count_in_set(const char* memaddr, unsigned which)
|
||||
{
|
||||
cheevos_cond_t dummy;
|
||||
unsigned index = 0;
|
||||
unsigned count = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
cheevos_cond_parse(&dummy, &memaddr);
|
||||
|
||||
if (index == which)
|
||||
count++;
|
||||
|
||||
if (*memaddr != '_')
|
||||
break;
|
||||
|
||||
memaddr++;
|
||||
}
|
||||
|
||||
index++;
|
||||
|
||||
if (*memaddr != 'S')
|
||||
break;
|
||||
|
||||
memaddr++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void cheevos_cond_parse_in_set(cheevos_cond_t* cond, const char* memaddr, unsigned which)
|
||||
{
|
||||
cheevos_cond_t dummy;
|
||||
unsigned index = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (index == which)
|
||||
{
|
||||
cheevos_cond_parse(cond, &memaddr);
|
||||
cond++;
|
||||
}
|
||||
else
|
||||
cheevos_cond_parse(&dummy, &memaddr);
|
||||
|
||||
if (*memaddr != '_')
|
||||
break;
|
||||
|
||||
memaddr++;
|
||||
}
|
||||
|
||||
index++;
|
||||
|
||||
if (*memaddr != 'S')
|
||||
break;
|
||||
|
||||
memaddr++;
|
||||
}
|
||||
}
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2017 - Andre Leiradella
|
||||
*
|
||||
* RetroArch 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 Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch 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 RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "cond.h"
|
||||
#include "var.h"
|
||||
|
||||
#include "../retroarch.h"
|
||||
#include "../verbosity.h"
|
||||
|
||||
/*****************************************************************************
|
||||
Parsing
|
||||
*****************************************************************************/
|
||||
|
||||
static cheevos_cond_op_t cheevos_cond_parse_operator(const char** memaddr)
|
||||
{
|
||||
const char *str = *memaddr;
|
||||
cheevos_cond_op_t op;
|
||||
|
||||
if (*str == '=' && str[1] == '=')
|
||||
{
|
||||
op = CHEEVOS_COND_OP_EQUALS;
|
||||
str += 2;
|
||||
}
|
||||
else if (*str == '=')
|
||||
{
|
||||
op = CHEEVOS_COND_OP_EQUALS;
|
||||
str++;
|
||||
}
|
||||
else if (*str == '!' && str[1] == '=')
|
||||
{
|
||||
op = CHEEVOS_COND_OP_NOT_EQUAL_TO;
|
||||
str += 2;
|
||||
}
|
||||
else if (*str == '<' && str[1] == '=')
|
||||
{
|
||||
op = CHEEVOS_COND_OP_LESS_THAN_OR_EQUAL;
|
||||
str += 2;
|
||||
}
|
||||
else if (*str == '<')
|
||||
{
|
||||
op = CHEEVOS_COND_OP_LESS_THAN;
|
||||
str++;
|
||||
}
|
||||
else if (*str == '>' && str[1] == '=')
|
||||
{
|
||||
op = CHEEVOS_COND_OP_GREATER_THAN_OR_EQUAL;
|
||||
str += 2;
|
||||
}
|
||||
else if (*str == '>')
|
||||
{
|
||||
op = CHEEVOS_COND_OP_GREATER_THAN;
|
||||
str++;
|
||||
}
|
||||
else
|
||||
{
|
||||
CHEEVOS_ERR(CHEEVOS_TAG "unknown operator %c\n.", *str);
|
||||
op = CHEEVOS_COND_OP_EQUALS;
|
||||
}
|
||||
|
||||
*memaddr = str;
|
||||
return op;
|
||||
}
|
||||
|
||||
void cheevos_cond_parse(cheevos_cond_t* cond, const char** memaddr)
|
||||
{
|
||||
const char* str = *memaddr;
|
||||
cond->type = CHEEVOS_COND_TYPE_STANDARD;
|
||||
|
||||
if (*str != 0 && str[1] == ':')
|
||||
{
|
||||
int skip = 2;
|
||||
|
||||
switch (*str)
|
||||
{
|
||||
case 'R':
|
||||
cond->type = CHEEVOS_COND_TYPE_RESET_IF;
|
||||
break;
|
||||
case 'P':
|
||||
cond->type = CHEEVOS_COND_TYPE_PAUSE_IF;
|
||||
break;
|
||||
case 'A':
|
||||
cond->type = CHEEVOS_COND_TYPE_ADD_SOURCE;
|
||||
break;
|
||||
case 'B':
|
||||
cond->type = CHEEVOS_COND_TYPE_SUB_SOURCE;
|
||||
break;
|
||||
case 'C':
|
||||
cond->type = CHEEVOS_COND_TYPE_ADD_HITS;
|
||||
break;
|
||||
default:
|
||||
skip = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
str += skip;
|
||||
}
|
||||
|
||||
cheevos_var_parse(&cond->source, &str);
|
||||
cond->op = cheevos_cond_parse_operator(&str);
|
||||
cheevos_var_parse(&cond->target, &str);
|
||||
cond->curr_hits = 0;
|
||||
|
||||
if (*str == '(' || *str == '.')
|
||||
{
|
||||
char* end;
|
||||
cond->req_hits = (unsigned)strtol(str + 1, &end, 10);
|
||||
str = end + (*end == ')' || *end == '.');
|
||||
}
|
||||
else
|
||||
cond->req_hits = 0;
|
||||
|
||||
*memaddr = str;
|
||||
}
|
||||
|
||||
unsigned cheevos_cond_count_in_set(const char* memaddr, unsigned which)
|
||||
{
|
||||
cheevos_cond_t dummy;
|
||||
unsigned index = 0;
|
||||
unsigned count = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
cheevos_cond_parse(&dummy, &memaddr);
|
||||
|
||||
if (index == which)
|
||||
count++;
|
||||
|
||||
if (*memaddr != '_')
|
||||
break;
|
||||
|
||||
memaddr++;
|
||||
}
|
||||
|
||||
index++;
|
||||
|
||||
if (*memaddr != 'S')
|
||||
break;
|
||||
|
||||
memaddr++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void cheevos_cond_parse_in_set(cheevos_cond_t* cond, const char* memaddr, unsigned which)
|
||||
{
|
||||
cheevos_cond_t dummy;
|
||||
unsigned index = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (index == which)
|
||||
{
|
||||
cheevos_cond_parse(cond, &memaddr);
|
||||
cond++;
|
||||
}
|
||||
else
|
||||
cheevos_cond_parse(&dummy, &memaddr);
|
||||
|
||||
if (*memaddr != '_')
|
||||
break;
|
||||
|
||||
memaddr++;
|
||||
}
|
||||
|
||||
index++;
|
||||
|
||||
if (*memaddr != 'S')
|
||||
break;
|
||||
|
||||
memaddr++;
|
||||
}
|
||||
}
|
||||
|
126
cheevos/cond.h
126
cheevos/cond.h
@ -1,63 +1,63 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2017 - Andre Leiradella
|
||||
*
|
||||
* RetroArch 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 Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch 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 RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __RARCH_CHEEVOS_COND_H
|
||||
#define __RARCH_CHEEVOS_COND_H
|
||||
|
||||
#include "var.h"
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CHEEVOS_COND_TYPE_STANDARD,
|
||||
CHEEVOS_COND_TYPE_PAUSE_IF,
|
||||
CHEEVOS_COND_TYPE_RESET_IF,
|
||||
CHEEVOS_COND_TYPE_ADD_SOURCE,
|
||||
CHEEVOS_COND_TYPE_SUB_SOURCE,
|
||||
CHEEVOS_COND_TYPE_ADD_HITS
|
||||
} cheevos_cond_type_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CHEEVOS_COND_OP_EQUALS,
|
||||
CHEEVOS_COND_OP_LESS_THAN,
|
||||
CHEEVOS_COND_OP_LESS_THAN_OR_EQUAL,
|
||||
CHEEVOS_COND_OP_GREATER_THAN,
|
||||
CHEEVOS_COND_OP_GREATER_THAN_OR_EQUAL,
|
||||
CHEEVOS_COND_OP_NOT_EQUAL_TO
|
||||
} cheevos_cond_op_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
cheevos_cond_type_t type;
|
||||
unsigned req_hits;
|
||||
unsigned curr_hits;
|
||||
char pause;
|
||||
|
||||
cheevos_var_t source;
|
||||
cheevos_cond_op_t op;
|
||||
cheevos_var_t target;
|
||||
} cheevos_cond_t;
|
||||
|
||||
void cheevos_cond_parse(cheevos_cond_t* cond, const char** memaddr);
|
||||
unsigned cheevos_cond_count_in_set(const char* memaddr, unsigned which);
|
||||
void cheevos_cond_parse_in_set(cheevos_cond_t* cond, const char* memaddr, unsigned which);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif /* __RARCH_CHEEVOS_COND_H */
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2017 - Andre Leiradella
|
||||
*
|
||||
* RetroArch 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 Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch 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 RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __RARCH_CHEEVOS_COND_H
|
||||
#define __RARCH_CHEEVOS_COND_H
|
||||
|
||||
#include "var.h"
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CHEEVOS_COND_TYPE_STANDARD,
|
||||
CHEEVOS_COND_TYPE_PAUSE_IF,
|
||||
CHEEVOS_COND_TYPE_RESET_IF,
|
||||
CHEEVOS_COND_TYPE_ADD_SOURCE,
|
||||
CHEEVOS_COND_TYPE_SUB_SOURCE,
|
||||
CHEEVOS_COND_TYPE_ADD_HITS
|
||||
} cheevos_cond_type_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CHEEVOS_COND_OP_EQUALS,
|
||||
CHEEVOS_COND_OP_LESS_THAN,
|
||||
CHEEVOS_COND_OP_LESS_THAN_OR_EQUAL,
|
||||
CHEEVOS_COND_OP_GREATER_THAN,
|
||||
CHEEVOS_COND_OP_GREATER_THAN_OR_EQUAL,
|
||||
CHEEVOS_COND_OP_NOT_EQUAL_TO
|
||||
} cheevos_cond_op_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
cheevos_cond_type_t type;
|
||||
unsigned req_hits;
|
||||
unsigned curr_hits;
|
||||
char pause;
|
||||
|
||||
cheevos_var_t source;
|
||||
cheevos_cond_op_t op;
|
||||
cheevos_var_t target;
|
||||
} cheevos_cond_t;
|
||||
|
||||
void cheevos_cond_parse(cheevos_cond_t* cond, const char** memaddr);
|
||||
unsigned cheevos_cond_count_in_set(const char* memaddr, unsigned which);
|
||||
void cheevos_cond_parse_in_set(cheevos_cond_t* cond, const char* memaddr, unsigned which);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif /* __RARCH_CHEEVOS_COND_H */
|
||||
|
150
cheevos/coro.h
150
cheevos/coro.h
@ -1,75 +1,75 @@
|
||||
#ifndef CORO_H
|
||||
#define CORO_H
|
||||
|
||||
/*
|
||||
Released under the CC0: https://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/* Use at the beginning of the coroutine, you must have declared a variable coro_t* coro */
|
||||
#define CORO_ENTER() \
|
||||
{ \
|
||||
CORO_again: ; \
|
||||
switch ( coro->step ) { \
|
||||
case CORO_BEGIN: ;
|
||||
|
||||
/* Use to define labels which are targets to GOTO and GOSUB */
|
||||
#define CORO_SUB( x ) \
|
||||
case x: ;
|
||||
|
||||
/* Use at the end of the coroutine */
|
||||
#define CORO_LEAVE() \
|
||||
} } \
|
||||
do { return 0; } while ( 0 )
|
||||
|
||||
/* Go to the x label */
|
||||
#define CORO_GOTO( x ) \
|
||||
do { \
|
||||
coro->step = ( x ); \
|
||||
goto CORO_again; \
|
||||
} while ( 0 )
|
||||
|
||||
/* Go to a subroutine, execution continues until the subroutine returns via RET */
|
||||
#define CORO_GOSUB( x ) \
|
||||
do { \
|
||||
coro->stack[ coro->sp++ ] = __LINE__; \
|
||||
coro->step = ( x ); \
|
||||
goto CORO_again; \
|
||||
case __LINE__: ; \
|
||||
} while ( 0 )
|
||||
|
||||
/* Returns from a subroutine */
|
||||
#define CORO_RET() \
|
||||
do { \
|
||||
coro->step = coro->stack[ --coro->sp ]; \
|
||||
goto CORO_again; \
|
||||
} while ( 0 )
|
||||
|
||||
/* Yields to the caller, execution continues from this point when the coroutine is resumed */
|
||||
#define CORO_YIELD() \
|
||||
do { \
|
||||
coro->step = __LINE__; \
|
||||
return 1; \
|
||||
case __LINE__: ; \
|
||||
} while ( 0 )
|
||||
|
||||
/* The coroutine entry point, never use 0 as a label */
|
||||
#define CORO_BEGIN 0
|
||||
|
||||
/* Sets up the coroutine */
|
||||
#define CORO_SETUP() \
|
||||
do { \
|
||||
coro->step = CORO_BEGIN; \
|
||||
coro->sp = 0; \
|
||||
} while ( 0 )
|
||||
|
||||
#define CORO_STOP() \
|
||||
do { \
|
||||
return 0; \
|
||||
} while ( 0 )
|
||||
|
||||
/* Add this macro to your coro_t structure containing the variables for the coroutine */
|
||||
#define CORO_FIELDS \
|
||||
int step, sp; \
|
||||
int stack[ 8 ];
|
||||
|
||||
#endif /* CORO_H */
|
||||
#ifndef CORO_H
|
||||
#define CORO_H
|
||||
|
||||
/*
|
||||
Released under the CC0: https://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/* Use at the beginning of the coroutine, you must have declared a variable coro_t* coro */
|
||||
#define CORO_ENTER() \
|
||||
{ \
|
||||
CORO_again: ; \
|
||||
switch ( coro->step ) { \
|
||||
case CORO_BEGIN: ;
|
||||
|
||||
/* Use to define labels which are targets to GOTO and GOSUB */
|
||||
#define CORO_SUB( x ) \
|
||||
case x: ;
|
||||
|
||||
/* Use at the end of the coroutine */
|
||||
#define CORO_LEAVE() \
|
||||
} } \
|
||||
do { return 0; } while ( 0 )
|
||||
|
||||
/* Go to the x label */
|
||||
#define CORO_GOTO( x ) \
|
||||
do { \
|
||||
coro->step = ( x ); \
|
||||
goto CORO_again; \
|
||||
} while ( 0 )
|
||||
|
||||
/* Go to a subroutine, execution continues until the subroutine returns via RET */
|
||||
#define CORO_GOSUB( x ) \
|
||||
do { \
|
||||
coro->stack[ coro->sp++ ] = __LINE__; \
|
||||
coro->step = ( x ); \
|
||||
goto CORO_again; \
|
||||
case __LINE__: ; \
|
||||
} while ( 0 )
|
||||
|
||||
/* Returns from a subroutine */
|
||||
#define CORO_RET() \
|
||||
do { \
|
||||
coro->step = coro->stack[ --coro->sp ]; \
|
||||
goto CORO_again; \
|
||||
} while ( 0 )
|
||||
|
||||
/* Yields to the caller, execution continues from this point when the coroutine is resumed */
|
||||
#define CORO_YIELD() \
|
||||
do { \
|
||||
coro->step = __LINE__; \
|
||||
return 1; \
|
||||
case __LINE__: ; \
|
||||
} while ( 0 )
|
||||
|
||||
/* The coroutine entry point, never use 0 as a label */
|
||||
#define CORO_BEGIN 0
|
||||
|
||||
/* Sets up the coroutine */
|
||||
#define CORO_SETUP() \
|
||||
do { \
|
||||
coro->step = CORO_BEGIN; \
|
||||
coro->sp = 0; \
|
||||
} while ( 0 )
|
||||
|
||||
#define CORO_STOP() \
|
||||
do { \
|
||||
return 0; \
|
||||
} while ( 0 )
|
||||
|
||||
/* Add this macro to your coro_t structure containing the variables for the coroutine */
|
||||
#define CORO_FIELDS \
|
||||
int step, sp; \
|
||||
int stack[ 8 ];
|
||||
|
||||
#endif /* CORO_H */
|
||||
|
830
cheevos/var.c
830
cheevos/var.c
@ -1,415 +1,415 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2017 - Andre Leiradella
|
||||
*
|
||||
* RetroArch 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 Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch 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 RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <libretro.h>
|
||||
|
||||
#include "var.h"
|
||||
|
||||
#include "../retroarch.h"
|
||||
#include "../core.h"
|
||||
#include "../verbosity.h"
|
||||
|
||||
/*****************************************************************************
|
||||
Parsing
|
||||
*****************************************************************************/
|
||||
|
||||
static cheevos_var_size_t cheevos_var_parse_prefix(const char** memaddr)
|
||||
{
|
||||
/* Careful not to use ABCDEF here, this denotes part of an actual variable! */
|
||||
const char* str = *memaddr;
|
||||
cheevos_var_size_t size;
|
||||
|
||||
switch (toupper((unsigned char)*str++))
|
||||
{
|
||||
case 'M':
|
||||
size = CHEEVOS_VAR_SIZE_BIT_0;
|
||||
break;
|
||||
case 'N':
|
||||
size = CHEEVOS_VAR_SIZE_BIT_1;
|
||||
break;
|
||||
case 'O':
|
||||
size = CHEEVOS_VAR_SIZE_BIT_2;
|
||||
break;
|
||||
case 'P':
|
||||
size = CHEEVOS_VAR_SIZE_BIT_3;
|
||||
break;
|
||||
case 'Q':
|
||||
size = CHEEVOS_VAR_SIZE_BIT_4;
|
||||
break;
|
||||
case 'R':
|
||||
size = CHEEVOS_VAR_SIZE_BIT_5;
|
||||
break;
|
||||
case 'S':
|
||||
size = CHEEVOS_VAR_SIZE_BIT_6;
|
||||
break;
|
||||
case 'T':
|
||||
size = CHEEVOS_VAR_SIZE_BIT_7;
|
||||
break;
|
||||
case 'L':
|
||||
size = CHEEVOS_VAR_SIZE_NIBBLE_LOWER;
|
||||
break;
|
||||
case 'U':
|
||||
size = CHEEVOS_VAR_SIZE_NIBBLE_UPPER;
|
||||
break;
|
||||
case 'H':
|
||||
size = CHEEVOS_VAR_SIZE_EIGHT_BITS;
|
||||
break;
|
||||
case 'X':
|
||||
size = CHEEVOS_VAR_SIZE_THIRTYTWO_BITS;
|
||||
break;
|
||||
default:
|
||||
str--;
|
||||
/* fall through */
|
||||
case ' ':
|
||||
size = CHEEVOS_VAR_SIZE_SIXTEEN_BITS;
|
||||
break;
|
||||
}
|
||||
|
||||
*memaddr = str;
|
||||
return size;
|
||||
}
|
||||
|
||||
static size_t cheevos_var_reduce(size_t addr, size_t mask)
|
||||
{
|
||||
while (mask)
|
||||
{
|
||||
size_t tmp = (mask - 1) & ~mask;
|
||||
addr = (addr & tmp) | ((addr >> 1) & ~tmp);
|
||||
mask = (mask & (mask - 1)) >> 1;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
static size_t cheevos_var_highest_bit(size_t n)
|
||||
{
|
||||
n |= n >> 1;
|
||||
n |= n >> 2;
|
||||
n |= n >> 4;
|
||||
n |= n >> 8;
|
||||
n |= n >> 16;
|
||||
|
||||
return n ^ (n >> 1);
|
||||
}
|
||||
|
||||
void cheevos_var_parse(cheevos_var_t* var, const char** memaddr)
|
||||
{
|
||||
char *end = NULL;
|
||||
const char *str = *memaddr;
|
||||
unsigned base = 16;
|
||||
|
||||
var->is_bcd = false;
|
||||
|
||||
if (toupper((unsigned char)*str) == 'D' && str[1] == '0' && toupper((unsigned char)str[2]) == 'X')
|
||||
{
|
||||
/* d0x + 4 hex digits */
|
||||
str += 3;
|
||||
var->type = CHEEVOS_VAR_TYPE_DELTA_MEM;
|
||||
}
|
||||
else if (toupper((unsigned char)*str) == 'B' && str[1] == '0' && toupper((unsigned char)str[2]) == 'X')
|
||||
{
|
||||
/* b0x (binary-coded decimal) */
|
||||
str += 3;
|
||||
var->is_bcd = true;
|
||||
var->type = CHEEVOS_VAR_TYPE_ADDRESS;
|
||||
}
|
||||
else if (*str == '0' && toupper((unsigned char)str[1]) == 'X')
|
||||
{
|
||||
/* 0x + 4 hex digits */
|
||||
str += 2;
|
||||
var->type = CHEEVOS_VAR_TYPE_ADDRESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
var->type = CHEEVOS_VAR_TYPE_VALUE_COMP;
|
||||
|
||||
if (toupper((unsigned char)*str) == 'H')
|
||||
str++;
|
||||
else
|
||||
{
|
||||
if (toupper((unsigned char)*str) == 'V')
|
||||
str++;
|
||||
|
||||
base = 10;
|
||||
}
|
||||
}
|
||||
|
||||
if (var->type != CHEEVOS_VAR_TYPE_VALUE_COMP)
|
||||
{
|
||||
var->size = cheevos_var_parse_prefix(&str);
|
||||
}
|
||||
|
||||
var->value = (unsigned)strtol(str, &end, base);
|
||||
*memaddr = end;
|
||||
}
|
||||
|
||||
void cheevos_var_patch_addr(cheevos_var_t* var, cheevos_console_t console)
|
||||
{
|
||||
rarch_system_info_t *system = runloop_get_system_info();
|
||||
|
||||
var->bank_id = -1;
|
||||
|
||||
if (console == CHEEVOS_CONSOLE_NINTENDO)
|
||||
{
|
||||
if (var->value >= 0x0800 && var->value < 0x2000)
|
||||
{
|
||||
CHEEVOS_LOG(CHEEVOS_TAG "NES memory address in mirrorred RAM %X, adjusted to %X\n", var->value, var->value & 0x07ff);
|
||||
var->value &= 0x07ff;
|
||||
}
|
||||
}
|
||||
else if (console == CHEEVOS_CONSOLE_GAMEBOY_COLOR)
|
||||
{
|
||||
if (var->value >= 0xe000 && var->value <= 0xfdff)
|
||||
{
|
||||
CHEEVOS_LOG(CHEEVOS_TAG "GBC memory address in echo RAM %X, adjusted to %X\n", var->value, var->value - 0x2000);
|
||||
var->value -= 0x2000;
|
||||
}
|
||||
}
|
||||
|
||||
if (system->mmaps.num_descriptors != 0)
|
||||
{
|
||||
const rarch_memory_descriptor_t *desc = NULL;
|
||||
const rarch_memory_descriptor_t *end = NULL;
|
||||
|
||||
/* Patch the address to correctly map it to the mmaps */
|
||||
if (console == CHEEVOS_CONSOLE_GAMEBOY_ADVANCE)
|
||||
{
|
||||
if (var->value < 0x8000) /* Internal RAM */
|
||||
{
|
||||
CHEEVOS_LOG(CHEEVOS_TAG "GBA memory address %X adjusted to %X\n", var->value, var->value + 0x3000000);
|
||||
var->value += 0x3000000;
|
||||
}
|
||||
else /* Work RAM */
|
||||
{
|
||||
CHEEVOS_LOG(CHEEVOS_TAG "GBA memory address %X adjusted to %X\n", var->value, var->value + 0x2000000 - 0x8000);
|
||||
var->value += 0x2000000 - 0x8000;
|
||||
}
|
||||
}
|
||||
else if (console == CHEEVOS_CONSOLE_PC_ENGINE)
|
||||
{
|
||||
CHEEVOS_LOG(CHEEVOS_TAG "PCE memory address %X adjusted to %X\n", var->value, var->value + 0x1f0000);
|
||||
var->value += 0x1f0000;
|
||||
}
|
||||
else if (console == CHEEVOS_CONSOLE_SUPER_NINTENDO)
|
||||
{
|
||||
if (var->value < 0x020000) /* Work RAM */
|
||||
{
|
||||
CHEEVOS_LOG(CHEEVOS_TAG "SNES memory address %X adjusted to %X\n", var->value, var->value + 0x7e0000);
|
||||
var->value += 0x7e0000;
|
||||
}
|
||||
else /* Save RAM */
|
||||
{
|
||||
CHEEVOS_LOG(CHEEVOS_TAG "SNES memory address %X adjusted to %X\n", var->value, var->value + 0x006000 - 0x020000);
|
||||
var->value += 0x006000 - 0x020000;
|
||||
}
|
||||
}
|
||||
|
||||
desc = system->mmaps.descriptors;
|
||||
end = desc + system->mmaps.num_descriptors;
|
||||
|
||||
for (; desc < end; desc++)
|
||||
{
|
||||
if (((desc->core.start ^ var->value) & desc->core.select) == 0)
|
||||
{
|
||||
unsigned addr = var->value;
|
||||
var->bank_id = (int)(desc - system->mmaps.descriptors);
|
||||
var->value = (unsigned)cheevos_var_reduce(
|
||||
(addr - desc->core.start) & desc->disconnect_mask,
|
||||
desc->core.disconnect);
|
||||
|
||||
if (var->value >= desc->core.len)
|
||||
var->value -= cheevos_var_highest_bit(var->value);
|
||||
|
||||
var->value += desc->core.offset;
|
||||
|
||||
CHEEVOS_LOG(CHEEVOS_TAG "address %X set to descriptor %d at offset %X\n", addr, var->bank_id + 1, var->value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
retro_ctx_memory_info_t meminfo;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
meminfo.id = RETRO_MEMORY_SYSTEM_RAM;
|
||||
break;
|
||||
case 1:
|
||||
meminfo.id = RETRO_MEMORY_SAVE_RAM;
|
||||
break;
|
||||
case 2:
|
||||
meminfo.id = RETRO_MEMORY_VIDEO_RAM;
|
||||
break;
|
||||
case 3:
|
||||
meminfo.id = RETRO_MEMORY_RTC;
|
||||
break;
|
||||
}
|
||||
|
||||
core_get_memory(&meminfo);
|
||||
|
||||
if (var->value < meminfo.size)
|
||||
{
|
||||
var->bank_id = i;
|
||||
break;
|
||||
}
|
||||
|
||||
/* HACK subtract the correct amount of bytes to reach the save RAM */
|
||||
if (i == 0 && console == CHEEVOS_CONSOLE_NINTENDO)
|
||||
var->value -= 0x6000;
|
||||
else
|
||||
var->value -= meminfo.size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Testing
|
||||
*****************************************************************************/
|
||||
|
||||
uint8_t* cheevos_var_get_memory(const cheevos_var_t* var)
|
||||
{
|
||||
uint8_t* memory = NULL;
|
||||
|
||||
if (var->bank_id >= 0)
|
||||
{
|
||||
rarch_system_info_t* system = runloop_get_system_info();
|
||||
|
||||
if (system->mmaps.num_descriptors != 0)
|
||||
memory = (uint8_t*)system->mmaps.descriptors[var->bank_id].core.ptr;
|
||||
else
|
||||
{
|
||||
retro_ctx_memory_info_t meminfo = {NULL, 0, 0};
|
||||
|
||||
switch (var->bank_id)
|
||||
{
|
||||
case 0:
|
||||
meminfo.id = RETRO_MEMORY_SYSTEM_RAM;
|
||||
break;
|
||||
case 1:
|
||||
meminfo.id = RETRO_MEMORY_SAVE_RAM;
|
||||
break;
|
||||
case 2:
|
||||
meminfo.id = RETRO_MEMORY_VIDEO_RAM;
|
||||
break;
|
||||
case 3:
|
||||
meminfo.id = RETRO_MEMORY_RTC;
|
||||
break;
|
||||
default:
|
||||
CHEEVOS_ERR(CHEEVOS_TAG "invalid bank id: %s\n", var->bank_id);
|
||||
break;
|
||||
}
|
||||
|
||||
core_get_memory(&meminfo);
|
||||
memory = (uint8_t*)meminfo.data;
|
||||
}
|
||||
|
||||
if (memory)
|
||||
memory += var->value;
|
||||
}
|
||||
|
||||
return memory;
|
||||
}
|
||||
|
||||
unsigned cheevos_var_get_value(cheevos_var_t* var)
|
||||
{
|
||||
const uint8_t* memory = NULL;
|
||||
unsigned value = 0;
|
||||
|
||||
switch (var->type)
|
||||
{
|
||||
case CHEEVOS_VAR_TYPE_VALUE_COMP:
|
||||
value = var->value;
|
||||
break;
|
||||
|
||||
case CHEEVOS_VAR_TYPE_ADDRESS:
|
||||
case CHEEVOS_VAR_TYPE_DELTA_MEM:
|
||||
memory = cheevos_var_get_memory(var);
|
||||
|
||||
if (memory)
|
||||
{
|
||||
value = memory[0];
|
||||
|
||||
switch (var->size)
|
||||
{
|
||||
case CHEEVOS_VAR_SIZE_BIT_0:
|
||||
value &= 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_BIT_1:
|
||||
value = (value >> 1) & 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_BIT_2:
|
||||
value = (value >> 2) & 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_BIT_3:
|
||||
value = (value >> 3) & 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_BIT_4:
|
||||
value = (value >> 4) & 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_BIT_5:
|
||||
value = (value >> 5) & 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_BIT_6:
|
||||
value = (value >> 6) & 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_BIT_7:
|
||||
value = (value >> 7) & 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_NIBBLE_LOWER:
|
||||
value &= 0x0f;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_NIBBLE_UPPER:
|
||||
value = (value >> 4) & 0x0f;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_EIGHT_BITS:
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_SIXTEEN_BITS:
|
||||
value |= memory[1] << 8;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_THIRTYTWO_BITS:
|
||||
value |= memory[1] << 8;
|
||||
value |= memory[2] << 16;
|
||||
value |= memory[3] << 24;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (var->type == CHEEVOS_VAR_TYPE_DELTA_MEM)
|
||||
{
|
||||
unsigned previous = var->previous;
|
||||
var->previous = value;
|
||||
value = previous;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CHEEVOS_VAR_TYPE_DYNAMIC_VAR:
|
||||
/* We shouldn't get here... */
|
||||
break;
|
||||
}
|
||||
|
||||
if(var->is_bcd)
|
||||
return (((value >> 4) & 0xf) * 10) + (value & 0xf);
|
||||
return value;
|
||||
}
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2017 - Andre Leiradella
|
||||
*
|
||||
* RetroArch 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 Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch 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 RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <libretro.h>
|
||||
|
||||
#include "var.h"
|
||||
|
||||
#include "../retroarch.h"
|
||||
#include "../core.h"
|
||||
#include "../verbosity.h"
|
||||
|
||||
/*****************************************************************************
|
||||
Parsing
|
||||
*****************************************************************************/
|
||||
|
||||
static cheevos_var_size_t cheevos_var_parse_prefix(const char** memaddr)
|
||||
{
|
||||
/* Careful not to use ABCDEF here, this denotes part of an actual variable! */
|
||||
const char* str = *memaddr;
|
||||
cheevos_var_size_t size;
|
||||
|
||||
switch (toupper((unsigned char)*str++))
|
||||
{
|
||||
case 'M':
|
||||
size = CHEEVOS_VAR_SIZE_BIT_0;
|
||||
break;
|
||||
case 'N':
|
||||
size = CHEEVOS_VAR_SIZE_BIT_1;
|
||||
break;
|
||||
case 'O':
|
||||
size = CHEEVOS_VAR_SIZE_BIT_2;
|
||||
break;
|
||||
case 'P':
|
||||
size = CHEEVOS_VAR_SIZE_BIT_3;
|
||||
break;
|
||||
case 'Q':
|
||||
size = CHEEVOS_VAR_SIZE_BIT_4;
|
||||
break;
|
||||
case 'R':
|
||||
size = CHEEVOS_VAR_SIZE_BIT_5;
|
||||
break;
|
||||
case 'S':
|
||||
size = CHEEVOS_VAR_SIZE_BIT_6;
|
||||
break;
|
||||
case 'T':
|
||||
size = CHEEVOS_VAR_SIZE_BIT_7;
|
||||
break;
|
||||
case 'L':
|
||||
size = CHEEVOS_VAR_SIZE_NIBBLE_LOWER;
|
||||
break;
|
||||
case 'U':
|
||||
size = CHEEVOS_VAR_SIZE_NIBBLE_UPPER;
|
||||
break;
|
||||
case 'H':
|
||||
size = CHEEVOS_VAR_SIZE_EIGHT_BITS;
|
||||
break;
|
||||
case 'X':
|
||||
size = CHEEVOS_VAR_SIZE_THIRTYTWO_BITS;
|
||||
break;
|
||||
default:
|
||||
str--;
|
||||
/* fall through */
|
||||
case ' ':
|
||||
size = CHEEVOS_VAR_SIZE_SIXTEEN_BITS;
|
||||
break;
|
||||
}
|
||||
|
||||
*memaddr = str;
|
||||
return size;
|
||||
}
|
||||
|
||||
static size_t cheevos_var_reduce(size_t addr, size_t mask)
|
||||
{
|
||||
while (mask)
|
||||
{
|
||||
size_t tmp = (mask - 1) & ~mask;
|
||||
addr = (addr & tmp) | ((addr >> 1) & ~tmp);
|
||||
mask = (mask & (mask - 1)) >> 1;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
static size_t cheevos_var_highest_bit(size_t n)
|
||||
{
|
||||
n |= n >> 1;
|
||||
n |= n >> 2;
|
||||
n |= n >> 4;
|
||||
n |= n >> 8;
|
||||
n |= n >> 16;
|
||||
|
||||
return n ^ (n >> 1);
|
||||
}
|
||||
|
||||
void cheevos_var_parse(cheevos_var_t* var, const char** memaddr)
|
||||
{
|
||||
char *end = NULL;
|
||||
const char *str = *memaddr;
|
||||
unsigned base = 16;
|
||||
|
||||
var->is_bcd = false;
|
||||
|
||||
if (toupper((unsigned char)*str) == 'D' && str[1] == '0' && toupper((unsigned char)str[2]) == 'X')
|
||||
{
|
||||
/* d0x + 4 hex digits */
|
||||
str += 3;
|
||||
var->type = CHEEVOS_VAR_TYPE_DELTA_MEM;
|
||||
}
|
||||
else if (toupper((unsigned char)*str) == 'B' && str[1] == '0' && toupper((unsigned char)str[2]) == 'X')
|
||||
{
|
||||
/* b0x (binary-coded decimal) */
|
||||
str += 3;
|
||||
var->is_bcd = true;
|
||||
var->type = CHEEVOS_VAR_TYPE_ADDRESS;
|
||||
}
|
||||
else if (*str == '0' && toupper((unsigned char)str[1]) == 'X')
|
||||
{
|
||||
/* 0x + 4 hex digits */
|
||||
str += 2;
|
||||
var->type = CHEEVOS_VAR_TYPE_ADDRESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
var->type = CHEEVOS_VAR_TYPE_VALUE_COMP;
|
||||
|
||||
if (toupper((unsigned char)*str) == 'H')
|
||||
str++;
|
||||
else
|
||||
{
|
||||
if (toupper((unsigned char)*str) == 'V')
|
||||
str++;
|
||||
|
||||
base = 10;
|
||||
}
|
||||
}
|
||||
|
||||
if (var->type != CHEEVOS_VAR_TYPE_VALUE_COMP)
|
||||
{
|
||||
var->size = cheevos_var_parse_prefix(&str);
|
||||
}
|
||||
|
||||
var->value = (unsigned)strtol(str, &end, base);
|
||||
*memaddr = end;
|
||||
}
|
||||
|
||||
void cheevos_var_patch_addr(cheevos_var_t* var, cheevos_console_t console)
|
||||
{
|
||||
rarch_system_info_t *system = runloop_get_system_info();
|
||||
|
||||
var->bank_id = -1;
|
||||
|
||||
if (console == CHEEVOS_CONSOLE_NINTENDO)
|
||||
{
|
||||
if (var->value >= 0x0800 && var->value < 0x2000)
|
||||
{
|
||||
CHEEVOS_LOG(CHEEVOS_TAG "NES memory address in mirrorred RAM %X, adjusted to %X\n", var->value, var->value & 0x07ff);
|
||||
var->value &= 0x07ff;
|
||||
}
|
||||
}
|
||||
else if (console == CHEEVOS_CONSOLE_GAMEBOY_COLOR)
|
||||
{
|
||||
if (var->value >= 0xe000 && var->value <= 0xfdff)
|
||||
{
|
||||
CHEEVOS_LOG(CHEEVOS_TAG "GBC memory address in echo RAM %X, adjusted to %X\n", var->value, var->value - 0x2000);
|
||||
var->value -= 0x2000;
|
||||
}
|
||||
}
|
||||
|
||||
if (system->mmaps.num_descriptors != 0)
|
||||
{
|
||||
const rarch_memory_descriptor_t *desc = NULL;
|
||||
const rarch_memory_descriptor_t *end = NULL;
|
||||
|
||||
/* Patch the address to correctly map it to the mmaps */
|
||||
if (console == CHEEVOS_CONSOLE_GAMEBOY_ADVANCE)
|
||||
{
|
||||
if (var->value < 0x8000) /* Internal RAM */
|
||||
{
|
||||
CHEEVOS_LOG(CHEEVOS_TAG "GBA memory address %X adjusted to %X\n", var->value, var->value + 0x3000000);
|
||||
var->value += 0x3000000;
|
||||
}
|
||||
else /* Work RAM */
|
||||
{
|
||||
CHEEVOS_LOG(CHEEVOS_TAG "GBA memory address %X adjusted to %X\n", var->value, var->value + 0x2000000 - 0x8000);
|
||||
var->value += 0x2000000 - 0x8000;
|
||||
}
|
||||
}
|
||||
else if (console == CHEEVOS_CONSOLE_PC_ENGINE)
|
||||
{
|
||||
CHEEVOS_LOG(CHEEVOS_TAG "PCE memory address %X adjusted to %X\n", var->value, var->value + 0x1f0000);
|
||||
var->value += 0x1f0000;
|
||||
}
|
||||
else if (console == CHEEVOS_CONSOLE_SUPER_NINTENDO)
|
||||
{
|
||||
if (var->value < 0x020000) /* Work RAM */
|
||||
{
|
||||
CHEEVOS_LOG(CHEEVOS_TAG "SNES memory address %X adjusted to %X\n", var->value, var->value + 0x7e0000);
|
||||
var->value += 0x7e0000;
|
||||
}
|
||||
else /* Save RAM */
|
||||
{
|
||||
CHEEVOS_LOG(CHEEVOS_TAG "SNES memory address %X adjusted to %X\n", var->value, var->value + 0x006000 - 0x020000);
|
||||
var->value += 0x006000 - 0x020000;
|
||||
}
|
||||
}
|
||||
|
||||
desc = system->mmaps.descriptors;
|
||||
end = desc + system->mmaps.num_descriptors;
|
||||
|
||||
for (; desc < end; desc++)
|
||||
{
|
||||
if (((desc->core.start ^ var->value) & desc->core.select) == 0)
|
||||
{
|
||||
unsigned addr = var->value;
|
||||
var->bank_id = (int)(desc - system->mmaps.descriptors);
|
||||
var->value = (unsigned)cheevos_var_reduce(
|
||||
(addr - desc->core.start) & desc->disconnect_mask,
|
||||
desc->core.disconnect);
|
||||
|
||||
if (var->value >= desc->core.len)
|
||||
var->value -= cheevos_var_highest_bit(var->value);
|
||||
|
||||
var->value += desc->core.offset;
|
||||
|
||||
CHEEVOS_LOG(CHEEVOS_TAG "address %X set to descriptor %d at offset %X\n", addr, var->bank_id + 1, var->value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
retro_ctx_memory_info_t meminfo;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
meminfo.id = RETRO_MEMORY_SYSTEM_RAM;
|
||||
break;
|
||||
case 1:
|
||||
meminfo.id = RETRO_MEMORY_SAVE_RAM;
|
||||
break;
|
||||
case 2:
|
||||
meminfo.id = RETRO_MEMORY_VIDEO_RAM;
|
||||
break;
|
||||
case 3:
|
||||
meminfo.id = RETRO_MEMORY_RTC;
|
||||
break;
|
||||
}
|
||||
|
||||
core_get_memory(&meminfo);
|
||||
|
||||
if (var->value < meminfo.size)
|
||||
{
|
||||
var->bank_id = i;
|
||||
break;
|
||||
}
|
||||
|
||||
/* HACK subtract the correct amount of bytes to reach the save RAM */
|
||||
if (i == 0 && console == CHEEVOS_CONSOLE_NINTENDO)
|
||||
var->value -= 0x6000;
|
||||
else
|
||||
var->value -= meminfo.size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Testing
|
||||
*****************************************************************************/
|
||||
|
||||
uint8_t* cheevos_var_get_memory(const cheevos_var_t* var)
|
||||
{
|
||||
uint8_t* memory = NULL;
|
||||
|
||||
if (var->bank_id >= 0)
|
||||
{
|
||||
rarch_system_info_t* system = runloop_get_system_info();
|
||||
|
||||
if (system->mmaps.num_descriptors != 0)
|
||||
memory = (uint8_t*)system->mmaps.descriptors[var->bank_id].core.ptr;
|
||||
else
|
||||
{
|
||||
retro_ctx_memory_info_t meminfo = {NULL, 0, 0};
|
||||
|
||||
switch (var->bank_id)
|
||||
{
|
||||
case 0:
|
||||
meminfo.id = RETRO_MEMORY_SYSTEM_RAM;
|
||||
break;
|
||||
case 1:
|
||||
meminfo.id = RETRO_MEMORY_SAVE_RAM;
|
||||
break;
|
||||
case 2:
|
||||
meminfo.id = RETRO_MEMORY_VIDEO_RAM;
|
||||
break;
|
||||
case 3:
|
||||
meminfo.id = RETRO_MEMORY_RTC;
|
||||
break;
|
||||
default:
|
||||
CHEEVOS_ERR(CHEEVOS_TAG "invalid bank id: %s\n", var->bank_id);
|
||||
break;
|
||||
}
|
||||
|
||||
core_get_memory(&meminfo);
|
||||
memory = (uint8_t*)meminfo.data;
|
||||
}
|
||||
|
||||
if (memory)
|
||||
memory += var->value;
|
||||
}
|
||||
|
||||
return memory;
|
||||
}
|
||||
|
||||
unsigned cheevos_var_get_value(cheevos_var_t* var)
|
||||
{
|
||||
const uint8_t* memory = NULL;
|
||||
unsigned value = 0;
|
||||
|
||||
switch (var->type)
|
||||
{
|
||||
case CHEEVOS_VAR_TYPE_VALUE_COMP:
|
||||
value = var->value;
|
||||
break;
|
||||
|
||||
case CHEEVOS_VAR_TYPE_ADDRESS:
|
||||
case CHEEVOS_VAR_TYPE_DELTA_MEM:
|
||||
memory = cheevos_var_get_memory(var);
|
||||
|
||||
if (memory)
|
||||
{
|
||||
value = memory[0];
|
||||
|
||||
switch (var->size)
|
||||
{
|
||||
case CHEEVOS_VAR_SIZE_BIT_0:
|
||||
value &= 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_BIT_1:
|
||||
value = (value >> 1) & 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_BIT_2:
|
||||
value = (value >> 2) & 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_BIT_3:
|
||||
value = (value >> 3) & 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_BIT_4:
|
||||
value = (value >> 4) & 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_BIT_5:
|
||||
value = (value >> 5) & 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_BIT_6:
|
||||
value = (value >> 6) & 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_BIT_7:
|
||||
value = (value >> 7) & 1;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_NIBBLE_LOWER:
|
||||
value &= 0x0f;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_NIBBLE_UPPER:
|
||||
value = (value >> 4) & 0x0f;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_EIGHT_BITS:
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_SIXTEEN_BITS:
|
||||
value |= memory[1] << 8;
|
||||
break;
|
||||
case CHEEVOS_VAR_SIZE_THIRTYTWO_BITS:
|
||||
value |= memory[1] << 8;
|
||||
value |= memory[2] << 16;
|
||||
value |= memory[3] << 24;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (var->type == CHEEVOS_VAR_TYPE_DELTA_MEM)
|
||||
{
|
||||
unsigned previous = var->previous;
|
||||
var->previous = value;
|
||||
value = previous;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CHEEVOS_VAR_TYPE_DYNAMIC_VAR:
|
||||
/* We shouldn't get here... */
|
||||
break;
|
||||
}
|
||||
|
||||
if(var->is_bcd)
|
||||
return (((value >> 4) & 0xf) * 10) + (value & 0xf);
|
||||
return value;
|
||||
}
|
||||
|
156
cheevos/var.h
156
cheevos/var.h
@ -1,78 +1,78 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2018 - Andre Leiradella
|
||||
*
|
||||
* RetroArch 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 Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch 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 RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __RARCH_CHEEVOS_VAR_H
|
||||
#define __RARCH_CHEEVOS_VAR_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "cheevos.h"
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CHEEVOS_VAR_SIZE_BIT_0 = 0,
|
||||
CHEEVOS_VAR_SIZE_BIT_1,
|
||||
CHEEVOS_VAR_SIZE_BIT_2,
|
||||
CHEEVOS_VAR_SIZE_BIT_3,
|
||||
CHEEVOS_VAR_SIZE_BIT_4,
|
||||
CHEEVOS_VAR_SIZE_BIT_5,
|
||||
CHEEVOS_VAR_SIZE_BIT_6,
|
||||
CHEEVOS_VAR_SIZE_BIT_7,
|
||||
CHEEVOS_VAR_SIZE_NIBBLE_LOWER,
|
||||
CHEEVOS_VAR_SIZE_NIBBLE_UPPER,
|
||||
/* Byte, */
|
||||
CHEEVOS_VAR_SIZE_EIGHT_BITS, /* =Byte, */
|
||||
CHEEVOS_VAR_SIZE_SIXTEEN_BITS,
|
||||
CHEEVOS_VAR_SIZE_THIRTYTWO_BITS
|
||||
} cheevos_var_size_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/* compare to the value of a live address in RAM */
|
||||
CHEEVOS_VAR_TYPE_ADDRESS = 0,
|
||||
|
||||
/* a number. assume 32 bit */
|
||||
CHEEVOS_VAR_TYPE_VALUE_COMP,
|
||||
|
||||
/* the value last known at this address. */
|
||||
CHEEVOS_VAR_TYPE_DELTA_MEM,
|
||||
|
||||
/* a custom user-set variable */
|
||||
CHEEVOS_VAR_TYPE_DYNAMIC_VAR
|
||||
} cheevos_var_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
cheevos_var_size_t size;
|
||||
cheevos_var_type_t type;
|
||||
int bank_id;
|
||||
bool is_bcd;
|
||||
unsigned value;
|
||||
unsigned previous;
|
||||
} cheevos_var_t;
|
||||
|
||||
void cheevos_var_parse(cheevos_var_t* var, const char** memaddr);
|
||||
void cheevos_var_patch_addr(cheevos_var_t* var, cheevos_console_t console);
|
||||
|
||||
uint8_t* cheevos_var_get_memory(const cheevos_var_t* var);
|
||||
unsigned cheevos_var_get_value(cheevos_var_t* var);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif /* __RARCH_CHEEVOS_VAR_H */
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2018 - Andre Leiradella
|
||||
*
|
||||
* RetroArch 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 Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch 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 RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __RARCH_CHEEVOS_VAR_H
|
||||
#define __RARCH_CHEEVOS_VAR_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "cheevos.h"
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CHEEVOS_VAR_SIZE_BIT_0 = 0,
|
||||
CHEEVOS_VAR_SIZE_BIT_1,
|
||||
CHEEVOS_VAR_SIZE_BIT_2,
|
||||
CHEEVOS_VAR_SIZE_BIT_3,
|
||||
CHEEVOS_VAR_SIZE_BIT_4,
|
||||
CHEEVOS_VAR_SIZE_BIT_5,
|
||||
CHEEVOS_VAR_SIZE_BIT_6,
|
||||
CHEEVOS_VAR_SIZE_BIT_7,
|
||||
CHEEVOS_VAR_SIZE_NIBBLE_LOWER,
|
||||
CHEEVOS_VAR_SIZE_NIBBLE_UPPER,
|
||||
/* Byte, */
|
||||
CHEEVOS_VAR_SIZE_EIGHT_BITS, /* =Byte, */
|
||||
CHEEVOS_VAR_SIZE_SIXTEEN_BITS,
|
||||
CHEEVOS_VAR_SIZE_THIRTYTWO_BITS
|
||||
} cheevos_var_size_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/* compare to the value of a live address in RAM */
|
||||
CHEEVOS_VAR_TYPE_ADDRESS = 0,
|
||||
|
||||
/* a number. assume 32 bit */
|
||||
CHEEVOS_VAR_TYPE_VALUE_COMP,
|
||||
|
||||
/* the value last known at this address. */
|
||||
CHEEVOS_VAR_TYPE_DELTA_MEM,
|
||||
|
||||
/* a custom user-set variable */
|
||||
CHEEVOS_VAR_TYPE_DYNAMIC_VAR
|
||||
} cheevos_var_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
cheevos_var_size_t size;
|
||||
cheevos_var_type_t type;
|
||||
int bank_id;
|
||||
bool is_bcd;
|
||||
unsigned value;
|
||||
unsigned previous;
|
||||
} cheevos_var_t;
|
||||
|
||||
void cheevos_var_parse(cheevos_var_t* var, const char** memaddr);
|
||||
void cheevos_var_patch_addr(cheevos_var_t* var, cheevos_console_t console);
|
||||
|
||||
uint8_t* cheevos_var_get_memory(const cheevos_var_t* var);
|
||||
unsigned cheevos_var_get_value(cheevos_var_t* var);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif /* __RARCH_CHEEVOS_VAR_H */
|
||||
|
@ -68,8 +68,8 @@ static bool bundle_assets_extract_enable = false;
|
||||
static bool materialui_icons_enable = true;
|
||||
#endif
|
||||
|
||||
static const unsigned crt_switch_resolution = CRT_SWITCH_NONE;
|
||||
static const int crt_switch_resolution_super = 2560;
|
||||
static const unsigned crt_switch_resolution = CRT_SWITCH_NONE;
|
||||
static const int crt_switch_resolution_super = 2560;
|
||||
static const int crt_switch_center_adjust = 0;
|
||||
|
||||
static const bool def_history_list_enable = true;
|
||||
|
@ -574,7 +574,7 @@ static enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_RGUI;
|
||||
static enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_XUI;
|
||||
#elif defined(HAVE_MATERIALUI) && defined(RARCH_MOBILE)
|
||||
static enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_MATERIALUI;
|
||||
#elif defined(HAVE_OZONE) && (defined(HAVE_LIBNX) || TARGET_OS_TV)
|
||||
#elif defined(HAVE_OZONE) && (defined(HAVE_LIBNX) || TARGET_OS_TV)
|
||||
static enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_OZONE;
|
||||
#elif defined(HAVE_XMB) && !defined(_XBOX)
|
||||
static enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_XMB;
|
||||
@ -2490,7 +2490,7 @@ static bool check_menu_driver_compatibility(void)
|
||||
string_is_equal(video_driver, "metal") ||
|
||||
string_is_equal(video_driver, "ctr") ||
|
||||
string_is_equal(video_driver, "vita2d"))
|
||||
return true;
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ INTERNAL_LIBLAME = 0
|
||||
INTERNAL_LIBFAAC = 0
|
||||
INTERNAL_LIBSPEEX = 0
|
||||
INTERNAL_LIBTHEORA = 0
|
||||
INTERNAL_LIBOPUS = 0
|
||||
INTERNAL_LIBOPUS = 0
|
||||
INTERNAL_LIBVORBIS = 0
|
||||
INTERNAL_WEBP = 0
|
||||
INTERNAL_ZLIB = 0
|
||||
|
@ -3,7 +3,7 @@ LIBAVFORMAT_SOURCE :=
|
||||
LIBAVUTIL_SOURCE :=
|
||||
DEPS_SOURCE :=
|
||||
DEFINES := -DHAVE_SWRESAMPLE
|
||||
LIBRETRO_SOURCE :=
|
||||
LIBRETRO_SOURCE :=
|
||||
GL_SOURCE :=
|
||||
|
||||
CPUOPTS :=
|
||||
|
@ -368,7 +368,7 @@ endif
|
||||
ifeq ($(HAVE_NVENC),1)
|
||||
DEFINES += -DCONFIG_NVENC_ENCODER=1 \
|
||||
-DCONFIG_NVENC_H264_ENCODER=1 \
|
||||
-DCONFIG_NVENC_HEVC_ENCODER=1
|
||||
-DCONFIG_NVENC_HEVC_ENCODER=1
|
||||
else
|
||||
DEFINES += -DCONFIG_NVENC_ENCODER=0 \
|
||||
-DCONFIG_NVENC_H264_ENCODER=0 \
|
||||
@ -424,7 +424,7 @@ endif
|
||||
ifeq ($(HAVE_ZLIB),1)
|
||||
DEFINES += -DCONFIG_ZLIB=1
|
||||
else
|
||||
DEFINES += -DCONFIG_ZLIB=0
|
||||
DEFINES += -DCONFIG_ZLIB=0
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_LIBDCADEC),1)
|
||||
@ -1205,7 +1205,7 @@ DEFINES += \
|
||||
-DCONFIG_LIBZVBI_TELETEXT_DECODER=0 \
|
||||
-DCONFIG_BINTEXT_DECODER=1 \
|
||||
-DCONFIG_XBIN_DECODER=1 \
|
||||
-DCONFIG_IDF_DECODER=1
|
||||
-DCONFIG_IDF_DECODER=1
|
||||
|
||||
ifeq ($(HAVE_ZLIB),1)
|
||||
DEFINES += -DCONFIG_ZLIB_DECODER=1
|
||||
@ -1644,7 +1644,7 @@ ifeq ($(INTERNAL_LIBAVUTIL),1)
|
||||
AVCODEC_BLACKLIST += $(AVCODEC_DIR)/file_open.c
|
||||
endif
|
||||
|
||||
#Codec HW Acceleration flags - all disabled for now - not sure if
|
||||
#Codec HW Acceleration flags - all disabled for now - not sure if
|
||||
# libretro will ever support this
|
||||
|
||||
ifeq ($(HAVE_MMAL),1)
|
||||
|
@ -460,7 +460,7 @@ static void draw_number(Game_Offscreen_Buffer *buffer, unsigned number, unsigned
|
||||
draw_rect(buffer, color, at_x + 2.f, y, .5f, 4.5f);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 2:
|
||||
{
|
||||
draw_rect(buffer, color, at_x - 2.f, y - 2.f, .5f, 2.f);
|
||||
@ -470,7 +470,7 @@ static void draw_number(Game_Offscreen_Buffer *buffer, unsigned number, unsigned
|
||||
draw_rect(buffer, color, at_x, y - 4.f, 2.5f, .5f);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 3:
|
||||
{
|
||||
draw_rect(buffer, color, at_x + 2.f, y, .5f, 4.f);
|
||||
@ -565,7 +565,7 @@ static void game_update_and_render(Game_Input *input, Game_Offscreen_Buffer *dra
|
||||
{
|
||||
float speed = 80.f;
|
||||
player1_dpy = 0.f;
|
||||
|
||||
|
||||
if (is_down(input->buttons[B_SPEED_UP]))
|
||||
speed = 150.f;
|
||||
|
||||
|
@ -166,7 +166,7 @@ void IMAGE_CORE_PREFIX(retro_set_environment)(retro_environment_t cb)
|
||||
IMAGE_CORE_PREFIX(environ_cb) = cb;
|
||||
|
||||
cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)vars);
|
||||
|
||||
|
||||
#ifndef RARCH_INTERNAL
|
||||
/* I don't trust filestream_vfs_init to work inside rarch */
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VFS_INTERFACE, &vfs_iface_info))
|
||||
@ -254,7 +254,7 @@ static bool imageviewer_load(const char *path, int image_index)
|
||||
buf = malloc(len);
|
||||
filestream_read(f, buf, len);
|
||||
filestream_close(f);
|
||||
|
||||
|
||||
image_buffer = (uint32_t*)stbi_load_from_memory(
|
||||
buf, len,
|
||||
&image_width, &image_height,
|
||||
|
@ -21,5 +21,4 @@ endif
|
||||
LOCAL_SRC_FILES += ../libretro-test.c
|
||||
LOCAL_CFLAGS += -O3 -std=gnu99 -ffast-math -funroll-loops
|
||||
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
@ -33,7 +33,7 @@ TARGET_NAME := video_processor
|
||||
LIBV4L2 = -lv4l2
|
||||
|
||||
ifneq ($(findstring Linux,$(shell uname -a)),)
|
||||
CFLAGS += -DHAVE_UDEV
|
||||
CFLAGS += -DHAVE_UDEV
|
||||
LIBUDEV = -ludev
|
||||
CFLAGS += -DHAVE_ALSA
|
||||
LIBASOUND = -lasound
|
||||
|
@ -3,7 +3,6 @@ Libretro core for V4L2 capture devices
|
||||
|
||||
The basic idea is this -- plug your legacy console into a capture device and use RetroArch to upscale it and apply shaders to taste.
|
||||
|
||||
|
||||
## Raspberry Pi specific config
|
||||
|
||||
Add to /boot/config.txt:
|
||||
|
@ -535,7 +535,7 @@ RETRO_API void VIDEOPROC_CORE_PREFIX(retro_get_system_av_info)(struct retro_syst
|
||||
printf("Aspect ratio: %f\n",info->geometry.aspect_ratio);
|
||||
printf("Buffer Resolution %ux%u %f fps\n", info->geometry.base_width,
|
||||
info->geometry.base_height, info->timing.fps);
|
||||
printf("Buffer Max Resolution %ux%u\n", info->geometry.max_width,
|
||||
printf("Buffer Max Resolution %ux%u\n", info->geometry.max_width,
|
||||
info->geometry.max_height);
|
||||
}
|
||||
|
||||
@ -552,7 +552,7 @@ RETRO_API void VIDEOPROC_CORE_PREFIX(retro_reset)(void)
|
||||
//TODO improve this mess and make it generic enough for use with dummy mode
|
||||
void v4l2_frame_times(struct v4l2_buffer buf) {
|
||||
if (strcmp("Off", video_frame_times) == 0)
|
||||
return;
|
||||
return;
|
||||
|
||||
if (ft_info == NULL)
|
||||
ft_info = calloc(5000, sizeof(char));
|
||||
@ -626,15 +626,15 @@ void source_dummy(int width, int height) {
|
||||
}
|
||||
}
|
||||
|
||||
if(video_buf.field == V4L2_FIELD_TOP)
|
||||
if(video_buf.field == V4L2_FIELD_TOP)
|
||||
video_buf.field = V4L2_FIELD_BOTTOM;
|
||||
else if (video_buf.field == V4L2_FIELD_BOTTOM)
|
||||
else if (video_buf.field == V4L2_FIELD_BOTTOM)
|
||||
video_buf.field = V4L2_FIELD_TOP;
|
||||
}
|
||||
|
||||
void source_v4l2_normal(int width, int height) {
|
||||
struct v4l2_buffer bufcp;
|
||||
|
||||
|
||||
int error;
|
||||
|
||||
// Wait until v4l2 dequees a buffer
|
||||
@ -651,7 +651,7 @@ void source_v4l2_normal(int width, int height) {
|
||||
|
||||
bufcp = video_buf;
|
||||
memcpy( (uint32_t*) frame_cap, (uint8_t*) v4l2_capbuf[video_buf.index].start, video_format.fmt.pix.width * video_format.fmt.pix.height * 3);
|
||||
|
||||
|
||||
error = v4l2_ioctl(video_device_fd, VIDIOC_QBUF, &video_buf);
|
||||
if (error != 0)
|
||||
printf("VIDIOC_QBUF failed: %s\n", strerror(errno));
|
||||
@ -664,7 +664,7 @@ void source_v4l2_alternate_hack(int width, int height) {
|
||||
struct v4l2_format fmt;
|
||||
struct v4l2_requestbuffers reqbufs;
|
||||
enum v4l2_buf_type type;
|
||||
|
||||
|
||||
int error;
|
||||
uint32_t index;
|
||||
|
||||
@ -844,7 +844,7 @@ void processing_deinterlacing_crap(uint32_t *src, uint32_t *dst, int width, int
|
||||
|
||||
// Skips a scanline if we reach the end of the current one
|
||||
//On progressive sources, should only skip the destination lines,
|
||||
//On interlaced sources, should skip both the source and the destination lines
|
||||
//On interlaced sources, should skip both the source and the destination lines
|
||||
if ( ((i+1) % width) == 0 ) {
|
||||
dst += width;
|
||||
if (skip_lines_src == 1) {
|
||||
@ -888,7 +888,7 @@ RETRO_API void VIDEOPROC_CORE_PREFIX(retro_run)(void)
|
||||
(outputmode.value && (strcmp(video_output_mode, outputmode.value) != 0))) {
|
||||
VIDEOPROC_CORE_PREFIX(retro_unload_game)();
|
||||
// This core does not cares for the retro_game_info * argument?
|
||||
VIDEOPROC_CORE_PREFIX(retro_load_game)(NULL);
|
||||
VIDEOPROC_CORE_PREFIX(retro_load_game)(NULL);
|
||||
}
|
||||
|
||||
if (frametimes.value != NULL) {
|
||||
@ -915,7 +915,7 @@ RETRO_API void VIDEOPROC_CORE_PREFIX(retro_run)(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (video_buf.field == V4L2_FIELD_INTERLACED)
|
||||
if (video_buf.field == V4L2_FIELD_INTERLACED)
|
||||
video_half_feed_rate = 1;
|
||||
} else {
|
||||
video_half_feed_rate = 0;
|
||||
@ -927,7 +927,7 @@ RETRO_API void VIDEOPROC_CORE_PREFIX(retro_run)(void)
|
||||
if (strcmp(video_output_mode, "deinterlaced") == 0) {
|
||||
processing_bgr_xrgb(frame_cap, frame_curr, video_cap_width, video_cap_height);
|
||||
// When deinterlacing a interlaced intput, we need to process both fields of a frame,
|
||||
//one at a time (retro_run needs to be called twice, vide_half_feed_rate prevents the
|
||||
//one at a time (retro_run needs to be called twice, vide_half_feed_rate prevents the
|
||||
//source from being read twice...
|
||||
if (strcmp(video_capture_mode, "interlaced") == 0) {
|
||||
enum v4l2_field field_read;
|
||||
@ -1106,7 +1106,7 @@ RETRO_API bool VIDEOPROC_CORE_PREFIX(retro_load_game)(const struct retro_game_in
|
||||
|
||||
fmt.fmt.pix.height = 240;
|
||||
fmt.fmt.pix.field = V4L2_FIELD_TOP;
|
||||
|
||||
|
||||
//TODO Query the size and FPS
|
||||
if (strcmp(video_capture_mode, "interlaced") == 0) {
|
||||
v4l2_ncapbuf_target = 2;
|
||||
@ -1244,7 +1244,7 @@ RETRO_API bool VIDEOPROC_CORE_PREFIX(retro_load_game)(const struct retro_game_in
|
||||
}
|
||||
// Each frame has one field, full frame-rate
|
||||
} else if (strcmp(video_output_mode, "progressive") == 0) {
|
||||
video_out_height = video_cap_height;
|
||||
video_out_height = video_cap_height;
|
||||
// Each frame has one or both field to be deinterlaced into a full frame (double the lines if one field), full frame-rate
|
||||
} else if (strcmp(video_output_mode, "deinterlaced") == 0) {
|
||||
if (strcmp(video_capture_mode, "interlaced") == 0)
|
||||
@ -1252,7 +1252,7 @@ RETRO_API bool VIDEOPROC_CORE_PREFIX(retro_load_game)(const struct retro_game_in
|
||||
else
|
||||
video_out_height = video_cap_height*2;
|
||||
} else
|
||||
video_out_height = video_cap_height;
|
||||
video_out_height = video_cap_height;
|
||||
|
||||
printf("Capture Resolution %ux%u\n", video_cap_width, video_cap_height);
|
||||
printf("Output Resolution %ux%u\n", video_cap_width, video_out_height);
|
||||
|
@ -12,18 +12,18 @@ extern const loaderFuncs_s loader_Rosalina;
|
||||
static void (*launch_3dsx)(const char* path, argData_s* args, executableMetadata_s* em);
|
||||
|
||||
static int exec_3dsx_actual(const char* path, const char** args, bool appendPath){
|
||||
struct stat sBuff;
|
||||
struct stat sBuff;
|
||||
argData_s newProgramArgs;
|
||||
unsigned int argChars = 0;
|
||||
unsigned int argNum = 0;
|
||||
bool fileExists;
|
||||
bool inited;
|
||||
|
||||
|
||||
if(path == NULL || path[0] == '\0'){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
fileExists = stat(path, &sBuff) == 0;
|
||||
if(!fileExists){
|
||||
errno = ENOENT;
|
||||
@ -41,7 +41,7 @@ static int exec_3dsx_actual(const char* path, const char** args, bool appendPath
|
||||
strcpy(newProgramArgs.dst, path);
|
||||
newProgramArgs.dst += strlen(path) + 1;
|
||||
newProgramArgs.buf[0]++;
|
||||
|
||||
|
||||
}
|
||||
while(args[argNum] != NULL){
|
||||
strcpy(newProgramArgs.dst, args[argNum]);
|
||||
@ -49,10 +49,10 @@ static int exec_3dsx_actual(const char* path, const char** args, bool appendPath
|
||||
newProgramArgs.buf[0]++;
|
||||
argNum++;
|
||||
}
|
||||
|
||||
|
||||
inited = loader_Rosalina.init();
|
||||
launch_3dsx = loader_Rosalina.launchFile;
|
||||
|
||||
|
||||
if(!inited){
|
||||
inited = loader_Ninjhax2.init();
|
||||
launch_3dsx = loader_Ninjhax2.launchFile;
|
||||
@ -62,13 +62,13 @@ static int exec_3dsx_actual(const char* path, const char** args, bool appendPath
|
||||
inited = loader_Ninjhax1.init();
|
||||
launch_3dsx = loader_Ninjhax1.launchFile;
|
||||
}
|
||||
|
||||
|
||||
if(inited){
|
||||
osSetSpeedupEnable(false);
|
||||
launch_3dsx(path, &newProgramArgs, NULL);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
//should never be reached
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
|
@ -1,9 +1,9 @@
|
||||
#ifndef EXEC_3DSX_H
|
||||
#define EXEC_3DSX_H
|
||||
|
||||
//since 3dsx programs are not guaranteed access to the OS, the 3dsx bootloader run by the exploit must run the next program
|
||||
//your program must have no extra threads running when this is called, these limits do not apply to exec_cia
|
||||
int exec_3dsx_no_path_in_args(const char* path, const char** args);
|
||||
int exec_3dsx(const char* path, const char** args);
|
||||
|
||||
#ifndef EXEC_3DSX_H
|
||||
#define EXEC_3DSX_H
|
||||
|
||||
//since 3dsx programs are not guaranteed access to the OS, the 3dsx bootloader run by the exploit must run the next program
|
||||
//your program must have no extra threads running when this is called, these limits do not apply to exec_cia
|
||||
int exec_3dsx_no_path_in_args(const char* path, const char** args);
|
||||
int exec_3dsx(const char* path, const char** args);
|
||||
|
||||
#endif
|
@ -13,7 +13,6 @@ typedef struct{
|
||||
|
||||
char argvHmac[0x20] = {0x1d, 0x78, 0xff, 0xb9, 0xc5, 0xbc, 0x78, 0xb7, 0xac, 0x29, 0x1d, 0x3e, 0x16, 0xd0, 0xcf, 0x53, 0xef, 0x12, 0x58, 0x83, 0xb6, 0x9e, 0x2f, 0x79, 0x47, 0xf9, 0x35, 0x61, 0xeb, 0x50, 0xd7, 0x67};
|
||||
|
||||
|
||||
static void errorAndQuit(const char* errorStr){
|
||||
errorConf error;
|
||||
|
||||
@ -30,37 +29,37 @@ static int isCiaInstalled(u64 titleId, u16 version){
|
||||
bool titleExists = false;
|
||||
AM_TitleEntry titleInfo;
|
||||
Result failed;
|
||||
|
||||
|
||||
failed = AM_GetTitleCount(MEDIATYPE_SD, &titlesToRetrieve);
|
||||
if(R_FAILED(failed))
|
||||
return -1;
|
||||
|
||||
|
||||
titleIds = malloc(titlesToRetrieve * sizeof(uint64_t));
|
||||
if(titleIds == NULL)
|
||||
return -1;
|
||||
|
||||
|
||||
failed = AM_GetTitleList(&titlesRetrieved, MEDIATYPE_SD, titlesToRetrieve, titleIds);
|
||||
if(R_FAILED(failed))
|
||||
return -1;
|
||||
|
||||
|
||||
for(u32 titlesToCheck = 0; titlesToCheck < titlesRetrieved; titlesToCheck++){
|
||||
if(titleIds[titlesToCheck] == titleId){
|
||||
titleExists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free(titleIds);
|
||||
|
||||
|
||||
if(titleExists){
|
||||
failed = AM_GetTitleInfo(MEDIATYPE_SD, 1 /*titleCount*/, &titleId, &titleInfo);
|
||||
if(R_FAILED(failed))
|
||||
return -1;
|
||||
|
||||
|
||||
if(titleInfo.version == version)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -72,15 +71,15 @@ static int installCia(Handle ciaFile){
|
||||
u32 bytesRead;
|
||||
u32 bytesWritten;
|
||||
u8 transferBuffer[FILE_CHUNK_SIZE];
|
||||
|
||||
|
||||
failed = AM_StartCiaInstall(MEDIATYPE_SD, &outputHandle);
|
||||
if(R_FAILED(failed))
|
||||
return -1;
|
||||
|
||||
|
||||
failed = FSFILE_GetSize(ciaFile, &fileSize);
|
||||
if(R_FAILED(failed))
|
||||
return -1;
|
||||
|
||||
|
||||
while(fileOffset < fileSize){
|
||||
u64 bytesRemaining = fileSize - fileOffset;
|
||||
failed = FSFILE_Read(ciaFile, &bytesRead, fileOffset, transferBuffer, bytesRemaining < FILE_CHUNK_SIZE ? bytesRemaining : FILE_CHUNK_SIZE);
|
||||
@ -88,7 +87,7 @@ static int installCia(Handle ciaFile){
|
||||
AM_CancelCIAInstall(outputHandle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
failed = FSFILE_Write(outputHandle, &bytesWritten, fileOffset, transferBuffer, bytesRead, 0);
|
||||
if(R_FAILED(failed)){
|
||||
AM_CancelCIAInstall(outputHandle);
|
||||
@ -96,32 +95,32 @@ static int installCia(Handle ciaFile){
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if(bytesWritten != bytesRead){
|
||||
AM_CancelCIAInstall(outputHandle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
fileOffset += bytesWritten;
|
||||
}
|
||||
|
||||
|
||||
failed = AM_FinishCiaInstall(outputHandle);
|
||||
if(R_FAILED(failed))
|
||||
return -1;
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int exec_cia(const char* path, const char** args){
|
||||
struct stat sBuff;
|
||||
struct stat sBuff;
|
||||
bool fileExists;
|
||||
bool inited;
|
||||
|
||||
|
||||
if(path == NULL || path[0] == '\0'){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
fileExists = stat(path, &sBuff) == 0;
|
||||
if(!fileExists){
|
||||
errno = ENOENT;
|
||||
@ -131,7 +130,7 @@ int exec_cia(const char* path, const char** args){
|
||||
errno = EINVAL;;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
inited = R_SUCCEEDED(amInit()) && R_SUCCEEDED(fsInit());
|
||||
if(inited){
|
||||
Result res;
|
||||
@ -141,20 +140,20 @@ int exec_cia(const char* path, const char** args){
|
||||
int ciaInstalled;
|
||||
ciaParam param;
|
||||
int argsLength;
|
||||
|
||||
|
||||
//open cia file
|
||||
res = FSUSER_OpenArchive(&ciaArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""));
|
||||
if(R_FAILED(res))
|
||||
errorAndQuit("Cant open SD FS archive.");
|
||||
|
||||
|
||||
res = FSUSER_OpenFile(&ciaFile, ciaArchive, fsMakePath(PATH_ASCII, path + 5/*skip "sdmc:"*/), FS_OPEN_READ, 0);
|
||||
if(R_FAILED(res))
|
||||
errorAndQuit("Cant open CIA file.");
|
||||
|
||||
|
||||
res = AM_GetCiaFileInfo(MEDIATYPE_SD, &ciaInfo, ciaFile);
|
||||
if(R_FAILED(res))
|
||||
errorAndQuit("Cant get CIA file info.");
|
||||
|
||||
|
||||
ciaInstalled = isCiaInstalled(ciaInfo.titleID, ciaInfo.version);
|
||||
if(ciaInstalled == -1){
|
||||
//error
|
||||
@ -166,10 +165,10 @@ int exec_cia(const char* path, const char** args){
|
||||
if(error == -1)
|
||||
errorAndQuit("Cant install CIA.");
|
||||
}
|
||||
|
||||
|
||||
FSFILE_Close(ciaFile);
|
||||
FSUSER_CloseArchive(ciaArchive);
|
||||
|
||||
|
||||
param.argc = 0;
|
||||
argsLength = 0;
|
||||
char* argLocation = param.args;
|
||||
@ -179,19 +178,19 @@ int exec_cia(const char* path, const char** args){
|
||||
argsLength += strlen(args[param.argc]) + 1;
|
||||
param.argc++;
|
||||
}
|
||||
|
||||
|
||||
res = APT_PrepareToDoApplicationJump(0, ciaInfo.titleID, 0x1);
|
||||
if(R_FAILED(res))
|
||||
errorAndQuit("CIA cant run, cant prepare.");
|
||||
|
||||
|
||||
res = APT_DoApplicationJump(¶m, sizeof(param.argc) + argsLength, argvHmac);
|
||||
if(R_FAILED(res))
|
||||
errorAndQuit("CIA cant run, cant jump.");
|
||||
|
||||
|
||||
//wait for application jump, for some reason its not instant
|
||||
while(1);
|
||||
}
|
||||
|
||||
|
||||
//should never be reached
|
||||
amExit();
|
||||
fsExit();
|
||||
|
@ -1,6 +1,6 @@
|
||||
#ifndef EXEC_CIA_H
|
||||
#define EXEC_CIA_H
|
||||
|
||||
int exec_cia(const char* path, const char** args);
|
||||
|
||||
#ifndef EXEC_CIA_H
|
||||
#define EXEC_CIA_H
|
||||
|
||||
int exec_cia(const char* path, const char** args);
|
||||
|
||||
#endif
|
@ -1,95 +1,92 @@
|
||||
#pragma once
|
||||
|
||||
// C stdlib includes
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
// 3DS includes
|
||||
#include <3ds.h>
|
||||
|
||||
|
||||
#define ENTRY_ARGBUFSIZE 0x400
|
||||
#define NUM_SERVICESTHATMATTER 5
|
||||
|
||||
typedef enum
|
||||
{
|
||||
StrId_Loading = 0,
|
||||
StrId_Directory,
|
||||
StrId_DefaultLongTitle,
|
||||
StrId_DefaultPublisher,
|
||||
StrId_IOError,
|
||||
StrId_CouldNotOpenFile,
|
||||
|
||||
StrId_NoAppsFound_Title,
|
||||
StrId_NoAppsFound_Msg,
|
||||
|
||||
StrId_Reboot,
|
||||
StrId_ReturnToHome,
|
||||
|
||||
StrId_TitleSelector,
|
||||
StrId_ErrorReadingTitleMetadata,
|
||||
StrId_NoTitlesFound,
|
||||
StrId_SelectTitle,
|
||||
|
||||
StrId_NoTargetTitleSupport,
|
||||
StrId_MissingTargetTitle,
|
||||
|
||||
StrId_NetLoader,
|
||||
StrId_NetLoaderUnavailable,
|
||||
StrId_NetLoaderOffline,
|
||||
StrId_NetLoaderError,
|
||||
StrId_NetLoaderActive,
|
||||
StrId_NetLoaderTransferring,
|
||||
|
||||
StrId_Max,
|
||||
} StrId;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char* dst;
|
||||
u32 buf[ENTRY_ARGBUFSIZE/sizeof(u32)];
|
||||
} argData_s;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool scanned;
|
||||
u32 sectionSizes[3];
|
||||
bool servicesThatMatter[NUM_SERVICESTHATMATTER];
|
||||
} executableMetadata_s;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 num;
|
||||
u32 text_end;
|
||||
u32 data_address;
|
||||
u32 data_size;
|
||||
u32 processLinearOffset;
|
||||
u32 processHookAddress;
|
||||
u32 processAppCodeAddress;
|
||||
u32 processHookTidLow, processHookTidHigh;
|
||||
u32 mediatype;
|
||||
bool capabilities[0x10]; // {socuAccess, csndAccess, qtmAccess, nfcAccess, httpcAccess, reserved...}
|
||||
} memmap_header_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 src, dst, size;
|
||||
} memmap_entry_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
memmap_header_t header;
|
||||
memmap_entry_t map[];
|
||||
} memmap_t;
|
||||
|
||||
#define memmapSize(m) (sizeof(memmap_header_t) + sizeof(memmap_entry_t)*(m)->header.num)
|
||||
|
||||
|
||||
#include "launch.h"
|
||||
#pragma once
|
||||
|
||||
// C stdlib includes
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
// 3DS includes
|
||||
#include <3ds.h>
|
||||
|
||||
#define ENTRY_ARGBUFSIZE 0x400
|
||||
#define NUM_SERVICESTHATMATTER 5
|
||||
|
||||
typedef enum
|
||||
{
|
||||
StrId_Loading = 0,
|
||||
StrId_Directory,
|
||||
StrId_DefaultLongTitle,
|
||||
StrId_DefaultPublisher,
|
||||
StrId_IOError,
|
||||
StrId_CouldNotOpenFile,
|
||||
|
||||
StrId_NoAppsFound_Title,
|
||||
StrId_NoAppsFound_Msg,
|
||||
|
||||
StrId_Reboot,
|
||||
StrId_ReturnToHome,
|
||||
|
||||
StrId_TitleSelector,
|
||||
StrId_ErrorReadingTitleMetadata,
|
||||
StrId_NoTitlesFound,
|
||||
StrId_SelectTitle,
|
||||
|
||||
StrId_NoTargetTitleSupport,
|
||||
StrId_MissingTargetTitle,
|
||||
|
||||
StrId_NetLoader,
|
||||
StrId_NetLoaderUnavailable,
|
||||
StrId_NetLoaderOffline,
|
||||
StrId_NetLoaderError,
|
||||
StrId_NetLoaderActive,
|
||||
StrId_NetLoaderTransferring,
|
||||
|
||||
StrId_Max,
|
||||
} StrId;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char* dst;
|
||||
u32 buf[ENTRY_ARGBUFSIZE/sizeof(u32)];
|
||||
} argData_s;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool scanned;
|
||||
u32 sectionSizes[3];
|
||||
bool servicesThatMatter[NUM_SERVICESTHATMATTER];
|
||||
} executableMetadata_s;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 num;
|
||||
u32 text_end;
|
||||
u32 data_address;
|
||||
u32 data_size;
|
||||
u32 processLinearOffset;
|
||||
u32 processHookAddress;
|
||||
u32 processAppCodeAddress;
|
||||
u32 processHookTidLow, processHookTidHigh;
|
||||
u32 mediatype;
|
||||
bool capabilities[0x10]; // {socuAccess, csndAccess, qtmAccess, nfcAccess, httpcAccess, reserved...}
|
||||
} memmap_header_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 src, dst, size;
|
||||
} memmap_entry_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
memmap_header_t header;
|
||||
memmap_entry_t map[];
|
||||
} memmap_t;
|
||||
|
||||
#define memmapSize(m) (sizeof(memmap_header_t) + sizeof(memmap_entry_t)*(m)->header.num)
|
||||
|
||||
#include "launch.h"
|
||||
|
@ -327,7 +327,7 @@ void discord_update(enum discord_presence presence)
|
||||
case DISCORD_PRESENCE_GAME:
|
||||
if (core_info)
|
||||
{
|
||||
const char *system_id = core_info->system_id
|
||||
const char *system_id = core_info->system_id
|
||||
? core_info->system_id : "core";
|
||||
char *label = NULL;
|
||||
playlist_t *current_playlist = playlist_get_cached();
|
||||
|
@ -125,7 +125,6 @@ if [ $SALAMANDER = "yes" ]; then
|
||||
make -C ../ -f Makefile.${platform}.salamander clean || exit 1
|
||||
fi
|
||||
|
||||
|
||||
# Cleanup existing core if it exists
|
||||
if [ $PLATFORM = "ode-ps3" ]; then
|
||||
make -C ../ -f Makefile.${platform}.cobra clean || exit 1
|
||||
|
@ -28,7 +28,6 @@ rm -f ../retroarch_wiiu_salamander.rpx.elf
|
||||
cp -f ../pkg/wiiu/meta.xml ../pkg/wiiu/rpx/wiiu/apps/retroarch/meta.xml
|
||||
cp -f ../pkg/wiiu/icon.png ../pkg/wiiu/rpx/wiiu/apps/retroarch/icon.png
|
||||
|
||||
|
||||
make -C ../ -f Makefile.${platform} clean || exit 1
|
||||
|
||||
lookup()
|
||||
|
@ -37,7 +37,7 @@ fi
|
||||
|
||||
filesToUpload()
|
||||
{
|
||||
find . -type f \( -name "*.rpx" -o -name "*.xml" -o -name "*.png" -o -name "*.info" \)
|
||||
find . -type f \( -name "*.rpx" -o -name "*.xml" -o -name "*.png" -o -name "*.info" \)
|
||||
}
|
||||
|
||||
cd ../pkg/wiiu/rpx
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
:Usage
|
||||
|
||||
@echo. VSINSTALLDIR variable is not set.
|
||||
@echo. VSINSTALLDIR variable is not set.
|
||||
@echo.
|
||||
@echo SYNTAX: %0
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
:Usage
|
||||
|
||||
@echo. VSINSTALLDIR variable is not set.
|
||||
@echo. VSINSTALLDIR variable is not set.
|
||||
@echo.
|
||||
@echo SYNTAX: %0
|
||||
|
||||
|
6
driver.c
6
driver.c
@ -311,7 +311,7 @@ static bool driver_update_system_av_info(const struct retro_system_av_info *info
|
||||
command_event(CMD_EVENT_RECORD_INIT, NULL);
|
||||
}
|
||||
|
||||
/* Hide mouse cursor in fullscreen after
|
||||
/* Hide mouse cursor in fullscreen after
|
||||
* a RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO call. */
|
||||
if (settings->bools.video_fullscreen)
|
||||
video_driver_hide_mouse();
|
||||
@ -459,7 +459,7 @@ void driver_uninit(int flags)
|
||||
|
||||
if (flags & DRIVER_LED)
|
||||
led_driver_free();
|
||||
|
||||
|
||||
if (flags & DRIVERS_VIDEO_INPUT)
|
||||
video_driver_free();
|
||||
|
||||
@ -471,7 +471,7 @@ void driver_uninit(int flags)
|
||||
|
||||
if ((flags & DRIVER_INPUT_MASK) && !input_driver_owns_driver())
|
||||
input_driver_destroy_data();
|
||||
|
||||
|
||||
if ((flags & DRIVER_AUDIO_MASK) && !audio_driver_owns_driver())
|
||||
audio_driver_destroy_data();
|
||||
|
||||
|
16
dynamic.c
16
dynamic.c
@ -466,13 +466,13 @@ bool libretro_get_system_info(const char *path,
|
||||
current_valid_extensions[0] = '\0';
|
||||
|
||||
if (!string_is_empty(dummy_info.library_name))
|
||||
strlcpy(current_library_name,
|
||||
strlcpy(current_library_name,
|
||||
dummy_info.library_name, sizeof(current_library_name));
|
||||
if (!string_is_empty(dummy_info.library_version))
|
||||
strlcpy(current_library_version,
|
||||
strlcpy(current_library_version,
|
||||
dummy_info.library_version, sizeof(current_library_version));
|
||||
if (dummy_info.valid_extensions)
|
||||
strlcpy(current_valid_extensions,
|
||||
strlcpy(current_valid_extensions,
|
||||
dummy_info.valid_extensions, sizeof(current_valid_extensions));
|
||||
|
||||
info->library_name = current_library_name;
|
||||
@ -517,8 +517,8 @@ bool init_libretro_sym_custom(enum rarch_core_type type, struct retro_core_t *cu
|
||||
#ifdef HAVE_RUNAHEAD
|
||||
else
|
||||
{
|
||||
/* for a secondary core, we already have a
|
||||
* primary library loaded, so we can skip
|
||||
/* for a secondary core, we already have a
|
||||
* primary library loaded, so we can skip
|
||||
* some checks and just load the library */
|
||||
retro_assert(lib_path != NULL && lib_handle_p != NULL);
|
||||
lib_handle_local = dylib_load(lib_path);
|
||||
@ -847,7 +847,7 @@ bool init_libretro_sym(enum rarch_core_type type, struct retro_core_t *current_c
|
||||
return false;
|
||||
|
||||
#ifdef HAVE_RUNAHEAD
|
||||
/* remember last core type created, so creating a
|
||||
/* remember last core type created, so creating a
|
||||
* secondary core will know what core type to use. */
|
||||
set_last_core_type(type);
|
||||
#endif
|
||||
@ -1923,7 +1923,7 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
||||
core_set_shared_context = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case RETRO_ENVIRONMENT_GET_VFS_INTERFACE:
|
||||
{
|
||||
const uint32_t supported_vfs_version = 3;
|
||||
@ -2034,7 +2034,7 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
||||
*(retro_environment_t *)data = rarch_clear_all_thread_waits;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
RARCH_LOG("Environ UNSUPPORTED (#%u).\n", cmd);
|
||||
return false;
|
||||
|
@ -108,7 +108,7 @@ var LibraryRWebCam = {
|
||||
if (!RWC.ready(data)) return 0;
|
||||
var ret = 0;
|
||||
|
||||
if (RWC.contexts[data].glTexId !== 0 && frame_gl_cb !== 0) {
|
||||
if (RWC.contexts[data].glTexId !== 0 && frame_gl_cb !== 0) {
|
||||
_glGetIntegerv(0x8069 /* GL_TEXTURE_BINDING_2D */, RWC.tmp);
|
||||
var prev = {{{ makeGetValue('RWC.tmp', '0', 'i32') }}};
|
||||
_glBindTexture(0x0DE1 /* GL_TEXTURE_2D */, RWC.contexts[data].glTexId);
|
||||
|
@ -56,7 +56,6 @@ fetch_revision_git() {
|
||||
git log -n 1 --pretty=format:%H
|
||||
}
|
||||
|
||||
|
||||
# fetch_revision: Output SCM-dependent revision string of a module
|
||||
# (currently just calls fetch_revision_git)
|
||||
#
|
||||
@ -65,10 +64,8 @@ fetch_revision() {
|
||||
fetch_revision_git $1
|
||||
}
|
||||
|
||||
|
||||
### END OF FETCH-RULES.SH
|
||||
|
||||
|
||||
echo "Fetching RetroArch's submodules..."
|
||||
fetch_git "https://github.com/libretro/common-shaders.git" "media/shaders_cg"
|
||||
fetch_git "https://github.com/libretro/common-overlays.git" "media/overlays"
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -436,7 +436,7 @@ static void frontend_darwin_get_environment_settings(int *argc, char *argv[],
|
||||
strlcpy(g_defaults.path.buildbot_server_url, "http://buildbot.libretro.com/nightly/apple/ios9/latest/", sizeof(g_defaults.path.buildbot_server_url));
|
||||
|
||||
fill_pathname_join(assets_zip_path, bundle_path_buf, "assets.zip", sizeof(assets_zip_path));
|
||||
|
||||
|
||||
if (filestream_exists(assets_zip_path))
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
@ -466,7 +466,6 @@ static void frontend_darwin_get_environment_settings(int *argc, char *argv[],
|
||||
RARCH_ERR("Failed to create or access system directory: %s.\n", g_defaults.dirs[DEFAULT_DIR_SYSTEM]);
|
||||
}
|
||||
|
||||
|
||||
CFRelease(bundle_path);
|
||||
CFRelease(bundle_url);
|
||||
}
|
||||
@ -535,7 +534,7 @@ static int frontend_darwin_get_rating(void)
|
||||
if (strstr(model, "iPad5,3") || strstr(model, "iPad5,4"))
|
||||
return 18;
|
||||
|
||||
/* TODO/FIXME -
|
||||
/* TODO/FIXME -
|
||||
- more ratings for more systems
|
||||
- determine rating more intelligently*/
|
||||
return -1;
|
||||
@ -633,7 +632,7 @@ static enum frontend_architecture frontend_darwin_get_architecture(void)
|
||||
|
||||
if (uname(&buffer) != 0)
|
||||
return FRONTEND_ARCH_NONE;
|
||||
|
||||
|
||||
(void)buffer_hash;
|
||||
|
||||
#ifdef OSX
|
||||
@ -706,7 +705,7 @@ static uint64_t frontend_darwin_get_mem_total(void)
|
||||
int mib[2] = { CTL_HW, HW_MEMSIZE };
|
||||
u_int namelen = sizeof(mib) / sizeof(mib[0]);
|
||||
size_t len = sizeof(size);
|
||||
|
||||
|
||||
if (sysctl(mib, namelen, &size, &len, NULL, 0) < 0)
|
||||
return 0;
|
||||
return size;
|
||||
@ -722,12 +721,12 @@ static uint64_t frontend_darwin_get_mem_used(void)
|
||||
vm_statistics64_data_t vm_stats;
|
||||
mach_port_t mach_port = mach_host_self();
|
||||
mach_msg_type_number_t count = sizeof(vm_stats) / sizeof(natural_t);
|
||||
|
||||
|
||||
if (KERN_SUCCESS == host_page_size(mach_port, &page_size) &&
|
||||
KERN_SUCCESS == host_statistics64(mach_port, HOST_VM_INFO,
|
||||
(host_info64_t)&vm_stats, &count))
|
||||
{
|
||||
|
||||
|
||||
long long used_memory = ((int64_t)vm_stats.active_count +
|
||||
(int64_t)vm_stats.inactive_count +
|
||||
(int64_t)vm_stats.wire_count) * (int64_t)page_size;
|
||||
|
@ -115,7 +115,6 @@ static void frontend_orbis_get_environment_settings(int *argc, char *argv[],
|
||||
|
||||
sceSystemServiceHideSplashScreen();
|
||||
|
||||
|
||||
uintptr_t intptr=0;
|
||||
sscanf(argv[1],"%p",&intptr);
|
||||
argv[1] = NULL;
|
||||
|
@ -34,7 +34,7 @@ enum BootDeviceIDs{
|
||||
BOOT_DEVICE_MASS,
|
||||
BOOT_DEVICE_HDD,
|
||||
BOOT_DEVICE_HOST,
|
||||
|
||||
|
||||
BOOT_DEVICE_COUNT,
|
||||
};
|
||||
|
||||
@ -84,9 +84,9 @@ char user_path[512];
|
||||
|
||||
static enum frontend_fork ps2_fork_mode = FRONTEND_FORK_NONE;
|
||||
|
||||
/* Only paths residing on "basic" devices
|
||||
* (devices that don't require mounting)
|
||||
* can be specified here, since this system
|
||||
/* Only paths residing on "basic" devices
|
||||
* (devices that don't require mounting)
|
||||
* can be specified here, since this system
|
||||
* doesn't perform mounting based on the path.
|
||||
*/
|
||||
#define DEFAULT_PATH "mass:"
|
||||
@ -111,8 +111,8 @@ static int getBootDeviceID(char *path)
|
||||
return BOOT_DEVICE_HOST;
|
||||
}
|
||||
|
||||
/* HACK! If booting from a USB device, keep trying to
|
||||
* open this program again until it succeeds.
|
||||
/* HACK! If booting from a USB device, keep trying to
|
||||
* open this program again until it succeeds.
|
||||
*
|
||||
* This will ensure that the emulator will be able to load its files.
|
||||
*/
|
||||
@ -123,7 +123,7 @@ static void waitUntilDeviceIsReady(const char *path)
|
||||
|
||||
while((file=fopen(path, "rb"))==NULL)
|
||||
{
|
||||
/* Wait for a while first, or the IOP
|
||||
/* Wait for a while first, or the IOP
|
||||
* will get swamped by requests from the EE. */
|
||||
nopdelay();
|
||||
nopdelay();
|
||||
@ -351,7 +351,7 @@ static void frontend_ps2_init(void *data)
|
||||
/* Memory Card */
|
||||
SifExecModuleBuffer(mcman_irx_start, mcman_irx_size, 0, NULL, NULL);
|
||||
SifExecModuleBuffer(mcserv_irx_start, mcserv_irx_size, 0, NULL, NULL);
|
||||
|
||||
|
||||
/* USB */
|
||||
SifExecModuleBuffer(usbd_irx_start, usbd_irx_size, 0, NULL, NULL);
|
||||
SifExecModuleBuffer(usbhdfsd_irx_start, usbhdfsd_irx_size, 0, NULL, NULL);
|
||||
@ -365,7 +365,7 @@ static void frontend_ps2_init(void *data)
|
||||
RARCH_ERR("audsrv library not initalizated\n");
|
||||
}
|
||||
|
||||
/* Initializes pad library
|
||||
/* Initializes pad library
|
||||
Must be init with 0 as parameter*/
|
||||
if (padInit(0) != 1) {
|
||||
RARCH_ERR("padInit library not initalizated\n");
|
||||
@ -514,7 +514,7 @@ static int frontend_ps2_parse_drive_list(void *data, bool load_content)
|
||||
"cdfs:/",
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR),
|
||||
enum_idx,
|
||||
FILE_TYPE_DIRECTORY, 0, 0);
|
||||
FILE_TYPE_DIRECTORY, 0, 0);
|
||||
menu_entries_append_enum(list,
|
||||
"hdd0:/",
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR),
|
||||
|
@ -260,7 +260,7 @@ static void frontend_ps3_get_environment_settings(int *argc, char *argv[],
|
||||
fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_CHEATS],
|
||||
g_defaults.dirs[DEFAULT_DIR_CORE], "cheats",
|
||||
sizeof(g_defaults.dirs[DEFAULT_DIR_CHEATS]));
|
||||
fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_AUTOCONFIG],
|
||||
fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_AUTOCONFIG],
|
||||
g_defaults.dirs[DEFAULT_DIR_CORE],
|
||||
"autoconfig", sizeof(g_defaults.dirs[DEFAULT_DIR_AUTOCONFIG]));
|
||||
}
|
||||
|
@ -230,7 +230,7 @@ static void frontend_switch_get_environment_settings(int *argc, char *argv[], vo
|
||||
if (!string_is_empty(dir_path))
|
||||
path_mkdir(dir_path);
|
||||
}
|
||||
|
||||
|
||||
fill_pathname_join(g_defaults.path.config, g_defaults.dirs[DEFAULT_DIR_PORT],
|
||||
file_path_str(FILE_PATH_MAIN_CONFIG), sizeof(g_defaults.path.config));
|
||||
}
|
||||
@ -886,7 +886,7 @@ static void frontend_switch_get_os(char *s, size_t len, int *major, int *minor)
|
||||
|
||||
int patch;
|
||||
sscanf(firmware_version + 0x68, "%d.%d.%d", major, minor, &patch);
|
||||
|
||||
|
||||
fail_object:
|
||||
ipc_close(set_sys);
|
||||
fail_sm:
|
||||
|
@ -2409,14 +2409,14 @@ static bool frontend_unix_check_for_path_changes(path_change_data_t *change_data
|
||||
{
|
||||
unsigned j;
|
||||
|
||||
/* A successful close does not guarantee that the
|
||||
* data has been successfully saved to disk,
|
||||
* as the kernel defers writes. It is
|
||||
* not common for a file system to flush
|
||||
/* A successful close does not guarantee that the
|
||||
* data has been successfully saved to disk,
|
||||
* as the kernel defers writes. It is
|
||||
* not common for a file system to flush
|
||||
* the buffers when the stream is closed.
|
||||
*
|
||||
* So we manually fsync() here to flush the data
|
||||
* to disk, to make sure that the new data is
|
||||
* So we manually fsync() here to flush the data
|
||||
* to disk, to make sure that the new data is
|
||||
* immediately available when the file is re-read.
|
||||
*/
|
||||
for (j = 0; j < inotify_data->wd_list->count; j++)
|
||||
|
@ -323,7 +323,7 @@ static int frontend_uwp_parse_drive_list(void *data, bool load_content)
|
||||
static void frontend_uwp_environment_get(int *argc, char *argv[],
|
||||
void *args, void *params_data)
|
||||
{
|
||||
/* On UWP, we have to use the writable directory
|
||||
/* On UWP, we have to use the writable directory
|
||||
* instead of the install directory. */
|
||||
fill_pathname_expand_special(g_defaults.dirs[DEFAULT_DIR_ASSETS],
|
||||
"~\\assets", sizeof(g_defaults.dirs[DEFAULT_DIR_ASSETS]));
|
||||
@ -353,7 +353,7 @@ static void frontend_uwp_environment_get(int *argc, char *argv[],
|
||||
"~\\thumbnails", sizeof(g_defaults.dirs[DEFAULT_DIR_THUMBNAILS]));
|
||||
fill_pathname_expand_special(g_defaults.dirs[DEFAULT_DIR_OVERLAY],
|
||||
"~\\overlays", sizeof(g_defaults.dirs[DEFAULT_DIR_OVERLAY]));
|
||||
/* This one is an exception: cores have to be loaded from
|
||||
/* This one is an exception: cores have to be loaded from
|
||||
* the install directory,
|
||||
* since this is the only place UWP apps can take .dlls from */
|
||||
fill_pathname_expand_special(g_defaults.dirs[DEFAULT_DIR_CORE],
|
||||
|
@ -101,7 +101,7 @@ static bool gfx_init_dwm(void)
|
||||
|
||||
DragAcceptFiles_func =
|
||||
(VOID (WINAPI*)(HWND, BOOL))dylib_proc(shell32lib, "DragAcceptFiles");
|
||||
|
||||
|
||||
mmcss =
|
||||
(HRESULT(WINAPI*)(BOOL))dylib_proc(dwmlib, "DwmEnableMMCSS");
|
||||
#else
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -246,7 +246,7 @@ bool d3d10_init_shader(
|
||||
|
||||
if (vs_code && input_element_descs)
|
||||
D3D10CreateInputLayout(
|
||||
device,
|
||||
device,
|
||||
(D3D10_INPUT_ELEMENT_DESC*)input_element_descs, num_elements, D3DGetBufferPointer(vs_code),
|
||||
D3DGetBufferSize(vs_code), &out->layout);
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
#define CINTERFACE
|
||||
|
||||
/* For Xbox we will just link statically
|
||||
/* For Xbox we will just link statically
|
||||
* to Direct3D libraries instead. */
|
||||
|
||||
#if !defined(_XBOX) && defined(HAVE_DYLIB)
|
||||
@ -113,7 +113,7 @@ bool d3d8_initialize_symbols(enum gfx_ctx_api api)
|
||||
if (!g_d3d8_dll)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
|
||||
SDKVersion = 220;
|
||||
#ifdef HAVE_DYNAMIC_D3D
|
||||
D3DCreate = (D3DCreate_t)dylib_proc(g_d3d8_dll, "Direct3DCreate8");
|
||||
|
@ -72,7 +72,7 @@ typedef struct d3d8_video
|
||||
|
||||
static INLINE bool d3d8_swap(void *data, LPDIRECT3DDEVICE8 dev)
|
||||
{
|
||||
if (IDirect3DDevice8_Present(dev, NULL, NULL, NULL, NULL)
|
||||
if (IDirect3DDevice8_Present(dev, NULL, NULL, NULL, NULL)
|
||||
== D3DERR_DEVICELOST)
|
||||
return false;
|
||||
return true;
|
||||
@ -388,7 +388,7 @@ static INLINE void d3d8_device_set_render_target(
|
||||
static INLINE bool d3d8_get_render_state(LPDIRECT3DDEVICE8 dev,
|
||||
D3DRENDERSTATETYPE state, DWORD *value)
|
||||
{
|
||||
if (dev &&
|
||||
if (dev &&
|
||||
IDirect3DDevice8_GetRenderState(dev, state, value) == D3D_OK)
|
||||
return true;
|
||||
return false;
|
||||
@ -433,8 +433,8 @@ bool d3d8_create_device(void *dev,
|
||||
bool d3d8_reset(void *dev, void *d3dpp);
|
||||
|
||||
static INLINE bool d3d8_device_get_backbuffer(
|
||||
LPDIRECT3DDEVICE8 dev,
|
||||
unsigned idx, unsigned swapchain_idx,
|
||||
LPDIRECT3DDEVICE8 dev,
|
||||
unsigned idx, unsigned swapchain_idx,
|
||||
unsigned backbuffer_type, void **data)
|
||||
{
|
||||
if (dev &&
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
#define CINTERFACE
|
||||
|
||||
/* For Xbox we will just link statically
|
||||
/* For Xbox we will just link statically
|
||||
* to Direct3D libraries instead. */
|
||||
|
||||
#if !defined(_XBOX) && defined(HAVE_DYLIB)
|
||||
@ -115,7 +115,7 @@ void *d3d9_create(void)
|
||||
#ifdef HAVE_DYNAMIC_D3D
|
||||
|
||||
#ifdef HAVE_D3DX
|
||||
static const char *d3dx9_dll_list[] =
|
||||
static const char *d3dx9_dll_list[] =
|
||||
{
|
||||
"d3dx9_24.dll",
|
||||
"d3dx9_25.dll",
|
||||
@ -176,7 +176,7 @@ bool d3d9_initialize_symbols(enum gfx_ctx_api api)
|
||||
if (!g_d3d9_dll)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
|
||||
d3d9_SDKVersion = 31;
|
||||
#ifdef HAVE_DYNAMIC_D3D
|
||||
D3D9Create = (D3D9Create_t)dylib_proc(g_d3d9_dll, "Direct3DCreate9");
|
||||
@ -301,7 +301,7 @@ void *d3d9_vertex_buffer_new(void *_dev,
|
||||
if (usage == 0)
|
||||
if (IDirect3DDevice9_GetSoftwareVertexProcessing(dev))
|
||||
usage = D3DUSAGE_SOFTWAREPROCESSING;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (FAILED(IDirect3DDevice9_CreateVertexBuffer(
|
||||
dev, length, usage, fvf,
|
||||
@ -316,7 +316,7 @@ void d3d9_vertex_buffer_free(void *vertex_data, void *vertex_declaration)
|
||||
{
|
||||
if (vertex_data)
|
||||
{
|
||||
LPDIRECT3DVERTEXBUFFER9 buf =
|
||||
LPDIRECT3DVERTEXBUFFER9 buf =
|
||||
(LPDIRECT3DVERTEXBUFFER9)vertex_data;
|
||||
IDirect3DVertexBuffer9_Release(buf);
|
||||
buf = NULL;
|
||||
@ -324,7 +324,7 @@ void d3d9_vertex_buffer_free(void *vertex_data, void *vertex_declaration)
|
||||
|
||||
if (vertex_declaration)
|
||||
{
|
||||
LPDIRECT3DVERTEXDECLARATION9 vertex_decl =
|
||||
LPDIRECT3DVERTEXDECLARATION9 vertex_decl =
|
||||
(LPDIRECT3DVERTEXDECLARATION9)vertex_declaration;
|
||||
d3d9_vertex_declaration_free(vertex_decl);
|
||||
vertex_decl = NULL;
|
||||
@ -336,7 +336,7 @@ static bool d3d9_reset_internal(void *data,
|
||||
)
|
||||
{
|
||||
LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)data;
|
||||
if (dev &&
|
||||
if (dev &&
|
||||
IDirect3DDevice9_Reset(dev, d3dpp) == D3D_OK)
|
||||
return true;
|
||||
|
||||
@ -576,7 +576,7 @@ void d3d9x_constant_table_set_float_array(LPDIRECT3DDEVICE9 dev,
|
||||
D3DXHANDLE handle = (D3DXHANDLE)_handle;
|
||||
CONST FLOAT *pf = (CONST FLOAT*)_pf;
|
||||
if (consttbl && dev)
|
||||
consttbl->lpVtbl->SetFloatArray(consttbl, dev, handle, pf,
|
||||
consttbl->lpVtbl->SetFloatArray(consttbl, dev, handle, pf,
|
||||
(UINT)count);
|
||||
#endif
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ static INLINE bool d3d9_swap(void *data, LPDIRECT3DDEVICE9 dev)
|
||||
#ifdef _XBOX
|
||||
IDirect3DDevice9_Present(dev, NULL, NULL, NULL, NULL);
|
||||
#else
|
||||
if (IDirect3DDevice9_Present(dev, NULL, NULL, NULL, NULL)
|
||||
if (IDirect3DDevice9_Present(dev, NULL, NULL, NULL, NULL)
|
||||
== D3DERR_DEVICELOST)
|
||||
return false;
|
||||
#endif
|
||||
@ -161,7 +161,7 @@ static INLINE bool d3d9_texture_get_surface_level(
|
||||
LPDIRECT3DTEXTURE9 tex,
|
||||
unsigned idx, void **_ppsurface_level)
|
||||
{
|
||||
if (tex &&
|
||||
if (tex &&
|
||||
SUCCEEDED(IDirect3DTexture9_GetSurfaceLevel(
|
||||
tex, idx, (IDirect3DSurface9**)_ppsurface_level)))
|
||||
return true;
|
||||
@ -485,7 +485,7 @@ static INLINE void d3d9_disable_blend_func(LPDIRECT3DDEVICE9 dev)
|
||||
d3d9_set_render_state(dev, D3DRS_ALPHABLENDENABLE, false);
|
||||
}
|
||||
|
||||
static INLINE void
|
||||
static INLINE void
|
||||
d3d9_set_vertex_declaration(LPDIRECT3DDEVICE9 dev,
|
||||
LPDIRECT3DVERTEXDECLARATION9 vertex_data)
|
||||
{
|
||||
@ -646,13 +646,13 @@ bool d3d9_create_device(void *dev,
|
||||
bool d3d9_reset(void *dev, void *d3dpp);
|
||||
|
||||
static INLINE bool d3d9_device_get_backbuffer(
|
||||
LPDIRECT3DDEVICE9 dev,
|
||||
unsigned idx, unsigned swapchain_idx,
|
||||
LPDIRECT3DDEVICE9 dev,
|
||||
unsigned idx, unsigned swapchain_idx,
|
||||
unsigned backbuffer_type, void **data)
|
||||
{
|
||||
if (dev &&
|
||||
SUCCEEDED(IDirect3DDevice9_GetBackBuffer(dev,
|
||||
swapchain_idx, idx,
|
||||
SUCCEEDED(IDirect3DDevice9_GetBackBuffer(dev,
|
||||
swapchain_idx, idx,
|
||||
(D3DBACKBUFFER_TYPE)backbuffer_type,
|
||||
(LPDIRECT3DSURFACE9*)data)))
|
||||
return true;
|
||||
|
@ -88,9 +88,9 @@ void *d3d_matrix_multiply(void *_pout,
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
for (j = 0; j < 4; j++)
|
||||
pout->m[i][j] = pm1->m[i][0] *
|
||||
pm2->m[0][j] + pm1->m[i][1] * pm2->m[1][j] +
|
||||
pm1->m[i][2] * pm2->m[2][j] +
|
||||
pout->m[i][j] = pm1->m[i][0] *
|
||||
pm2->m[0][j] + pm1->m[i][1] * pm2->m[1][j] +
|
||||
pm1->m[i][2] * pm2->m[2][j] +
|
||||
pm1->m[i][3] * pm2->m[3][j];
|
||||
}
|
||||
return pout;
|
||||
@ -131,7 +131,7 @@ int32_t d3d_translate_filter(unsigned type)
|
||||
void d3d_input_driver(const char* input_name, const char* joypad_name, const input_driver_t** input, void** input_data)
|
||||
{
|
||||
#if defined(__WINRT__)
|
||||
/* Plain xinput is supported on UWP, but it
|
||||
/* Plain xinput is supported on UWP, but it
|
||||
* supports joypad only (uwp driver was added later) */
|
||||
if (string_is_equal(input_name, "xinput"))
|
||||
{
|
||||
|
@ -88,7 +88,7 @@ typedef struct Vertex
|
||||
#define D3DPT_COMM_TRIANGLESTRIP 5
|
||||
|
||||
/* Clear target surface */
|
||||
#define D3D_COMM_CLEAR_TARGET 0x00000001l
|
||||
#define D3D_COMM_CLEAR_TARGET 0x00000001l
|
||||
|
||||
void *d3d_matrix_transpose(void *_pout, const void *_pm);
|
||||
|
||||
|
@ -132,10 +132,9 @@ bool d3d_compile(const char* src, size_t size, LPCSTR src_name, LPCSTR entrypoin
|
||||
compileflags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
|
||||
#endif
|
||||
|
||||
|
||||
if (!size)
|
||||
size = strlen(src);
|
||||
|
||||
|
||||
if (FAILED(D3DCompile(
|
||||
src, size, src_name, NULL, NULL, entrypoint, target, compileflags, 0, out, &error_msg)))
|
||||
{
|
||||
|
@ -41,26 +41,26 @@
|
||||
video_viewport_t _viewport;
|
||||
id<MTLSamplerState> _samplers[TEXTURE_FILTER_MIPMAP_NEAREST + 1];
|
||||
Filter *_filters[RPixelFormatCount]; // convert to bgra8888
|
||||
|
||||
|
||||
// main render pass state
|
||||
id<MTLRenderCommandEncoder> _rce;
|
||||
|
||||
|
||||
id<MTLCommandBuffer> _blitCommandBuffer;
|
||||
|
||||
|
||||
NSUInteger _currentChain;
|
||||
BufferChain *_chain[CHAIN_LENGTH];
|
||||
MTLClearColor _clearColor;
|
||||
|
||||
|
||||
id<MTLRenderPipelineState> _states[GFX_MAX_SHADERS][2];
|
||||
id<MTLRenderPipelineState> _clearState;
|
||||
|
||||
|
||||
bool _captureEnabled;
|
||||
id<MTLTexture> _backBuffer;
|
||||
|
||||
|
||||
unsigned _rotation;
|
||||
matrix_float4x4 _mvp_no_rot;
|
||||
matrix_float4x4 _mvp;
|
||||
|
||||
|
||||
Uniforms _uniforms;
|
||||
Uniforms _uniformsNoRotate;
|
||||
}
|
||||
@ -86,37 +86,37 @@
|
||||
[self setRotation:0];
|
||||
_mvp_no_rot = matrix_proj_ortho(0, 1, 0, 1);
|
||||
_mvp = matrix_proj_ortho(0, 1, 0, 1);
|
||||
|
||||
|
||||
{
|
||||
MTLSamplerDescriptor *sd = [MTLSamplerDescriptor new];
|
||||
|
||||
|
||||
sd.label = @"NEAREST";
|
||||
_samplers[TEXTURE_FILTER_NEAREST] = [d newSamplerStateWithDescriptor:sd];
|
||||
|
||||
|
||||
sd.mipFilter = MTLSamplerMipFilterNearest;
|
||||
sd.label = @"MIPMAP_NEAREST";
|
||||
_samplers[TEXTURE_FILTER_MIPMAP_NEAREST] = [d newSamplerStateWithDescriptor:sd];
|
||||
|
||||
|
||||
sd.mipFilter = MTLSamplerMipFilterNotMipmapped;
|
||||
sd.minFilter = MTLSamplerMinMagFilterLinear;
|
||||
sd.magFilter = MTLSamplerMinMagFilterLinear;
|
||||
sd.label = @"LINEAR";
|
||||
_samplers[TEXTURE_FILTER_LINEAR] = [d newSamplerStateWithDescriptor:sd];
|
||||
|
||||
|
||||
sd.mipFilter = MTLSamplerMipFilterLinear;
|
||||
sd.label = @"MIPMAP_LINEAR";
|
||||
_samplers[TEXTURE_FILTER_MIPMAP_LINEAR] = [d newSamplerStateWithDescriptor:sd];
|
||||
}
|
||||
|
||||
|
||||
if (![self _initConversionFilters])
|
||||
return nil;
|
||||
|
||||
|
||||
if (![self _initClearState])
|
||||
return nil;
|
||||
|
||||
|
||||
if (![self _initMenuStates])
|
||||
return nil;
|
||||
|
||||
|
||||
for (int i = 0; i < CHAIN_LENGTH; i++)
|
||||
{
|
||||
_chain[i] = [[BufferChain alloc] initWithDevice:_device blockLen:65536];
|
||||
@ -144,20 +144,20 @@
|
||||
- (void)setRotation:(unsigned)rotation
|
||||
{
|
||||
_rotation = 270 * rotation;
|
||||
|
||||
|
||||
/* Calculate projection. */
|
||||
_mvp_no_rot = matrix_proj_ortho(0, 1, 0, 1);
|
||||
|
||||
|
||||
bool allow_rotate = true;
|
||||
if (!allow_rotate)
|
||||
{
|
||||
_mvp = _mvp_no_rot;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
matrix_float4x4 rot = matrix_rotate_z((float)(M_PI * _rotation / 180.0f));
|
||||
_mvp = simd_mul(rot, _mvp_no_rot);
|
||||
|
||||
|
||||
_uniforms.projectionMatrix = _mvp;
|
||||
_uniformsNoRotate.projectionMatrix = _mvp_no_rot;
|
||||
}
|
||||
@ -181,7 +181,7 @@
|
||||
- (id<MTLRenderPipelineState>)getStockShader:(int)index blend:(bool)blend
|
||||
{
|
||||
assert(index > 0 && index < GFX_MAX_SHADERS);
|
||||
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case VIDEO_SHADER_STOCK_BLEND:
|
||||
@ -196,7 +196,7 @@
|
||||
index = VIDEO_SHADER_STOCK_BLEND;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return _states[index][blend ? 1 : 0];
|
||||
}
|
||||
|
||||
@ -218,14 +218,14 @@
|
||||
MTLVertexDescriptor *vd = [self _spriteVertexDescriptor];
|
||||
MTLRenderPipelineDescriptor *psd = [MTLRenderPipelineDescriptor new];
|
||||
psd.label = @"clear_state";
|
||||
|
||||
|
||||
MTLRenderPipelineColorAttachmentDescriptor *ca = psd.colorAttachments[0];
|
||||
ca.pixelFormat = _layer.pixelFormat;
|
||||
|
||||
|
||||
psd.vertexDescriptor = vd;
|
||||
psd.vertexFunction = [_library newFunctionWithName:@"stock_vertex"];
|
||||
psd.fragmentFunction = [_library newFunctionWithName:@"stock_fragment_color"];
|
||||
|
||||
|
||||
NSError *err;
|
||||
_clearState = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
if (err != nil)
|
||||
@ -233,7 +233,7 @@
|
||||
RARCH_ERR("[Metal]: error creating clear pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@ -242,7 +242,7 @@
|
||||
MTLVertexDescriptor *vd = [self _spriteVertexDescriptor];
|
||||
MTLRenderPipelineDescriptor *psd = [MTLRenderPipelineDescriptor new];
|
||||
psd.label = @"stock";
|
||||
|
||||
|
||||
MTLRenderPipelineColorAttachmentDescriptor *ca = psd.colorAttachments[0];
|
||||
ca.pixelFormat = _layer.pixelFormat;
|
||||
ca.blendingEnabled = NO;
|
||||
@ -250,12 +250,12 @@
|
||||
ca.destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
|
||||
ca.sourceAlphaBlendFactor = MTLBlendFactorSourceAlpha;
|
||||
ca.destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
|
||||
|
||||
|
||||
psd.sampleCount = 1;
|
||||
psd.vertexDescriptor = vd;
|
||||
psd.vertexFunction = [_library newFunctionWithName:@"stock_vertex"];
|
||||
psd.fragmentFunction = [_library newFunctionWithName:@"stock_fragment"];
|
||||
|
||||
|
||||
NSError *err;
|
||||
_states[VIDEO_SHADER_STOCK_BLEND][0] = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
if (err != nil)
|
||||
@ -263,7 +263,7 @@
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
psd.label = @"stock_blend";
|
||||
ca.blendingEnabled = YES;
|
||||
_states[VIDEO_SHADER_STOCK_BLEND][1] = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
@ -272,9 +272,9 @@
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
MTLFunctionConstantValues *vals;
|
||||
|
||||
|
||||
psd.label = @"snow_simple";
|
||||
ca.blendingEnabled = YES;
|
||||
{
|
||||
@ -295,7 +295,7 @@
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
psd.label = @"snow";
|
||||
ca.blendingEnabled = YES;
|
||||
{
|
||||
@ -316,7 +316,7 @@
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
psd.label = @"bokeh";
|
||||
ca.blendingEnabled = YES;
|
||||
psd.fragmentFunction = [_library newFunctionWithName:@"bokeh_fragment"];
|
||||
@ -326,7 +326,7 @@
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
psd.label = @"snowflake";
|
||||
ca.blendingEnabled = YES;
|
||||
psd.fragmentFunction = [_library newFunctionWithName:@"snowflake_fragment"];
|
||||
@ -336,7 +336,7 @@
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
psd.label = @"ribbon";
|
||||
ca.blendingEnabled = NO;
|
||||
psd.vertexFunction = [_library newFunctionWithName:@"ribbon_vertex"];
|
||||
@ -347,7 +347,7 @@
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
psd.label = @"ribbon_blend";
|
||||
ca.blendingEnabled = YES;
|
||||
ca.sourceRGBBlendFactor = MTLBlendFactorOne;
|
||||
@ -358,7 +358,7 @@
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
psd.label = @"ribbon_simple";
|
||||
ca.blendingEnabled = NO;
|
||||
psd.vertexFunction = [_library newFunctionWithName:@"ribbon_simple_vertex"];
|
||||
@ -369,7 +369,7 @@
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
psd.label = @"ribbon_simple_blend";
|
||||
ca.blendingEnabled = YES;
|
||||
ca.sourceRGBBlendFactor = MTLBlendFactorOne;
|
||||
@ -380,11 +380,10 @@
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
- (bool)_initConversionFilters
|
||||
{
|
||||
NSError *err = nil;
|
||||
@ -398,7 +397,7 @@
|
||||
err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
_filters[RPixelFormatB5G6R5Unorm] = [Filter newFilterWithFunctionName:@"convert_rgb565_to_bgra8888"
|
||||
device:_device
|
||||
library:_library
|
||||
@ -409,14 +408,14 @@
|
||||
err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (Texture *)newTexture:(struct texture_image)image filter:(enum texture_filter_type)filter
|
||||
{
|
||||
assert(filter >= TEXTURE_FILTER_LINEAR && filter <= TEXTURE_FILTER_MIPMAP_NEAREST);
|
||||
|
||||
|
||||
if (!image.pixels || !image.width || !image.height)
|
||||
{
|
||||
/* Create a dummy texture instead. */
|
||||
@ -434,19 +433,19 @@
|
||||
};
|
||||
#undef T0
|
||||
#undef T1
|
||||
|
||||
|
||||
image.pixels = (uint32_t *)checkerboard;
|
||||
image.width = 8;
|
||||
image.height = 8;
|
||||
filter = TEXTURE_FILTER_MIPMAP_NEAREST;
|
||||
}
|
||||
|
||||
|
||||
BOOL mipmapped = filter == TEXTURE_FILTER_MIPMAP_LINEAR || filter == TEXTURE_FILTER_MIPMAP_NEAREST;
|
||||
|
||||
|
||||
Texture *tex = [Texture new];
|
||||
tex.texture = [self newTexture:image mipmapped:mipmapped];
|
||||
tex.sampler = _samplers[filter];
|
||||
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
@ -456,13 +455,13 @@
|
||||
width:image.width
|
||||
height:image.height
|
||||
mipmapped:mipmapped];
|
||||
|
||||
|
||||
id<MTLTexture> t = [_device newTextureWithDescriptor:td];
|
||||
[t replaceRegion:MTLRegionMake2D(0, 0, image.width, image.height)
|
||||
mipmapLevel:0
|
||||
withBytes:image.pixels
|
||||
bytesPerRow:4 * image.width];
|
||||
|
||||
|
||||
if (mipmapped)
|
||||
{
|
||||
id<MTLCommandBuffer> cb = self.blitCommandBuffer;
|
||||
@ -470,7 +469,7 @@
|
||||
[bce generateMipmapsForTexture:t];
|
||||
[bce endEncoding];
|
||||
}
|
||||
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
@ -509,7 +508,7 @@
|
||||
{
|
||||
if (_captureEnabled == captureEnabled)
|
||||
return;
|
||||
|
||||
|
||||
_captureEnabled = captureEnabled;
|
||||
//_layer.framebufferOnly = !captureEnabled;
|
||||
}
|
||||
@ -523,26 +522,26 @@
|
||||
{
|
||||
if (!_captureEnabled || _backBuffer == nil)
|
||||
return NO;
|
||||
|
||||
|
||||
if (_backBuffer.pixelFormat != MTLPixelFormatBGRA8Unorm)
|
||||
{
|
||||
RARCH_WARN("[Metal]: unexpected pixel format %d\n", _backBuffer.pixelFormat);
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
uint8_t *tmp = malloc(_backBuffer.width * _backBuffer.height * 4);
|
||||
|
||||
|
||||
[_backBuffer getBytes:tmp
|
||||
bytesPerRow:4 * _backBuffer.width
|
||||
fromRegion:MTLRegionMake2D(0, 0, _backBuffer.width, _backBuffer.height)
|
||||
mipmapLevel:0];
|
||||
|
||||
|
||||
NSUInteger srcStride = _backBuffer.width * 4;
|
||||
uint8_t const *src = tmp + (_viewport.y * srcStride);
|
||||
|
||||
|
||||
NSUInteger dstStride = _viewport.width * 3;
|
||||
uint8_t *dst = buffer + (_viewport.height - 1) * dstStride;
|
||||
|
||||
|
||||
for (int y = _viewport.y; y < _viewport.height; y++, src += srcStride, dst -= dstStride)
|
||||
{
|
||||
for (int x = _viewport.x; x < _viewport.width; x++)
|
||||
@ -552,9 +551,9 @@
|
||||
dst[3 * x + 2] = src[4 * x + 2];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free(tmp);
|
||||
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@ -616,13 +615,13 @@
|
||||
v[1].position = simd_make_float2(x + w, y);
|
||||
v[2].position = simd_make_float2(x, y + h);
|
||||
v[3].position = simd_make_float2(x + w, y + h);
|
||||
|
||||
|
||||
simd_float4 color = simd_make_float4(r, g, b, a);
|
||||
v[0].color = color;
|
||||
v[1].color = color;
|
||||
v[2].color = color;
|
||||
v[3].color = color;
|
||||
|
||||
|
||||
id<MTLRenderCommandEncoder> rce = self.rce;
|
||||
[rce setRenderPipelineState:_clearState];
|
||||
[rce setVertexBytes:&v length:sizeof(v) atIndex:BufferIndexPositions];
|
||||
@ -633,9 +632,9 @@
|
||||
- (void)end
|
||||
{
|
||||
assert(_commandBuffer != nil);
|
||||
|
||||
|
||||
[_chain[_currentChain] commitRanges];
|
||||
|
||||
|
||||
if (_blitCommandBuffer)
|
||||
{
|
||||
// pending blits for mipmaps or render passes for slang shaders
|
||||
@ -643,25 +642,25 @@
|
||||
[_blitCommandBuffer waitUntilCompleted];
|
||||
_blitCommandBuffer = nil;
|
||||
}
|
||||
|
||||
|
||||
if (_rce)
|
||||
{
|
||||
[_rce endEncoding];
|
||||
_rce = nil;
|
||||
}
|
||||
|
||||
|
||||
__block dispatch_semaphore_t inflight = _inflightSemaphore;
|
||||
[_commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> _) {
|
||||
dispatch_semaphore_signal(inflight);
|
||||
}];
|
||||
|
||||
|
||||
if (self.nextDrawable)
|
||||
{
|
||||
[_commandBuffer presentDrawable:self.nextDrawable];
|
||||
}
|
||||
|
||||
|
||||
[_commandBuffer commit];
|
||||
|
||||
|
||||
_commandBuffer = nil;
|
||||
_drawable = nil;
|
||||
[self _nextChain];
|
||||
@ -708,7 +707,6 @@ static const NSUInteger kConstantAlignment = 256;
|
||||
static const NSUInteger kConstantAlignment = 4;
|
||||
#endif
|
||||
|
||||
|
||||
- (instancetype)initWithDevice:(id<MTLDevice>)device blockLen:(NSUInteger)blockLen
|
||||
{
|
||||
if (self = [super init])
|
||||
@ -753,7 +751,7 @@ static const NSUInteger kConstantAlignment = 4;
|
||||
#else
|
||||
MTLResourceOptions opts = MTLResourceStorageModeShared;
|
||||
#endif
|
||||
|
||||
|
||||
if (!_head)
|
||||
{
|
||||
_head = [[BufferNode alloc] initWithBuffer:[_device newBufferWithLength:_blockLen options:opts]];
|
||||
@ -761,29 +759,29 @@ static const NSUInteger kConstantAlignment = 4;
|
||||
_current = _head;
|
||||
_offset = 0;
|
||||
}
|
||||
|
||||
|
||||
if ([self _subAllocRange:range length:length])
|
||||
return YES;
|
||||
|
||||
|
||||
while (_current.next)
|
||||
{
|
||||
[self _nextNode];
|
||||
if ([self _subAllocRange:range length:length])
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
NSUInteger blockLen = _blockLen;
|
||||
if (length > blockLen)
|
||||
{
|
||||
blockLen = length;
|
||||
}
|
||||
|
||||
|
||||
_current.next = [[BufferNode alloc] initWithBuffer:[_device newBufferWithLength:blockLen options:opts]];
|
||||
if (!_current.next)
|
||||
return NO;
|
||||
|
||||
|
||||
_length += blockLen;
|
||||
|
||||
|
||||
[self _nextNode];
|
||||
retro_assert([self _subAllocRange:range length:length]);
|
||||
return YES;
|
||||
@ -811,5 +809,4 @@ static const NSUInteger kConstantAlignment = 4;
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
@ -26,7 +26,7 @@
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
MTLSamplerDescriptor *sd = [MTLSamplerDescriptor new];
|
||||
sd.minFilter = MTLSamplerMinMagFilterNearest;
|
||||
sd.magFilter = MTLSamplerMinMagFilterNearest;
|
||||
@ -34,7 +34,7 @@
|
||||
sd.tAddressMode = MTLSamplerAddressModeClampToEdge;
|
||||
sd.mipFilter = MTLSamplerMipFilterNotMipmapped;
|
||||
id<MTLSamplerState> sampler = [device newSamplerStateWithDescriptor:sd];
|
||||
|
||||
|
||||
return [[Filter alloc] initWithKernel:kernel sampler:sampler];
|
||||
}
|
||||
|
||||
@ -53,20 +53,20 @@
|
||||
id<MTLComputeCommandEncoder> ce = [cb computeCommandEncoder];
|
||||
ce.label = @"filter kernel";
|
||||
[ce pushDebugGroup:@"filter kernel"];
|
||||
|
||||
|
||||
[ce setComputePipelineState:_kernel];
|
||||
|
||||
|
||||
[ce setTexture:tin atIndex:0];
|
||||
[ce setTexture:tout atIndex:1];
|
||||
|
||||
|
||||
[self.delegate configure:ce];
|
||||
|
||||
|
||||
MTLSize size = MTLSizeMake(16, 16, 1);
|
||||
MTLSize count = MTLSizeMake((tin.width + size.width + 1) / size.width, (tin.height + size.height + 1) / size.height,
|
||||
1);
|
||||
|
||||
|
||||
[ce dispatchThreadgroups:count threadsPerThreadgroup:size];
|
||||
|
||||
|
||||
[ce popDebugGroup];
|
||||
[ce endEncoding];
|
||||
}
|
||||
@ -76,19 +76,19 @@
|
||||
id<MTLComputeCommandEncoder> ce = [cb computeCommandEncoder];
|
||||
ce.label = @"filter kernel";
|
||||
[ce pushDebugGroup:@"filter kernel"];
|
||||
|
||||
|
||||
[ce setComputePipelineState:_kernel];
|
||||
|
||||
|
||||
[ce setBuffer:tin offset:0 atIndex:0];
|
||||
[ce setTexture:tout atIndex:0];
|
||||
|
||||
|
||||
[self.delegate configure:ce];
|
||||
|
||||
|
||||
MTLSize size = MTLSizeMake(32, 1, 1);
|
||||
MTLSize count = MTLSizeMake((tin.length + 00) / 32, 1, 1);
|
||||
|
||||
|
||||
[ce dispatchThreadgroups:count threadsPerThreadgroup:size];
|
||||
|
||||
|
||||
[ce popDebugGroup];
|
||||
[ce endEncoding];
|
||||
}
|
||||
|
@ -88,7 +88,6 @@
|
||||
[_context resetScissorRect];
|
||||
}
|
||||
|
||||
|
||||
- (MTLPrimitiveType)_toPrimitiveType:(enum menu_display_prim_type)prim
|
||||
{
|
||||
switch (prim)
|
||||
@ -106,16 +105,16 @@
|
||||
- (void)drawPipeline:(menu_display_ctx_draw_t *)draw video:(video_frame_info_t *)video
|
||||
{
|
||||
static struct video_coords blank_coords;
|
||||
|
||||
|
||||
draw->x = 0;
|
||||
draw->y = 0;
|
||||
draw->matrix_data = NULL;
|
||||
|
||||
|
||||
_uniforms.outputSize = simd_make_float2(_context.viewport->full_width, _context.viewport->full_height);
|
||||
|
||||
|
||||
draw->pipeline.backend_data = &_uniforms;
|
||||
draw->pipeline.backend_data_size = sizeof(_uniforms);
|
||||
|
||||
|
||||
switch (draw->pipeline.id)
|
||||
{
|
||||
// ribbon
|
||||
@ -127,7 +126,7 @@
|
||||
draw->coords = (struct video_coords *)&ca->coords;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case VIDEO_SHADER_MENU_3:
|
||||
case VIDEO_SHADER_MENU_4:
|
||||
case VIDEO_SHADER_MENU_5:
|
||||
@ -139,7 +138,7 @@
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_uniforms.time += 0.01;
|
||||
}
|
||||
|
||||
@ -148,7 +147,7 @@
|
||||
const float *vertex = draw->coords->vertex ?: MenuDisplay.defaultVertices;
|
||||
const float *tex_coord = draw->coords->tex_coord ?: MenuDisplay.defaultTexCoords;
|
||||
const float *color = draw->coords->color ?: MenuDisplay.defaultColor;
|
||||
|
||||
|
||||
NSUInteger needed = draw->coords->vertices * sizeof(SpriteVertex);
|
||||
BufferRange range;
|
||||
if (![_context allocRange:&range length:needed])
|
||||
@ -156,21 +155,21 @@
|
||||
RARCH_ERR("[Metal]: MenuDisplay unable to allocate buffer of %d bytes", needed);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
NSUInteger vertexCount = draw->coords->vertices;
|
||||
SpriteVertex *pv = (SpriteVertex *)range.data;
|
||||
for (unsigned i = 0; i < draw->coords->vertices; i++, pv++)
|
||||
{
|
||||
pv->position = simd_make_float2(vertex[0], 1.0f - vertex[1]);
|
||||
vertex += 2;
|
||||
|
||||
|
||||
pv->texCoord = simd_make_float2(tex_coord[0], tex_coord[1]);
|
||||
tex_coord += 2;
|
||||
|
||||
|
||||
pv->color = simd_make_float4(color[0], color[1], color[2], color[3]);
|
||||
color += 4;
|
||||
}
|
||||
|
||||
|
||||
id<MTLRenderCommandEncoder> rce = _context.rce;
|
||||
if (_clearNextRender)
|
||||
{
|
||||
@ -186,7 +185,7 @@
|
||||
];
|
||||
_clearNextRender = NO;
|
||||
}
|
||||
|
||||
|
||||
MTLViewport vp = {
|
||||
.originX = draw->x,
|
||||
.originY = _context.viewport->full_height - draw->y - draw->height,
|
||||
@ -196,11 +195,11 @@
|
||||
.zfar = 1,
|
||||
};
|
||||
[rce setViewport:vp];
|
||||
|
||||
|
||||
if (_useScissorRect) {
|
||||
[rce setScissorRect:_scissorRect];
|
||||
}
|
||||
|
||||
|
||||
switch (draw->pipeline.id)
|
||||
{
|
||||
#if HAVE_SHADERPIPELINE
|
||||
@ -220,13 +219,13 @@
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Texture *tex = (__bridge Texture *)(void *)draw->texture;
|
||||
if (tex == nil)
|
||||
return;
|
||||
|
||||
|
||||
[rce setRenderPipelineState:[_context getStockShader:VIDEO_SHADER_STOCK_BLEND blend:_blend]];
|
||||
|
||||
|
||||
Uniforms uniforms = {
|
||||
.projectionMatrix = draw->matrix_data ? make_matrix_float4x4((const float *)draw->matrix_data)
|
||||
: _uniforms.projectionMatrix
|
||||
|
@ -30,16 +30,16 @@
|
||||
|
||||
typedef NS_ENUM(NSUInteger, RPixelFormat)
|
||||
{
|
||||
|
||||
|
||||
RPixelFormatInvalid,
|
||||
|
||||
|
||||
/* 16-bit formats */
|
||||
RPixelFormatBGRA4Unorm,
|
||||
RPixelFormatB5G6R5Unorm,
|
||||
|
||||
|
||||
RPixelFormatBGRA8Unorm,
|
||||
RPixelFormatBGRX8Unorm, // RetroArch XRGB
|
||||
|
||||
|
||||
RPixelFormatCount,
|
||||
};
|
||||
|
||||
@ -50,7 +50,7 @@ typedef NS_ENUM(NSUInteger, RTextureFilter)
|
||||
{
|
||||
RTextureFilterNearest,
|
||||
RTextureFilterLinear,
|
||||
|
||||
|
||||
RTextureFilterCount,
|
||||
};
|
||||
|
||||
|
@ -16,11 +16,11 @@ NSUInteger RPixelFormatToBPP(RPixelFormat format)
|
||||
case RPixelFormatBGRA8Unorm:
|
||||
case RPixelFormatBGRX8Unorm:
|
||||
return 4;
|
||||
|
||||
|
||||
case RPixelFormatB5G6R5Unorm:
|
||||
case RPixelFormatBGRA4Unorm:
|
||||
return 2;
|
||||
|
||||
|
||||
default:
|
||||
RARCH_ERR("[Metal]: unknown RPixel format: %d\n", format);
|
||||
return 4;
|
||||
@ -41,14 +41,14 @@ NSString *NSStringFromRPixelFormat(RPixelFormat format)
|
||||
STRING(RPixelFormatBGRA8Unorm);
|
||||
STRING(RPixelFormatBGRX8Unorm);
|
||||
#undef STRING
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
if (format >= RPixelFormatCount)
|
||||
{
|
||||
format = RPixelFormatInvalid;
|
||||
}
|
||||
|
||||
|
||||
return RPixelStrings[format];
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ matrix_float4x4 make_matrix_float4x4(const float *v)
|
||||
simd_float4 R = simd_make_float4(v[0], v[1], v[2], v[3]);
|
||||
v += 4;
|
||||
simd_float4 S = simd_make_float4(v[0], v[1], v[2], v[3]);
|
||||
|
||||
|
||||
matrix_float4x4 mat = {P, Q, R, S};
|
||||
return mat;
|
||||
}
|
||||
@ -70,19 +70,19 @@ matrix_float4x4 matrix_proj_ortho(float left, float right, float top, float bott
|
||||
{
|
||||
float near = 0;
|
||||
float far = 1;
|
||||
|
||||
|
||||
float sx = 2 / (right - left);
|
||||
float sy = 2 / (top - bottom);
|
||||
float sz = 1 / (far - near);
|
||||
float tx = (right + left) / (left - right);
|
||||
float ty = (top + bottom) / (bottom - top);
|
||||
float tz = near / (far - near);
|
||||
|
||||
|
||||
simd_float4 P = simd_make_float4(sx, 0, 0, 0);
|
||||
simd_float4 Q = simd_make_float4(0, sy, 0, 0);
|
||||
simd_float4 R = simd_make_float4(0, 0, sz, 0);
|
||||
simd_float4 S = simd_make_float4(tx, ty, tz, 1);
|
||||
|
||||
|
||||
matrix_float4x4 mat = {P, Q, R, S};
|
||||
return mat;
|
||||
}
|
||||
@ -91,12 +91,12 @@ matrix_float4x4 matrix_rotate_z(float rot)
|
||||
{
|
||||
float cz, sz;
|
||||
__sincosf(rot, &sz, &cz);
|
||||
|
||||
|
||||
simd_float4 P = simd_make_float4(cz, -sz, 0, 0);
|
||||
simd_float4 Q = simd_make_float4(sz, cz, 0, 0);
|
||||
simd_float4 R = simd_make_float4( 0, 0, 1, 0);
|
||||
simd_float4 S = simd_make_float4( 0, 0, 0, 1);
|
||||
|
||||
|
||||
matrix_float4x4 mat = {P, Q, R, S};
|
||||
return mat;
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ kernel void convert_bgra4444_to_bgra8888(texture2d<ushort, access::read> in [[
|
||||
extract_bits(pix, 12, 4),
|
||||
extract_bits(pix, 0, 4)
|
||||
);
|
||||
|
||||
|
||||
out.write(half4(pix2) / 15.0, gid);
|
||||
}
|
||||
|
||||
@ -107,6 +107,6 @@ kernel void convert_rgb565_to_bgra8888(texture2d<ushort, access::read> in [[ te
|
||||
extract_bits(pix, 0, 5),
|
||||
0xf
|
||||
);
|
||||
|
||||
|
||||
out.write(half4(pix2) / half4(0x1f, 0x3f, 0x1f, 0xf), gid);
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
CGSize _size; // size of view in pixels
|
||||
CGRect _frame;
|
||||
NSUInteger _bpp;
|
||||
|
||||
|
||||
id<MTLTexture> _src; // source texture
|
||||
bool _srcDirty;
|
||||
}
|
||||
@ -50,9 +50,9 @@
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
_size = size;
|
||||
|
||||
|
||||
{
|
||||
MTLTextureDescriptor *td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
|
||||
width:(NSUInteger)size.width
|
||||
@ -61,7 +61,7 @@
|
||||
td.usage = MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite;
|
||||
_texture = [_context.device newTextureWithDescriptor:td];
|
||||
}
|
||||
|
||||
|
||||
if (_format != RPixelFormatBGRA8Unorm && _format != RPixelFormatBGRX8Unorm)
|
||||
{
|
||||
MTLTextureDescriptor *td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR16Uint
|
||||
@ -83,14 +83,14 @@
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
_frame = frame;
|
||||
|
||||
|
||||
float l = (float)CGRectGetMinX(frame);
|
||||
float t = (float)CGRectGetMinY(frame);
|
||||
float r = (float)CGRectGetMaxX(frame);
|
||||
float b = (float)CGRectGetMaxY(frame);
|
||||
|
||||
|
||||
Vertex v[4] = {
|
||||
{simd_make_float3(l, b, 0), simd_make_float2(0, 1)},
|
||||
{simd_make_float3(r, b, 0), simd_make_float2(1, 1)},
|
||||
@ -109,10 +109,10 @@
|
||||
{
|
||||
if (_format == RPixelFormatBGRA8Unorm || _format == RPixelFormatBGRX8Unorm)
|
||||
return;
|
||||
|
||||
|
||||
if (!_srcDirty)
|
||||
return;
|
||||
|
||||
|
||||
[_context convertFormat:_format from:_src to:_texture];
|
||||
_srcDirty = NO;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ typedef NS_ENUM(NSInteger, ViewDrawState)
|
||||
ViewDrawStateNone = 0x00,
|
||||
ViewDrawStateContext = 0x01,
|
||||
ViewDrawStateEncoder = 0x02,
|
||||
|
||||
|
||||
ViewDrawStateAll = 0x03,
|
||||
};
|
||||
|
||||
|
@ -44,10 +44,10 @@ float xmb_noise2(float3 x, const device Uniforms &constants)
|
||||
vertex FontFragmentIn ribbon_simple_vertex(const SpriteVertex in [[ stage_in ]], const device Uniforms &constants [[ buffer(BufferIndexUniforms) ]])
|
||||
{
|
||||
float4 t = (constants.projectionMatrix * float4(in.position, 0, 1));
|
||||
|
||||
|
||||
float3 v = float3(t.x, 0.0, 1.0-t.y);
|
||||
float3 v2 = v;
|
||||
|
||||
|
||||
v2.x = v2.x + constants.time / 2.0;
|
||||
v2.z = v.z * 3.0;
|
||||
v.y = cos((v.x + v.z / 3.0 + constants.time) * 2.0) / 10.0 + ribbon::noise(v2.xyz) / 4.0;
|
||||
@ -71,7 +71,6 @@ typedef struct
|
||||
vector_float3 vEC;
|
||||
} RibbonOutIn;
|
||||
|
||||
|
||||
vertex RibbonOutIn ribbon_vertex(const SpriteVertex in [[ stage_in ]], const device Uniforms &constants [[ buffer(BufferIndexUniforms) ]])
|
||||
{
|
||||
float4 t = (constants.projectionMatrix * float4(in.position, 0, 1));
|
||||
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user