diff options
author | gameblabla | 2019-10-05 03:04:57 +0200 |
---|---|---|
committer | gameblabla | 2019-10-05 03:04:57 +0200 |
commit | d4753076e89d42cdad4a4f1ca4688fad3c56d873 (patch) | |
tree | c8641cf282f427d9329db00325e16609acca8663 | |
parent | 943821f94b9b2e22315fce876c2e369da7a79bcf (diff) | |
download | snesemu-d4753076e89d42cdad4a4f1ca4688fad3c56d873.tar.gz snesemu-d4753076e89d42cdad4a4f1ca4688fad3c56d873.tar.bz2 snesemu-d4753076e89d42cdad4a4f1ca4688fad3c56d873.zip |
Port the libretro core and make it standalone.
TODO :
- Input should use our config file instead.
- Missing audio in some games. (Star Ocean, doesn't happen with stock retroarch code. Odd...)
45 files changed, 2531 insertions, 4309 deletions
diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 3f95faf..0000000 --- a/.travis.yml +++ /dev/null @@ -1,36 +0,0 @@ -language: generic -os: linux -dist: trusty -sudo: required -addons: - apt: - packages: - - g++-7 - sources: - - ubuntu-toolchain-r-test -env: - global: - - CORE=snes9x2005 - - COMPILER_NAME=gcc CXX=g++-7 CC=gcc-7 - matrix: - - PLATFORM=3ds - - PLATFORM=linux_x64 - - PLATFORM=ngc - - PLATFORM=wii - - PLATFORM=wiiu -before_script: - - pwd - - mkdir -p ~/bin - - ln -s /usr/bin/gcc-7 ~/bin/gcc - - ln -s /usr/bin/g++-7 ~/bin/g++ - - ln -s /usr/bin/cpp-7 ~/bin/cpp - - export PATH=~/bin:$PATH - - ls -l ~/bin - - echo $PATH - - g++-7 --version - - g++ --version -script: - - cd ~/ - - git clone --depth=50 https://github.com/libretro/libretro-super - - cd libretro-super/travis - - ./build.sh @@ -1,555 +1,33 @@ -DEBUG = 0 -PERF_TEST = 0 -LOAD_FROM_MEMORY_TEST = 1 -USE_BLARGG_APU = 0 -LAGFIX = 1 +PRGNAME = PocketSNES -SPACE := -SPACE := $(SPACE) $(SPACE) -BACKSLASH := -BACKSLASH := \$(BACKSLASH) -filter_out1 = $(filter-out $(firstword $1),$1) -filter_out2 = $(call filter_out1,$(call filter_out1,$1)) -unixpath = $(subst \,/,$1) -unixcygpath = /$(subst :,,$(call unixpath,$1)) +# define regarding OS, which compiler to use +CC = gcc -ifeq ($(platform),) - ifeq (,$(findstring classic_,$(platform))) - platform = unix - endif -ifeq ($(shell uname -a),) - platform = win -else ifneq ($(findstring Darwin,$(shell uname -a)),) - platform = osx - arch = intel -ifeq ($(shell uname -p),powerpc) - arch = ppc -endif -else ifneq ($(findstring MINGW,$(shell uname -a)),) - platform = win -else ifneq ($(findstring SunOS,$(shell uname -a)),) - platform = sun -endif -endif +# change compilation / linking flag options +CFLAGS = -DLSB_FIRST -I. -Ilibretro-common/include -Isrc -DINLINE="inline" -DRIGHTSHIFT_IS_SAR +CFLAGS += -Isource -I./shell/emu -I./shell/scalers -I./shell/emu -I./shell/audio -I./shell/menu -I./shell/video/sdl -I./shell/input -Ishell/headers -# 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 - arch = intel - ifeq ($(shell uname -p),powerpc) - arch = ppc - endif -else ifneq ($(findstring MINGW,$(shell uname -a)),) - system_platform = win -endif +CFLAGS += -O2 -DNDEBUG -DLAGFIX -DGIT_VERSION=\"" c9b3980"\" -fno-builtin -fno-exceptions -ffunction-sections -std=gnu99 +CFLAGS += -Wall -Wextra -pedantic -Wno-implicit-function-declaration -Wno-implicit-fallthrough -Wno-sign-compare -Wno-unused-variable -Wno-unused-function -Wno-uninitialized -Wno-strict-aliasing -Wno-overflow -fno-strict-overflow -ifeq ($(USE_BLARGG_APU), 1) - TARGET_NAME := snes9x2005_plus -else - TARGET_NAME := snes9x2005 -endif -GIT_VERSION := " $(shell git rev-parse --short HEAD || echo unknown)" -ifneq ($(GIT_VERSION)," unknown") - CFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\" -endif +#-fprofile-generate=/mnt/int_sd/profile +LDFLAGS = -lSDL -lasound -lm -DEFS := -ifneq (,$(findstring msvc,$(platform))) -LIBM := -else -LIBM := -lm -endif -LIBS := +# Files to be compiled +SRCDIR = ./source ./shell/emu ./shell/scalers ./shell/audio/alsa ./shell/menu ./shell/video/sdl ./shell/input/sdl ./shell/other +VPATH = $(SRCDIR) +SRC_C = $(foreach dir, $(SRCDIR), $(wildcard $(dir)/*.c)) +SRC_CP = $(foreach dir, $(SRCDIR), $(wildcard $(dir)/*.cpp)) +OBJ_C = $(notdir $(patsubst %.c, %.o, $(SRC_C))) +OBJ_CP = $(notdir $(patsubst %.cpp, %.o, $(SRC_CP))) +OBJS = $(OBJ_C) $(OBJ_CP) -ifeq ($(platform), unix) - TARGET := $(TARGET_NAME)_libretro.so - fpic := -fPIC - SHARED := -shared -Wl,--no-undefined -Wl,--version-script=link.T - CFLAGS += -fno-builtin -fno-exceptions -ffunction-sections -else ifeq ($(platform), linux-portable) - TARGET := $(TARGET_NAME)_libretro.so - fpic := -fPIC -nostdlib - SHARED := -shared -Wl,--version-script=link.T - CFLAGS += -fno-builtin -fno-exceptions -ffunction-sections - LIBM := -else ifeq ($(platform),sun) - TARGET := $(TARGET_NAME)_libretro.so - fpic := -fPIC - SHARED := -shared -z defs - CFLAGS += -fno-builtin -fno-exceptions -ffunction-sections - CC = gcc -else ifeq ($(platform), osx) - TARGET := $(TARGET_NAME)_libretro.dylib - fpic := -fPIC - SHARED := -dynamiclib +# Rules to make executable +$(PRGNAME): $(OBJS) + $(CC) $(CFLAGS) -o $(PRGNAME) $^ $(LDFLAGS) -ifeq ($(arch),ppc) - FLAGS += -DMSB_FIRST - OLD_GCC = 1 -endif - OSXVER = $(shell sw_vers -productVersion | cut -d. -f 2) - OSX_GT_MOJAVE = $(shell (( $(OSXVER) >= 14)) && echo "YES") -ifneq ($(OSX_GT_MOJAVE),YES) - #this breaks compiling on Mac OS Mojave - fpic += -mmacosx-version-min=10.1 -endif -ifndef ($(NOUNIVERSAL)) - FLAGS += $(ARCHFLAGS) - LDFLAGS += $(ARCHFLAGS) -endif -# iOS -else ifneq (,$(findstring ios,$(platform))) - TARGET := $(TARGET_NAME)_libretro_ios.dylib - fpic := -fPIC - SHARED := -dynamiclib - -ifeq ($(IOSSDK),) - IOSSDK := $(shell xcodebuild -version -sdk iphoneos Path) -endif - -ifeq ($(platform),ios-arm64) - CC = cc -arch arm64 -isysroot $(IOSSDK) - CXX = c++ -arch arm64 -isysroot $(IOSSDK) -else - CC = cc -arch armv7 -isysroot $(IOSSDK) - CXX = c++ -arch armv7 -isysroot $(IOSSDK) -endif - -ifeq ($(platform),$(filter $(platform),ios9 ios-arm64)) - SHARED += -miphoneos-version-min=8.0 - CC += -miphoneos-version-min=8.0 - CXX += -miphoneos-version-min=8.0 -else - SHARED += -miphoneos-version-min=5.0 - CC += -miphoneos-version-min=5.0 - CXX += -miphoneos-version-min=5.0 -endif -# Theos iOS -else ifeq ($(platform), theos_ios) - DEPLOYMENT_IOSVERSION = 5.0 - TARGET = iphone:latest:$(DEPLOYMENT_IOSVERSION) - ARCHS = armv7 armv7s - TARGET_IPHONEOS_DEPLOYMENT_VERSION=$(DEPLOYMENT_IOSVERSION) - THEOS_BUILD_DIR := objs - include $(THEOS)/makefiles/common.mk - LIBRARY_NAME = $(TARGET_NAME)_libretro_ios -else ifeq ($(platform), qnx) - TARGET := $(TARGET_NAME)_libretro_$(platform).so - fpic := -fPIC - SHARED := -shared -Wl,--no-undefined -Wl,--version-script=link.T - CC = qcc -Vgcc_ntoarmv7le - CXX = QCC -Vgcc_ntoarmv7le_cpp -# PS3 -else ifeq ($(platform), ps3) - TARGET := $(TARGET_NAME)_libretro_$(platform).a - CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe - CXX = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-g++.exe - AR = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ar.exe - STATIC_LINKING = 1 - FLAGS += -DMSB_FIRST - OLD_GCC = 1 -# PS3 (SNC) -else ifeq ($(platform), sncps3) - TARGET := $(TARGET_NAME)_libretro_ps3.a - CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe - CXX = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe - AR = $(CELL_SDK)/host-win32/sn/bin/ps3snarl.exe - STATIC_LINKING = 1 - FLAGS += -DMSB_FIRST - NO_GCC = 1 -# PSP1 -else ifeq ($(platform), psp1) - TARGET := $(TARGET_NAME)_libretro_$(platform).a - CC = psp-gcc$(EXE_EXT) - CXX = psp-g++$(EXE_EXT) - AR = psp-ar$(EXE_EXT) - STATIC_LINKING = 1 - LOAD_FROM_MEMORY_TEST = 0 - FLAGS += -G0 - CFLAGS += \ - -march=allegrex -mno-abicalls -fno-pic \ - -fno-builtin -fno-exceptions -ffunction-sections - DEFS += -DPSP -D_PSP_FW_VERSION=371 - STATIC_LINKING := 1 -# Vita -else ifeq ($(platform), vita) - TARGET := $(TARGET_NAME)_libretro_$(platform).a - CC = arm-vita-eabi-gcc$(EXE_EXT) - CXX = arm-vita-eabi-g++$(EXE_EXT) - AR = arm-vita-eabi-ar$(EXE_EXT) - STATIC_LINKING = 1 - LOAD_FROM_MEMORY_TEST = 0 - DEFS += -DVITA - STATIC_LINKING := 1 -# CTR (3DS) -else ifeq ($(platform), ctr) - TARGET := $(TARGET_NAME)_libretro_$(platform).a - CC = $(DEVKITARM)/bin/arm-none-eabi-gcc$(EXE_EXT) - CXX = $(DEVKITARM)/bin/arm-none-eabi-g++$(EXE_EXT) - AR = $(DEVKITARM)/bin/arm-none-eabi-ar$(EXE_EXT) - CFLAGS += -DARM11 -D_3DS - CFLAGS += -march=armv6k -mtune=mpcore -mfloat-abi=hard - CFLAGS += -Wall -mword-relocations - CFLAGS += -fomit-frame-pointer -ffast-math - CFLAGS += -D_3DS - PLATFORM_DEFINES := -D_3DS - STATIC_LINKING = 1 -# Nintendo Game Cube -else ifeq ($(platform), ngc) - TARGET := $(TARGET_NAME)_libretro_$(platform).a - CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) - AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) - CFLAGS += -DGEKKO -DHW_DOL -mrvl -mcpu=750 -meabi -mhard-float -D__ppc__ -DMSB_FIRST - CFLAGS += -U__INT32_TYPE__ -U __UINT32_TYPE__ -D__INT32_TYPE__=int - STATIC_LINKING = 1 -# Nintendo Wii -else ifeq ($(platform), wii) - TARGET := $(TARGET_NAME)_libretro_$(platform).a - CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) - AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) - CFLAGS += -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -D__ppc__ -DMSB_FIRST - CFLAGS += -U__INT32_TYPE__ -U __UINT32_TYPE__ -D__INT32_TYPE__=int - STATIC_LINKING = 1 -# Nintendo WiiU -else ifeq ($(platform), wiiu) - TARGET := $(TARGET_NAME)_libretro_$(platform).a - CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) - AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) - CFLAGS += -DGEKKO -DWIIU -DHW_RVL -mwup -mcpu=750 -meabi -mhard-float -D__ppc__ -DMSB_FIRST - CFLAGS += -U__INT32_TYPE__ -U __UINT32_TYPE__ -D__INT32_TYPE__=int - STATIC_LINKING = 1 -else ifeq ($(platform), emscripten) - TARGET := $(TARGET_NAME)_libretro_$(platform).bc - STATIC_LINKING = 1 -# GCW0 -else ifeq ($(platform), gcw0) - TARGET := $(TARGET_NAME)_libretro.so - CC = /opt/gcw0-toolchain/usr/bin/mipsel-linux-gcc - CXX = /opt/gcw0-toolchain/usr/bin/mipsel-linux-g++ - AR = /opt/gcw0-toolchain/usr/bin/mipsel-linux-ar - fpic := -fPIC -nostdlib - SHARED := -shared -Wl,--version-script=link.T - LIBM := - LOAD_FROM_MEMORY_TEST = 0 - CFLAGS += -ffast-math -march=mips32 -mtune=mips32r2 -mhard-float - -# (armv7 a7, hard point, neon based) ### -# NESC, SNESC, C64 mini -else ifeq ($(platform), classic_armv7_a7) - TARGET := $(TARGET_NAME)_libretro.so - fpic := -fPIC - SHARED := -shared -Wl,--version-script=link.T -Wl,--no-undefined - CFLAGS += -Ofast \ - -flto=4 -fwhole-program -fuse-linker-plugin \ - -fdata-sections -ffunction-sections -Wl,--gc-sections \ - -fno-stack-protector -fno-ident -fomit-frame-pointer \ - -falign-functions=1 -falign-jumps=1 -falign-loops=1 \ - -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-unroll-loops \ - -fmerge-all-constants -fno-math-errno \ - -marm -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard - CXXFLAGS += $(CFLAGS) - CPPFLAGS += $(CFLAGS) - ASFLAGS += $(CFLAGS) - HAVE_NEON = 1 - ARCH = arm - BUILTIN_GPU = neon - USE_DYNAREC = 1 - ifeq ($(shell echo `$(CC) -dumpversion` "< 4.9" | bc -l), 1) - CFLAGS += -march=armv7-a - else - CFLAGS += -march=armv7ve - # If gcc is 5.0 or later - ifeq ($(shell echo `$(CC) -dumpversion` ">= 5" | bc -l), 1) - LDFLAGS += -static-libgcc -static-libstdc++ - endif - endif -####################################### - -# Windows MSVC 2010 x86 -else ifeq ($(platform), windows_msvc2010_x86) - CC = cl.exe - CXX = cl.exe - -PATH := $(shell IFS=$$'\n'; cygpath "$(VS100COMNTOOLS)../../VC/bin"):$(PATH) -PATH := $(PATH):$(shell IFS=$$'\n'; cygpath "$(VS100COMNTOOLS)../IDE") -INCLUDE := $(shell IFS=$$'\n'; cygpath "$(VS100COMNTOOLS)../../VC/include") -LIB := $(shell IFS=$$'\n'; cygpath -w "$(VS100COMNTOOLS)../../VC/lib") -BIN := $(shell IFS=$$'\n'; cygpath "$(VS100COMNTOOLS)../../VC/bin") - -WindowsSdkDir := $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')lib -WindowsSdkDir ?= $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')lib - -WindowsSdkDirInc := $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')Include -WindowsSdkDirInc ?= $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')Include - -INCFLAGS_PLATFORM = -I"$(WindowsSdkDirInc)" -export INCLUDE := $(INCLUDE) -export LIB := $(LIB);$(WindowsSdkDir) -TARGET := $(TARGET_NAME)_libretro.dll -PSS_STYLE :=2 -LDFLAGS += -DLL -CFLAGS += -D_CRT_SECURE_NO_DEPRECATE -NO_GCC = 1 - -# Windows MSVC 2008 x86 -else ifeq ($(platform), windows_msvc2008_x86) - CC = cl.exe - CXX = cl.exe - -PATH := $(shell IFS=$$'\n'; cygpath "$(VS90COMNTOOLS)../../VC/bin"):$(PATH) -PATH := $(PATH):$(shell IFS=$$'\n'; cygpath "$(VS90COMNTOOLS)../IDE") -INCLUDE := $(shell IFS=$$'\n'; cygpath "$(VS90COMNTOOLS)../../VC/include") -LIB := $(shell IFS=$$'\n'; cygpath -w "$(VS90COMNTOOLS)../../VC/lib") -BIN := $(shell IFS=$$'\n'; cygpath "$(VS90COMNTOOLS)../../VC/bin") - -WindowsSdkDir := $(INETSDK) - -export INCLUDE := $(INCLUDE);$(INETSDK)/Include;libretro-common/include/compat/msvc -export LIB := $(LIB);$(WindowsSdkDir);$(INETSDK)/Lib -TARGET := $(TARGET_NAME)_libretro.dll -PSS_STYLE :=2 -LDFLAGS += -DLL -CFLAGS += -D_CRT_SECURE_NO_DEPRECATE -NO_GCC = 1 - -# Windows MSVC 2005 x86 -else ifeq ($(platform), windows_msvc2005_x86) - CC = cl.exe - CXX = cl.exe - -PATH := $(shell IFS=$$'\n'; cygpath "$(VS80COMNTOOLS)../../VC/bin"):$(PATH) -PATH := $(PATH):$(shell IFS=$$'\n'; cygpath "$(VS80COMNTOOLS)../IDE") -INCLUDE := $(shell IFS=$$'\n'; cygpath "$(VS80COMNTOOLS)../../VC/include") -LIB := $(shell IFS=$$'\n'; cygpath -w "$(VS80COMNTOOLS)../../VC/lib") -BIN := $(shell IFS=$$'\n'; cygpath "$(VS80COMNTOOLS)../../VC/bin") - -WindowsSdkDir := $(INETSDK) - -export INCLUDE := $(INCLUDE);$(INETSDK)/Include;libretro-common/include/compat/msvc -export LIB := $(LIB);$(WindowsSdkDir);$(INETSDK)/Lib -TARGET := $(TARGET_NAME)_libretro.dll -PSS_STYLE :=2 -LDFLAGS += -DLL -CFLAGS += -D_CRT_SECURE_NO_DEPRECATE -NO_GCC = 1 - -# Windows MSVC 2003 x86 -else ifeq ($(platform), windows_msvc2003_x86) - CC = cl.exe - CXX = cl.exe - -PATH := $(shell IFS=$$'\n'; cygpath "$(VS71COMNTOOLS)../../Vc7/bin"):$(PATH) -PATH := $(PATH):$(shell IFS=$$'\n'; cygpath "$(VS71COMNTOOLS)../IDE") -INCLUDE := $(shell IFS=$$'\n'; cygpath "$(VS71COMNTOOLS)../../Vc7/include") -LIB := $(shell IFS=$$'\n'; cygpath -w "$(VS71COMNTOOLS)../../Vc7/lib") -BIN := $(shell IFS=$$'\n'; cygpath "$(VS71COMNTOOLS)../../Vc7/bin") - -WindowsSdkDir := $(INETSDK) - -export INCLUDE := $(INCLUDE);$(INETSDK)/Include;libretro-common/include/compat/msvc -export LIB := $(LIB);$(WindowsSdkDir);$(INETSDK)/Lib -TARGET := $(TARGET_NAME)_libretro.dll -PSS_STYLE :=2 -LDFLAGS += -DLL -CFLAGS += -D_CRT_SECURE_NO_DEPRECATE -NO_GCC = 1 - -# Windows MSVC 2017 all architectures -else ifneq (,$(findstring windows_msvc2017,$(platform))) - - NO_GCC := 1 - CFLAGS += -DNOMINMAX - CXXFLAGS += -DNOMINMAX - WINDOWS_VERSION = 1 - - PlatformSuffix = $(subst windows_msvc2017_,,$(platform)) - ifneq (,$(findstring desktop,$(PlatformSuffix))) - WinPartition = desktop - MSVC2017CompileFlags = -DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP -FS - LDFLAGS += -MANIFEST -LTCG:incremental -NXCOMPAT -DYNAMICBASE -DEBUG -OPT:REF -INCREMENTAL:NO -SUBSYSTEM:WINDOWS -MANIFESTUAC:"level='asInvoker' uiAccess='false'" -OPT:ICF -ERRORREPORT:PROMPT -NOLOGO -TLBID:1 - LIBS += kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib - else ifneq (,$(findstring uwp,$(PlatformSuffix))) - WinPartition = uwp - MSVC2017CompileFlags = -DWINAPI_FAMILY=WINAPI_FAMILY_APP -D_WINDLL -D_UNICODE -DUNICODE -D__WRL_NO_DEFAULT_LIB__ -EHsc -FS - LDFLAGS += -APPCONTAINER -NXCOMPAT -DYNAMICBASE -MANIFEST:NO -LTCG -OPT:REF -SUBSYSTEM:CONSOLE -MANIFESTUAC:NO -OPT:ICF -ERRORREPORT:PROMPT -NOLOGO -TLBID:1 -DEBUG:FULL -WINMD:NO - LIBS += WindowsApp.lib - endif - - CFLAGS += $(MSVC2017CompileFlags) - CXXFLAGS += $(MSVC2017CompileFlags) - - TargetArchMoniker = $(subst $(WinPartition)_,,$(PlatformSuffix)) - - CC = cl.exe - CXX = cl.exe - LD = link.exe - - reg_query = $(call filter_out2,$(subst $2,,$(shell reg query "$2" -v "$1" 2>nul))) - fix_path = $(subst $(SPACE),\ ,$(subst \,/,$1)) - - ProgramFiles86w := $(shell cmd /c "echo %PROGRAMFILES(x86)%") - ProgramFiles86 := $(shell cygpath "$(ProgramFiles86w)") - - WindowsSdkDir ?= $(call reg_query,InstallationFolder,HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v10.0) - WindowsSdkDir ?= $(call reg_query,InstallationFolder,HKEY_CURRENT_USER\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v10.0) - WindowsSdkDir ?= $(call reg_query,InstallationFolder,HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0) - WindowsSdkDir ?= $(call reg_query,InstallationFolder,HKEY_CURRENT_USER\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0) - WindowsSdkDir := $(WindowsSdkDir) - - WindowsSDKVersion ?= $(firstword $(foreach folder,$(subst $(subst \,/,$(WindowsSdkDir)Include/),,$(wildcard $(call fix_path,$(WindowsSdkDir)Include\*))),$(if $(wildcard $(call fix_path,$(WindowsSdkDir)Include/$(folder)/um/Windows.h)),$(folder),)))$(BACKSLASH) - WindowsSDKVersion := $(WindowsSDKVersion) - - VsInstallBuildTools = $(ProgramFiles86)/Microsoft Visual Studio/2017/BuildTools - VsInstallEnterprise = $(ProgramFiles86)/Microsoft Visual Studio/2017/Enterprise - VsInstallProfessional = $(ProgramFiles86)/Microsoft Visual Studio/2017/Professional - VsInstallCommunity = $(ProgramFiles86)/Microsoft Visual Studio/2017/Community - - VsInstallRoot ?= $(shell if [ -d "$(VsInstallBuildTools)" ]; then echo "$(VsInstallBuildTools)"; fi) - ifeq ($(VsInstallRoot), ) - VsInstallRoot = $(shell if [ -d "$(VsInstallEnterprise)" ]; then echo "$(VsInstallEnterprise)"; fi) - endif - ifeq ($(VsInstallRoot), ) - VsInstallRoot = $(shell if [ -d "$(VsInstallProfessional)" ]; then echo "$(VsInstallProfessional)"; fi) - endif - ifeq ($(VsInstallRoot), ) - VsInstallRoot = $(shell if [ -d "$(VsInstallCommunity)" ]; then echo "$(VsInstallCommunity)"; fi) - endif - VsInstallRoot := $(VsInstallRoot) - - VcCompilerToolsVer := $(shell cat "$(VsInstallRoot)/VC/Auxiliary/Build/Microsoft.VCToolsVersion.default.txt" | grep -o '[0-9\.]*') - VcCompilerToolsDir := $(VsInstallRoot)/VC/Tools/MSVC/$(VcCompilerToolsVer) - - WindowsSDKSharedIncludeDir := $(shell cygpath -w "$(WindowsSdkDir)\Include\$(WindowsSDKVersion)\shared") - WindowsSDKUCRTIncludeDir := $(shell cygpath -w "$(WindowsSdkDir)\Include\$(WindowsSDKVersion)\ucrt") - WindowsSDKUMIncludeDir := $(shell cygpath -w "$(WindowsSdkDir)\Include\$(WindowsSDKVersion)\um") - WindowsSDKUCRTLibDir := $(shell cygpath -w "$(WindowsSdkDir)\Lib\$(WindowsSDKVersion)\ucrt\$(TargetArchMoniker)") - WindowsSDKUMLibDir := $(shell cygpath -w "$(WindowsSdkDir)\Lib\$(WindowsSDKVersion)\um\$(TargetArchMoniker)") - - # For some reason the HostX86 compiler doesn't like compiling for x64 - # ("no such file" opening a shared library), and vice-versa. - # Work around it for now by using the strictly x86 compiler for x86, and x64 for x64. - # NOTE: What about ARM? - ifneq (,$(findstring x64,$(TargetArchMoniker))) - VCCompilerToolsBinDir := $(VcCompilerToolsDir)\bin\HostX64 - else - VCCompilerToolsBinDir := $(VcCompilerToolsDir)\bin\HostX86 - endif - - PATH := $(shell IFS=$$'\n'; cygpath "$(VCCompilerToolsBinDir)/$(TargetArchMoniker)"):$(PATH) - PATH := $(PATH):$(shell IFS=$$'\n'; cygpath "$(VsInstallRoot)/Common7/IDE") - INCLUDE := $(shell IFS=$$'\n'; cygpath -w "$(VcCompilerToolsDir)/include") - LIB := $(shell IFS=$$'\n'; cygpath -w "$(VcCompilerToolsDir)/lib/$(TargetArchMoniker)") - ifneq (,$(findstring uwp,$(PlatformSuffix))) - LIB := $(LIB);$(shell IFS=$$'\n'; cygpath -w "$(LIB)/store") - endif - - export INCLUDE := $(INCLUDE);$(WindowsSDKSharedIncludeDir);$(WindowsSDKUCRTIncludeDir);$(WindowsSDKUMIncludeDir) - export LIB := $(LIB);$(WindowsSDKUCRTLibDir);$(WindowsSDKUMLibDir) - TARGET := $(TARGET_NAME)_libretro.dll - PSS_STYLE :=2 - LDFLAGS += -DLL - -else - TARGET := $(TARGET_NAME)_libretro.dll - CC = gcc - CXX = g++ - SHARED := -shared -Wl,--no-undefined -Wl,--version-script=link.T - LDFLAGS += -static-libgcc -static-libstdc++ -lwinmm -endif - -LDFLAGS += $(LIBM) - -CORE_DIR := ./source -LIBRETRO_DIR := . - -include Makefile.common - -ifeq ($(OLD_GCC), 1) - WARNINGS := -Wall -else ifeq ($(NO_GCC), 1) - WARNINGS := -else - WARNINGS := \ - -Wall \ - -Wextra \ - -pedantic \ - -Wno-implicit-function-declaration \ - -Wno-implicit-fallthrough \ - -Wno-sign-compare \ - -Wno-unused-variable \ - -Wno-unused-function \ - -Wno-uninitialized \ - -Wno-strict-aliasing \ - -Wno-overflow \ - -fno-strict-overflow -endif - -ifeq ($(DEBUG),1) - FLAGS += -O0 -g -else - FLAGS += -O2 -DNDEBUG -endif - -ifeq ($(PERF_TEST),1) - FLAGS += -DPERF_TEST -endif - -ifeq ($(LAGFIX),1) - FLAGS += -DLAGFIX -endif - -FLAGS += $(INCFLAGS_PLATFORM) - -ifeq ($(platform), psp1) - INCFLAGS += -I$(shell psp-config --pspsdk-path)/include -endif - -OBJECTS := $(SOURCES_C:.c=.o) - -LDFLAGS += $(fpic) - -FLAGS += $(fpic) - -CXXFLAGS += $(FLAGS) -CFLAGS += $(FLAGS) - -ifneq (,$(findstring msvc,$(platform))) - LIBM = - OBJOUT = -Fo - LINKOUT = -out: - LD = link.exe -else - OBJOUT = -o - LINKOUT = -o - LD = $(CC) -endif - -%.o: %.cpp - $(CXX) $(CXXFLAGS) -c $(OBJOUT)$@ $< - -%.o: %.c - $(CC) $(CFLAGS) -c $(OBJOUT)$@ $< - -ifeq ($(platform), theos_ios) - COMMON_FLAGS := -DIOS $(COMMON_DEFINES) $(INCFLAGS) -I$(THEOS_INCLUDE_PATH) -Wno-error - $(LIBRARY_NAME)_CFLAGS += $(COMMON_FLAGS) $(CFLAGS) - ${LIBRARY_NAME}_FILES = $(SOURCES_C) - include $(THEOS_MAKE_PATH)/library.mk -else -all: $(TARGET) -$(TARGET): $(OBJECTS) -ifeq ($(STATIC_LINKING), 1) - $(AR) rcs $@ $(OBJECTS) -else - $(LD) $(LINKOUT)$@ $(SHARED) $(OBJECTS) $(LDFLAGS) $(LIBS) -endif +$(OBJ_C) : %.o : %.c + $(CC) $(CFLAGS) -c -o $@ $< clean: - rm -f $(TARGET) $(OBJECTS) - -.PHONY: clean -endif + rm -f $(PRGNAME)$(EXESUFFIX) *.o diff --git a/Makefile.common b/Makefile.common deleted file mode 100644 index 48256bb..0000000 --- a/Makefile.common +++ /dev/null @@ -1,53 +0,0 @@ -LIBRETRO_COMM_DIR := $(LIBRETRO_DIR)/libretro-common - -INCFLAGS := -I$(CORE_DIR) -I$(LIBRETRO_DIR) -I$(LIBRETRO_COMM_DIR)/include - -SOURCES_C := \ - $(CORE_DIR)/c4.c \ - $(CORE_DIR)/c4emu.c \ - $(CORE_DIR)/cheats2.c \ - $(CORE_DIR)/cheats.c \ - $(CORE_DIR)/clip.c \ - $(CORE_DIR)/cpu.c \ - $(CORE_DIR)/cpuexec.c \ - $(CORE_DIR)/cpuops.c \ - $(CORE_DIR)/data.c\ - $(CORE_DIR)/dma.c \ - $(CORE_DIR)/dsp1.c \ - $(CORE_DIR)/fxemu.c \ - $(CORE_DIR)/fxinst.c \ - $(CORE_DIR)/gfx.c \ - $(CORE_DIR)/getset.c \ - $(CORE_DIR)/globals.c \ - $(CORE_DIR)/memmap.c \ - $(CORE_DIR)/obc1.c \ - $(CORE_DIR)/ppu.c \ - $(CORE_DIR)/sa1.c \ - $(CORE_DIR)/sa1cpu.c \ - $(CORE_DIR)/sdd1.c \ - $(CORE_DIR)/sdd1emu.c \ - $(CORE_DIR)/seta010.c \ - $(CORE_DIR)/seta011.c \ - $(CORE_DIR)/seta018.c \ - $(CORE_DIR)/seta.c \ - $(CORE_DIR)/spc7110.c \ - $(CORE_DIR)/spc7110dec.c \ - $(CORE_DIR)/srtc.c \ - $(CORE_DIR)/tile.c \ - $(LIBRETRO_DIR)/libretro.c - -ifeq ($(USE_BLARGG_APU),1) - SOURCES_C += $(CORE_DIR)/apu_blargg.c - FLAGS += -DUSE_BLARGG_APU -else - SOURCES_C += \ - $(CORE_DIR)/apu.c \ - $(CORE_DIR)/soundux.c \ - $(CORE_DIR)/spc700.c -endif - -ifeq ($(LOAD_FROM_MEMORY_TEST),1) - FLAGS += -DLOAD_FROM_MEMORY_TEST -endif - -FLAGS += $(DEFS) $(WARNINGS) $(INCFLAGS) @@ -1,3 +1,11 @@ +SnesEmu fork based on snes9x2005 libretro core by the Retroarch team.
+
+The libretro team had switched the core entirely to C and made it less prone to crashes.
+It made more sense to me to just reuse that work rather than trying to fix up PocketSNES,
+which is now unmaintained.
+
+==========================
+
snes9x2005 libretro core.
A Super Nintendo emulator core using the libretro API.
diff --git a/control b/control deleted file mode 100644 index 9397a89..0000000 --- a/control +++ /dev/null @@ -1,10 +0,0 @@ -Package: com.libretro.catsfc -Name: catsfc -Depends: -Version: 0.0.1 -Architecture: iphoneos-arm -Description: Libretro iOS core of catSFC -Maintainer: libretro -Author: libretro -Section: System -Tag: role::developer diff --git a/jni/Android.mk b/jni/Android.mk deleted file mode 100644 index e5cf6e3..0000000 --- a/jni/Android.mk +++ /dev/null @@ -1,24 +0,0 @@ -LOCAL_PATH := $(call my-dir) - -ROOT_DIR := $(LOCAL_PATH)/.. -CORE_DIR := $(ROOT_DIR)/source -LIBRETRO_DIR := $(ROOT_DIR) - -LOAD_FROM_MEMORY_TEST := 1 -FLAGS := - -include $(ROOT_DIR)/Makefile.common - -COREFLAGS := -ffast-math $(FLAGS) - -GIT_VERSION := " $(shell git rev-parse --short HEAD || echo unknown)" -ifneq ($(GIT_VERSION)," unknown") - COREFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\" -endif - -include $(CLEAR_VARS) -LOCAL_MODULE := retro -LOCAL_SRC_FILES := $(SOURCES_C) -LOCAL_CFLAGS := $(COREFLAGS) -LOCAL_LDFLAGS := -Wl,-version-script=$(LIBRETRO_DIR)/link.T -include $(BUILD_SHARED_LIBRARY) diff --git a/jni/Application.mk b/jni/Application.mk deleted file mode 100644 index a252a72..0000000 --- a/jni/Application.mk +++ /dev/null @@ -1 +0,0 @@ -APP_ABI := all diff --git a/libretro-common/include/compat/msvc.h b/libretro-common/include/compat/msvc.h deleted file mode 100644 index 5175214..0000000 --- a/libretro-common/include/compat/msvc.h +++ /dev/null @@ -1,132 +0,0 @@ -/* Copyright (C) 2010-2017 The RetroArch team - * - * --------------------------------------------------------------------------------------- - * The following license statement only applies to this file (msvc.h). - * --------------------------------------------------------------------------------------- - * - * Permission is hereby granted, free of charge, - * to any person obtaining a copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef __LIBRETRO_SDK_COMPAT_MSVC_H -#define __LIBRETRO_SDK_COMPAT_MSVC_H - -#ifdef _MSC_VER - -#ifdef __cplusplus -extern "C" { -#endif - -/* Pre-MSVC 2015 compilers don't implement snprintf in a cross-platform manner. */ -#if _MSC_VER < 1900 - #include <stdlib.h> - #ifndef snprintf - #define snprintf c99_snprintf_retro__ - #endif - - int c99_snprintf_retro__(char *outBuf, size_t size, const char *format, ...); -#endif - -/* Pre-MSVC 2010 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */ -#if _MSC_VER < 1600 - #include <stdarg.h> - #include <stdlib.h> - #ifndef vsnprintf - #define vsnprintf c99_vsnprintf_retro__ - #endif - int c99_vsnprintf_retro__(char *outBuf, size_t size, const char *format, va_list ap); -#endif - -#ifdef __cplusplus -} -#endif - -#undef UNICODE /* Do not bother with UNICODE at this time. */ -#include <direct.h> -#include <stddef.h> -#include <math.h> - -/* Python headers defines ssize_t and sets HAVE_SSIZE_T. - * Cannot duplicate these efforts. - */ -#ifndef HAVE_SSIZE_T -#if defined(_WIN64) -typedef __int64 ssize_t; -#elif defined(_WIN32) -typedef int ssize_t; -#endif -#endif - -#define mkdir(dirname, unused) _mkdir(dirname) -#define strtoull _strtoui64 -#undef strcasecmp -#define strcasecmp _stricmp -#undef strncasecmp -#define strncasecmp _strnicmp - -/* Disable some of the annoying warnings. */ -#pragma warning(disable : 4800) -#pragma warning(disable : 4805) -#pragma warning(disable : 4244) -#pragma warning(disable : 4305) -#pragma warning(disable : 4146) -#pragma warning(disable : 4267) -#pragma warning(disable : 4723) -#pragma warning(disable : 4996) - -/* roundf and va_copy is available since MSVC 2013 */ -#if _MSC_VER < 1800 -#define roundf(in) (in >= 0.0f ? floorf(in + 0.5f) : ceilf(in - 0.5f)) -#define va_copy(x, y) ((x) = (y)) -#endif - -#if _MSC_VER <= 1200 - #ifndef __cplusplus - /* VC6 math.h doesn't define some functions when in C mode. - * Trying to define a prototype gives "undefined reference". - * But providing an implementation then gives "function already has body". - * So the equivalent of the implementations from math.h are used as - * defines here instead, and it seems to work. - */ - #define cosf(x) ((float)cos((double)x)) - #define powf(x, y) ((float)pow((double)x, (double)y)) - #define sinf(x) ((float)sin((double)x)) - #define ceilf(x) ((float)ceil((double)x)) - #define floorf(x) ((float)floor((double)x)) - #define sqrtf(x) ((float)sqrt((double)x)) - #endif - - #ifndef _vscprintf - #define _vscprintf c89_vscprintf_retro__ - int c89_vscprintf_retro__(const char *format, va_list pargs); - #endif - - #ifndef _strtoui64 - #define _strtoui64(x, y, z) (_atoi64(x)) - #endif - -#endif - -#ifndef PATH_MAX -#define PATH_MAX _MAX_PATH -#endif - -#ifndef SIZE_MAX -#define SIZE_MAX _UI32_MAX -#endif - -#endif -#endif - diff --git a/libretro-common/include/compat/msvc/stdint.h b/libretro-common/include/compat/msvc/stdint.h deleted file mode 100644 index c791176..0000000 --- a/libretro-common/include/compat/msvc/stdint.h +++ /dev/null @@ -1,258 +0,0 @@ -/* ISO C9x compliant stdint.h for Microsoft Visual Studio - * Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 - * - * Copyright (c) 2006-2008 Alexander Chemeris - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. The name of the author may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __RARCH_STDINT_H -#define __RARCH_STDINT_H - -#if _MSC_VER && (_MSC_VER < 1600) -/* Pre-MSVC 2010 needs an implementation of stdint.h. */ - -#if _MSC_VER > 1000 -#pragma once -#endif - -#include <limits.h> - -/* For Visual Studio 6 in C++ mode and for many Visual Studio versions when - * compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}' - * or compiler give many errors like this: - * - * error C2733: second C linkage of overloaded function 'wmemchr' not allowed - */ -#ifdef __cplusplus -#if _MSC_VER <= 1200 -extern "C++" { -#else -extern "C" { -#endif -#endif -# include <wchar.h> -#ifdef __cplusplus -} -#endif - -/* Define _W64 macros to mark types changing their size, like intptr_t. */ -#ifndef _W64 -# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 -# define _W64 __w64 -# else -# define _W64 -# endif -#endif - - -/* 7.18.1 Integer types. */ - -/* 7.18.1.1 Exact-width integer types. */ - -/* Visual Studio 6 and Embedded Visual C++ 4 doesn't - * realize that, e.g. char has the same size as __int8 - * so we give up on __intX for them. - */ -#if (_MSC_VER < 1300) - typedef signed char int8_t; - typedef signed short int16_t; - typedef signed int int32_t; - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; -#else - typedef signed __int8 int8_t; - typedef signed __int16 int16_t; - typedef signed __int32 int32_t; - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; -#endif -typedef signed __int64 int64_t; -typedef unsigned __int64 uint64_t; - - -/* 7.18.1.2 Minimum-width integer types. */ -typedef int8_t int_least8_t; -typedef int16_t int_least16_t; -typedef int32_t int_least32_t; -typedef int64_t int_least64_t; -typedef uint8_t uint_least8_t; -typedef uint16_t uint_least16_t; -typedef uint32_t uint_least32_t; -typedef uint64_t uint_least64_t; - -/* 7.18.1.3 Fastest minimum-width integer types. */ -typedef int8_t int_fast8_t; -typedef int16_t int_fast16_t; -typedef int32_t int_fast32_t; -typedef int64_t int_fast64_t; -typedef uint8_t uint_fast8_t; -typedef uint16_t uint_fast16_t; -typedef uint32_t uint_fast32_t; -typedef uint64_t uint_fast64_t; - -/* 7.18.1.4 Integer types capable of holding object pointers. */ -#ifdef _WIN64 /* [ */ - typedef signed __int64 intptr_t; - typedef unsigned __int64 uintptr_t; -#else /* _WIN64 ][ */ - typedef _W64 signed int intptr_t; - typedef _W64 unsigned int uintptr_t; -#endif /* _WIN64 ] */ - -/* 7.18.1.5 Greatest-width integer types. */ -typedef int64_t intmax_t; -typedef uint64_t uintmax_t; - -/* 7.18.2 Limits of specified-width integer types. */ - -#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) -/* [ See footnote 220 at page 257 and footnote 221 at page 259. */ - -/* 7.18.2.1 Limits of exact-width integer types. */ -#define INT8_MIN ((int8_t)_I8_MIN) -#define INT8_MAX _I8_MAX -#define INT16_MIN ((int16_t)_I16_MIN) -#define INT16_MAX _I16_MAX -#define INT32_MIN ((int32_t)_I32_MIN) -#define INT32_MAX _I32_MAX -#define INT64_MIN ((int64_t)_I64_MIN) -#define INT64_MAX _I64_MAX -#define UINT8_MAX _UI8_MAX -#define UINT16_MAX _UI16_MAX -#define UINT32_MAX _UI32_MAX -#define UINT64_MAX _UI64_MAX - -/* 7.18.2.2 Limits of minimum-width integer types. */ -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MIN INT64_MIN -#define INT_LEAST64_MAX INT64_MAX -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -/* 7.18.2.3 Limits of fastest minimum-width integer types. */ -#define INT_FAST8_MIN INT8_MIN -#define INT_FAST8_MAX INT8_MAX -#define INT_FAST16_MIN INT16_MIN -#define INT_FAST16_MAX INT16_MAX -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST32_MAX INT32_MAX -#define INT_FAST64_MIN INT64_MIN -#define INT_FAST64_MAX INT64_MAX -#define UINT_FAST8_MAX UINT8_MAX -#define UINT_FAST16_MAX UINT16_MAX -#define UINT_FAST32_MAX UINT32_MAX -#define UINT_FAST64_MAX UINT64_MAX - -/* 7.18.2.4 Limits of integer types capable of holding object pointers. */ -#ifdef _WIN64 /* [ */ -# define INTPTR_MIN INT64_MIN -# define INTPTR_MAX INT64_MAX -# define UINTPTR_MAX UINT64_MAX -#else /* _WIN64 ][ */ -# define INTPTR_MIN INT32_MIN -# define INTPTR_MAX INT32_MAX -# define UINTPTR_MAX UINT32_MAX -#endif /* _WIN64 ] */ - -/* 7.18.2.5 Limits of greatest-width integer types */ -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -/* 7.18.3 Limits of other integer types */ - -#ifdef _WIN64 /* [ */ -# define PTRDIFF_MIN _I64_MIN -# define PTRDIFF_MAX _I64_MAX -#else /* _WIN64 ][ */ -# define PTRDIFF_MIN _I32_MIN -# define PTRDIFF_MAX _I32_MAX -#endif /* _WIN64 ] */ - -#define SIG_ATOMIC_MIN INT_MIN -#define SIG_ATOMIC_MAX INT_MAX - -#ifndef SIZE_MAX /* [ */ -# ifdef _WIN64 /* [ */ -# define SIZE_MAX _UI64_MAX -# else /* _WIN64 ][ */ -# define SIZE_MAX _UI32_MAX -# endif /* _WIN64 ] */ -#endif /* SIZE_MAX ] */ - -/* WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h> */ -#ifndef WCHAR_MIN /* [ */ -# define WCHAR_MIN 0 -#endif /* WCHAR_MIN ] */ -#ifndef WCHAR_MAX // [ -# define WCHAR_MAX _UI16_MAX -#endif /* WCHAR_MAX ] */ - -#define WINT_MIN 0 -#define WINT_MAX _UI16_MAX - -#endif /* __STDC_LIMIT_MACROS ] */ - -/* 7.18.4 Limits of other integer types */ - -#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) -/* [ See footnote 224 at page 260 */ - -/* 7.18.4.1 Macros for minimum-width integer constants */ - -#define INT8_C(val) val##i8 -#define INT16_C(val) val##i16 -#define INT32_C(val) val##i32 -#define INT64_C(val) val##i64 - -#define UINT8_C(val) val##ui8 -#define UINT16_C(val) val##ui16 -#define UINT32_C(val) val##ui32 -#define UINT64_C(val) val##ui64 - -/* 7.18.4.2 Macros for greatest-width integer constants */ -#define INTMAX_C INT64_C -#define UINTMAX_C UINT64_C - -#endif -/* __STDC_CONSTANT_MACROS ] */ - -#else -/* Sanity for everything else. */ -#include <stdint.h> -#endif - -#endif - diff --git a/libretro-common/include/retro_miscellaneous.h b/libretro-common/include/retro_miscellaneous.h deleted file mode 100644 index e526d6e..0000000 --- a/libretro-common/include/retro_miscellaneous.h +++ /dev/null @@ -1,155 +0,0 @@ -/* Copyright (C) 2010-2017 The RetroArch team - * - * --------------------------------------------------------------------------------------- - * The following license statement only applies to this file (retro_miscellaneous.h). - * --------------------------------------------------------------------------------------- - * - * Permission is hereby granted, free of charge, - * to any person obtaining a copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef __RARCH_MISCELLANEOUS_H -#define __RARCH_MISCELLANEOUS_H - -#include <stdint.h> -#include <boolean.h> -#include <retro_inline.h> - -#if defined(_WIN32) && !defined(_XBOX) -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include <windows.h> -#elif defined(_WIN32) && defined(_XBOX) -#include <Xtl.h> -#endif - -#if defined(__CELLOS_LV2__) -#include <sys/fs_external.h> -#endif - -#include <limits.h> - -#ifdef _MSC_VER -#include <compat/msvc.h> -#endif - -static INLINE void bits_or_bits(uint32_t *a, uint32_t *b, uint32_t count) -{ - uint32_t i; - for (i = 0; i < count;i++) - a[i] |= b[i]; -} - -static INLINE void bits_clear_bits(uint32_t *a, uint32_t *b, uint32_t count) -{ - uint32_t i; - for (i = 0; i < count;i++) - a[i] &= ~b[i]; -} - -static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count) -{ - uint32_t i; - for (i = 0; i < count; i++) - { - if (ptr[i] != 0) - return true; - } - return false; -} - -#ifndef PATH_MAX_LENGTH -#if defined(__CELLOS_LV2__) -#define PATH_MAX_LENGTH CELL_FS_MAX_FS_PATH_LENGTH -#elif defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(GEKKO)|| defined(WIIU) -#define PATH_MAX_LENGTH 512 -#else -#define PATH_MAX_LENGTH 4096 -#endif -#endif - -#ifndef MAX -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#endif - -#ifndef MIN -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#endif - -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) - -#define BITS_GET_ELEM(a, i) ((a).data[i]) -#define BITS_GET_ELEM_PTR(a, i) ((a)->data[i]) - -#define BIT_SET(a, bit) ((a)[(bit) >> 3] |= (1 << ((bit) & 7))) -#define BIT_CLEAR(a, bit) ((a)[(bit) >> 3] &= ~(1 << ((bit) & 7))) -#define BIT_GET(a, bit) (((a)[(bit) >> 3] >> ((bit) & 7)) & 1) - -#define BIT16_SET(a, bit) ((a) |= (1 << ((bit) & 15))) -#define BIT16_CLEAR(a, bit) ((a) &= ~(1 << ((bit) & 15))) -#define BIT16_GET(a, bit) (((a) >> ((bit) & 15)) & 1) -#define BIT16_CLEAR_ALL(a) ((a) = 0) - -#define BIT32_SET(a, bit) ((a) |= (1 << ((bit) & 31))) -#define BIT32_CLEAR(a, bit) ((a) &= ~(1 << ((bit) & 31))) -#define BIT32_GET(a, bit) (((a) >> ((bit) & 31)) & 1) -#define BIT32_CLEAR_ALL(a) ((a) = 0) - -#define BIT64_SET(a, bit) ((a) |= (UINT64_C(1) << ((bit) & 63))) -#define BIT64_CLEAR(a, bit) ((a) &= ~(UINT64_C(1) << ((bit) & 63))) -#define BIT64_GET(a, bit) (((a) >> ((bit) & 63)) & 1) -#define BIT64_CLEAR_ALL(a) ((a) = 0) - -#define BIT128_SET(a, bit) ((a).data[(bit) >> 5] |= (1 << ((bit) & 31))) -#define BIT128_CLEAR(a, bit) ((a).data[(bit) >> 5] &= ~(1 << ((bit) & 31))) -#define BIT128_GET(a, bit) (((a).data[(bit) >> 5] >> ((bit) & 31)) & 1) -#define BIT128_CLEAR_ALL(a) memset(&(a), 0, sizeof(a)) - -#define BIT128_SET_PTR(a, bit) BIT128_SET(*a, bit) -#define BIT128_CLEAR_PTR(a, bit) BIT128_CLEAR(*a, bit) -#define BIT128_GET_PTR(a, bit) BIT128_GET(*a, bit) -#define BIT128_CLEAR_ALL_PTR(a) BIT128_CLEAR_ALL(*a) - -#define BIT256_SET(a, bit) BIT128_SET(a, bit) -#define BIT256_CLEAR(a, bit) BIT128_CLEAR(a, bit) -#define BIT256_GET(a, bit) BIT128_GET(a, bit) -#define BIT256_CLEAR_ALL(a) BIT128_CLEAR_ALL(a) - -#define BIT256_SET_PTR(a, bit) BIT256_SET(*a, bit) -#define BIT256_CLEAR_PTR(a, bit) BIT256_CLEAR(*a, bit) -#define BIT256_GET_PTR(a, bit) BIT256_GET(*a, bit) -#define BIT256_CLEAR_ALL_PTR(a) BIT256_CLEAR_ALL(*a) - -#define BITS_COPY16_PTR(a,bits) \ -{ \ - BIT128_CLEAR_ALL_PTR(a); \ - BITS_GET_ELEM_PTR(a, 0) = (bits) & 0xffff; \ -} - -#define BITS_COPY32_PTR(a,bits) \ -{ \ - BIT128_CLEAR_ALL_PTR(a); \ - BITS_GET_ELEM_PTR(a, 0) = (bits); \ -} - -/* Helper macros and struct to keep track of many booleans. */ -/* This struct has 256 bits. */ -typedef struct -{ - uint32_t data[8]; -} retro_bits_t; - -#endif diff --git a/libretro.c b/libretro.c deleted file mode 100644 index a3d2beb..0000000 --- a/libretro.c +++ /dev/null @@ -1,933 +0,0 @@ -#include "copyright" - -#include <stdio.h> - -#include "snes9x.h" -#include "soundux.h" -#include "memmap.h" -#include "apu.h" -#include "cheats.h" -#include "display.h" -#include "gfx.h" -#include "cpuexec.h" -#include "spc7110.h" -#include "srtc.h" -#include "sa1.h" - -#ifdef PSP -#include <pspkernel.h> -#include <pspgu.h> -#endif - -#include <libretro.h> -#include <retro_miscellaneous.h> - -#ifdef _3DS -void* linearMemAlign(size_t size, size_t alignment); -void linearFree(void* mem); -#endif - -static retro_log_printf_t log_cb = NULL; -static retro_video_refresh_t video_cb = NULL; -static retro_input_poll_t poll_cb = NULL; -static retro_input_state_t input_cb = NULL; -static retro_audio_sample_batch_t audio_batch_cb = NULL; -static retro_environment_t environ_cb = NULL; -struct retro_perf_callback perf_cb; - -char retro_save_directory[PATH_MAX_LENGTH]; -char retro_base_name[PATH_MAX_LENGTH]; -bool overclock_cycles = false; -bool reduce_sprite_flicker = false; -int one_c, slow_one_c, two_c; - -#ifdef _WIN32 - char slash = '\\'; -#else - char slash = '/'; -#endif - -static int32_t samples_per_frame = 0; -static int32_t samplerate = (((SNES_CLOCK_SPEED * 6) / (32 * ONE_APU_CYCLE))); - -#ifdef PERF_TEST -#define RETRO_PERFORMANCE_INIT(name) \ - retro_perf_tick_t current_ticks; \ - static struct retro_perf_counter name = {#name}; \ - if (!name.registered) \ - perf_cb.perf_register(&(name)); \ - current_ticks = name.total - -#define RETRO_PERFORMANCE_START(name) \ - perf_cb.perf_start(&(name)) - -#define RETRO_PERFORMANCE_STOP(name) \ - perf_cb.perf_stop(&(name)); \ - current_ticks = name.total - current_ticks; -#else -#define RETRO_PERFORMANCE_INIT(name) -#define RETRO_PERFORMANCE_START(name) -#define RETRO_PERFORMANCE_STOP(name) -#endif - -void retro_set_environment(retro_environment_t cb) -{ - struct retro_log_callback log; - environ_cb = cb; - - if (environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log)) - log_cb = log.log; - else - log_cb = NULL; - - environ_cb(RETRO_ENVIRONMENT_GET_PERF_INTERFACE, &perf_cb); -} - -void retro_set_video_refresh(retro_video_refresh_t cb) -{ - video_cb = cb; -} - -void retro_set_audio_sample(retro_audio_sample_t cb) -{ - (void) cb; -} - -void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) -{ - audio_batch_cb = cb; -} - -void retro_set_input_poll(retro_input_poll_t cb) -{ - poll_cb = cb; -} - -void retro_set_input_state(retro_input_state_t cb) -{ - input_cb = cb; -} - -void retro_set_controller_port_device(unsigned in_port, unsigned device) -{ - (void) in_port; - (void) device; -} - -unsigned retro_api_version() -{ - return RETRO_API_VERSION; -} - -void S9xDeinitDisplay(void) -{ -#ifdef DS2_DMA - if (GFX.Screen_buffer) - AlignedFree(GFX.Screen, PtrAdj.GFXScreen); -#elif defined(_3DS) - if (GFX.Screen_buffer) - linearFree(GFX.Screen_buffer); -#else - if (GFX.Screen_buffer) - free(GFX.Screen_buffer); -#endif - if (GFX.SubScreen_buffer) - free(GFX.SubScreen_buffer); - if (GFX.ZBuffer_buffer) - free(GFX.ZBuffer_buffer); - if (GFX.SubZBuffer_buffer) - free(GFX.SubZBuffer_buffer); - - GFX.Screen = NULL; - GFX.Screen_buffer = NULL; - GFX.SubScreen = NULL; - GFX.SubScreen_buffer = NULL; - GFX.ZBuffer = NULL; - GFX.ZBuffer_buffer = NULL; - GFX.SubZBuffer = NULL; - GFX.SubZBuffer_buffer = NULL; -} - -void S9xInitDisplay(void) -{ - int32_t h = IMAGE_HEIGHT; - int32_t safety = 32; - - GFX.Pitch = IMAGE_WIDTH * 2; -#ifdef DS2_DMA - GFX.Screen_buffer = (uint8_t *) AlignedMalloc(GFX.Pitch * h + safety, 32, &PtrAdj.GFXScreen); -#elif defined(_3DS) - safety = 0x80; - GFX.Screen_buffer = (uint8_t *) linearMemAlign(GFX.Pitch * h + safety, 0x80); -#else - GFX.Screen_buffer = (uint8_t *) malloc(GFX.Pitch * h + safety); -#endif - GFX.SubScreen_buffer = (uint8_t *) malloc(GFX.Pitch * h + safety); - GFX.ZBuffer_buffer = (uint8_t *) malloc((GFX.Pitch >> 1) * h + safety); - GFX.SubZBuffer_buffer = (uint8_t *) malloc((GFX.Pitch >> 1) * h + safety); - - GFX.Screen = GFX.Screen_buffer + safety; - GFX.SubScreen = GFX.SubScreen_buffer + safety; - GFX.ZBuffer = GFX.ZBuffer_buffer + safety; - GFX.SubZBuffer = GFX.SubZBuffer_buffer + safety; - - GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1; -} - -#ifndef _WIN32 -void _makepath(char* path, const char* drive, const char* dir, const char* fname, const char* ext) -{ - (void) drive; - - if (dir && *dir) - { - strcpy(path, dir); - strcat(path, "/"); - } - else - *path = 0; - - if (fname) - strcat(path, fname); - - if (ext && *ext) - { - strcat(path, "."); - strcat(path, ext); - } -} - -void _splitpath (const char* path, char* drive, char* dir, char* fname, char* ext) -{ - const char* slash = strrchr(path, '/'); - const char* dot = strrchr(path, '.'); - (void) drive; - - if (!slash) - slash = strrchr((char*)path, '\\'); - - if (dot && slash && dot < slash) - dot = NULL; - - if (!slash) - { - *dir = 0; - strcpy(fname, path); - if (dot) - { - fname[dot - path] = 0; - strcpy(ext, dot + 1); - } - else - *ext = 0; - } - else - { - strcpy(dir, path); - dir[slash - path] = 0; - strcpy(fname, slash + 1); - if (dot) - { - fname[dot - slash - 1] = 0; - strcpy(ext, dot + 1); - } - else - *ext = 0; - } -} -#endif - -const char* S9xGetFilename(const char* in) -{ - static char filename [PATH_MAX + 1]; - char drive [_MAX_DRIVE + 1]; - char dir [_MAX_DIR + 1]; - char fname [_MAX_FNAME + 1]; - char ext [_MAX_EXT + 1]; - _splitpath(Memory.ROMFilename, drive, dir, fname, ext); - _makepath(filename, drive, dir, fname, in); - return filename; -} - -void init_sfc_setting(void) -{ - memset(&Settings, 0, sizeof(Settings)); - Settings.JoystickEnabled = false; - Settings.SoundPlaybackRate = samplerate; - Settings.CyclesPercentage = 100; - - Settings.DisableSoundEcho = false; - Settings.InterpolatedSound = true; - Settings.APUEnabled = true; - - Settings.H_Max = SNES_CYCLES_PER_SCANLINE; - Settings.FrameTimePAL = 20000; - Settings.FrameTimeNTSC = 16667; - Settings.DisableMasterVolume = false; - Settings.Mouse = true; - Settings.SuperScope = true; - Settings.MultiPlayer5 = true; - Settings.ControllerOption = SNES_JOYPAD; -#ifdef USE_BLARGG_APU - Settings.SoundSync = false; -#endif - Settings.ApplyCheats = true; - Settings.HBlankStart = (256 * Settings.H_Max) / SNES_HCOUNTER_MAX; -} - -#ifdef USE_BLARGG_APU -static void S9xAudioCallback() -{ - size_t avail; - /* Just pick a big buffer. We won't use it all. */ - static int16_t audio_buf[0x20000]; - - S9xFinalizeSamples(); - avail = S9xGetSampleCount(); - S9xMixSamples(audio_buf, avail); - audio_batch_cb(audio_buf, avail >> 1); -} -#endif - -void retro_init(void) -{ - struct retro_log_callback log; - enum retro_pixel_format rgb565; - bool achievements = true; - - static const struct retro_variable vars[] = - { - { "catsfc_VideoMode", "Video Mode; auto|NTSC|PAL" }, - { "catsfc_overclock_cycles", "Reduce Slowdown (Hack, Unsafe, Restart); disabled|compatible|max" }, - { "catsfc_reduce_sprite_flicker", "Reduce Flickering (Hack, Unsafe); disabled|enabled" }, - { NULL, NULL }, - }; - - if (environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log)) - log_cb = log.log; - else - log_cb = NULL; - - /* State that the core supports achievements. */ - environ_cb(RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS, &achievements); - - rgb565 = RETRO_PIXEL_FORMAT_RGB565; - if (environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb565) && log_cb) - log_cb(RETRO_LOG_INFO, "Frontend supports RGB565 - will use that instead of XRGB1555.\n"); - - init_sfc_setting(); - S9xInitMemory(); - S9xInitAPU(); - S9xInitDisplay(); - S9xInitGFX(); -#ifdef USE_BLARGG_APU - S9xInitSound(1000, 0); /* just give it a 1 second buffer */ - S9xSetSamplesAvailableCallback(S9xAudioCallback); -#else - S9xInitSound(); -#endif - environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)vars); - CPU.SaveStateVersion = 0; -} - -void retro_deinit(void) -{ - if (Settings.SPC7110) - Del7110Gfx(); - - S9xDeinitGFX(); - S9xDeinitDisplay(); - S9xDeinitAPU(); - S9xDeinitMemory(); - -#ifdef PERF_TEST - perf_cb.perf_log(); -#endif -} - -uint32_t S9xReadJoypad(int32_t port) -{ - static const uint32_t snes_lut[] = - { - SNES_B_MASK, - SNES_Y_MASK, - SNES_SELECT_MASK, - SNES_START_MASK, - SNES_UP_MASK, - SNES_DOWN_MASK, - SNES_LEFT_MASK, - SNES_RIGHT_MASK, - SNES_A_MASK, - SNES_X_MASK, - SNES_TL_MASK, - SNES_TR_MASK - }; - - int32_t i; - uint32_t joypad = 0; - - for (i = RETRO_DEVICE_ID_JOYPAD_B; i <= RETRO_DEVICE_ID_JOYPAD_R; i++) - if (input_cb(port, RETRO_DEVICE_JOYPAD, 0, i)) - joypad |= snes_lut[i]; - - return joypad; -} - -static void check_variables(void) -{ - struct retro_variable var; - - var.key = "catsfc_VideoMode"; - var.value = NULL; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - Settings.ForceNTSC = !strcmp(var.value, "NTSC"); - Settings.ForcePAL = !strcmp(var.value, "PAL"); - } - - var.key = "catsfc_overclock_cycles"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "compatible") == 0) - { - overclock_cycles = true; - one_c = 4; - slow_one_c = 5; - two_c = 6; - } - else if (strcmp(var.value, "max") == 0) - { - overclock_cycles = true; - one_c = 3; - slow_one_c = 3; - two_c = 3; - } - else - overclock_cycles = false; - } - - var.key = "catsfc_reduce_sprite_flicker"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "enabled") == 0) - reduce_sprite_flicker = true; - else - reduce_sprite_flicker = false; - } -} - -#ifdef PSP -#define FRAMESKIP -#endif - -static int32_t samples_to_play = 0; -void retro_run(void) -{ - bool updated = false; - int result; - bool okay; -#ifndef USE_BLARGG_APU - static int16_t audio_buf[2048]; -#endif - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) - check_variables(); - -#ifdef NO_VIDEO_OUTPUT - video_cb(NULL, IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, GFX.Pitch); - IPPU.RenderThisFrame = false; -#endif - - result = -1; - okay = environ_cb(RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE, &result); - if (okay) - { - bool audioEnabled = 0 != (result & 2); - bool videoEnabled = 0 != (result & 1); - bool hardDisableAudio = 0 != (result & 8); - IPPU.RenderThisFrame = videoEnabled; -#ifdef USE_BLARGG_APU - S9xSetSoundMute(!audioEnabled || hardDisableAudio); -#endif - Settings.HardDisableAudio = hardDisableAudio; - } - else - { - IPPU.RenderThisFrame = true; -#ifdef USE_BLARGG_APU - S9xSetSoundMute(false); -#endif - Settings.HardDisableAudio = false; - } - - poll_cb(); - - RETRO_PERFORMANCE_INIT(S9xMainLoop_func); - RETRO_PERFORMANCE_START(S9xMainLoop_func); - S9xMainLoop(); - RETRO_PERFORMANCE_STOP(S9xMainLoop_func); - -#ifndef USE_BLARGG_APU - samples_to_play += samples_per_frame; - - if (samples_to_play > 512) - { - S9xMixSamples(audio_buf, samples_to_play * 2); - audio_batch_cb(audio_buf, samples_to_play); - samples_to_play = 0; - } -#else - S9xAudioCallback(); -#endif - -#ifdef NO_VIDEO_OUTPUT - return; -#endif - -#ifdef FRAMESKIP - if (IPPU.RenderThisFrame) - { -#endif - -#ifdef PSP - static unsigned int __attribute__((aligned(16))) d_list[32]; - void* const texture_vram_p = (void*)(0x44200000 - (512 * 512)); /* max VRAM address - frame size */ - sceKernelDcacheWritebackRange(GFX.Screen, GFX.Pitch * IPPU.RenderedScreenHeight); - sceGuStart(GU_DIRECT, d_list); - sceGuCopyImage(GU_PSM_4444, 0, 0, IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, GFX.Pitch >> 1, GFX.Screen, 0, 0, 512, texture_vram_p); - sceGuTexSync(); - sceGuTexImage(0, 512, 512, 512, texture_vram_p); - sceGuTexMode(GU_PSM_5551, 0, 0, GU_FALSE); - sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGB); - sceGuDisable(GU_BLEND); - sceGuFinish(); - video_cb(texture_vram_p, IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, GFX.Pitch); -#else - video_cb(GFX.Screen, IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, GFX.Pitch); -#endif - -#ifdef FRAMESKIP - IPPU.RenderThisFrame = false; - } - else - { - video_cb(NULL, IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, GFX.Pitch); - IPPU.RenderThisFrame = true; - } -#endif -} - -bool S9xReadMousePosition(int32_t which1, int32_t* x, int32_t* y, uint32_t* buttons) -{ - (void) which1; - (void) x; - (void) y; - (void) buttons; - return false; -} - -bool S9xReadSuperScopePosition(int32_t* x, int32_t* y, uint32_t* buttons) -{ - (void) x; - (void) y; - (void) buttons; - return true; -} - -bool JustifierOffscreen(void) -{ - return false; -} - -void JustifierButtons(uint32_t* justifiers) -{ - (void) justifiers; -} - -unsigned retro_get_region(void) -{ - return Settings.PAL ? RETRO_REGION_PAL : RETRO_REGION_NTSC; -} - -void retro_get_system_info(struct retro_system_info* info) -{ -#ifdef LOAD_FROM_MEMORY_TEST - info->need_fullpath = false; -#else - info->need_fullpath = true; -#endif - info->valid_extensions = "smc|fig|sfc|gd3|gd7|dx2|bsx|swc"; -#ifndef GIT_VERSION -#define GIT_VERSION "" -#endif - info->library_version = "v1.36" GIT_VERSION; -#ifdef USE_BLARGG_APU - info->library_name = "Snes9x 2005 Plus"; -#else - info->library_name = "Snes9x 2005"; -#endif - info->block_extract = false; -} - -void retro_get_system_av_info(struct retro_system_av_info* info) -{ - info->geometry.base_width = 256; - info->geometry.base_height = 224; - info->geometry.max_width = 512; - info->geometry.max_height = 512; - info->geometry.aspect_ratio = 4.0 / 3.0; - - if (!Settings.PAL) - info->timing.fps = (SNES_CLOCK_SPEED * 6.0 / (SNES_CYCLES_PER_SCANLINE * SNES_MAX_NTSC_VCOUNTER)); - else - info->timing.fps = (SNES_CLOCK_SPEED * 6.0 / (SNES_CYCLES_PER_SCANLINE * SNES_MAX_PAL_VCOUNTER)); - - info->timing.sample_rate = samplerate; -} - -void retro_reset(void) -{ - CPU.Flags = 0; - S9xReset(); -} - -size_t retro_serialize_size(void) -{ - return sizeof(CPU) + sizeof(ICPU) + sizeof(PPU) + sizeof(DMA) + - 0x10000 + 0x20000 + 0x20000 + 0x8000 + -#ifndef USE_BLARGG_APU - sizeof(APU) + sizeof(IAPU) + 0x10000 + -#else - SPC_SAVE_STATE_BLOCK_SIZE + -#endif - sizeof(SA1) + sizeof(s7r) + sizeof(rtc_f9); -} - -bool retro_serialize(void* data, size_t size) -{ - int32_t i; - uint8_t* buffer = data; - (void) size; -#ifdef LAGFIX - S9xPackStatus(); -#ifndef USE_BLARGG_APU - S9xAPUPackStatus(); -#endif -#endif - S9xUpdateRTC(); - S9xSRTCPreSaveState(); - memcpy(buffer, &CPU, sizeof(CPU)); - buffer += sizeof(CPU); - memcpy(buffer, &ICPU, sizeof(ICPU)); - buffer += sizeof(ICPU); - memcpy(buffer, &PPU, sizeof(PPU)); - buffer += sizeof(PPU); - memcpy(buffer, &DMA, sizeof(DMA)); - buffer += sizeof(DMA); - memcpy(buffer, Memory.VRAM, 0x10000); - buffer += 0x10000; - memcpy(buffer, Memory.RAM, 0x20000); - buffer += 0x20000; - memcpy(buffer, Memory.SRAM, 0x20000); - buffer += 0x20000; - memcpy(buffer, Memory.FillRAM, 0x8000); - buffer += 0x8000; -#ifndef USE_BLARGG_APU - memcpy(buffer, &APU, sizeof(APU)); - buffer += sizeof(APU); - memcpy(buffer, &IAPU, sizeof(IAPU)); - buffer += sizeof(IAPU); - memcpy(buffer, IAPU.RAM, 0x10000); - buffer += 0x10000; -#else - S9xAPUSaveState(buffer); - buffer += SPC_SAVE_STATE_BLOCK_SIZE; -#endif - - SA1.Registers.PC = SA1.PC - SA1.PCBase; - S9xSA1PackStatus(); - - memcpy(buffer, &SA1, sizeof(SA1)); - buffer += sizeof(SA1); - memcpy(buffer, &s7r, sizeof(s7r)); - buffer += sizeof(s7r); - memcpy(buffer, &rtc_f9, sizeof(rtc_f9)); - - return true; -} - -bool retro_unserialize(const void* data, size_t size) -{ - const uint8_t* buffer = data; -#ifndef USE_BLARGG_APU - uint8_t* IAPU_RAM_current = IAPU.RAM; - uintptr_t IAPU_RAM_offset; -#endif - - if (size != retro_serialize_size()) - return false; - - S9xReset(); - memcpy(&CPU, buffer, sizeof(CPU)); - buffer += sizeof(CPU); - memcpy(&ICPU, buffer, sizeof(ICPU)); - buffer += sizeof(ICPU); - memcpy(&PPU, buffer, sizeof(PPU)); - buffer += sizeof(PPU); - memcpy(&DMA, buffer, sizeof(DMA)); - buffer += sizeof(DMA); - memcpy(Memory.VRAM, buffer, 0x10000); - buffer += 0x10000; - memcpy(Memory.RAM, buffer, 0x20000); - buffer += 0x20000; - memcpy(Memory.SRAM, buffer, 0x20000); - buffer += 0x20000; - memcpy(Memory.FillRAM, buffer, 0x8000); - buffer += 0x8000; -#ifndef USE_BLARGG_APU - memcpy(&APU, buffer, sizeof(APU)); - buffer += sizeof(APU); - memcpy(&IAPU, buffer, sizeof(IAPU)); - buffer += sizeof(IAPU); - IAPU_RAM_offset = IAPU_RAM_current - IAPU.RAM; - IAPU.PC += IAPU_RAM_offset; - IAPU.DirectPage += IAPU_RAM_offset; - IAPU.WaitAddress1 += IAPU_RAM_offset; - IAPU.WaitAddress2 += IAPU_RAM_offset; - IAPU.RAM = IAPU_RAM_current; - memcpy(IAPU.RAM, buffer, 0x10000); - buffer += 0x10000; -#else - S9xAPULoadState(buffer); - buffer += SPC_SAVE_STATE_BLOCK_SIZE; -#endif - - memcpy(&SA1, buffer, sizeof(SA1)); - buffer += sizeof(SA1); - memcpy(&s7r, buffer, sizeof(s7r)); - buffer += sizeof(s7r); - memcpy(&rtc_f9, buffer, sizeof(rtc_f9)); - - S9xFixSA1AfterSnapshotLoad(); - FixROMSpeed(); - IPPU.ColorsChanged = true; - IPPU.OBJChanged = true; - CPU.InDMA = false; - S9xFixColourBrightness(); - S9xSA1UnpackStatus(); -#ifndef USE_BLARGG_APU - S9xAPUUnpackStatus(); - S9xFixSoundAfterSnapshotLoad(); -#endif - ICPU.ShiftedPB = ICPU.Registers.PB << 16; - ICPU.ShiftedDB = ICPU.Registers.DB << 16; - S9xSetPCBase(ICPU.ShiftedPB + ICPU.Registers.PC); - S9xUnpackStatus(); - S9xFixCycles(); - S9xReschedule(); - return true; -} - -void retro_cheat_reset(void) -{ - S9xDeleteCheats(); - S9xApplyCheats(); -} - -extern SCheatData Cheat; - -void retro_cheat_set(unsigned index, bool enabled, const char* code) -{ - uint32_t address; - uint8_t val; - - bool sram; - uint8_t bytes[3];/* used only by GoldFinger, ignored for now */ - - if (S9xGameGenieToRaw(code, &address, &val) && S9xProActionReplayToRaw(code, &address, &val) && S9xGoldFingerToRaw(code, &address, &sram, &val, bytes)) - return; /* bad code, ignore */ - if (index > Cheat.num_cheats) - return; /* cheat added in weird order, ignore */ - if (index == Cheat.num_cheats) - Cheat.num_cheats++; - - Cheat.c[index].address = address; - Cheat.c[index].byte = val; - Cheat.c[index].enabled = enabled; - Cheat.c[index].saved = false; /* it'll be saved next time cheats run anyways */ - - Settings.ApplyCheats = true; - S9xApplyCheats(); -} - -static void init_descriptors(void) -{ - struct retro_input_descriptor desc[] = - { - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "A" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "X" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Y" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, - - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "A" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "X" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Y" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, - - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" }, - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "A" }, - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "X" }, - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Y" }, - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L" }, - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R" }, - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, - - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" }, - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "A" }, - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "X" }, - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Y" }, - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L" }, - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R" }, - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, - - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" }, - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "A" }, - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "X" }, - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Y" }, - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L" }, - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R" }, - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, - - { 0 }, - }; - - environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc); -} - -bool retro_load_game(const struct retro_game_info* game) -{ - struct retro_system_av_info av_info; - if (!game) - return false; - - CPU.Flags = 0; - init_descriptors(); - check_variables(); - -#ifdef LOAD_FROM_MEMORY_TEST - if (!LoadROM(game)) -#else - if (!LoadROM(game->path)) -#endif - return false; - - Settings.FrameTime = (Settings.PAL ? Settings.FrameTimePAL : Settings.FrameTimeNTSC); - - retro_get_system_av_info(&av_info); - -#ifdef USE_BLARGG_APU - Settings.SoundPlaybackRate = av_info.timing.sample_rate; -#else - samples_per_frame = av_info.timing.sample_rate / av_info.timing.fps; - S9xSetPlaybackRate(Settings.SoundPlaybackRate); -#endif - return true; -} - -bool retro_load_game_special(unsigned game_type, const struct retro_game_info* info, size_t num_info) -{ - (void) game_type; - (void) info; - (void) num_info; - return false; -} - -void retro_unload_game(void) -{ -} - -void* retro_get_memory_data(unsigned type) -{ - uint8_t* data; - - switch(type) - { - case RETRO_MEMORY_SAVE_RAM: - data = Memory.SRAM; - break; - case RETRO_MEMORY_SYSTEM_RAM: - data = Memory.RAM; - break; - case RETRO_MEMORY_VIDEO_RAM: - data = Memory.VRAM; - break; - default: - data = NULL; - break; - } - - return data; -} - -size_t retro_get_memory_size(unsigned type) -{ - uint32_t size; - - switch(type) - { - case RETRO_MEMORY_SAVE_RAM: - size = (uint32_t) (Memory.SRAMSize ? (1 << (Memory.SRAMSize + 3)) * 128 : 0); - if (size > 0x20000) - size = 0x20000; - break; - case RETRO_MEMORY_RTC: - size = (Settings.SRTC || Settings.SPC7110RTC) ? 20 : 0; - break; - case RETRO_MEMORY_SYSTEM_RAM: - size = 128 * 1024; - break; - case RETRO_MEMORY_VIDEO_RAM: - size = 64 * 1024; - break; - default: - size = 0; - break; - } - - return size; -} diff --git a/libretro.h b/libretro.h deleted file mode 100644 index ed1902b..0000000 --- a/libretro.h +++ /dev/null @@ -1,2149 +0,0 @@ -#include "copyright" - -#ifndef LIBRETRO_H__ -#define LIBRETRO_H__ - -#include <stdint.h> -#include <stddef.h> -#include <limits.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef __cplusplus -#if defined(_MSC_VER) && !defined(SN_TARGET_PS3) -/* Hack applied for MSVC when compiling in C89 mode - * as it isn't C99-compliant. */ -#define bool unsigned char -#define true 1 -#define false 0 -#else -#include <stdbool.h> -#endif -#endif - -#ifndef RETRO_CALLCONV -# if defined(__GNUC__) && defined(__i386__) && !defined(__x86_64__) -# define RETRO_CALLCONV __attribute__((cdecl)) -# elif defined(_MSC_VER) && defined(_M_X86) && !defined(_M_X64) -# define RETRO_CALLCONV __cdecl -# else -# define RETRO_CALLCONV /* all other platforms only have one calling convention each */ -# endif -#endif - -#ifndef RETRO_API -# if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) -# ifdef RETRO_IMPORT_SYMBOLS -# ifdef __GNUC__ -# define RETRO_API RETRO_CALLCONV __attribute__((__dllimport__)) -# else -# define RETRO_API RETRO_CALLCONV __declspec(dllimport) -# endif -# else -# ifdef __GNUC__ -# define RETRO_API RETRO_CALLCONV __attribute__((__dllexport__)) -# else -# define RETRO_API RETRO_CALLCONV __declspec(dllexport) -# endif -# endif -# else -# if defined(__GNUC__) && __GNUC__ >= 4 && !defined(__CELLOS_LV2__) -# define RETRO_API RETRO_CALLCONV __attribute__((__visibility__("default"))) -# else -# define RETRO_API RETRO_CALLCONV -# endif -# endif -#endif - -/* Used for checking API/ABI mismatches that can break libretro - * implementations. - * It is not incremented for compatible changes to the API. - */ -#define RETRO_API_VERSION 1 - -/* - * Libretro's fundamental device abstractions. - * - * Libretro's input system consists of some standardized device types, - * such as a joypad (with/without analog), mouse, keyboard, lightgun - * and a pointer. - * - * The functionality of these devices are fixed, and individual cores - * map their own concept of a controller to libretro's abstractions. - * This makes it possible for frontends to map the abstract types to a - * real input device, and not having to worry about binding input - * correctly to arbitrary controller layouts. - */ - -#define RETRO_DEVICE_TYPE_SHIFT 8 -#define RETRO_DEVICE_MASK ((1 << RETRO_DEVICE_TYPE_SHIFT) - 1) -#define RETRO_DEVICE_SUBCLASS(base, id) (((id + 1) << RETRO_DEVICE_TYPE_SHIFT) | base) - -/* Input disabled. */ -#define RETRO_DEVICE_NONE 0 - -/* The JOYPAD is called RetroPad. It is essentially a Super Nintendo - * controller, but with additional L2/R2/L3/R3 buttons, similar to a - * PS1 DualShock. */ -#define RETRO_DEVICE_JOYPAD 1 - -/* The mouse is a simple mouse, similar to Super Nintendo's mouse. - * X and Y coordinates are reported relatively to last poll (poll callback). - * It is up to the libretro implementation to keep track of where the mouse - * pointer is supposed to be on the screen. - * The frontend must make sure not to interfere with its own hardware - * mouse pointer. - */ -#define RETRO_DEVICE_MOUSE 2 - -/* KEYBOARD device lets one poll for raw key pressed. - * It is poll based, so input callback will return with the current - * pressed state. - * For event/text based keyboard input, see - * RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. - */ -#define RETRO_DEVICE_KEYBOARD 3 - -/* Lightgun X/Y coordinates are reported relatively to last poll, - * similar to mouse. */ -#define RETRO_DEVICE_LIGHTGUN 4 - -/* The ANALOG device is an extension to JOYPAD (RetroPad). - * Similar to DualShock it adds two analog sticks. - * This is treated as a separate device type as it returns values in the - * full analog range of [-0x8000, 0x7fff]. Positive X axis is right. - * Positive Y axis is down. - * Only use ANALOG type when polling for analog values of the axes. - */ -#define RETRO_DEVICE_ANALOG 5 - -/* Abstracts the concept of a pointing mechanism, e.g. touch. - * This allows libretro to query in absolute coordinates where on the - * screen a mouse (or something similar) is being placed. - * For a touch centric device, coordinates reported are the coordinates - * of the press. - * - * Coordinates in X and Y are reported as: - * [-0x7fff, 0x7fff]: -0x7fff corresponds to the far left/top of the screen, - * and 0x7fff corresponds to the far right/bottom of the screen. - * The "screen" is here defined as area that is passed to the frontend and - * later displayed on the monitor. - * - * The frontend is free to scale/resize this screen as it sees fit, however, - * (X, Y) = (-0x7fff, -0x7fff) will correspond to the top-left pixel of the - * game image, etc. - * - * To check if the pointer coordinates are valid (e.g. a touch display - * actually being touched), PRESSED returns 1 or 0. - * - * If using a mouse on a desktop, PRESSED will usually correspond to the - * left mouse button, but this is a frontend decision. - * PRESSED will only return 1 if the pointer is inside the game screen. - * - * For multi-touch, the index variable can be used to successively query - * more presses. - * If index = 0 returns true for _PRESSED, coordinates can be extracted - * with _X, _Y for index = 0. One can then query _PRESSED, _X, _Y with - * index = 1, and so on. - * Eventually _PRESSED will return false for an index. No further presses - * are registered at this point. */ -#define RETRO_DEVICE_POINTER 6 - -/* Buttons for the RetroPad (JOYPAD). - * The placement of these is equivalent to placements on the - * Super Nintendo controller. - * L2/R2/L3/R3 buttons correspond to the PS1 DualShock. */ -#define RETRO_DEVICE_ID_JOYPAD_B 0 -#define RETRO_DEVICE_ID_JOYPAD_Y 1 -#define RETRO_DEVICE_ID_JOYPAD_SELECT 2 -#define RETRO_DEVICE_ID_JOYPAD_START 3 -#define RETRO_DEVICE_ID_JOYPAD_UP 4 -#define RETRO_DEVICE_ID_JOYPAD_DOWN 5 -#define RETRO_DEVICE_ID_JOYPAD_LEFT 6 -#define RETRO_DEVICE_ID_JOYPAD_RIGHT 7 -#define RETRO_DEVICE_ID_JOYPAD_A 8 -#define RETRO_DEVICE_ID_JOYPAD_X 9 -#define RETRO_DEVICE_ID_JOYPAD_L 10 -#define RETRO_DEVICE_ID_JOYPAD_R 11 -#define RETRO_DEVICE_ID_JOYPAD_L2 12 -#define RETRO_DEVICE_ID_JOYPAD_R2 13 -#define RETRO_DEVICE_ID_JOYPAD_L3 14 -#define RETRO_DEVICE_ID_JOYPAD_R3 15 - -/* Index / Id values for ANALOG device. */ -#define RETRO_DEVICE_INDEX_ANALOG_LEFT 0 -#define RETRO_DEVICE_INDEX_ANALOG_RIGHT 1 -#define RETRO_DEVICE_ID_ANALOG_X 0 -#define RETRO_DEVICE_ID_ANALOG_Y 1 - -/* Id values for MOUSE. */ -#define RETRO_DEVICE_ID_MOUSE_X 0 -#define RETRO_DEVICE_ID_MOUSE_Y 1 -#define RETRO_DEVICE_ID_MOUSE_LEFT 2 -#define RETRO_DEVICE_ID_MOUSE_RIGHT 3 -#define RETRO_DEVICE_ID_MOUSE_WHEELUP 4 -#define RETRO_DEVICE_ID_MOUSE_WHEELDOWN 5 -#define RETRO_DEVICE_ID_MOUSE_MIDDLE 6 -#define RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP 7 -#define RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN 8 - -/* Id values for LIGHTGUN types. */ -#define RETRO_DEVICE_ID_LIGHTGUN_X 0 -#define RETRO_DEVICE_ID_LIGHTGUN_Y 1 -#define RETRO_DEVICE_ID_LIGHTGUN_TRIGGER 2 -#define RETRO_DEVICE_ID_LIGHTGUN_CURSOR 3 -#define RETRO_DEVICE_ID_LIGHTGUN_TURBO 4 -#define RETRO_DEVICE_ID_LIGHTGUN_PAUSE 5 -#define RETRO_DEVICE_ID_LIGHTGUN_START 6 - -/* Id values for POINTER. */ -#define RETRO_DEVICE_ID_POINTER_X 0 -#define RETRO_DEVICE_ID_POINTER_Y 1 -#define RETRO_DEVICE_ID_POINTER_PRESSED 2 - -/* Returned from retro_get_region(). */ -#define RETRO_REGION_NTSC 0 -#define RETRO_REGION_PAL 1 - -/* Id values for LANGUAGE */ -enum retro_language -{ - RETRO_LANGUAGE_ENGLISH = 0, - RETRO_LANGUAGE_JAPANESE = 1, - RETRO_LANGUAGE_FRENCH = 2, - RETRO_LANGUAGE_SPANISH = 3, - RETRO_LANGUAGE_GERMAN = 4, - RETRO_LANGUAGE_ITALIAN = 5, - RETRO_LANGUAGE_DUTCH = 6, - RETRO_LANGUAGE_PORTUGUESE = 7, - RETRO_LANGUAGE_RUSSIAN = 8, - RETRO_LANGUAGE_KOREAN = 9, - RETRO_LANGUAGE_CHINESE_TRADITIONAL = 10, - RETRO_LANGUAGE_CHINESE_SIMPLIFIED = 11, - RETRO_LANGUAGE_ESPERANTO = 12, - RETRO_LANGUAGE_POLISH = 13, - RETRO_LANGUAGE_LAST, - - /* Ensure sizeof(enum) == sizeof(int) */ - RETRO_LANGUAGE_DUMMY = INT_MAX -}; - -/* Passed to retro_get_memory_data/size(). - * If the memory type doesn't apply to the - * implementation NULL/0 can be returned. - */ -#define RETRO_MEMORY_MASK 0xff - -/* Regular save RAM. This RAM is usually found on a game cartridge, - * backed up by a battery. - * If save game data is too complex for a single memory buffer, - * the SAVE_DIRECTORY (preferably) or SYSTEM_DIRECTORY environment - * callback can be used. */ -#define RETRO_MEMORY_SAVE_RAM 0 - -/* Some games have a built-in clock to keep track of time. - * This memory is usually just a couple of bytes to keep track of time. - */ -#define RETRO_MEMORY_RTC 1 - -/* System ram lets a frontend peek into a game systems main RAM. */ -#define RETRO_MEMORY_SYSTEM_RAM 2 - -/* Video ram lets a frontend peek into a game systems video RAM (VRAM). */ -#define RETRO_MEMORY_VIDEO_RAM 3 - -/* Keysyms used for ID in input state callback when polling RETRO_KEYBOARD. */ -enum retro_key -{ - RETROK_UNKNOWN = 0, - RETROK_FIRST = 0, - RETROK_BACKSPACE = 8, - RETROK_TAB = 9, - RETROK_CLEAR = 12, - RETROK_RETURN = 13, - RETROK_PAUSE = 19, - RETROK_ESCAPE = 27, - RETROK_SPACE = 32, - RETROK_EXCLAIM = 33, - RETROK_QUOTEDBL = 34, - RETROK_HASH = 35, - RETROK_DOLLAR = 36, - RETROK_AMPERSAND = 38, - RETROK_QUOTE = 39, - RETROK_LEFTPAREN = 40, - RETROK_RIGHTPAREN = 41, - RETROK_ASTERISK = 42, - RETROK_PLUS = 43, - RETROK_COMMA = 44, - RETROK_MINUS = 45, - RETROK_PERIOD = 46, - RETROK_SLASH = 47, - RETROK_0 = 48, - RETROK_1 = 49, - RETROK_2 = 50, - RETROK_3 = 51, - RETROK_4 = 52, - RETROK_5 = 53, - RETROK_6 = 54, - RETROK_7 = 55, - RETROK_8 = 56, - RETROK_9 = 57, - RETROK_COLON = 58, - RETROK_SEMICOLON = 59, - RETROK_LESS = 60, - RETROK_EQUALS = 61, - RETROK_GREATER = 62, - RETROK_QUESTION = 63, - RETROK_AT = 64, - RETROK_LEFTBRACKET = 91, - RETROK_BACKSLASH = 92, - RETROK_RIGHTBRACKET = 93, - RETROK_CARET = 94, - RETROK_UNDERSCORE = 95, - RETROK_BACKQUOTE = 96, - RETROK_a = 97, - RETROK_b = 98, - RETROK_c = 99, - RETROK_d = 100, - RETROK_e = 101, - RETROK_f = 102, - RETROK_g = 103, - RETROK_h = 104, - RETROK_i = 105, - RETROK_j = 106, - RETROK_k = 107, - RETROK_l = 108, - RETROK_m = 109, - RETROK_n = 110, - RETROK_o = 111, - RETROK_p = 112, - RETROK_q = 113, - RETROK_r = 114, - RETROK_s = 115, - RETROK_t = 116, - RETROK_u = 117, - RETROK_v = 118, - RETROK_w = 119, - RETROK_x = 120, - RETROK_y = 121, - RETROK_z = 122, - RETROK_DELETE = 127, - - RETROK_KP0 = 256, - RETROK_KP1 = 257, - RETROK_KP2 = 258, - RETROK_KP3 = 259, - RETROK_KP4 = 260, - RETROK_KP5 = 261, - RETROK_KP6 = 262, - RETROK_KP7 = 263, - RETROK_KP8 = 264, - RETROK_KP9 = 265, - RETROK_KP_PERIOD = 266, - RETROK_KP_DIVIDE = 267, - RETROK_KP_MULTIPLY = 268, - RETROK_KP_MINUS = 269, - RETROK_KP_PLUS = 270, - RETROK_KP_ENTER = 271, - RETROK_KP_EQUALS = 272, - - RETROK_UP = 273, - RETROK_DOWN = 274, - RETROK_RIGHT = 275, - RETROK_LEFT = 276, - RETROK_INSERT = 277, - RETROK_HOME = 278, - RETROK_END = 279, - RETROK_PAGEUP = 280, - RETROK_PAGEDOWN = 281, - - RETROK_F1 = 282, - RETROK_F2 = 283, - RETROK_F3 = 284, - RETROK_F4 = 285, - RETROK_F5 = 286, - RETROK_F6 = 287, - RETROK_F7 = 288, - RETROK_F8 = 289, - RETROK_F9 = 290, - RETROK_F10 = 291, - RETROK_F11 = 292, - RETROK_F12 = 293, - RETROK_F13 = 294, - RETROK_F14 = 295, - RETROK_F15 = 296, - - RETROK_NUMLOCK = 300, - RETROK_CAPSLOCK = 301, - RETROK_SCROLLOCK = 302, - RETROK_RSHIFT = 303, - RETROK_LSHIFT = 304, - RETROK_RCTRL = 305, - RETROK_LCTRL = 306, - RETROK_RALT = 307, - RETROK_LALT = 308, - RETROK_RMETA = 309, - RETROK_LMETA = 310, - RETROK_LSUPER = 311, - RETROK_RSUPER = 312, - RETROK_MODE = 313, - RETROK_COMPOSE = 314, - - RETROK_HELP = 315, - RETROK_PRINT = 316, - RETROK_SYSREQ = 317, - RETROK_BREAK = 318, - RETROK_MENU = 319, - RETROK_POWER = 320, - RETROK_EURO = 321, - RETROK_UNDO = 322, - - RETROK_LAST, - - RETROK_DUMMY = INT_MAX /* Ensure sizeof(enum) == sizeof(int) */ -}; - -enum retro_mod -{ - RETROKMOD_NONE = 0x0000, - - RETROKMOD_SHIFT = 0x01, - RETROKMOD_CTRL = 0x02, - RETROKMOD_ALT = 0x04, - RETROKMOD_META = 0x08, - - RETROKMOD_NUMLOCK = 0x10, - RETROKMOD_CAPSLOCK = 0x20, - RETROKMOD_SCROLLOCK = 0x40, - - RETROKMOD_DUMMY = INT_MAX /* Ensure sizeof(enum) == sizeof(int) */ -}; - -/* If set, this call is not part of the public libretro API yet. It can - * change or be removed at any time. */ -#define RETRO_ENVIRONMENT_EXPERIMENTAL 0x10000 -/* Environment callback to be used internally in frontend. */ -#define RETRO_ENVIRONMENT_PRIVATE 0x20000 - -/* Environment commands. */ -#define RETRO_ENVIRONMENT_SET_ROTATION 1 /* const unsigned * -- - * Sets screen rotation of graphics. - * Is only implemented if rotation can be accelerated by hardware. - * Valid values are 0, 1, 2, 3, which rotates screen by 0, 90, 180, - * 270 degrees counter-clockwise respectively. - */ -#define RETRO_ENVIRONMENT_GET_OVERSCAN 2 /* bool * -- - * Boolean value whether or not the implementation should use overscan, - * or crop away overscan. - */ -#define RETRO_ENVIRONMENT_GET_CAN_DUPE 3 /* bool * -- - * Boolean value whether or not frontend supports frame duping, - * passing NULL to video frame callback. - */ - - /* Environ 4, 5 are no longer supported (GET_VARIABLE / SET_VARIABLES), - * and reserved to avoid possible ABI clash. - */ - -#define RETRO_ENVIRONMENT_SET_MESSAGE 6 /* const struct retro_message * -- - * Sets a message to be displayed in implementation-specific manner - * for a certain amount of 'frames'. - * Should not be used for trivial messages, which should simply be - * logged via RETRO_ENVIRONMENT_GET_LOG_INTERFACE (or as a - * fallback, stderr). - */ -#define RETRO_ENVIRONMENT_SHUTDOWN 7 /* N/A (NULL) -- - * Requests the frontend to shutdown. - * Should only be used if game has a specific - * way to shutdown the game from a menu item or similar. - */ -#define RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL 8 - /* const unsigned * -- - * Gives a hint to the frontend how demanding this implementation - * is on a system. E.g. reporting a level of 2 means - * this implementation should run decently on all frontends - * of level 2 and up. - * - * It can be used by the frontend to potentially warn - * about too demanding implementations. - * - * The levels are "floating". - * - * This function can be called on a per-game basis, - * as certain games an implementation can play might be - * particularly demanding. - * If called, it should be called in retro_load_game(). - */ -#define RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY 9 - /* const char ** -- - * Returns the "system" directory of the frontend. - * This directory can be used to store system specific - * content such as BIOSes, configuration data, etc. - * The returned value can be NULL. - * If so, no such directory is defined, - * and it's up to the implementation to find a suitable directory. - * - * NOTE: Some cores used this folder also for "save" data such as - * memory cards, etc, for lack of a better place to put it. - * This is now discouraged, and if possible, cores should try to - * use the new GET_SAVE_DIRECTORY. - */ -#define RETRO_ENVIRONMENT_SET_PIXEL_FORMAT 10 - /* const enum retro_pixel_format * -- - * Sets the internal pixel format used by the implementation. - * The default pixel format is RETRO_PIXEL_FORMAT_0RGB1555. - * This pixel format however, is deprecated (see enum retro_pixel_format). - * If the call returns false, the frontend does not support this pixel - * format. - * - * This function should be called inside retro_load_game() or - * retro_get_system_av_info(). - */ -#define RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS 11 - /* const struct retro_input_descriptor * -- - * Sets an array of retro_input_descriptors. - * It is up to the frontend to present this in a usable way. - * The array is terminated by retro_input_descriptor::description - * being set to NULL. - * This function can be called at any time, but it is recommended - * to call it as early as possible. - */ -#define RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK 12 - /* const struct retro_keyboard_callback * -- - * Sets a callback function used to notify core about keyboard events. - */ -#define RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE 13 - /* const struct retro_disk_control_callback * -- - * Sets an interface which frontend can use to eject and insert - * disk images. - * This is used for games which consist of multiple images and - * must be manually swapped out by the user (e.g. PSX). - */ -#define RETRO_ENVIRONMENT_SET_HW_RENDER 14 - /* struct retro_hw_render_callback * -- - * Sets an interface to let a libretro core render with - * hardware acceleration. - * Should be called in retro_load_game(). - * If successful, libretro cores will be able to render to a - * frontend-provided framebuffer. - * The size of this framebuffer will be at least as large as - * max_width/max_height provided in get_av_info(). - * If HW rendering is used, pass only RETRO_HW_FRAME_BUFFER_VALID or - * NULL to retro_video_refresh_t. - */ -#define RETRO_ENVIRONMENT_GET_VARIABLE 15 - /* struct retro_variable * -- - * Interface to acquire user-defined information from environment - * that cannot feasibly be supported in a multi-system way. - * 'key' should be set to a key which has already been set by - * SET_VARIABLES. - * 'data' will be set to a value or NULL. - */ -#define RETRO_ENVIRONMENT_SET_VARIABLES 16 - /* const struct retro_variable * -- - * Allows an implementation to signal the environment - * which variables it might want to check for later using - * GET_VARIABLE. - * This allows the frontend to present these variables to - * a user dynamically. - * This should be called as early as possible (ideally in - * retro_set_environment). - * - * 'data' points to an array of retro_variable structs - * terminated by a { NULL, NULL } element. - * retro_variable::key should be namespaced to not collide - * with other implementations' keys. E.g. A core called - * 'foo' should use keys named as 'foo_option'. - * retro_variable::value should contain a human readable - * description of the key as well as a '|' delimited list - * of expected values. - * - * The number of possible options should be very limited, - * i.e. it should be feasible to cycle through options - * without a keyboard. - * - * First entry should be treated as a default. - * - * Example entry: - * { "foo_option", "Speed hack coprocessor X; false|true" } - * - * Text before first ';' is description. This ';' must be - * followed by a space, and followed by a list of possible - * values split up with '|'. - * - * Only strings are operated on. The possible values will - * generally be displayed and stored as-is by the frontend. - */ -#define RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE 17 - /* bool * -- - * Result is set to true if some variables are updated by - * frontend since last call to RETRO_ENVIRONMENT_GET_VARIABLE. - * Variables should be queried with GET_VARIABLE. - */ -#define RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME 18 - /* const bool * -- - * If true, the libretro implementation supports calls to - * retro_load_game() with NULL as argument. - * Used by cores which can run without particular game data. - * This should be called within retro_set_environment() only. - */ -#define RETRO_ENVIRONMENT_GET_LIBRETRO_PATH 19 - /* const char ** -- - * Retrieves the absolute path from where this libretro - * implementation was loaded. - * NULL is returned if the libretro was loaded statically - * (i.e. linked statically to frontend), or if the path cannot be - * determined. - * Mostly useful in cooperation with SET_SUPPORT_NO_GAME as assets can - * be loaded without ugly hacks. - */ - - /* Environment 20 was an obsolete version of SET_AUDIO_CALLBACK. - * It was not used by any known core at the time, - * and was removed from the API. */ -#define RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK 22 - /* const struct retro_audio_callback * -- - * Sets an interface which is used to notify a libretro core about audio - * being available for writing. - * The callback can be called from any thread, so a core using this must - * have a thread safe audio implementation. - * It is intended for games where audio and video are completely - * asynchronous and audio can be generated on the fly. - * This interface is not recommended for use with emulators which have - * highly synchronous audio. - * - * The callback only notifies about writability; the libretro core still - * has to call the normal audio callbacks - * to write audio. The audio callbacks must be called from within the - * notification callback. - * The amount of audio data to write is up to the implementation. - * Generally, the audio callback will be called continously in a loop. - * - * Due to thread safety guarantees and lack of sync between audio and - * video, a frontend can selectively disallow this interface based on - * internal configuration. A core using this interface must also - * implement the "normal" audio interface. - * - * A libretro core using SET_AUDIO_CALLBACK should also make use of - * SET_FRAME_TIME_CALLBACK. - */ -#define RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK 21 - /* const struct retro_frame_time_callback * -- - * Lets the core know how much time has passed since last - * invocation of retro_run(). - * The frontend can tamper with the timing to fake fast-forward, - * slow-motion, frame stepping, etc. - * In this case the delta time will use the reference value - * in frame_time_callback.. - */ -#define RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE 23 - /* struct retro_rumble_interface * -- - * Gets an interface which is used by a libretro core to set - * state of rumble motors in controllers. - * A strong and weak motor is supported, and they can be - * controlled indepedently. - */ -#define RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES 24 - /* uint64_t * -- - * Gets a bitmask telling which device type are expected to be - * handled properly in a call to retro_input_state_t. - * Devices which are not handled or recognized always return - * 0 in retro_input_state_t. - * Example bitmask: caps = (1 << RETRO_DEVICE_JOYPAD) | (1 << RETRO_DEVICE_ANALOG). - * Should only be called in retro_run(). - */ -#define RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE (25 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* struct retro_sensor_interface * -- - * Gets access to the sensor interface. - * The purpose of this interface is to allow - * setting state related to sensors such as polling rate, - * enabling/disable it entirely, etc. - * Reading sensor state is done via the normal - * input_state_callback API. - */ -#define RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE (26 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* struct retro_camera_callback * -- - * Gets an interface to a video camera driver. - * A libretro core can use this interface to get access to a - * video camera. - * New video frames are delivered in a callback in same - * thread as retro_run(). - * - * GET_CAMERA_INTERFACE should be called in retro_load_game(). - * - * Depending on the camera implementation used, camera frames - * will be delivered as a raw framebuffer, - * or as an OpenGL texture directly. - * - * The core has to tell the frontend here which types of - * buffers can be handled properly. - * An OpenGL texture can only be handled when using a - * libretro GL core (SET_HW_RENDER). - * It is recommended to use a libretro GL core when - * using camera interface. - * - * The camera is not started automatically. The retrieved start/stop - * functions must be used to explicitly - * start and stop the camera driver. - */ -#define RETRO_ENVIRONMENT_GET_LOG_INTERFACE 27 - /* struct retro_log_callback * -- - * Gets an interface for logging. This is useful for - * logging in a cross-platform way - * as certain platforms cannot use use stderr for logging. - * It also allows the frontend to - * show logging information in a more suitable way. - * If this interface is not used, libretro cores should - * log to stderr as desired. - */ -#define RETRO_ENVIRONMENT_GET_PERF_INTERFACE 28 - /* struct retro_perf_callback * -- - * Gets an interface for performance counters. This is useful - * for performance logging in a cross-platform way and for detecting - * architecture-specific features, such as SIMD support. - */ -#define RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE 29 - /* struct retro_location_callback * -- - * Gets access to the location interface. - * The purpose of this interface is to be able to retrieve - * location-based information from the host device, - * such as current latitude / longitude. - */ -#define RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY 30 /* Old name, kept for compatibility. */ -#define RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY 30 - /* const char ** -- - * Returns the "core assets" directory of the frontend. - * This directory can be used to store specific assets that the - * core relies upon, such as art assets, - * input data, etc etc. - * The returned value can be NULL. - * If so, no such directory is defined, - * and it's up to the implementation to find a suitable directory. - */ -#define RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY 31 - /* const char ** -- - * Returns the "save" directory of the frontend. - * This directory can be used to store SRAM, memory cards, - * high scores, etc, if the libretro core - * cannot use the regular memory interface (retro_get_memory_data()). - * - * NOTE: libretro cores used to check GET_SYSTEM_DIRECTORY for - * similar things before. - * They should still check GET_SYSTEM_DIRECTORY if they want to - * be backwards compatible. - * The path here can be NULL. It should only be non-NULL if the - * frontend user has set a specific save path. - */ -#define RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO 32 - /* const struct retro_system_av_info * -- - * Sets a new av_info structure. This can only be called from - * within retro_run(). - * This should *only* be used if the core is completely altering the - * internal resolutions, aspect ratios, timings, sampling rate, etc. - * Calling this can require a full reinitialization of video/audio - * drivers in the frontend, - * - * so it is important to call it very sparingly, and usually only with - * the users explicit consent. - * An eventual driver reinitialize will happen so that video and - * audio callbacks - * happening after this call within the same retro_run() call will - * target the newly initialized driver. - * - * This callback makes it possible to support configurable resolutions - * in games, which can be useful to - * avoid setting the "worst case" in max_width/max_height. - * - * ***HIGHLY RECOMMENDED*** Do not call this callback every time - * resolution changes in an emulator core if it's - * expected to be a temporary change, for the reasons of possible - * driver reinitialization. - * This call is not a free pass for not trying to provide - * correct values in retro_get_system_av_info(). If you need to change - * things like aspect ratio or nominal width/height, - * use RETRO_ENVIRONMENT_SET_GEOMETRY, which is a softer variant - * of SET_SYSTEM_AV_INFO. - * - * If this returns false, the frontend does not acknowledge a - * changed av_info struct. - */ -#define RETRO_ENVIRONMENT_SET_PROC_ADDRESS_CALLBACK 33 - /* const struct retro_get_proc_address_interface * -- - * Allows a libretro core to announce support for the - * get_proc_address() interface. - * This interface allows for a standard way to extend libretro where - * use of environment calls are too indirect, - * e.g. for cases where the frontend wants to call directly into the core. - * - * If a core wants to expose this interface, SET_PROC_ADDRESS_CALLBACK - * **MUST** be called from within retro_set_environment(). - */ -#define RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO 34 - /* const struct retro_subsystem_info * -- - * This environment call introduces the concept of libretro "subsystems". - * A subsystem is a variant of a libretro core which supports - * different kinds of games. - * The purpose of this is to support e.g. emulators which might - * have special needs, e.g. Super Nintendo's Super GameBoy, Sufami Turbo. - * It can also be used to pick among subsystems in an explicit way - * if the libretro implementation is a multi-system emulator itself. - * - * Loading a game via a subsystem is done with retro_load_game_special(), - * and this environment call allows a libretro core to expose which - * subsystems are supported for use with retro_load_game_special(). - * A core passes an array of retro_game_special_info which is terminated - * with a zeroed out retro_game_special_info struct. - * - * If a core wants to use this functionality, SET_SUBSYSTEM_INFO - * **MUST** be called from within retro_set_environment(). - */ -#define RETRO_ENVIRONMENT_SET_CONTROLLER_INFO 35 - /* const struct retro_controller_info * -- - * This environment call lets a libretro core tell the frontend - * which controller types are recognized in calls to - * retro_set_controller_port_device(). - * - * Some emulators such as Super Nintendo - * support multiple lightgun types which must be specifically - * selected from. - * It is therefore sometimes necessary for a frontend to be able - * to tell the core about a special kind of input device which is - * not covered by the libretro input API. - * - * In order for a frontend to understand the workings of an input device, - * it must be a specialized type - * of the generic device types already defined in the libretro API. - * - * Which devices are supported can vary per input port. - * The core must pass an array of const struct retro_controller_info which - * is terminated with a blanked out struct. Each element of the struct - * corresponds to an ascending port index to - * retro_set_controller_port_device(). - * Even if special device types are set in the libretro core, - * libretro should only poll input based on the base input device types. - */ -#define RETRO_ENVIRONMENT_SET_MEMORY_MAPS (36 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* const struct retro_memory_map * -- - * This environment call lets a libretro core tell the frontend - * about the memory maps this core emulates. - * This can be used to implement, for example, cheats in a core-agnostic way. - * - * Should only be used by emulators; it doesn't make much sense for - * anything else. - * It is recommended to expose all relevant pointers through - * retro_get_memory_* as well. - * - * Can be called from retro_init and retro_load_game. - */ -#define RETRO_ENVIRONMENT_SET_GEOMETRY 37 - /* const struct retro_game_geometry * -- - * This environment call is similar to SET_SYSTEM_AV_INFO for changing - * video parameters, but provides a guarantee that drivers will not be - * reinitialized. - * This can only be called from within retro_run(). - * - * The purpose of this call is to allow a core to alter nominal - * width/heights as well as aspect ratios on-the-fly, which can be - * useful for some emulators to change in run-time. - * - * max_width/max_height arguments are ignored and cannot be changed - * with this call as this could potentially require a reinitialization or a - * non-constant time operation. - * If max_width/max_height are to be changed, SET_SYSTEM_AV_INFO is required. - * - * A frontend must guarantee that this environment call completes in - * constant time. - */ -#define RETRO_ENVIRONMENT_GET_USERNAME 38 - /* const char ** - * Returns the specified username of the frontend, if specified by the user. - * This username can be used as a nickname for a core that has online facilities - * or any other mode where personalization of the user is desirable. - * The returned value can be NULL. - * If this environ callback is used by a core that requires a valid username, - * a default username should be specified by the core. - */ -#define RETRO_ENVIRONMENT_GET_LANGUAGE 39 - /* unsigned * -- - * Returns the specified language of the frontend, if specified by the user. - * It can be used by the core for localization purposes. - */ -#define RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER (40 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* struct retro_framebuffer * -- - * Returns a preallocated framebuffer which the core can use for rendering - * the frame into when not using SET_HW_RENDER. - * The framebuffer returned from this call must not be used - * after the current call to retro_run() returns. - * - * The goal of this call is to allow zero-copy behavior where a core - * can render directly into video memory, avoiding extra bandwidth cost by copying - * memory from core to video memory. - * - * If this call succeeds and the core renders into it, - * the framebuffer pointer and pitch can be passed to retro_video_refresh_t. - * If the buffer from GET_CURRENT_SOFTWARE_FRAMEBUFFER is to be used, - * the core must pass the exact - * same pointer as returned by GET_CURRENT_SOFTWARE_FRAMEBUFFER; - * i.e. passing a pointer which is offset from the - * buffer is undefined. The width, height and pitch parameters - * must also match exactly to the values obtained from GET_CURRENT_SOFTWARE_FRAMEBUFFER. - * - * It is possible for a frontend to return a different pixel format - * than the one used in SET_PIXEL_FORMAT. This can happen if the frontend - * needs to perform conversion. - * - * It is still valid for a core to render to a different buffer - * even if GET_CURRENT_SOFTWARE_FRAMEBUFFER succeeds. - * - * A frontend must make sure that the pointer obtained from this function is - * writeable (and readable). - */ - -#define RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE (47 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* int * -- - * Tells the core if the frontend wants audio or video. - * If disabled, the frontend will discard the audio or video, - * so the core may decide to skip generating a frame or generating audio. - * This is mainly used for increasing performance. - * Bit 0 (value 1): Enable Video - * Bit 1 (value 2): Enable Audio - * Bit 2 (value 4): Use Fast Savestates. - * Bit 3 (value 8): Hard Disable Audio - * Other bits are reserved for future use and will default to zero. - * If video is disabled: - * * The frontend wants the core to not generate any video, - * including presenting frames via hardware acceleration. - * * The frontend's video frame callback will do nothing. - * * After running the frame, the video output of the next frame should be - * no different than if video was enabled, and saving and loading state - * should have no issues. - * If audio is disabled: - * * The frontend wants the core to not generate any audio. - * * The frontend's audio callbacks will do nothing. - * * After running the frame, the audio output of the next frame should be - * no different than if audio was enabled, and saving and loading state - * should have no issues. - * Fast Savestates: - * * Guaranteed to be created by the same binary that will load them. - * * Will not be written to or read from the disk. - * * Suggest that the core assumes loading state will succeed. - * * Suggest that the core updates its memory buffers in-place if possible. - * * Suggest that the core skips clearing memory. - * * Suggest that the core skips resetting the system. - * * Suggest that the core may skip validation steps. - * Hard Disable Audio: - * * Used for a secondary core when running ahead. - * * Indicates that the frontend will never need audio from the core. - * * Suggests that the core may stop synthesizing audio, but this should not - * compromise emulation accuracy. - * * Audio output for the next frame does not matter, and the frontend will - * never need an accurate audio state in the future. - * * State will never be saved when using Hard Disable Audio. - */ -enum retro_hw_render_interface_type -{ - RETRO_HW_RENDER_INTERFACE_VULKAN = 0, - RETRO_HW_RENDER_INTERFACE_DUMMY = INT_MAX -}; - -/* Base struct. All retro_hw_render_interface_* types - * contain at least these fields. */ -struct retro_hw_render_interface -{ - enum retro_hw_render_interface_type interface_type; - unsigned interface_version; -}; -#define RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE (41 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* const struct retro_hw_render_interface ** -- - * Returns an API specific rendering interface for accessing API specific data. - * Not all HW rendering APIs support or need this. - * The contents of the returned pointer is specific to the rendering API - * being used. See the various headers like libretro_vulkan.h, etc. - * - * GET_HW_RENDER_INTERFACE cannot be called before context_reset has been called. - * Similarly, after context_destroyed callback returns, - * the contents of the HW_RENDER_INTERFACE are invalidated. - */ - -#define RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS (42 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* const bool * -- - * If true, the libretro implementation supports achievements - * either via memory descriptors set with RETRO_ENVIRONMENT_SET_MEMORY_MAPS - * or via retro_get_memory_data/retro_get_memory_size. - * - * This must be called before the first call to retro_run. - */ - -enum retro_hw_render_context_negotiation_interface_type -{ - RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN = 0, - RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_DUMMY = INT_MAX -}; - -/* Base struct. All retro_hw_render_context_negotiation_interface_* types - * contain at least these fields. */ -struct retro_hw_render_context_negotiation_interface -{ - enum retro_hw_render_context_negotiation_interface_type interface_type; - unsigned interface_version; -}; -#define RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE (43 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* const struct retro_hw_render_context_negotiation_interface * -- - * Sets an interface which lets the libretro core negotiate with frontend how a context is created. - * The semantics of this interface depends on which API is used in SET_HW_RENDER earlier. - * This interface will be used when the frontend is trying to create a HW rendering context, - * so it will be used after SET_HW_RENDER, but before the context_reset callback. - */ - -#define RETRO_MEMDESC_CONST (1 << 0) /* The frontend will never change this memory area once retro_load_game has returned. */ -#define RETRO_MEMDESC_BIGENDIAN (1 << 1) /* The memory area contains big endian data. Default is little endian. */ -#define RETRO_MEMDESC_ALIGN_2 (1 << 16) /* All memory access in this area is aligned to their own size, or 2, whichever is smaller. */ -#define RETRO_MEMDESC_ALIGN_4 (2 << 16) -#define RETRO_MEMDESC_ALIGN_8 (3 << 16) -#define RETRO_MEMDESC_MINSIZE_2 (1 << 24) /* All memory in this region is accessed at least 2 bytes at the time. */ -#define RETRO_MEMDESC_MINSIZE_4 (2 << 24) -#define RETRO_MEMDESC_MINSIZE_8 (3 << 24) -struct retro_memory_descriptor -{ - uint64_t flags; - - /* Pointer to the start of the relevant ROM or RAM chip. - * It's strongly recommended to use 'offset' if possible, rather than - * doing math on the pointer. - * - * If the same byte is mapped my multiple descriptors, their descriptors - * must have the same pointer. - * If 'start' does not point to the first byte in the pointer, put the - * difference in 'offset' instead. - * - * May be NULL if there's nothing usable here (e.g. hardware registers and - * open bus). No flags should be set if the pointer is NULL. - * It's recommended to minimize the number of descriptors if possible, - * but not mandatory. */ - void *ptr; - size_t offset; - - /* This is the location in the emulated address space - * where the mapping starts. */ - size_t start; - - /* Which bits must be same as in 'start' for this mapping to apply. - * The first memory descriptor to claim a certain byte is the one - * that applies. - * A bit which is set in 'start' must also be set in this. - * Can be zero, in which case each byte is assumed mapped exactly once. - * In this case, 'len' must be a power of two. */ - size_t select; - - /* If this is nonzero, the set bits are assumed not connected to the - * memory chip's address pins. */ - size_t disconnect; - - /* This one tells the size of the current memory area. - * If, after start+disconnect are applied, the address is higher than - * this, the highest bit of the address is cleared. - * - * If the address is still too high, the next highest bit is cleared. - * Can be zero, in which case it's assumed to be infinite (as limited - * by 'select' and 'disconnect'). */ - size_t len; - - /* To go from emulated address to physical address, the following - * order applies: - * Subtract 'start', pick off 'disconnect', apply 'len', add 'offset'. */ - - /* The address space name must consist of only a-zA-Z0-9_-, - * should be as short as feasible (maximum length is 8 plus the NUL), - * and may not be any other address space plus one or more 0-9A-F - * at the end. - * However, multiple memory descriptors for the same address space is - * allowed, and the address space name can be empty. NULL is treated - * as empty. - * - * Address space names are case sensitive, but avoid lowercase if possible. - * The same pointer may exist in multiple address spaces. - * - * Examples: - * blank+blank - valid (multiple things may be mapped in the same namespace) - * 'Sp'+'Sp' - valid (multiple things may be mapped in the same namespace) - * 'A'+'B' - valid (neither is a prefix of each other) - * 'S'+blank - valid ('S' is not in 0-9A-F) - * 'a'+blank - valid ('a' is not in 0-9A-F) - * 'a'+'A' - valid (neither is a prefix of each other) - * 'AR'+blank - valid ('R' is not in 0-9A-F) - * 'ARB'+blank - valid (the B can't be part of the address either, because - * there is no namespace 'AR') - * blank+'B' - not valid, because it's ambigous which address space B1234 - * would refer to. - * The length can't be used for that purpose; the frontend may want - * to append arbitrary data to an address, without a separator. */ - const char *addrspace; - - /* TODO: When finalizing this one, add a description field, which should be - * "WRAM" or something roughly equally long. */ - - /* TODO: When finalizing this one, replace 'select' with 'limit', which tells - * which bits can vary and still refer to the same address (limit = ~select). - * TODO: limit? range? vary? something else? */ - - /* TODO: When finalizing this one, if 'len' is above what 'select' (or - * 'limit') allows, it's bankswitched. Bankswitched data must have both 'len' - * and 'select' != 0, and the mappings don't tell how the system switches the - * banks. */ - - /* TODO: When finalizing this one, fix the 'len' bit removal order. - * For len=0x1800, pointer 0x1C00 should go to 0x1400, not 0x0C00. - * Algorithm: Take bits highest to lowest, but if it goes above len, clear - * the most recent addition and continue on the next bit. - * TODO: Can the above be optimized? Is "remove the lowest bit set in both - * pointer and 'len'" equivalent? */ - - /* TODO: Some emulators (MAME?) emulate big endian systems by only accessing - * the emulated memory in 32-bit chunks, native endian. But that's nothing - * compared to Darek Mihocka <http://www.emulators.com/docs/nx07_vm101.htm> - * (section Emulation 103 - Nearly Free Byte Reversal) - he flips the ENTIRE - * RAM backwards! I'll want to represent both of those, via some flags. - * - * I suspect MAME either didn't think of that idea, or don't want the #ifdef. - * Not sure which, nor do I really care. */ - - /* TODO: Some of those flags are unused and/or don't really make sense. Clean - * them up. */ -}; - -/* The frontend may use the largest value of 'start'+'select' in a - * certain namespace to infer the size of the address space. - * - * If the address space is larger than that, a mapping with .ptr=NULL - * should be at the end of the array, with .select set to all ones for - * as long as the address space is big. - * - * Sample descriptors (minus .ptr, and RETRO_MEMFLAG_ on the flags): - * SNES WRAM: - * .start=0x7E0000, .len=0x20000 - * (Note that this must be mapped before the ROM in most cases; some of the - * ROM mappers - * try to claim $7E0000, or at least $7E8000.) - * SNES SPC700 RAM: - * .addrspace="S", .len=0x10000 - * SNES WRAM mirrors: - * .flags=MIRROR, .start=0x000000, .select=0xC0E000, .len=0x2000 - * .flags=MIRROR, .start=0x800000, .select=0xC0E000, .len=0x2000 - * SNES WRAM mirrors, alternate equivalent descriptor: - * .flags=MIRROR, .select=0x40E000, .disconnect=~0x1FFF - * (Various similar constructions can be created by combining parts of - * the above two.) - * SNES LoROM (512KB, mirrored a couple of times): - * .flags=CONST, .start=0x008000, .select=0x408000, .disconnect=0x8000, .len=512*1024 - * .flags=CONST, .start=0x400000, .select=0x400000, .disconnect=0x8000, .len=512*1024 - * SNES HiROM (4MB): - * .flags=CONST, .start=0x400000, .select=0x400000, .len=4*1024*1024 - * .flags=CONST, .offset=0x8000, .start=0x008000, .select=0x408000, .len=4*1024*1024 - * SNES ExHiROM (8MB): - * .flags=CONST, .offset=0, .start=0xC00000, .select=0xC00000, .len=4*1024*1024 - * .flags=CONST, .offset=4*1024*1024, .start=0x400000, .select=0xC00000, .len=4*1024*1024 - * .flags=CONST, .offset=0x8000, .start=0x808000, .select=0xC08000, .len=4*1024*1024 - * .flags=CONST, .offset=4*1024*1024+0x8000, .start=0x008000, .select=0xC08000, .len=4*1024*1024 - * Clarify the size of the address space: - * .ptr=NULL, .select=0xFFFFFF - * .len can be implied by .select in many of them, but was included for clarity. - */ - -struct retro_memory_map -{ - const struct retro_memory_descriptor *descriptors; - unsigned num_descriptors; -}; - -struct retro_controller_description -{ - /* Human-readable description of the controller. Even if using a generic - * input device type, this can be set to the particular device type the - * core uses. */ - const char *desc; - - /* Device type passed to retro_set_controller_port_device(). If the device - * type is a sub-class of a generic input device type, use the - * RETRO_DEVICE_SUBCLASS macro to create an ID. - * - * E.g. RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 1). */ - unsigned id; -}; - -struct retro_controller_info -{ - const struct retro_controller_description *types; - unsigned num_types; -}; - -struct retro_subsystem_memory_info -{ - /* The extension associated with a memory type, e.g. "psram". */ - const char *extension; - - /* The memory type for retro_get_memory(). This should be at - * least 0x100 to avoid conflict with standardized - * libretro memory types. */ - unsigned type; -}; - -struct retro_subsystem_rom_info -{ - /* Describes what the content is (SGB BIOS, GB ROM, etc). */ - const char *desc; - - /* Same definition as retro_get_system_info(). */ - const char *valid_extensions; - - /* Same definition as retro_get_system_info(). */ - bool need_fullpath; - - /* Same definition as retro_get_system_info(). */ - bool block_extract; - - /* This is set if the content is required to load a game. - * If this is set to false, a zeroed-out retro_game_info can be passed. */ - bool required; - - /* Content can have multiple associated persistent - * memory types (retro_get_memory()). */ - const struct retro_subsystem_memory_info *memory; - unsigned num_memory; -}; - -struct retro_subsystem_info -{ - /* Human-readable string of the subsystem type, e.g. "Super GameBoy" */ - const char *desc; - - /* A computer friendly short string identifier for the subsystem type. - * This name must be [a-z]. - * E.g. if desc is "Super GameBoy", this can be "sgb". - * This identifier can be used for command-line interfaces, etc. - */ - const char *ident; - - /* Infos for each content file. The first entry is assumed to be the - * "most significant" content for frontend purposes. - * E.g. with Super GameBoy, the first content should be the GameBoy ROM, - * as it is the most "significant" content to a user. - * If a frontend creates new file paths based on the content used - * (e.g. savestates), it should use the path for the first ROM to do so. */ - const struct retro_subsystem_rom_info *roms; - - /* Number of content files associated with a subsystem. */ - unsigned num_roms; - - /* The type passed to retro_load_game_special(). */ - unsigned id; -}; - -typedef void (RETRO_CALLCONV *retro_proc_address_t)(void); - -/* libretro API extension functions: - * (None here so far). - * - * Get a symbol from a libretro core. - * Cores should only return symbols which are actual - * extensions to the libretro API. - * - * Frontends should not use this to obtain symbols to standard - * libretro entry points (static linking or dlsym). - * - * The symbol name must be equal to the function name, - * e.g. if void retro_foo(void); exists, the symbol must be called "retro_foo". - * The returned function pointer must be cast to the corresponding type. - */ -typedef retro_proc_address_t (RETRO_CALLCONV *retro_get_proc_address_t)(const char *sym); - -struct retro_get_proc_address_interface -{ - retro_get_proc_address_t get_proc_address; -}; - -enum retro_log_level -{ - RETRO_LOG_DEBUG = 0, - RETRO_LOG_INFO, - RETRO_LOG_WARN, - RETRO_LOG_ERROR, - - RETRO_LOG_DUMMY = INT_MAX -}; - -/* Logging function. Takes log level argument as well. */ -typedef void (RETRO_CALLCONV *retro_log_printf_t)(enum retro_log_level level, - const char *fmt, ...); - -struct retro_log_callback -{ - retro_log_printf_t log; -}; - -/* Performance related functions */ - -/* ID values for SIMD CPU features */ -#define RETRO_SIMD_SSE (1 << 0) -#define RETRO_SIMD_SSE2 (1 << 1) -#define RETRO_SIMD_VMX (1 << 2) -#define RETRO_SIMD_VMX128 (1 << 3) -#define RETRO_SIMD_AVX (1 << 4) -#define RETRO_SIMD_NEON (1 << 5) -#define RETRO_SIMD_SSE3 (1 << 6) -#define RETRO_SIMD_SSSE3 (1 << 7) -#define RETRO_SIMD_MMX (1 << 8) -#define RETRO_SIMD_MMXEXT (1 << 9) -#define RETRO_SIMD_SSE4 (1 << 10) -#define RETRO_SIMD_SSE42 (1 << 11) -#define RETRO_SIMD_AVX2 (1 << 12) -#define RETRO_SIMD_VFPU (1 << 13) -#define RETRO_SIMD_PS (1 << 14) -#define RETRO_SIMD_AES (1 << 15) -#define RETRO_SIMD_VFPV3 (1 << 16) -#define RETRO_SIMD_VFPV4 (1 << 17) -#define RETRO_SIMD_POPCNT (1 << 18) -#define RETRO_SIMD_MOVBE (1 << 19) - -typedef uint64_t retro_perf_tick_t; -typedef int64_t retro_time_t; - -struct retro_perf_counter -{ - const char *ident; - retro_perf_tick_t start; - retro_perf_tick_t total; - retro_perf_tick_t call_cnt; - - bool registered; -}; - -/* Returns current time in microseconds. - * Tries to use the most accurate timer available. - */ -typedef retro_time_t (RETRO_CALLCONV *retro_perf_get_time_usec_t)(void); - -/* A simple counter. Usually nanoseconds, but can also be CPU cycles. - * Can be used directly if desired (when creating a more sophisticated - * performance counter system). - * */ -typedef retro_perf_tick_t (RETRO_CALLCONV *retro_perf_get_counter_t)(void); - -/* Returns a bit-mask of detected CPU features (RETRO_SIMD_*). */ -typedef uint64_t (RETRO_CALLCONV *retro_get_cpu_features_t)(void); - -/* Asks frontend to log and/or display the state of performance counters. - * Performance counters can always be poked into manually as well. - */ -typedef void (RETRO_CALLCONV *retro_perf_log_t)(void); - -/* Register a performance counter. - * ident field must be set with a discrete value and other values in - * retro_perf_counter must be 0. - * Registering can be called multiple times. To avoid calling to - * frontend redundantly, you can check registered field first. */ -typedef void (RETRO_CALLCONV *retro_perf_register_t)(struct retro_perf_counter *counter); - -/* Starts a registered counter. */ -typedef void (RETRO_CALLCONV *retro_perf_start_t)(struct retro_perf_counter *counter); - -/* Stops a registered counter. */ -typedef void (RETRO_CALLCONV *retro_perf_stop_t)(struct retro_perf_counter *counter); - -/* For convenience it can be useful to wrap register, start and stop in macros. - * E.g.: - * #ifdef LOG_PERFORMANCE - * #define RETRO_PERFORMANCE_INIT(perf_cb, name) static struct retro_perf_counter name = {#name}; if (!name.registered) perf_cb.perf_register(&(name)) - * #define RETRO_PERFORMANCE_START(perf_cb, name) perf_cb.perf_start(&(name)) - * #define RETRO_PERFORMANCE_STOP(perf_cb, name) perf_cb.perf_stop(&(name)) - * #else - * ... Blank macros ... - * #endif - * - * These can then be used mid-functions around code snippets. - * - * extern struct retro_perf_callback perf_cb; * Somewhere in the core. - * - * void do_some_heavy_work(void) - * { - * RETRO_PERFORMANCE_INIT(cb, work_1; - * RETRO_PERFORMANCE_START(cb, work_1); - * heavy_work_1(); - * RETRO_PERFORMANCE_STOP(cb, work_1); - * - * RETRO_PERFORMANCE_INIT(cb, work_2); - * RETRO_PERFORMANCE_START(cb, work_2); - * heavy_work_2(); - * RETRO_PERFORMANCE_STOP(cb, work_2); - * } - * - * void retro_deinit(void) - * { - * perf_cb.perf_log(); * Log all perf counters here for example. - * } - */ - -struct retro_perf_callback -{ - retro_perf_get_time_usec_t get_time_usec; - retro_get_cpu_features_t get_cpu_features; - - retro_perf_get_counter_t get_perf_counter; - retro_perf_register_t perf_register; - retro_perf_start_t perf_start; - retro_perf_stop_t perf_stop; - retro_perf_log_t perf_log; -}; - -/* FIXME: Document the sensor API and work out behavior. - * It will be marked as experimental until then. - */ -enum retro_sensor_action -{ - RETRO_SENSOR_ACCELEROMETER_ENABLE = 0, - RETRO_SENSOR_ACCELEROMETER_DISABLE, - - RETRO_SENSOR_DUMMY = INT_MAX -}; - -/* Id values for SENSOR types. */ -#define RETRO_SENSOR_ACCELEROMETER_X 0 -#define RETRO_SENSOR_ACCELEROMETER_Y 1 -#define RETRO_SENSOR_ACCELEROMETER_Z 2 - -typedef bool (RETRO_CALLCONV *retro_set_sensor_state_t)(unsigned port, - enum retro_sensor_action action, unsigned rate); - -typedef float (RETRO_CALLCONV *retro_sensor_get_input_t)(unsigned port, unsigned id); - -struct retro_sensor_interface -{ - retro_set_sensor_state_t set_sensor_state; - retro_sensor_get_input_t get_sensor_input; -}; - -enum retro_camera_buffer -{ - RETRO_CAMERA_BUFFER_OPENGL_TEXTURE = 0, - RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER, - - RETRO_CAMERA_BUFFER_DUMMY = INT_MAX -}; - -/* Starts the camera driver. Can only be called in retro_run(). */ -typedef bool (RETRO_CALLCONV *retro_camera_start_t)(void); - -/* Stops the camera driver. Can only be called in retro_run(). */ -typedef void (RETRO_CALLCONV *retro_camera_stop_t)(void); - -/* Callback which signals when the camera driver is initialized - * and/or deinitialized. - * retro_camera_start_t can be called in initialized callback. - */ -typedef void (RETRO_CALLCONV *retro_camera_lifetime_status_t)(void); - -/* A callback for raw framebuffer data. buffer points to an XRGB8888 buffer. - * Width, height and pitch are similar to retro_video_refresh_t. - * First pixel is top-left origin. - */ -typedef void (RETRO_CALLCONV *retro_camera_frame_raw_framebuffer_t)(const uint32_t *buffer, - unsigned width, unsigned height, size_t pitch); - -/* A callback for when OpenGL textures are used. - * - * texture_id is a texture owned by camera driver. - * Its state or content should be considered immutable, except for things like - * texture filtering and clamping. - * - * texture_target is the texture target for the GL texture. - * These can include e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE, and possibly - * more depending on extensions. - * - * affine points to a packed 3x3 column-major matrix used to apply an affine - * transform to texture coordinates. (affine_matrix * vec3(coord_x, coord_y, 1.0)) - * After transform, normalized texture coord (0, 0) should be bottom-left - * and (1, 1) should be top-right (or (width, height) for RECTANGLE). - * - * GL-specific typedefs are avoided here to avoid relying on gl.h in - * the API definition. - */ -typedef void (RETRO_CALLCONV *retro_camera_frame_opengl_texture_t)(unsigned texture_id, - unsigned texture_target, const float *affine); - -struct retro_camera_callback -{ - /* Set by libretro core. - * Example bitmask: caps = (1 << RETRO_CAMERA_BUFFER_OPENGL_TEXTURE) | (1 << RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER). - */ - uint64_t caps; - - /* Desired resolution for camera. Is only used as a hint. */ - unsigned width; - unsigned height; - - /* Set by frontend. */ - retro_camera_start_t start; - retro_camera_stop_t stop; - - /* Set by libretro core if raw framebuffer callbacks will be used. */ - retro_camera_frame_raw_framebuffer_t frame_raw_framebuffer; - - /* Set by libretro core if OpenGL texture callbacks will be used. */ - retro_camera_frame_opengl_texture_t frame_opengl_texture; - - /* Set by libretro core. Called after camera driver is initialized and - * ready to be started. - * Can be NULL, in which this callback is not called. - */ - retro_camera_lifetime_status_t initialized; - - /* Set by libretro core. Called right before camera driver is - * deinitialized. - * Can be NULL, in which this callback is not called. - */ - retro_camera_lifetime_status_t deinitialized; -}; - -/* Sets the interval of time and/or distance at which to update/poll - * location-based data. - * - * To ensure compatibility with all location-based implementations, - * values for both interval_ms and interval_distance should be provided. - * - * interval_ms is the interval expressed in milliseconds. - * interval_distance is the distance interval expressed in meters. - */ -typedef void (RETRO_CALLCONV *retro_location_set_interval_t)(unsigned interval_ms, - unsigned interval_distance); - -/* Start location services. The device will start listening for changes to the - * current location at regular intervals (which are defined with - * retro_location_set_interval_t). */ -typedef bool (RETRO_CALLCONV *retro_location_start_t)(void); - -/* Stop location services. The device will stop listening for changes - * to the current location. */ -typedef void (RETRO_CALLCONV *retro_location_stop_t)(void); - -/* Get the position of the current location. Will set parameters to - * 0 if no new location update has happened since the last time. */ -typedef bool (RETRO_CALLCONV *retro_location_get_position_t)(double *lat, double *lon, - double *horiz_accuracy, double *vert_accuracy); - -/* Callback which signals when the location driver is initialized - * and/or deinitialized. - * retro_location_start_t can be called in initialized callback. - */ -typedef void (RETRO_CALLCONV *retro_location_lifetime_status_t)(void); - -struct retro_location_callback -{ - retro_location_start_t start; - retro_location_stop_t stop; - retro_location_get_position_t get_position; - retro_location_set_interval_t set_interval; - - retro_location_lifetime_status_t initialized; - retro_location_lifetime_status_t deinitialized; -}; - -enum retro_rumble_effect -{ - RETRO_RUMBLE_STRONG = 0, - RETRO_RUMBLE_WEAK = 1, - - RETRO_RUMBLE_DUMMY = INT_MAX -}; - -/* Sets rumble state for joypad plugged in port 'port'. - * Rumble effects are controlled independently, - * and setting e.g. strong rumble does not override weak rumble. - * Strength has a range of [0, 0xffff]. - * - * Returns true if rumble state request was honored. - * Calling this before first retro_run() is likely to return false. */ -typedef bool (RETRO_CALLCONV *retro_set_rumble_state_t)(unsigned port, - enum retro_rumble_effect effect, uint16_t strength); - -struct retro_rumble_interface -{ - retro_set_rumble_state_t set_rumble_state; -}; - -/* Notifies libretro that audio data should be written. */ -typedef void (RETRO_CALLCONV *retro_audio_callback_t)(void); - -/* True: Audio driver in frontend is active, and callback is - * expected to be called regularily. - * False: Audio driver in frontend is paused or inactive. - * Audio callback will not be called until set_state has been - * called with true. - * Initial state is false (inactive). - */ -typedef void (RETRO_CALLCONV *retro_audio_set_state_callback_t)(bool enabled); - -struct retro_audio_callback -{ - retro_audio_callback_t callback; - retro_audio_set_state_callback_t set_state; -}; - -/* Notifies a libretro core of time spent since last invocation - * of retro_run() in microseconds. - * - * It will be called right before retro_run() every frame. - * The frontend can tamper with timing to support cases like - * fast-forward, slow-motion and framestepping. - * - * In those scenarios the reference frame time value will be used. */ -typedef int64_t retro_usec_t; -typedef void (RETRO_CALLCONV *retro_frame_time_callback_t)(retro_usec_t usec); -struct retro_frame_time_callback -{ - retro_frame_time_callback_t callback; - /* Represents the time of one frame. It is computed as - * 1000000 / fps, but the implementation will resolve the - * rounding to ensure that framestepping, etc is exact. */ - retro_usec_t reference; -}; - -/* Pass this to retro_video_refresh_t if rendering to hardware. - * Passing NULL to retro_video_refresh_t is still a frame dupe as normal. - * */ -#define RETRO_HW_FRAME_BUFFER_VALID ((void*)-1) - -/* Invalidates the current HW context. - * Any GL state is lost, and must not be deinitialized explicitly. - * If explicit deinitialization is desired by the libretro core, - * it should implement context_destroy callback. - * If called, all GPU resources must be reinitialized. - * Usually called when frontend reinits video driver. - * Also called first time video driver is initialized, - * allowing libretro core to initialize resources. - */ -typedef void (RETRO_CALLCONV *retro_hw_context_reset_t)(void); - -/* Gets current framebuffer which is to be rendered to. - * Could change every frame potentially. - */ -typedef uintptr_t (RETRO_CALLCONV *retro_hw_get_current_framebuffer_t)(void); - -/* Get a symbol from HW context. */ -typedef retro_proc_address_t (RETRO_CALLCONV *retro_hw_get_proc_address_t)(const char *sym); - -enum retro_hw_context_type -{ - RETRO_HW_CONTEXT_NONE = 0, - /* OpenGL 2.x. Driver can choose to use latest compatibility context. */ - RETRO_HW_CONTEXT_OPENGL = 1, - /* OpenGL ES 2.0. */ - RETRO_HW_CONTEXT_OPENGLES2 = 2, - /* Modern desktop core GL context. Use version_major/ - * version_minor fields to set GL version. */ - RETRO_HW_CONTEXT_OPENGL_CORE = 3, - /* OpenGL ES 3.0 */ - RETRO_HW_CONTEXT_OPENGLES3 = 4, - /* OpenGL ES 3.1+. Set version_major/version_minor. For GLES2 and GLES3, - * use the corresponding enums directly. */ - RETRO_HW_CONTEXT_OPENGLES_VERSION = 5, - - /* Vulkan, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE. */ - RETRO_HW_CONTEXT_VULKAN = 6, - - RETRO_HW_CONTEXT_DUMMY = INT_MAX -}; - -struct retro_hw_render_callback -{ - /* Which API to use. Set by libretro core. */ - enum retro_hw_context_type context_type; - - /* Called when a context has been created or when it has been reset. - * An OpenGL context is only valid after context_reset() has been called. - * - * When context_reset is called, OpenGL resources in the libretro - * implementation are guaranteed to be invalid. - * - * It is possible that context_reset is called multiple times during an - * application lifecycle. - * If context_reset is called without any notification (context_destroy), - * the OpenGL context was lost and resources should just be recreated - * without any attempt to "free" old resources. - */ - retro_hw_context_reset_t context_reset; - - /* Set by frontend. - * TODO: This is rather obsolete. The frontend should not - * be providing preallocated framebuffers. */ - retro_hw_get_current_framebuffer_t get_current_framebuffer; - - /* Set by frontend. */ - retro_hw_get_proc_address_t get_proc_address; - - /* Set if render buffers should have depth component attached. - * TODO: Obsolete. */ - bool depth; - - /* Set if stencil buffers should be attached. - * TODO: Obsolete. */ - bool stencil; - - /* If depth and stencil are true, a packed 24/8 buffer will be added. - * Only attaching stencil is invalid and will be ignored. */ - - /* Use conventional bottom-left origin convention. If false, - * standard libretro top-left origin semantics are used. - * TODO: Move to GL specific interface. */ - bool bottom_left_origin; - - /* Major version number for core GL context or GLES 3.1+. */ - unsigned version_major; - - /* Minor version number for core GL context or GLES 3.1+. */ - unsigned version_minor; - - /* If this is true, the frontend will go very far to avoid - * resetting context in scenarios like toggling fullscreen, etc. - * TODO: Obsolete? Maybe frontend should just always assume this ... - */ - bool cache_context; - - /* The reset callback might still be called in extreme situations - * such as if the context is lost beyond recovery. - * - * For optimal stability, set this to false, and allow context to be - * reset at any time. - */ - - /* A callback to be called before the context is destroyed in a - * controlled way by the frontend. */ - retro_hw_context_reset_t context_destroy; - - /* OpenGL resources can be deinitialized cleanly at this step. - * context_destroy can be set to NULL, in which resources will - * just be destroyed without any notification. - * - * Even when context_destroy is non-NULL, it is possible that - * context_reset is called without any destroy notification. - * This happens if context is lost by external factors (such as - * notified by GL_ARB_robustness). - * - * In this case, the context is assumed to be already dead, - * and the libretro implementation must not try to free any OpenGL - * resources in the subsequent context_reset. - */ - - /* Creates a debug context. */ - bool debug_context; -}; - -/* Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. - * Called by the frontend in response to keyboard events. - * down is set if the key is being pressed, or false if it is being released. - * keycode is the RETROK value of the char. - * character is the text character of the pressed key. (UTF-32). - * key_modifiers is a set of RETROKMOD values or'ed together. - * - * The pressed/keycode state can be indepedent of the character. - * It is also possible that multiple characters are generated from a - * single keypress. - * Keycode events should be treated separately from character events. - * However, when possible, the frontend should try to synchronize these. - * If only a character is posted, keycode should be RETROK_UNKNOWN. - * - * Similarily if only a keycode event is generated with no corresponding - * character, character should be 0. - */ -typedef void (RETRO_CALLCONV *retro_keyboard_event_t)(bool down, unsigned keycode, - uint32_t character, uint16_t key_modifiers); - -struct retro_keyboard_callback -{ - retro_keyboard_event_t callback; -}; - -/* Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE. - * Should be set for implementations which can swap out multiple disk - * images in runtime. - * - * If the implementation can do this automatically, it should strive to do so. - * However, there are cases where the user must manually do so. - * - * Overview: To swap a disk image, eject the disk image with - * set_eject_state(true). - * Set the disk index with set_image_index(index). Insert the disk again - * with set_eject_state(false). - */ - -/* If ejected is true, "ejects" the virtual disk tray. - * When ejected, the disk image index can be set. - */ -typedef bool (RETRO_CALLCONV *retro_set_eject_state_t)(bool ejected); - -/* Gets current eject state. The initial state is 'not ejected'. */ -typedef bool (RETRO_CALLCONV *retro_get_eject_state_t)(void); - -/* Gets current disk index. First disk is index 0. - * If return value is >= get_num_images(), no disk is currently inserted. - */ -typedef unsigned (RETRO_CALLCONV *retro_get_image_index_t)(void); - -/* Sets image index. Can only be called when disk is ejected. - * The implementation supports setting "no disk" by using an - * index >= get_num_images(). - */ -typedef bool (RETRO_CALLCONV *retro_set_image_index_t)(unsigned index); - -/* Gets total number of images which are available to use. */ -typedef unsigned (RETRO_CALLCONV *retro_get_num_images_t)(void); - -struct retro_game_info; - -/* Replaces the disk image associated with index. - * Arguments to pass in info have same requirements as retro_load_game(). - * Virtual disk tray must be ejected when calling this. - * - * Replacing a disk image with info = NULL will remove the disk image - * from the internal list. - * As a result, calls to get_image_index() can change. - * - * E.g. replace_image_index(1, NULL), and previous get_image_index() - * returned 4 before. - * Index 1 will be removed, and the new index is 3. - */ -typedef bool (RETRO_CALLCONV *retro_replace_image_index_t)(unsigned index, - const struct retro_game_info *info); - -/* Adds a new valid index (get_num_images()) to the internal disk list. - * This will increment subsequent return values from get_num_images() by 1. - * This image index cannot be used until a disk image has been set - * with replace_image_index. */ -typedef bool (RETRO_CALLCONV *retro_add_image_index_t)(void); - -struct retro_disk_control_callback -{ - retro_set_eject_state_t set_eject_state; - retro_get_eject_state_t get_eject_state; - - retro_get_image_index_t get_image_index; - retro_set_image_index_t set_image_index; - retro_get_num_images_t get_num_images; - - retro_replace_image_index_t replace_image_index; - retro_add_image_index_t add_image_index; -}; - -enum retro_pixel_format -{ - /* 0RGB1555, native endian. - * 0 bit must be set to 0. - * This pixel format is default for compatibility concerns only. - * If a 15/16-bit pixel format is desired, consider using RGB565. */ - RETRO_PIXEL_FORMAT_0RGB1555 = 0, - - /* XRGB8888, native endian. - * X bits are ignored. */ - RETRO_PIXEL_FORMAT_XRGB8888 = 1, - - /* RGB565, native endian. - * This pixel format is the recommended format to use if a 15/16-bit - * format is desired as it is the pixel format that is typically - * available on a wide range of low-power devices. - * - * It is also natively supported in APIs like OpenGL ES. */ - RETRO_PIXEL_FORMAT_RGB565 = 2, - - /* Ensure sizeof() == sizeof(int). */ - RETRO_PIXEL_FORMAT_UNKNOWN = INT_MAX -}; - -struct retro_message -{ - const char *msg; /* Message to be displayed. */ - unsigned frames; /* Duration in frames of message. */ -}; - -/* Describes how the libretro implementation maps a libretro input bind - * to its internal input system through a human readable string. - * This string can be used to better let a user configure input. */ -struct retro_input_descriptor -{ - /* Associates given parameters with a description. */ - unsigned port; - unsigned device; - unsigned index; - unsigned id; - - /* Human readable description for parameters. - * The pointer must remain valid until - * retro_unload_game() is called. */ - const char *description; -}; - -struct retro_system_info -{ - /* All pointers are owned by libretro implementation, and pointers must - * remain valid until retro_deinit() is called. */ - - const char *library_name; /* Descriptive name of library. Should not - * contain any version numbers, etc. */ - const char *library_version; /* Descriptive version of core. */ - - const char *valid_extensions; /* A string listing probably content - * extensions the core will be able to - * load, separated with pipe. - * I.e. "bin|rom|iso". - * Typically used for a GUI to filter - * out extensions. */ - - /* If true, retro_load_game() is guaranteed to provide a valid pathname - * in retro_game_info::path. - * ::data and ::size are both invalid. - * - * If false, ::data and ::size are guaranteed to be valid, but ::path - * might not be valid. - * - * This is typically set to true for libretro implementations that must - * load from file. - * Implementations should strive for setting this to false, as it allows - * the frontend to perform patching, etc. */ - bool need_fullpath; - - /* If true, the frontend is not allowed to extract any archives before - * loading the real content. - * Necessary for certain libretro implementations that load games - * from zipped archives. */ - bool block_extract; -}; - -struct retro_game_geometry -{ - unsigned base_width; /* Nominal video width of game. */ - unsigned base_height; /* Nominal video height of game. */ - unsigned max_width; /* Maximum possible width of game. */ - unsigned max_height; /* Maximum possible height of game. */ - - float aspect_ratio; /* Nominal aspect ratio of game. If - * aspect_ratio is <= 0.0, an aspect ratio - * of base_width / base_height is assumed. - * A frontend could override this setting, - * if desired. */ -}; - -struct retro_system_timing -{ - double fps; /* FPS of video content. */ - double sample_rate; /* Sampling rate of audio. */ -}; - -struct retro_system_av_info -{ - struct retro_game_geometry geometry; - struct retro_system_timing timing; -}; - -struct retro_variable -{ - /* Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. - * If NULL, obtains the complete environment string if more - * complex parsing is necessary. - * The environment string is formatted as key-value pairs - * delimited by semicolons as so: - * "key1=value1;key2=value2;..." - */ - const char *key; - - /* Value to be obtained. If key does not exist, it is set to NULL. */ - const char *value; -}; - -struct retro_game_info -{ - const char *path; /* Path to game, UTF-8 encoded. - * Usually used as a reference. - * May be NULL if rom was loaded from stdin - * or similar. - * retro_system_info::need_fullpath guaranteed - * that this path is valid. */ - const void *data; /* Memory buffer of loaded game. Will be NULL - * if need_fullpath was set. */ - size_t size; /* Size of memory buffer. */ - const char *meta; /* String of implementation specific meta-data. */ -}; - -#define RETRO_MEMORY_ACCESS_WRITE (1 << 0) - /* The core will write to the buffer provided by retro_framebuffer::data. */ -#define RETRO_MEMORY_ACCESS_READ (1 << 1) - /* The core will read from retro_framebuffer::data. */ -#define RETRO_MEMORY_TYPE_CACHED (1 << 0) - /* The memory in data is cached. - * If not cached, random writes and/or reading from the buffer is expected to be very slow. */ -struct retro_framebuffer -{ - void *data; /* The framebuffer which the core can render into. - Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. - The initial contents of data are unspecified. */ - unsigned width; /* The framebuffer width used by the core. Set by core. */ - unsigned height; /* The framebuffer height used by the core. Set by core. */ - size_t pitch; /* The number of bytes between the beginning of a scanline, - and beginning of the next scanline. - Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ - enum retro_pixel_format format; /* The pixel format the core must use to render into data. - This format could differ from the format used in - SET_PIXEL_FORMAT. - Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ - - unsigned access_flags; /* How the core will access the memory in the framebuffer. - RETRO_MEMORY_ACCESS_* flags. - Set by core. */ - unsigned memory_flags; /* Flags telling core how the memory has been mapped. - RETRO_MEMORY_TYPE_* flags. - Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ -}; - -/* Callbacks */ - -/* Environment callback. Gives implementations a way of performing - * uncommon tasks. Extensible. */ -typedef bool (RETRO_CALLCONV *retro_environment_t)(unsigned cmd, void *data); - -/* Render a frame. Pixel format is 15-bit 0RGB1555 native endian - * unless changed (see RETRO_ENVIRONMENT_SET_PIXEL_FORMAT). - * - * Width and height specify dimensions of buffer. - * Pitch specifices length in bytes between two lines in buffer. - * - * For performance reasons, it is highly recommended to have a frame - * that is packed in memory, i.e. pitch == width * byte_per_pixel. - * Certain graphic APIs, such as OpenGL ES, do not like textures - * that are not packed in memory. - */ -typedef void (RETRO_CALLCONV *retro_video_refresh_t)(const void *data, unsigned width, - unsigned height, size_t pitch); - -/* Renders a single audio frame. Should only be used if implementation - * generates a single sample at a time. - * Format is signed 16-bit native endian. - */ -typedef void (RETRO_CALLCONV *retro_audio_sample_t)(int16_t left, int16_t right); - -/* Renders multiple audio frames in one go. - * - * One frame is defined as a sample of left and right channels, interleaved. - * I.e. int16_t buf[4] = { l, r, l, r }; would be 2 frames. - * Only one of the audio callbacks must ever be used. - */ -typedef size_t (RETRO_CALLCONV *retro_audio_sample_batch_t)(const int16_t *data, - size_t frames); - -/* Polls input. */ -typedef void (RETRO_CALLCONV *retro_input_poll_t)(void); - -/* Queries for input for player 'port'. device will be masked with - * RETRO_DEVICE_MASK. - * - * Specialization of devices such as RETRO_DEVICE_JOYPAD_MULTITAP that - * have been set with retro_set_controller_port_device() - * will still use the higher level RETRO_DEVICE_JOYPAD to request input. - */ -typedef int16_t (RETRO_CALLCONV *retro_input_state_t)(unsigned port, unsigned device, - unsigned index, unsigned id); - -/* Sets callbacks. retro_set_environment() is guaranteed to be called - * before retro_init(). - * - * The rest of the set_* functions are guaranteed to have been called - * before the first call to retro_run() is made. */ -RETRO_API void retro_set_environment(retro_environment_t); -RETRO_API void retro_set_video_refresh(retro_video_refresh_t); -RETRO_API void retro_set_audio_sample(retro_audio_sample_t); -RETRO_API void retro_set_audio_sample_batch(retro_audio_sample_batch_t); -RETRO_API void retro_set_input_poll(retro_input_poll_t); -RETRO_API void retro_set_input_state(retro_input_state_t); - -/* Library global initialization/deinitialization. */ -RETRO_API void retro_init(void); -RETRO_API void retro_deinit(void); - -/* Must return RETRO_API_VERSION. Used to validate ABI compatibility - * when the API is revised. */ -RETRO_API unsigned retro_api_version(void); - -/* Gets statically known system info. Pointers provided in *info - * must be statically allocated. - * Can be called at any time, even before retro_init(). */ -RETRO_API void retro_get_system_info(struct retro_system_info *info); - -/* Gets information about system audio/video timings and geometry. - * Can be called only after retro_load_game() has successfully completed. - * NOTE: The implementation of this function might not initialize every - * variable if needed. - * E.g. geom.aspect_ratio might not be initialized if core doesn't - * desire a particular aspect ratio. */ -RETRO_API void retro_get_system_av_info(struct retro_system_av_info *info); - -/* Sets device to be used for player 'port'. - * By default, RETRO_DEVICE_JOYPAD is assumed to be plugged into all - * available ports. - * Setting a particular device type is not a guarantee that libretro cores - * will only poll input based on that particular device type. It is only a - * hint to the libretro core when a core cannot automatically detect the - * appropriate input device type on its own. It is also relevant when a - * core can change its behavior depending on device type. */ -RETRO_API void retro_set_controller_port_device(unsigned port, unsigned device); - -/* Resets the current game. */ -RETRO_API void retro_reset(void); - -/* Runs the game for one video frame. - * During retro_run(), input_poll callback must be called at least once. - * - * If a frame is not rendered for reasons where a game "dropped" a frame, - * this still counts as a frame, and retro_run() should explicitly dupe - * a frame if GET_CAN_DUPE returns true. - * In this case, the video callback can take a NULL argument for data. - */ -RETRO_API void retro_run(void); - -/* Returns the amount of data the implementation requires to serialize - * internal state (save states). - * Between calls to retro_load_game() and retro_unload_game(), the - * returned size is never allowed to be larger than a previous returned - * value, to ensure that the frontend can allocate a save state buffer once. - */ -RETRO_API size_t retro_serialize_size(void); - -/* Serializes internal state. If failed, or size is lower than - * retro_serialize_size(), it should return false, true otherwise. */ -RETRO_API bool retro_serialize(void *data, size_t size); -RETRO_API bool retro_unserialize(const void *data, size_t size); - -RETRO_API void retro_cheat_reset(void); -RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char *code); - -/* Loads a game. */ -RETRO_API bool retro_load_game(const struct retro_game_info *game); - -/* Loads a "special" kind of game. Should not be used, - * except in extreme cases. */ -RETRO_API bool retro_load_game_special( - unsigned game_type, - const struct retro_game_info *info, size_t num_info -); - -/* Unloads a currently loaded game. */ -RETRO_API void retro_unload_game(void); - -/* Gets region of game. */ -RETRO_API unsigned retro_get_region(void); - -/* Gets region of memory. */ -RETRO_API void *retro_get_memory_data(unsigned id); -RETRO_API size_t retro_get_memory_size(unsigned id); - -#ifdef __cplusplus -} -#endif - -#endif @@ -1,4 +0,0 @@ -{ - global: retro_*; - local: *; -}; diff --git a/shell/audio/alsa/sound_output.c b/shell/audio/alsa/sound_output.c new file mode 100644 index 0000000..5173bb6 --- /dev/null +++ b/shell/audio/alsa/sound_output.c @@ -0,0 +1,142 @@ +#include <sys/ioctl.h> +#include <stdint.h> +#include <fcntl.h> +#include <unistd.h> +#include <alsa/asoundlib.h> + +#include "sound_output.h" + +static snd_pcm_t *handle; + +uint32_t Audio_Init() +{ + snd_pcm_hw_params_t *params; + uint32_t val; + int32_t dir = -1; + snd_pcm_uframes_t frames; + + /* Open PCM device for playback. */ + int32_t rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0); + + if (rc < 0) + rc = snd_pcm_open(&handle, "plughw:0,0,0", SND_PCM_STREAM_PLAYBACK, 0); + + if (rc < 0) + rc = snd_pcm_open(&handle, "plughw:0,0", SND_PCM_STREAM_PLAYBACK, 0); + + if (rc < 0) + rc = snd_pcm_open(&handle, "plughw:1,0,0", SND_PCM_STREAM_PLAYBACK, 0); + + if (rc < 0) + rc = snd_pcm_open(&handle, "plughw:1,0", SND_PCM_STREAM_PLAYBACK, 0); + + if (rc < 0) + { + fprintf(stderr, "unable to open PCM device: %s\n", snd_strerror(rc)); + return 1; + } + + /* Allocate a hardware parameters object. */ + snd_pcm_hw_params_alloca(¶ms); + + /* Fill it in with default values. */ + rc = snd_pcm_hw_params_any(handle, params); + if (rc < 0) + { + fprintf(stderr, "Error:snd_pcm_hw_params_any %s\n", snd_strerror(rc)); + return 1; + } + + /* Set the desired hardware parameters. */ + + /* Interleaved mode */ + rc = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); + if (rc < 0) + { + fprintf(stderr, "Error:snd_pcm_hw_params_set_access %s\n", snd_strerror(rc)); + return 1; + } + + /* Signed 16-bit little-endian format */ + rc = snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); + if (rc < 0) + { + fprintf(stderr, "Error:snd_pcm_hw_params_set_format %s\n", snd_strerror(rc)); + return 1; + } + + /* Two channels (stereo) */ + rc = snd_pcm_hw_params_set_channels(handle, params, 2); + if (rc < 0) + { + fprintf(stderr, "Error:snd_pcm_hw_params_set_channels %s\n", snd_strerror(rc)); + return 1; + } + + val = SOUND_OUTPUT_FREQUENCY; + rc = snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); + if (rc < 0) + { + fprintf(stderr, "Error:snd_pcm_hw_params_set_rate_near %s\n", snd_strerror(rc)); + return 1; + } + + /* Set period size to settings.aica.BufferSize frames. */ + frames = SOUND_SAMPLES_SIZE; + rc = snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir); + if (rc < 0) + { + fprintf(stderr, "Error:snd_pcm_hw_params_set_buffer_size_near %s\n", snd_strerror(rc)); + return 1; + } + frames *= 4; + rc = snd_pcm_hw_params_set_buffer_size_near(handle, params, &frames); + if (rc < 0) + { + fprintf(stderr, "Error:snd_pcm_hw_params_set_buffer_size_near %s\n", snd_strerror(rc)); + return 1; + } + + /* Write the parameters to the driver */ + rc = snd_pcm_hw_params(handle, params); + if (rc < 0) + { + fprintf(stderr, "Unable to set hw parameters: %s\n", snd_strerror(rc)); + return 1; + } + + return 0; +} + +void Audio_Write(int16_t* restrict buffer, uint32_t buffer_size) +{ + uint32_t i; + long ret, len; + + if (!handle) return; + + len = buffer_size; + + ret = snd_pcm_writei(handle, buffer, len); + while(ret != len) + { + if (ret < 0) + { + snd_pcm_prepare( handle ); + } + else + { + len -= ret; + } + ret = snd_pcm_writei(handle, buffer, len); + } +} + +void Audio_Close() +{ + if (handle) + { + snd_pcm_drain(handle); + snd_pcm_close(handle); + } +} diff --git a/shell/audio/oss/sound_output.c b/shell/audio/oss/sound_output.c new file mode 100644 index 0000000..2d32b1f --- /dev/null +++ b/shell/audio/oss/sound_output.c @@ -0,0 +1,59 @@ +#include <stdio.h> +#include <sys/ioctl.h> +#include <stdint.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/soundcard.h> + +#include "sound_output.h" + +static int32_t oss_audio_fd = -1; + +uint32_t Audio_Init() +{ + uint32_t channels = 2; + uint32_t format = AFMT_S16_LE; + uint32_t tmp = SOUND_OUTPUT_FREQUENCY; + int32_t err_ret; + + oss_audio_fd = open("/dev/dsp", O_WRONLY | O_NONBLOCK); + if (oss_audio_fd < 0) + { + printf("Couldn't open /dev/dsp.\n"); + return 1; + } + + err_ret = ioctl(oss_audio_fd, SNDCTL_DSP_SPEED,&tmp); + if (err_ret == -1) + { + printf("Could not set sound frequency\n"); + return 1; + } + err_ret = ioctl(oss_audio_fd, SNDCTL_DSP_CHANNELS, &channels); + if (err_ret == -1) + { + printf("Could not set channels\n"); + return 1; + } + err_ret = ioctl(oss_audio_fd, SNDCTL_DSP_SETFMT, &format); + if (err_ret == -1) + { + printf("Could not set sound format\n"); + return 1; + } + return 0; +} + +void Audio_Write(int16_t* restrict buffer, uint32_t buffer_size) +{ + write(oss_audio_fd, buffer, buffer_size * 4 ); +} + +void Audio_Close() +{ + if (oss_audio_fd >= 0) + { + close(oss_audio_fd); + oss_audio_fd = -1; + } +} diff --git a/shell/audio/portaudio/sound_output.c b/shell/audio/portaudio/sound_output.c new file mode 100644 index 0000000..226db5c --- /dev/null +++ b/shell/audio/portaudio/sound_output.c @@ -0,0 +1,41 @@ +#include <portaudio.h> +#include <stdint.h> +#include <stdio.h> + +#include "shared.h" + +static PaStream *apu_stream; + +uint32_t Audio_Init() +{ + Pa_Initialize(); + + PaStreamParameters outputParameters; + + outputParameters.device = Pa_GetDefaultOutputDevice(); + + if (outputParameters.device == paNoDevice) + { + printf("No sound output\n"); + return 1; + } + + outputParameters.channelCount = 2; + outputParameters.sampleFormat = paInt16; + outputParameters.hostApiSpecificStreamInfo = NULL; + + Pa_OpenStream( &apu_stream, NULL, &outputParameters, SOUND_OUTPUT_FREQUENCY, SOUND_SAMPLES_SIZE, paNoFlag, NULL, NULL); + Pa_StartStream( apu_stream ); + + return 0; +} + +void Audio_Write(int16_t* restrict buffer, uint32_t buffer_size) +{ + Pa_WriteStream( apu_stream, buffer, buffer_size); +} + +void Audio_Close() +{ + //Pa_Close(); +} diff --git a/shell/audio/sdl/sound_output.c b/shell/audio/sdl/sound_output.c new file mode 100644 index 0000000..f14bb1d --- /dev/null +++ b/shell/audio/sdl/sound_output.c @@ -0,0 +1,104 @@ +#include <sys/ioctl.h> +#include <stdint.h> +#include <fcntl.h> +#include <unistd.h> +#include <SDL/SDL.h> + +#include "sound_output.h" + +static int32_t BUFFSIZE; +static uint8_t *buffer; +static uint32_t buf_read_pos = 0; +static uint32_t buf_write_pos = 0; +static int32_t buffered_bytes = 0; + +static int32_t sdl_read_buffer(uint8_t* data, int32_t len) +{ + if (buffered_bytes >= len) + { + if(buf_read_pos + len <= BUFFSIZE ) + { + memcpy(data, buffer + buf_read_pos, len); + } + else + { + int32_t tail = BUFFSIZE - buf_read_pos; + memcpy(data, buffer + buf_read_pos, tail); + memcpy(data + tail, buffer, len - tail); + } + buf_read_pos = (buf_read_pos + len) % BUFFSIZE; + buffered_bytes -= len; + } + + return len; +} + + +static void sdl_write_buffer(uint8_t* data, int32_t len) +{ + for(uint32_t i = 0; i < len; i += 4) + { + if(buffered_bytes == BUFFSIZE) return; // just drop samples + *(int32_t*)((char*)(buffer + buf_write_pos)) = *(int32_t*)((char*)(data + i)); + //memcpy(buffer + buf_write_pos, data + i, 4); + buf_write_pos = (buf_write_pos + 4) % BUFFSIZE; + buffered_bytes += 4; + } +} + +void sdl_callback(void *unused, uint8_t *stream, int32_t len) +{ + sdl_read_buffer((uint8_t *)stream, len); +} +uint32_t Audio_Init() +{ + SDL_AudioSpec aspec, obtained; + + BUFFSIZE = (SOUND_SAMPLES_SIZE * 2 * 2) * 4; + buffer = (uint8_t *) malloc(BUFFSIZE); + + /* Add some silence to the buffer */ + buffered_bytes = 0; + buf_read_pos = 0; + buf_write_pos = 0; + + aspec.format = AUDIO_S16SYS; + aspec.freq = SOUND_OUTPUT_FREQUENCY; + aspec.channels = 2; + aspec.samples = SOUND_SAMPLES_SIZE; + aspec.callback = (sdl_callback); + aspec.userdata = NULL; + + /* initialize the SDL Audio system */ + if (SDL_InitSubSystem (SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE)) + { + printf("SDL: Initializing of SDL Audio failed: %s.\n", SDL_GetError()); + return 1; + } + + /* Open the audio device and start playing sound! */ + if(SDL_OpenAudio(&aspec, &obtained) < 0) + { + printf("SDL: Unable to open audio: %s\n", SDL_GetError()); + return 1; + } + + SDL_PauseAudio(0); + + return 0; +} + +void Audio_Write(int16_t* restrict buffer, uint32_t buffer_size) +{ + SDL_LockAudio(); + sdl_write_buffer(buffer, buffer_size * 4); + SDL_UnlockAudio(); +} + +void Audio_Close() +{ + SDL_PauseAudio(1); + SDL_CloseAudio(); + SDL_QuitSubSystem(SDL_INIT_AUDIO); + buffer = NULL; +} diff --git a/shell/audio/sound_output.h b/shell/audio/sound_output.h new file mode 100644 index 0000000..ba8a318 --- /dev/null +++ b/shell/audio/sound_output.h @@ -0,0 +1,10 @@ +#ifndef SOUND_OUTPUT_H +#define SOUND_OUTPUT_H + +#include "shared.h" + +extern uint32_t Audio_Init(); +extern void Audio_Write(int16_t* restrict buffer, uint32_t buffer_size); +extern void Audio_Close(); + +#endif diff --git a/shell/emu/core.c b/shell/emu/core.c new file mode 100644 index 0000000..2edc457 --- /dev/null +++ b/shell/emu/core.c @@ -0,0 +1,435 @@ +// Author: skogaby +// Lots of examples were followed using other emulators found on github + +#include <SDL/SDL.h> +#include <libgen.h> +#include <sys/time.h> +#include <sys/types.h> + +#include "main.h" +#include "snes9x.h" +#include "soundux.h" +#include "memmap.h" +#include "apu.h" +#include "apu_blargg.h" +#include "cheats.h" +#include "display.h" +#include "gfx.h" +#include "cpuexec.h" +#include "spc7110.h" +#include "srtc.h" +#include "sa1.h" +#include "scaler.h" + +#include "shared.h" +#include "menu.h" +#include "video_blit.h" +#include "input.h" +#include "sound_output.h" + +char GameName_emu[512]; + +bool overclock_cycles = false; +bool reduce_sprite_flicker = true; +int one_c, slow_one_c, two_c; + +static int32_t samples_to_play = 0; +static int32_t samples_per_frame = 0; +static int32_t samplerate = (((SNES_CLOCK_SPEED * 6) / (32 * ONE_APU_CYCLE))); + +#ifdef USE_BLARGG_APU +static void S9xAudioCallback() +{ + size_t avail; + /* Just pick a big buffer. We won't use it all. */ + static int16_t audio_buf[0x20000]; + + S9xFinalizeSamples(); + avail = S9xGetSampleCount(); + S9xMixSamples(audio_buf, avail); + Audio_Write(audio_buf, avail >> 1); +} +#endif + +size_t retro_serialize_size(void) +{ + return sizeof(CPU) + sizeof(ICPU) + sizeof(PPU) + sizeof(DMA) + + 0x10000 + 0x20000 + 0x20000 + 0x8000 + +#ifndef USE_BLARGG_APU + sizeof(APU) + sizeof(IAPU) + 0x10000 + +#else + SPC_SAVE_STATE_BLOCK_SIZE + +#endif + sizeof(SA1) + sizeof(s7r) + sizeof(rtc_f9); +} + +void RTC_Save(char* path, uint_fast8_t state) +{ + FILE* savefp; + + /* If RTC is disabled then don't bother saving any RTC info */ + if (!Settings.SRTC) return; + + if (state == 1) + { + savefp = fopen(path, "rb"); + if (savefp) + { + if (Settings.SPC7110RTC) + { + fread(&rtc_f9, sizeof(uint8_t), sizeof(rtc_f9), savefp); + fclose(savefp); + S9xUpdateRTC(); + } + else + { + fread(&rtc, sizeof(uint8_t), sizeof(rtc), savefp); + fclose(savefp); + S9xSRTCPostLoadState(); + } + } + } + else + { + savefp = fopen(path, "wb"); + if (savefp) + { + if (Settings.SPC7110RTC) + { + fwrite(&rtc_f9, sizeof(uint8_t), sizeof(rtc_f9), savefp); + fclose(savefp); + S9xUpdateRTC(); + } + else + { + S9xSRTCPreSaveState(); + fwrite(&rtc, sizeof(uint8_t), sizeof(rtc), savefp); + fclose(savefp); + } + } + } +} + +void SRAM_Save(char* path, uint_fast8_t state) +{ + FILE* savefp; + + /* If SRAM is not used then don't bother saving any SRAM file */ + if (Memory.SRAMMask == 0) return; + + if (state == 1) + { + savefp = fopen(path, "rb"); + if (savefp) + { + fread(Memory.SRAM, sizeof(uint8_t), Memory.SRAMMask, savefp); + fclose(savefp); + } + } + else + { + savefp = fopen(path, "wb"); + if (savefp) + { + fwrite(Memory.SRAM, sizeof(uint8_t), Memory.SRAMMask, savefp); + fclose(savefp); + } + } +} + +void SaveState(char* path, uint_fast8_t state) +{ +#ifndef USE_BLARGG_APU + uint8_t* IAPU_RAM_current = IAPU.RAM; + uintptr_t IAPU_RAM_offset; +#endif + char* buffer; + FILE* savefp; + +#ifndef USE_BLARGG_APU + buffer = malloc(sizeof(APU) + sizeof(IAPU) + 0x10000); +#else + buffer = malloc(SPC_SAVE_STATE_BLOCK_SIZE); +#endif + + if (state == 1) + { + savefp = fopen(path, "rb"); + if (savefp) + { + S9xReset(); + + fread(&CPU, sizeof(uint8_t), sizeof(CPU), savefp); + fread(&ICPU, sizeof(uint8_t), sizeof(ICPU), savefp); + fread(&PPU, sizeof(uint8_t), sizeof(PPU), savefp); + fread(&DMA, sizeof(uint8_t), sizeof(DMA), savefp); + + fread(Memory.VRAM, sizeof(uint8_t), 0x10000, savefp); + fread(Memory.RAM, sizeof(uint8_t), 0x20000, savefp); + fread(Memory.SRAM, sizeof(uint8_t), 0x20000, savefp); + fread(Memory.FillRAM, sizeof(uint8_t), 0x8000, savefp); + + #ifndef USE_BLARGG_APU + fread(&APU, sizeof(uint8_t), sizeof(APU), savefp); + fread(&IAPU, sizeof(uint8_t), sizeof(IAPU), savefp); + IAPU_RAM_offset = IAPU_RAM_current - IAPU.RAM; + IAPU.PC += IAPU_RAM_offset; + IAPU.DirectPage += IAPU_RAM_offset; + IAPU.WaitAddress1 += IAPU_RAM_offset; + IAPU.WaitAddress2 += IAPU_RAM_offset; + IAPU.RAM = IAPU_RAM_current; + fread(IAPU.RAM, sizeof(uint8_t), 0x10000, savefp); + #else + S9xAPULoadState(buffer); + fread(buffer, sizeof(uint8_t), SPC_SAVE_STATE_BLOCK_SIZE, savefp); + #endif + + SA1.Registers.PC = SA1.PC - SA1.PCBase; + S9xSA1PackStatus(); + fread(&SA1, sizeof(uint8_t), sizeof(SA1), savefp); + fread(&s7r, sizeof(uint8_t), sizeof(s7r), savefp); + fread(&rtc_f9, sizeof(uint8_t), sizeof(rtc_f9), savefp); + fclose(savefp); + + S9xFixSA1AfterSnapshotLoad(); + FixROMSpeed(); + IPPU.ColorsChanged = true; + IPPU.OBJChanged = true; + CPU.InDMA = false; + S9xFixColourBrightness(); + S9xSA1UnpackStatus(); + #ifndef USE_BLARGG_APU + S9xAPUUnpackStatus(); + S9xFixSoundAfterSnapshotLoad(); + #endif + ICPU.ShiftedPB = ICPU.Registers.PB << 16; + ICPU.ShiftedDB = ICPU.Registers.DB << 16; + S9xSetPCBase(ICPU.ShiftedPB + ICPU.Registers.PC); + S9xUnpackStatus(); + S9xFixCycles(); + S9xReschedule(); + } + } + else + { + savefp = fopen(path, "wb"); + if (savefp) + { + #ifdef LAGFIX + S9xPackStatus(); + #ifndef USE_BLARGG_APU + S9xAPUPackStatus(); + #endif + #endif + + S9xUpdateRTC(); + S9xSRTCPreSaveState(); + fwrite(&CPU, sizeof(uint8_t), sizeof(CPU), savefp); + fwrite(&ICPU, sizeof(uint8_t), sizeof(ICPU), savefp); + fwrite(&PPU, sizeof(uint8_t), sizeof(PPU), savefp); + fwrite(&DMA, sizeof(uint8_t), sizeof(DMA), savefp); + + fwrite(Memory.VRAM, sizeof(uint8_t), 0x10000, savefp); + fwrite(Memory.RAM, sizeof(uint8_t), 0x20000, savefp); + fwrite(Memory.SRAM, sizeof(uint8_t), 0x20000, savefp); + fwrite(Memory.FillRAM, sizeof(uint8_t), 0x8000, savefp); + + #ifndef USE_BLARGG_APU + fwrite(&APU, sizeof(uint8_t), sizeof(APU), savefp); + fwrite(&IAPU, sizeof(uint8_t), sizeof(IAPU), savefp); + fwrite(IAPU.RAM, sizeof(uint8_t), 0x10000, savefp); + #else + S9xAPUSaveState(buffer); + fwrite(buffer, sizeof(uint8_t), SPC_SAVE_STATE_BLOCK_SIZE, savefp); + #endif + + SA1.Registers.PC = SA1.PC - SA1.PCBase; + S9xSA1PackStatus(); + fwrite(&SA1, sizeof(uint8_t), sizeof(SA1), savefp); + fwrite(&s7r, sizeof(uint8_t), sizeof(s7r), savefp); + fwrite(&rtc_f9, sizeof(uint8_t), sizeof(rtc_f9), savefp); + fclose(savefp); + } + } + + if (buffer) free(buffer); +} + +void Emulation_Run (void) +{ +#ifndef USE_BLARGG_APU + static int16_t audio_buf[2048]; +#endif + IPPU.RenderThisFrame = true; +#ifdef USE_BLARGG_APU + S9xSetSoundMute(false); +#endif + Settings.HardDisableAudio = false; + + S9xMainLoop(); + +#ifndef USE_BLARGG_APU + samples_to_play += samples_per_frame; + + if (samples_to_play > 512) + { + S9xMixSamples(audio_buf, samples_to_play * 2); + Audio_Write(audio_buf, samples_to_play); + samples_to_play = 0; + } +#else + S9xAudioCallback(); +#endif + + +#ifdef FRAMESKIP + if (IPPU.RenderThisFrame) + { +#endif + Update_Video_Ingame(); +#ifdef FRAMESKIP + IPPU.RenderThisFrame = false; + } + else + { + IPPU.RenderThisFrame = true; + } +#endif +} + + +bool Load_Game_Memory(char* game_path) +{ + uint64_t fps; + CPU.Flags = 0; + + if (!LoadROM(game_path)) + return false; + + Settings.FrameTime = (Settings.PAL ? Settings.FrameTimePAL : Settings.FrameTimeNTSC); + + if (!Settings.PAL) + fps = (SNES_CLOCK_SPEED * 6.0 / (SNES_CYCLES_PER_SCANLINE * SNES_MAX_NTSC_VCOUNTER)); + else + fps = (SNES_CLOCK_SPEED * 6.0 / (SNES_CYCLES_PER_SCANLINE * SNES_MAX_PAL_VCOUNTER)); + + samplerate = SOUND_OUTPUT_FREQUENCY; + Settings.SoundPlaybackRate = samplerate; + +#ifndef USE_BLARGG_APU + samples_per_frame = samplerate / fps; + S9xSetPlaybackRate(Settings.SoundPlaybackRate); +#endif + return true; +} + + +void init_sfc_setting(void) +{ + memset(&Settings, 0, sizeof(Settings)); + Settings.JoystickEnabled = false; + Settings.SoundPlaybackRate = samplerate; + Settings.CyclesPercentage = 100; + + Settings.DisableSoundEcho = false; + Settings.InterpolatedSound = true; + Settings.APUEnabled = true; + + Settings.H_Max = SNES_CYCLES_PER_SCANLINE; + Settings.FrameTimePAL = 20000; + Settings.FrameTimeNTSC = 16667; + Settings.DisableMasterVolume = false; + Settings.Mouse = true; + Settings.SuperScope = true; + Settings.MultiPlayer5 = true; + Settings.ControllerOption = SNES_JOYPAD; +#ifdef USE_BLARGG_APU + Settings.SoundSync = false; +#endif + Settings.ApplyCheats = true; + Settings.HBlankStart = (256 * Settings.H_Max) / SNES_HCOUNTER_MAX; +} + +void Init_SFC(void) +{ + init_sfc_setting(); + S9xInitMemory(); + S9xInitAPU(); + S9xInitDisplay(); + S9xInitGFX(); +#ifdef USE_BLARGG_APU + S9xInitSound(1000, 0); /* just give it a 1 second buffer */ + S9xSetSamplesAvailableCallback(S9xAudioCallback); +#else + S9xInitSound(); +#endif + CPU.SaveStateVersion = 0; +} + +void Deinit_SFC(void) +{ + if (Settings.SPC7110) + Del7110Gfx(); + + S9xDeinitGFX(); + S9xDeinitDisplay(); + S9xDeinitAPU(); + S9xDeinitMemory(); +} + + + +/* Main entrypoint of the emulator */ +int main(int argc, char* argv[]) +{ + int isloaded; + + printf("Starting Snes9x2005\n"); + + if (argc < 2) + { + printf("Specify a ROM to load in memory\n"); + return 0; + } + + snprintf(GameName_emu, sizeof(GameName_emu), "%s", basename(argv[1])); + Init_Video(); + + overclock_cycles = true; + one_c = 4; + slow_one_c = 5; + two_c = 6; + reduce_sprite_flicker = true; + + Audio_Init(); + Init_SFC(); + + isloaded = Load_Game_Memory(argv[1]); + if (!isloaded) + { + printf("Could not load ROM in memory\n"); + return 0; + } + + Init_Configuration(); + + // get the game ready + while (!exit_snes) + { + switch(emulator_state) + { + case 0: + Emulation_Run(); + break; + case 1: + Menu(); + break; + } + } + + Deinit_SFC(); + Audio_Close(); + Video_Close(); + + return 0; +} diff --git a/shell/emu/main.h b/shell/emu/main.h new file mode 100644 index 0000000..43688c3 --- /dev/null +++ b/shell/emu/main.h @@ -0,0 +1,9 @@ +#ifndef MAIN_H +#define MAIN_H + +int ResumeEmulation; +// utility functions that the core requires us to implement +extern const char* S9xGetFilename(const char* extension); +extern const char* S9xGetDirectory(uint32_t dirtype); + +#endif diff --git a/libretro-common/include/boolean.h b/shell/headers/boolean.h index 2c18ef7..2c18ef7 100644 --- a/libretro-common/include/boolean.h +++ b/shell/headers/boolean.h diff --git a/libretro-common/include/retro_inline.h b/shell/headers/retro_inline.h index ffdaa4a..ffdaa4a 100644 --- a/libretro-common/include/retro_inline.h +++ b/shell/headers/retro_inline.h diff --git a/shell/headers/shared.h b/shell/headers/shared.h new file mode 100644 index 0000000..a44f60e --- /dev/null +++ b/shell/headers/shared.h @@ -0,0 +1,31 @@ +#ifndef SHARED_H +#define SHARED_H + +#define SOUND_OUTPUT_FREQUENCY 44100 +#define SOUND_SAMPLES_SIZE 1024 + +/* +#if defined(BITTBOY) +#define SOUND_OUTPUT_FREQUENCY 22050 +#define SOUND_SAMPLES_SIZE 1024 +#elif defined(RS97) +#define SOUND_OUTPUT_FREQUENCY 22050 +#define SOUND_SAMPLES_SIZE 1024 +#elif defined(ARCADEMINI) +#define SOUND_OUTPUT_FREQUENCY 22050 +#define SOUND_SAMPLES_SIZE 1024 +#elif defined(RETROSTONE_1) +#define SOUND_OUTPUT_FREQUENCY 48000 +#define SOUND_SAMPLES_SIZE 2048 +#elif defined(RETROSTONE_2) +#define SOUND_OUTPUT_FREQUENCY 48000 +#define SOUND_SAMPLES_SIZE 2048 +#elif defined(ZIPIT) +#define SOUND_OUTPUT_FREQUENCY 44100 +#define SOUND_SAMPLES_SIZE 1024 +#else +#define SOUND_OUTPUT_FREQUENCY 48000 +#define SOUND_SAMPLES_SIZE 2048 +#endif +*/ +#endif diff --git a/shell/input/input.h b/shell/input/input.h new file mode 100644 index 0000000..a1a89c1 --- /dev/null +++ b/shell/input/input.h @@ -0,0 +1,6 @@ +#ifndef INPUT_H +#define INPUT_H +#include <stdint.h> +uint32_t S9xReadJoypad(int32_t port); +extern uint8_t exit_snes; +#endif diff --git a/shell/input/sdl/input.c b/shell/input/sdl/input.c new file mode 100644 index 0000000..357f7d1 --- /dev/null +++ b/shell/input/sdl/input.c @@ -0,0 +1,74 @@ +#include <SDL/SDL.h> +#include <stdint.h> +#include <stdio.h> +#include <portaudio.h> +#include "main.h" +#include "snes9x.h" +#include "soundux.h" +#include "memmap.h" +#include "apu.h" +#include "cheats.h" +#include "display.h" +#include "gfx.h" +#include "cpuexec.h" +#include "spc7110.h" +#include "srtc.h" +#include "sa1.h" +#include "scaler.h" + +#include "menu.h" +#include "config.h" + +uint8_t *keystate; +uint8_t exit_snes = 0; +extern uint32_t emulator_state; + +#define CASE(realkey, key) \ + if (keystate[realkey]) \ + joypad |= key; \ + else \ + joypad &= ~key; \ + +uint32_t S9xReadJoypad(int32_t port) +{ + SDL_Event event; + static const uint32_t snes_lut[] = + { + SNES_B_MASK, + SNES_Y_MASK, + SNES_SELECT_MASK, + SNES_START_MASK, + SNES_UP_MASK, + SNES_DOWN_MASK, + SNES_LEFT_MASK, + SNES_RIGHT_MASK, + SNES_A_MASK, + SNES_X_MASK, + SNES_TL_MASK, + SNES_TR_MASK + }; + + int32_t i; + uint32_t joypad = 0; + + keystate = SDL_GetKeyState(NULL); + + SDL_PollEvent(&event); + + CASE(SDLK_RETURN, SNES_START_MASK); + CASE(SDLK_ESCAPE, SNES_SELECT_MASK); + CASE(SDLK_LCTRL, SNES_A_MASK); + CASE(SDLK_LALT, SNES_B_MASK); + CASE(SDLK_LSHIFT, SNES_X_MASK); + CASE(SDLK_SPACE, SNES_Y_MASK); + CASE(SDLK_TAB, SNES_TL_MASK); + CASE(SDLK_BACKSPACE, SNES_TR_MASK); + CASE(SDLK_UP, SNES_UP_MASK); + CASE(SDLK_LEFT, SNES_LEFT_MASK); + CASE(SDLK_RIGHT, SNES_RIGHT_MASK); + CASE(SDLK_DOWN, SNES_DOWN_MASK); + + if (keystate[SDLK_END]) emulator_state = 1; + + return joypad; +} diff --git a/shell/menu/config.h b/shell/menu/config.h new file mode 100644 index 0000000..9b71fc2 --- /dev/null +++ b/shell/menu/config.h @@ -0,0 +1,11 @@ +#ifndef CONFIG_H__ +#define CONFIG_H__ + +typedef struct { + int32_t fullscreen; + /* For input remapping */ + uint32_t config_buttons[6][19]; +} t_config; +extern t_config option; + +#endif diff --git a/shell/menu/font_drawing.c b/shell/menu/font_drawing.c new file mode 100644 index 0000000..c1c97b9 --- /dev/null +++ b/shell/menu/font_drawing.c @@ -0,0 +1,131 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> + +#include "video_blit.h" +#include "font_drawing.h" +#include "font_menudata.h" + +extern int32_t screen_width; +//#define setPixel(buffer, x,y,c) + +static inline void setPixel(uint16_t* restrict buffer, uint32_t x, uint32_t y, uint16_t c) +{ + if (x < HOST_WIDTH_RESOLUTION && y < HOST_HEIGHT_RESOLUTION) + { + *((uint16_t* restrict)buffer + ((x) + (y) * HOST_WIDTH_RESOLUTION)) = c; + } +} + +static int32_t isOutlinePixel(uint8_t* charfont, uint32_t x, uint32_t y) +{ + uint32_t xis0 = !x, xis7 = x == 7, yis0 = !y, yis7 = y == 7; + + if(xis0) + { + if (yis0) + { + return !(*charfont & 0x80) && ((*charfont & 0x40) || (charfont[1] & 0x80) || (charfont[1] & 0x40)); + } + else if (yis7) + { + return !(charfont[7] & 0x80) && ((charfont[7] & 0x40) || (charfont[6] & 0x80) || (charfont[6] & 0x40)); + } + else + { + return !(charfont[y] & 0x80) && ( + (charfont[y - 1] & 0x80) || (charfont[y - 1] & 0x40) || + (charfont[y] & 0x40) || + (charfont[y + 1] & 0x80) || (charfont[y + 1] & 0x40)); + } + } + else if (xis7) + { + if (yis0) + { + return !(*charfont & 0x01) && ((*charfont & 0x02) || (charfont[1] & 0x01) || (charfont[1] & 0x02)); + } + else if (yis7) + { + return !(charfont[7] & 0x01) && ((charfont[7] & 0x02) || (charfont[6] & 0x01) || (charfont[6] & 0x02)); + } + else + { + return !(charfont[y] & 0x01) && ( + (charfont[y - 1] & 0x01) || (charfont[y - 1] & 0x02) || + (charfont[y] & 0x02) || + (charfont[y + 1] & 0x01) || (charfont[y + 1] & 0x02)); + } + } + else + { + uint32_t b = 1 << (7 - x); + if (yis0) + { + return !(*charfont & b) && ( + (*charfont & (b << 1)) || (*charfont & (b >> 1)) || + (charfont[1] & (b << 1)) || (charfont[1] & b) || (charfont[1] & (b >> 1))); + } + else if (yis7) + { + return !(charfont[7] & b) && ( + (charfont[7] & (b << 1)) || (charfont[7] & (b >> 1)) || + (charfont[6] & (b << 1)) || (charfont[6] & b) || (charfont[6] & (b >> 1))); + } + else + { + return !(charfont[y] & b) && ( + (charfont[y] & (b << 1)) || (charfont[y] & (b >> 1)) || + (charfont[y - 1] & (b << 1)) || (charfont[y - 1] & b) || (charfont[y - 1] & (b >> 1)) || + (charfont[y + 1] & (b << 1)) || (charfont[y + 1] & b) || (charfont[y + 1] & (b >> 1))); + } + } +} + +static void drawChar(uint16_t* restrict buffer, uint32_t *x, uint32_t *y, uint32_t margin, char ch, uint16_t fc, uint16_t olc) +{ + uint32_t i, j; + uint8_t *charSprite; + if (ch == '\n') + { + *x = margin; + *y += 8; + } + else if(*y < (HOST_HEIGHT_RESOLUTION-1)) + { + charSprite = ch * 8 + n2DLib_font; + // Draw charSprite as monochrome 8*8 image using given color + for(i = 0; i < 8; i++) + { + for(j = 7; j; j--) + { + if((charSprite[i] >> j) & 1) + { + setPixel(buffer, *x + (7 - j), *y + i, fc); + } + else if(isOutlinePixel(charSprite, 7 - j, i)) + { + setPixel(buffer, *x + (7 - j), *y + i, olc); + } + } + } + *x += 8; + } +} + +static void drawString(uint16_t* restrict buffer, uint32_t *x, uint32_t *y, uint32_t _x, const char *str, uint16_t fc, uint16_t olc) +{ + uint32_t i; + size_t size_font; + + size_font = strnlen(str, (HOST_WIDTH_RESOLUTION/8)) + 1; + for(i = 0; i < size_font; i++) + drawChar(buffer, x, y, _x, str[i], fc, olc); +} + +void print_string(const char *s, const uint16_t fg_color, const uint16_t bg_color, uint32_t x, uint32_t y, uint16_t* restrict buffer) +{ + if (!s) return; + + drawString(buffer, &x, &y, 0, s, fg_color, bg_color); +} diff --git a/shell/menu/font_drawing.h b/shell/menu/font_drawing.h new file mode 100644 index 0000000..e18ea04 --- /dev/null +++ b/shell/menu/font_drawing.h @@ -0,0 +1,13 @@ +#ifndef FONT_DRAWING_H +#define FONT_DRAWING_H + +#include <stdint.h> +#include <string.h> + +#define TextWhite 65535 +#define TextRed ((255>>3)<<11) + ((0>>2)<<5) + (0>>3) +#define TextBlue ((0>>3)<<11) + ((0>>2)<<5) + (255>>3) + +void print_string(const char *s, const uint16_t fg_color, const uint16_t bg_color, uint32_t x, uint32_t y, uint16_t* restrict buffer); + +#endif diff --git a/shell/menu/font_menudata.h b/shell/menu/font_menudata.h new file mode 100644 index 0000000..f5a8cbc --- /dev/null +++ b/shell/menu/font_menudata.h @@ -0,0 +1,135 @@ +#ifndef n2DLIB_FONT
+#define n2DLIB_FONT
+
+static uint8_t n2DLib_font[] =
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Char 000 (.) */
+ 0x7E, 0x81, 0xA5, 0x81, 0xBD, 0x99, 0x81, 0x7E, /* Char 001 (.) */
+ 0x7E, 0xFF, 0xDB, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E, /* Char 002 (.) */
+ 0x6C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, /* Char 003 (.) */
+ 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, /* Char 004 (.) */
+ 0x38, 0x7C, 0x38, 0xFE, 0xFE, 0x7C, 0x38, 0x7C, /* Char 005 (.) */
+ 0x10, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x7C, /* Char 006 (.) */
+ 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, /* Char 007 (.) */
+ 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, /* Char 008 (.) */
+ 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00, /* Char 009 (.) */
+ 0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF, /* Char 010 (.) */
+ 0x0F, 0x07, 0x0F, 0x7D, 0xCC, 0xCC, 0xCC, 0x78, /* Char 011 (.) */
+ 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, /* Char 012 (.) */
+ 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x70, 0xF0, 0xE0, /* Char 013 (.) */
+ 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x67, 0xE6, 0xC0, /* Char 014 (.) */
+ 0x99, 0x5A, 0x3C, 0xE7, 0xE7, 0x3C, 0x5A, 0x99, /* Char 015 (.) */
+ 0x80, 0xE0, 0xF8, 0xFE, 0xF8, 0xE0, 0x80, 0x00, /* Char 016 (.) */
+ 0x02, 0x0E, 0x3E, 0xFE, 0x3E, 0x0E, 0x02, 0x00, /* Char 017 (.) */
+ 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x7E, 0x3C, 0x18, /* Char 018 (.) */
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00, /* Char 019 (.) */
+ 0x7F, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x00, /* Char 020 (.) */
+ 0x3E, 0x63, 0x38, 0x6C, 0x6C, 0x38, 0xCC, 0x78, /* Char 021 (.) */
+ 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x00, /* Char 022 (.) */
+ 0x18, 0x3C, 0x7E, 0x18, 0x7E, 0x3C, 0x18, 0xFF, /* Char 023 (.) */
+ 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x00, /* Char 024 (.) */
+ 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, /* Char 025 (.) */
+ 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, /* Char 026 (<=)*/
+ 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, /* Char 027 (.) */
+ 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00, /* Char 028 (.) */
+ 0x00, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x00, 0x00, /* Char 029 (.) */
+ 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x00, 0x00, /* Char 030 (.) */
+ 0x00, 0xFF, 0xFF, 0x7E, 0x3C, 0x18, 0x00, 0x00, /* Char 031 (.) */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Char 032 ( ) */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x40, 0x00, /* Char 033 (!) */
+ 0x90, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Char 034 (") */
+ 0x50, 0x50, 0xF8, 0x50, 0xF8, 0x50, 0x50, 0x00, /* Char 035 (#) */
+ 0x20, 0x78, 0xA0, 0x70, 0x28, 0xF0, 0x20, 0x00, /* Char 036 ($) */
+ 0xC8, 0xC8, 0x10, 0x20, 0x40, 0x98, 0x98, 0x00, /* Char 037 (%) */
+ 0x70, 0x88, 0x50, 0x20, 0x54, 0x88, 0x74, 0x00, /* Char 038 (&) */
+ 0x60, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, /* Char 039 (') */
+ 0x20, 0x40, 0x80, 0x80, 0x80, 0x40, 0x20, 0x00, /* Char 040 (() */
+ 0x20, 0x10, 0x08, 0x08, 0x08, 0x10, 0x20, 0x00, /* Char 041 () */
+ 0x00, 0x20, 0xA8, 0x70, 0x70, 0xA8, 0x20, 0x00, /* Char 042 (*) */
+ 0x00, 0x00, 0x20, 0x20, 0xF8, 0x20, 0x20, 0x00, /* Char 043 (+) */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x20, 0x40, /* Char 044 (,) */
+ 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, /* Char 045 (-) */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, /* Char 046 (.) */
+ 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, /* Char 047 (/) */
+ 0x70, 0x88, 0x98, 0xA8, 0xC8, 0x88, 0x70, 0x00, /* Char 048 (0) */
+ 0x40, 0xC0, 0x40, 0x40, 0x40, 0x40, 0xE0, 0x00, /* Char 049 (1) */
+ 0x70, 0x88, 0x08, 0x10, 0x20, 0x40, 0xF8, 0x00, /* Char 050 (2) */
+ 0x70, 0x88, 0x08, 0x10, 0x08, 0x88, 0x70, 0x00, /* Char 051 (3) */
+ 0x08, 0x18, 0x28, 0x48, 0xFC, 0x08, 0x08, 0x00, /* Char 052 (4) */
+ 0xF8, 0x80, 0x80, 0xF0, 0x08, 0x88, 0x70, 0x00, /* Char 053 (5) */
+ 0x20, 0x40, 0x80, 0xF0, 0x88, 0x88, 0x70, 0x00, /* Char 054 (6) */
+ 0xF8, 0x08, 0x10, 0x20, 0x40, 0x40, 0x40, 0x00, /* Char 055 (7) */
+ 0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x70, 0x00, /* Char 056 (8) */
+ 0x70, 0x88, 0x88, 0x78, 0x08, 0x08, 0x70, 0x00, /* Char 057 (9) */
+ 0x00, 0x00, 0x60, 0x60, 0x00, 0x60, 0x60, 0x00, /* Char 058 (:) */
+ 0x00, 0x00, 0x60, 0x60, 0x00, 0x60, 0x60, 0x20, /* Char 059 (;) */
+ 0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10, 0x00, /* Char 060 (<) */
+ 0x00, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0x00, 0x00, /* Char 061 (=) */
+ 0x80, 0x40, 0x20, 0x10, 0x20, 0x40, 0x80, 0x00, /* Char 062 (>) */
+ 0x78, 0x84, 0x04, 0x08, 0x10, 0x00, 0x10, 0x00, /* Char 063 (?) */
+ 0x70, 0x88, 0x88, 0xA8, 0xB8, 0x80, 0x78, 0x00, /* Char 064 (@) */
+ 0x20, 0x50, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x00, /* Char 065 (A) */
+ 0xF0, 0x88, 0x88, 0xF0, 0x88, 0x88, 0xF0, 0x00, /* Char 066 (B) */
+ 0x70, 0x88, 0x80, 0x80, 0x80, 0x88, 0x70, 0x00, /* Char 067 (C) */
+ 0xF0, 0x88, 0x88, 0x88, 0x88, 0x88, 0xF0, 0x00, /* Char 068 (D) */
+ 0xF8, 0x80, 0x80, 0xE0, 0x80, 0x80, 0xF8, 0x00, /* Char 069 (E) */
+ 0xF8, 0x80, 0x80, 0xE0, 0x80, 0x80, 0x80, 0x00, /* Char 070 (F) */
+ 0x70, 0x88, 0x80, 0x80, 0x98, 0x88, 0x78, 0x00, /* Char 071 (G) */
+ 0x88, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x88, 0x00, /* Char 072 (H) */
+ 0xE0, 0x40, 0x40, 0x40, 0x40, 0x40, 0xE0, 0x00, /* Char 073 (I) */
+ 0x38, 0x10, 0x10, 0x10, 0x10, 0x90, 0x60, 0x00, /* Char 074 (J) */
+ 0x88, 0x90, 0xA0, 0xC0, 0xA0, 0x90, 0x88, 0x00, /* Char 075 (K) */
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xF8, 0x00, /* Char 076 (L) */
+ 0x82, 0xC6, 0xAA, 0x92, 0x82, 0x82, 0x82, 0x00, /* Char 077 (M) */
+ 0x84, 0xC4, 0xA4, 0x94, 0x8C, 0x84, 0x84, 0x00, /* Char 078 (N) */
+ 0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, /* Char 079 (O) */
+ 0xF0, 0x88, 0x88, 0xF0, 0x80, 0x80, 0x80, 0x00, /* Char 080 (P) */
+ 0x70, 0x88, 0x88, 0x88, 0xA8, 0x90, 0x68, 0x00, /* Char 081 (Q) */
+ 0xF0, 0x88, 0x88, 0xF0, 0xA0, 0x90, 0x88, 0x00, /* Char 082 (R) */
+ 0x70, 0x88, 0x80, 0x70, 0x08, 0x88, 0x70, 0x00, /* Char 083 (S) */
+ 0xF8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, /* Char 084 (T) */
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, /* Char 085 (U) */
+ 0x88, 0x88, 0x88, 0x50, 0x50, 0x20, 0x20, 0x00, /* Char 086 (V) */
+ 0x82, 0x82, 0x82, 0x82, 0x92, 0x92, 0x6C, 0x00, /* Char 087 (W) */
+ 0x88, 0x88, 0x50, 0x20, 0x50, 0x88, 0x88, 0x00, /* Char 088 (X) */
+ 0x88, 0x88, 0x88, 0x50, 0x20, 0x20, 0x20, 0x00, /* Char 089 (Y) */
+ 0xF8, 0x08, 0x10, 0x20, 0x40, 0x80, 0xF8, 0x00, /* Char 090 (Z) */
+ 0xE0, 0x80, 0x80, 0x80, 0x80, 0x80, 0xE0, 0x00, /* Char 091 ([) */
+ 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, /* Char 092 (\) */
+ 0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x00, /* Char 093 (]) */
+ 0x20, 0x50, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, /* Char 094 (^) */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, /* Char 095 (_) */
+ 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Char 096 (`) */
+ 0x00, 0x00, 0x70, 0x08, 0x78, 0x88, 0x74, 0x00, /* Char 097 (a) */
+ 0x80, 0x80, 0xB0, 0xC8, 0x88, 0xC8, 0xB0, 0x00, /* Char 098 (b) */
+ 0x00, 0x00, 0x70, 0x88, 0x80, 0x88, 0x70, 0x00, /* Char 099 (c) */
+ 0x08, 0x08, 0x68, 0x98, 0x88, 0x98, 0x68, 0x00, /* Char 100 (d) */
+ 0x00, 0x00, 0x70, 0x88, 0xF8, 0x80, 0x70, 0x00, /* Char 101 (e) */
+ 0x30, 0x48, 0x40, 0xE0, 0x40, 0x40, 0x40, 0x00, /* Char 102 (f) */
+ 0x00, 0x00, 0x34, 0x48, 0x48, 0x38, 0x08, 0x30, /* Char 103 (g) */
+ 0x80, 0x80, 0xB0, 0xC8, 0x88, 0x88, 0x88, 0x00, /* Char 104 (h) */
+ 0x20, 0x00, 0x60, 0x20, 0x20, 0x20, 0x70, 0x00, /* Char 105 (i) */
+ 0x10, 0x00, 0x30, 0x10, 0x10, 0x10, 0x90, 0x60, /* Char 106 (j) */
+ 0x80, 0x80, 0x88, 0x90, 0xA0, 0xD0, 0x88, 0x00, /* Char 107 (k) */
+ 0xC0, 0x40, 0x40, 0x40, 0x40, 0x40, 0xE0, 0x00, /* Char 108 (l) */
+ 0x00, 0x00, 0xEC, 0x92, 0x92, 0x92, 0x92, 0x00, /* Char 109 (m) */
+ 0x00, 0x00, 0xB0, 0xC8, 0x88, 0x88, 0x88, 0x00, /* Char 110 (n) */
+ 0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x70, 0x00, /* Char 111 (o) */
+ 0x00, 0x00, 0xB0, 0xC8, 0xC8, 0xB0, 0x80, 0x80, /* Char 112 (p) */
+ 0x00, 0x00, 0x68, 0x98, 0x98, 0x68, 0x08, 0x08, /* Char 113 (q) */
+ 0x00, 0x00, 0xB0, 0xC8, 0x80, 0x80, 0x80, 0x00, /* Char 114 (r) */
+ 0x00, 0x00, 0x78, 0x80, 0x70, 0x08, 0xF0, 0x00, /* Char 115 (s) */
+ 0x40, 0x40, 0xE0, 0x40, 0x40, 0x50, 0x20, 0x00, /* Char 116 (t) */
+ 0x00, 0x00, 0x88, 0x88, 0x88, 0x98, 0x68, 0x00, /* Char 117 (u) */
+ 0x00, 0x00, 0x88, 0x88, 0x88, 0x50, 0x20, 0x00, /* Char 118 (v) */
+ 0x00, 0x00, 0x82, 0x82, 0x92, 0x92, 0x6C, 0x00, /* Char 119 (w) */
+ 0x00, 0x00, 0x88, 0x50, 0x20, 0x50, 0x88, 0x00, /* Char 120 (x) */
+ 0x00, 0x00, 0x88, 0x88, 0x98, 0x68, 0x08, 0x70, /* Char 121 (y) */
+ 0x00, 0x00, 0xF8, 0x10, 0x20, 0x40, 0xF8, 0x00, /* Char 122 (z) */
+ 0x10, 0x20, 0x20, 0x40, 0x20, 0x20, 0x10, 0x00, /* Char 123 ({) */
+ 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, /* Char 124 (|) */
+ 0x40, 0x20, 0x20, 0x10, 0x20, 0x20, 0x40, 0x00, /* Char 125 (}) */
+ 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Char 126 (~) */
+ 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0x00 /* Char 127 (.) */
+};
+#endif
diff --git a/shell/menu/menu.c b/shell/menu/menu.c new file mode 100644 index 0000000..70096bf --- /dev/null +++ b/shell/menu/menu.c @@ -0,0 +1,597 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <libgen.h> +#include <errno.h> +#include <sys/stat.h> +#include <unistd.h> +#include <time.h> +#include <SDL/SDL.h> + +#include "scaler.h" +#include "font_drawing.h" +#include "sound_output.h" +#include "video_blit.h" +#include "config.h" +#include "menu.h" + +t_config option; +uint32_t emulator_state = 0; + +extern uint8_t exit_snes; + +static char home_path[256], save_path[256], sram_path[256], conf_path[256], rtc_path[256]; +static uint32_t controls_chosen = 0; + +extern SDL_Surface *sdl_screen; +extern char GameName_emu[512]; + +extern void SRAM_file(char* path, uint_fast8_t state); +extern void RTC_Save(char* path, uint_fast8_t state); +extern void SaveState(char* path, uint_fast8_t state); +extern void SRAM_Save(char* path, uint_fast8_t state); + +static uint8_t selectpressed = 0; +static uint8_t save_slot = 0; +static const int8_t upscalers_available = 2 +#ifdef SCALE2X_UPSCALER ++1 +#endif +; + +static void SaveState_Menu(uint_fast8_t load_mode, uint_fast8_t slot) +{ + char tmp[512]; + snprintf(tmp, sizeof(tmp), "%s/%s_%d.sts", save_path, GameName_emu, slot); + SaveState(tmp,load_mode); +} + +static void SRAM_Menu(uint_fast8_t load_mode) +{ + char tmp[512]; + snprintf(tmp, sizeof(tmp), "%s/%s.srm", sram_path, GameName_emu); + SRAM_Save(tmp,load_mode); +} + +static void RTC_Menu(uint_fast8_t load_mode) +{ + char tmp[512]; + snprintf(tmp, sizeof(tmp), "%s/%s.rtc", rtc_path, GameName_emu); + RTC_Save(tmp,load_mode); +} + +static void config_load() +{ + uint_fast8_t i; + char config_path[512]; + FILE* fp; + snprintf(config_path, sizeof(config_path), "%s/%s.cfg", conf_path, GameName_emu); + + fp = fopen(config_path, "rb"); + if (fp) + { + fread(&option, sizeof(option), sizeof(int8_t), fp); + fclose(fp); + } + else + { + /* Default mapping for Horizontal */ + option.config_buttons[0][0] = 273; + option.config_buttons[0][1] = 275; + option.config_buttons[0][2] = 274; + option.config_buttons[0][3] = 276; + + option.config_buttons[0][4] = 306; + option.config_buttons[0][5] = 308; + option.config_buttons[0][6] = 304; + option.config_buttons[0][7] = 32; + + option.config_buttons[0][8] = 9; + option.config_buttons[0][9] = 8; + + option.config_buttons[0][10] = 13; + option.config_buttons[0][11] = 27; + + option.fullscreen = 1; + } +} + +static void config_save() +{ + FILE* fp; + char config_path[512]; + snprintf(config_path, sizeof(config_path), "%s/%s.cfg", conf_path, GameName_emu); + + fp = fopen(config_path, "wb"); + if (fp) + { + fwrite(&option, sizeof(option), sizeof(int8_t), fp); + fclose(fp); + } +} + +static const char* Return_Text_Button(uint32_t button) +{ + switch(button) + { + /* UP button */ + case 273: + return "DPAD UP"; + break; + /* DOWN button */ + case 274: + return "DPAD DOWN"; + break; + /* LEFT button */ + case 276: + return "DPAD LEFT"; + break; + /* RIGHT button */ + case 275: + return "DPAD RIGHT"; + break; + /* A button */ + case 306: + return "A button"; + break; + /* B button */ + case 308: + return "B button"; + break; + /* X button */ + case 304: + return "X button"; + break; + /* Y button */ + case 32: + return "Y button"; + break; + /* L button */ + case 9: + return "L button"; + break; + /* R button */ + case 8: + return "R button"; + break; + /* Power button */ + case 279: + return "L2 button"; + break; + /* Brightness */ + case 51: + return "R2 button"; + break; + /* Volume - */ + case 38: + return "Volume -"; + break; + /* Volume + */ + case 233: + return "Volume +"; + break; + /* Start */ + case 13: + return "Start button"; + break; + /* Select */ + case 1: + return "Select button"; + break; + default: + return "Unknown key"; + break; + case 0: + return "..."; + break; + } +} + +static void Input_Remapping() +{ + SDL_Event Event; + char text[50]; + uint32_t pressed = 0; + int32_t currentselection = 1; + int32_t exit_input = 0; + uint32_t exit_map = 0; + + while(!exit_input) + { + pressed = 0; + SDL_FillRect( backbuffer, NULL, 0 ); + + while (SDL_PollEvent(&Event)) + { + if (Event.type == SDL_KEYDOWN) + { + switch(Event.key.keysym.sym) + { + case SDLK_UP: + currentselection--; + if (currentselection < 1) + { + if (currentselection > 9) currentselection = 12; + else currentselection = 9; + } + break; + case SDLK_DOWN: + currentselection++; + if (currentselection == 10) + { + currentselection = 1; + } + break; + case SDLK_LCTRL: + case SDLK_RETURN: + pressed = 1; + break; + case SDLK_ESCAPE: + option.config_buttons[controls_chosen][currentselection - 1] = 0; + break; + case SDLK_LALT: + exit_input = 1; + break; + case SDLK_LEFT: + if (currentselection > 9) currentselection -= 9; + break; + case SDLK_RIGHT: + if (currentselection < 10) currentselection += 9; + break; + case SDLK_BACKSPACE: + controls_chosen = 1; + break; + case SDLK_TAB: + controls_chosen = 0; + break; + default: + break; + } + } + } + + if (pressed) + { + SDL_Delay(1); + switch(currentselection) + { + default: + exit_map = 0; + while( !exit_map ) + { + SDL_FillRect( backbuffer, NULL, 0 ); + print_string("Please press button for mapping", TextWhite, TextBlue, 37, 108, backbuffer->pixels); + bitmap_scale(0,0,320,240,sdl_screen->w,sdl_screen->h,320,0,(uint16_t* restrict)backbuffer->pixels,(uint16_t* restrict)sdl_screen->pixels); + + while (SDL_PollEvent(&Event)) + { + if (Event.type == SDL_KEYDOWN) + { + if (Event.key.keysym.sym != SDLK_RCTRL) + { + option.config_buttons[controls_chosen][currentselection - 1] = Event.key.keysym.sym; + exit_map = 1; + } + } + } + SDL_Flip(sdl_screen); + } + break; + } + } + + if (currentselection > 12) currentselection = 12; + + if (controls_chosen == 0) print_string("Player 1", TextWhite, 0, 100, 10, backbuffer->pixels); + else print_string("Player 2", TextWhite, 0, 100, 10, backbuffer->pixels); + + print_string("Press [A] to map to a button", TextWhite, TextBlue, 50, 210, backbuffer->pixels); + print_string("Press [B] to Exit", TextWhite, TextBlue, 85, 225, backbuffer->pixels); + + snprintf(text, sizeof(text), "UP : %d\n", (option.config_buttons[controls_chosen][0])); + if (currentselection == 1) print_string(text, TextRed, 0, 5, 25+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, 25+2, backbuffer->pixels); + + snprintf(text, sizeof(text), "DOWN : %d\n", (option.config_buttons[controls_chosen][1])); + if (currentselection == 2) print_string(text, TextRed, 0, 5, 45+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, 45+2, backbuffer->pixels); + + snprintf(text, sizeof(text), "LEFT : %d\n", (option.config_buttons[controls_chosen][2])); + if (currentselection == 3) print_string(text, TextRed, 0, 5, 65+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, 65+2, backbuffer->pixels); + + snprintf(text, sizeof(text), "RIGHT : %d\n", (option.config_buttons[controls_chosen][3])); + if (currentselection == 4) print_string(text, TextRed, 0, 5, 85+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, 85+2, backbuffer->pixels); + + snprintf(text, sizeof(text), "A : %d\n", (option.config_buttons[controls_chosen][4])); + if (currentselection == 5) print_string(text, TextRed, 0, 5, 105+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, 105+2, backbuffer->pixels); + + snprintf(text, sizeof(text), "B : %d\n", (option.config_buttons[controls_chosen][5])); + if (currentselection == 6) print_string(text, TextRed, 0, 5, 125+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, 125+2, backbuffer->pixels); + + snprintf(text, sizeof(text), "X : %d\n", (option.config_buttons[controls_chosen][6])); + if (currentselection == 7) print_string(text, TextRed, 0, 5, 145+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, 145+2, backbuffer->pixels); + + snprintf(text, sizeof(text), "Y : %d\n", (option.config_buttons[controls_chosen][7])); + if (currentselection == 8) print_string(text, TextRed, 0, 5, 165+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, 165+2, backbuffer->pixels); + + snprintf(text, sizeof(text), "L : %d\n", (option.config_buttons[controls_chosen][8])); + if (currentselection == 9) print_string(text, TextRed, 0, 5, 185+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, 185+2, backbuffer->pixels); + + snprintf(text, sizeof(text), "R : %d\n", (option.config_buttons[controls_chosen][9])); + if (currentselection == 10) print_string(text, TextRed, 0, 165, 25+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 165, 25+2, backbuffer->pixels); + + snprintf(text, sizeof(text), "START : %d\n", (option.config_buttons[controls_chosen][10])); + if (currentselection == 11) print_string(text, TextRed, 0, 165, 45+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 165, 45+2, backbuffer->pixels); + + snprintf(text, sizeof(text), "SELECT : %d\n", (option.config_buttons[controls_chosen][11])); + if (currentselection == 12) print_string(text, TextRed, 0, 165, 65+2, backbuffer->pixels); + else print_string(text, TextWhite, 0, 165, 65+2, backbuffer->pixels); + + bitmap_scale(0,0,320,240,sdl_screen->w,sdl_screen->h,320,0,(uint16_t* restrict)backbuffer->pixels,(uint16_t* restrict)sdl_screen->pixels); + SDL_Flip(sdl_screen); + } + + config_save(); +} + +void Menu() +{ + char text[50]; + int16_t pressed = 0; + int16_t currentselection = 1; + SDL_Rect dstRect; + SDL_Event Event; + + Set_Video_Menu(); + + /* Save sram settings each time we bring up the menu */ + SRAM_Menu(0); + RTC_Menu(0); + + while (((currentselection != 1) && (currentselection != 6)) || (!pressed)) + { + pressed = 0; + + SDL_FillRect( backbuffer, NULL, 0 ); + + print_string("SNESEmu - Built on " __DATE__, TextWhite, 0, 5, 15, backbuffer->pixels); + + if (currentselection == 1) print_string("Continue", TextRed, 0, 5, 45, backbuffer->pixels); + else print_string("Continue", TextWhite, 0, 5, 45, backbuffer->pixels); + + snprintf(text, sizeof(text), "Load State %d", save_slot); + + if (currentselection == 2) print_string(text, TextRed, 0, 5, 65, backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, 65, backbuffer->pixels); + + snprintf(text, sizeof(text), "Save State %d", save_slot); + + if (currentselection == 3) print_string(text, TextRed, 0, 5, 85, backbuffer->pixels); + else print_string(text, TextWhite, 0, 5, 85, backbuffer->pixels); + + if (currentselection == 4) + { + switch(option.fullscreen) + { + case 0: + print_string("Scaling : Native", TextRed, 0, 5, 105, backbuffer->pixels); + break; + case 1: + print_string("Scaling : Stretched", TextRed, 0, 5, 105, backbuffer->pixels); + break; + case 2: + print_string("Scaling : Bilinear", TextRed, 0, 5, 105, backbuffer->pixels); + break; + case 3: + print_string("Scaling : EPX/Scale2x", TextRed, 0, 5, 105, backbuffer->pixels); + break; + } + } + else + { + switch(option.fullscreen) + { + case 0: + print_string("Scaling : Native", TextWhite, 0, 5, 105, backbuffer->pixels); + break; + case 1: + print_string("Scaling : Stretched", TextWhite, 0, 5, 105, backbuffer->pixels); + break; + case 2: + print_string("Scaling : Bilinear", TextWhite, 0, 5, 105, backbuffer->pixels); + break; + case 3: + print_string("Scaling : EPX/Scale2x", TextWhite, 0, 5, 105, backbuffer->pixels); + break; + } + } + + if (currentselection == 5) print_string("Input remapping", TextRed, 0, 5, 125, backbuffer->pixels); + else print_string("Input remapping", TextWhite, 0, 5, 125, backbuffer->pixels); + + if (currentselection == 6) print_string("Quit", TextRed, 0, 5, 145, backbuffer->pixels); + else print_string("Quit", TextWhite, 0, 5, 145, backbuffer->pixels); + + print_string("Libretro Fork by gameblabla", TextWhite, 0, 5, 205, backbuffer->pixels); + print_string("Credits: Snes9x dev team, libretro", TextWhite, 0, 5, 225, backbuffer->pixels); + + while (SDL_PollEvent(&Event)) + { + if (Event.type == SDL_KEYDOWN) + { + switch(Event.key.keysym.sym) + { + case SDLK_UP: + currentselection--; + if (currentselection == 0) + currentselection = 6; + break; + case SDLK_DOWN: + currentselection++; + if (currentselection == 7) + currentselection = 1; + break; + case SDLK_END: + case SDLK_RCTRL: + case SDLK_LALT: + pressed = 1; + currentselection = 1; + break; + case SDLK_LCTRL: + case SDLK_RETURN: + pressed = 1; + break; + case SDLK_LEFT: + switch(currentselection) + { + case 2: + case 3: + if (save_slot > 0) save_slot--; + break; + case 4: + option.fullscreen--; + if (option.fullscreen < 0) + option.fullscreen = upscalers_available; + break; + } + break; + case SDLK_RIGHT: + switch(currentselection) + { + case 2: + case 3: + save_slot++; + if (save_slot == 10) + save_slot = 9; + break; + case 4: + option.fullscreen++; + if (option.fullscreen > upscalers_available) + option.fullscreen = 0; + break; + } + break; + default: + break; + } + } + else if (Event.type == SDL_QUIT) + { + currentselection = 6; + pressed = 1; + } + } + + if (pressed) + { + switch(currentselection) + { + case 5: + Input_Remapping(); + break; + case 4 : + option.fullscreen++; + if (option.fullscreen > upscalers_available) + option.fullscreen = 0; + break; + case 2 : + SaveState_Menu(1, save_slot); + currentselection = 1; + break; + case 3 : + SaveState_Menu(0, save_slot); + currentselection = 1; + break; + default: + break; + } + } + + bitmap_scale(0,0,320,240,sdl_screen->w,sdl_screen->h,320,0,(uint16_t* restrict)backbuffer->pixels,(uint16_t* restrict)sdl_screen->pixels); + SDL_Flip(sdl_screen); + } + + SDL_FillRect(sdl_screen, NULL, 0); + SDL_Flip(sdl_screen); + #ifdef SDL_TRIPLEBUF + SDL_FillRect(sdl_screen, NULL, 0); + SDL_Flip(sdl_screen); + #endif + + if (currentselection == 6) + { + exit_snes = 1; + } + + /* Switch back to emulator core */ + emulator_state = 0; + Set_Video_InGame(); +} + +static void Cleanup(void) +{ +#ifdef SCALE2X_UPSCALER + if (scale2x_buf) SDL_FreeSurface(scale2x_buf); +#endif + if (sdl_screen) SDL_FreeSurface(sdl_screen); + if (backbuffer) SDL_FreeSurface(backbuffer); + + // Deinitialize audio and video output + Audio_Close(); + + SDL_Quit(); +} + +void Init_Configuration() +{ + snprintf(home_path, sizeof(home_path), "%s/.snesemu", getenv("HOME")); + + snprintf(conf_path, sizeof(conf_path), "%s/conf", home_path); + snprintf(save_path, sizeof(save_path), "%s/sstates", home_path); + snprintf(sram_path, sizeof(sram_path), "%s/sram", home_path); + snprintf(rtc_path, sizeof(sram_path), "%s/rtc", home_path); + + /* We check first if folder does not exist. + * Let's only try to create it if so in order to decrease boot times. + * */ + + if (access( home_path, F_OK ) == -1) + { + mkdir(home_path, 0755); + } + + if (access( save_path, F_OK ) == -1) + { + mkdir(save_path, 0755); + } + + if (access( conf_path, F_OK ) == -1) + { + mkdir(conf_path, 0755); + } + + if (access( sram_path, F_OK ) == -1) + { + mkdir(sram_path, 0755); + } + + if (access( rtc_path, F_OK ) == -1) + { + mkdir(rtc_path, 0755); + } + + /* Load sram file if it exists */ + SRAM_Menu(1); + RTC_Menu(1); + + config_load(); +} diff --git a/shell/menu/menu.h b/shell/menu/menu.h new file mode 100644 index 0000000..8b81ac3 --- /dev/null +++ b/shell/menu/menu.h @@ -0,0 +1,18 @@ +#ifndef MENU_H +#define MENU_H + +#include <stdint.h> + +#ifndef PATH_MAX +#define PATH_MAX 2048 +#endif + +#define RGB565(r,g,b) ((r << 8) | (g << 3) | (b >> 3)) + +extern uint32_t emulator_state; +extern uint32_t done; + +extern void Menu(void); +extern void Init_Configuration(void); + +#endif diff --git a/shell/other/compatibility_layer.c b/shell/other/compatibility_layer.c new file mode 100644 index 0000000..fea850b --- /dev/null +++ b/shell/other/compatibility_layer.c @@ -0,0 +1,185 @@ +#include <SDL/SDL.h> +#include <portaudio.h> +#include "main.h" +#include "snes9x.h" +#include "soundux.h" +#include "memmap.h" +#include "apu.h" +#include "cheats.h" +#include "display.h" +#include "gfx.h" +#include "cpuexec.h" +#include "spc7110.h" +#include "srtc.h" +#include "sa1.h" +#include "scaler.h" + +const char* S9xGetFilename(const char* in) +{ + static char filename [PATH_MAX + 1]; + char drive [_MAX_DRIVE + 1]; + char dir [_MAX_DIR + 1]; + char fname [_MAX_FNAME + 1]; + char ext [_MAX_EXT + 1]; + _splitpath(Memory.ROMFilename, drive, dir, fname, ext); + _makepath(filename, drive, dir, fname, in); + return filename; +} + +void S9xMessage(int a, int b, const char* msg) +{ + //printf("%s\n", msg); +} + +const char* S9xGetDirectory(uint32_t dirtype) { return NULL; } + +void S9xDeinitDisplay(void) +{ +#ifdef DS2_DMA + if (GFX.Screen_buffer) + AlignedFree(GFX.Screen, PtrAdj.GFXScreen); +#elif defined(_3DS) + if (GFX.Screen_buffer) + linearFree(GFX.Screen_buffer); +#else + if (GFX.Screen_buffer) + free(GFX.Screen_buffer); +#endif + if (GFX.SubScreen_buffer) + free(GFX.SubScreen_buffer); + if (GFX.ZBuffer_buffer) + free(GFX.ZBuffer_buffer); + if (GFX.SubZBuffer_buffer) + free(GFX.SubZBuffer_buffer); + + GFX.Screen = NULL; + GFX.Screen_buffer = NULL; + GFX.SubScreen = NULL; + GFX.SubScreen_buffer = NULL; + GFX.ZBuffer = NULL; + GFX.ZBuffer_buffer = NULL; + GFX.SubZBuffer = NULL; + GFX.SubZBuffer_buffer = NULL; +} + +void S9xInitDisplay(void) +{ + int32_t h = IMAGE_HEIGHT; + int32_t safety = 32; + + GFX.Pitch = IMAGE_WIDTH * 2; +#ifdef DS2_DMA + GFX.Screen_buffer = (uint8_t *) AlignedMalloc(GFX.Pitch * h + safety, 32, &PtrAdj.GFXScreen); +#elif defined(_3DS) + safety = 0x80; + GFX.Screen_buffer = (uint8_t *) linearMemAlign(GFX.Pitch * h + safety, 0x80); +#else + GFX.Screen_buffer = (uint8_t *) malloc(GFX.Pitch * h + safety); +#endif + GFX.SubScreen_buffer = (uint8_t *) malloc(GFX.Pitch * h + safety); + GFX.ZBuffer_buffer = (uint8_t *) malloc((GFX.Pitch >> 1) * h + safety); + GFX.SubZBuffer_buffer = (uint8_t *) malloc((GFX.Pitch >> 1) * h + safety); + + GFX.Screen = GFX.Screen_buffer + safety; + GFX.SubScreen = GFX.SubScreen_buffer + safety; + GFX.ZBuffer = GFX.ZBuffer_buffer + safety; + GFX.SubZBuffer = GFX.SubZBuffer_buffer + safety; + + GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1; +} + +void _splitpath (const char *path, char *drive, char *dir, char *fname, char *ext) +{ + char *slash = strrchr ((char *) path, SLASH_CHAR); + char *dot = strrchr ((char *) path, '.'); + + *drive = '\0'; + + if (dot && slash && dot < slash) + { + dot = 0; + } + + if (!slash) + { + *dir = '\0'; + strcpy (fname, path); + + if (dot) + { + fname[dot - path] = '\0'; + strcpy (ext, dot + 1); + } + else + { + *ext = '\0'; + } + } + else + { + strcpy (dir, path); + dir[slash - path] = '\0'; + strcpy (fname, slash + 1); + + if (dot) + { + fname[(dot - slash) - 1] = '\0'; + strcpy (ext, dot + 1); + } + else + { + *ext = '\0'; + } + } + + return; +} + +void _makepath (char *path, const char *drive, const char *dir, const char *fname,const char *ext) +{ + if (dir && *dir) + { + strcpy (path, dir); + strcat (path, "/"); + } + else + *path = '\0'; + + strcat (path, fname); + + if (ext && *ext) + { + strcat (path, "."); + strcat (path, ext); + } + + return; +} + + +bool S9xReadMousePosition(int32_t which1, int32_t* x, int32_t* y, uint32_t* buttons) +{ + (void) which1; + (void) x; + (void) y; + (void) buttons; + return false; +} + +bool S9xReadSuperScopePosition(int32_t* x, int32_t* y, uint32_t* buttons) +{ + (void) x; + (void) y; + (void) buttons; + return true; +} + +bool JustifierOffscreen(void) +{ + return false; +} + +void JustifierButtons(uint32_t* justifiers) +{ + (void) justifiers; +} diff --git a/shell/scalers/scaler.c b/shell/scalers/scaler.c new file mode 100644 index 0000000..3aeea05 --- /dev/null +++ b/shell/scalers/scaler.c @@ -0,0 +1,139 @@ +#include <stdio.h>
+#include <stdint.h>
+#include "scaler.h"
+
+#define AVERAGE(z, x) ((((z) & 0xF7DEF7DE) >> 1) + (((x) & 0xF7DEF7DE) >> 1))
+#define AVERAGEHI(AB) ((((AB) & 0xF7DE0000) >> 1) + (((AB) & 0xF7DE) << 15))
+#define AVERAGELO(CD) ((((CD) & 0xF7DE) >> 1) + (((CD) & 0xF7DE0000) >> 17))
+
+// Support math
+#define Half(A) (((A) >> 1) & 0x7BEF)
+#define Quarter(A) (((A) >> 2) & 0x39E7)
+// Error correction expressions to piece back the lower bits together
+#define RestHalf(A) ((A) & 0x0821)
+#define RestQuarter(A) ((A) & 0x1863)
+
+// Error correction expressions for quarters of pixels
+#define Corr1_3(A, B) Quarter(RestQuarter(A) + (RestHalf(B) << 1) + RestQuarter(B))
+#define Corr3_1(A, B) Quarter((RestHalf(A) << 1) + RestQuarter(A) + RestQuarter(B))
+
+// Error correction expressions for halves
+#define Corr1_1(A, B) ((A) & (B) & 0x0821)
+
+// Quarters
+#define Weight1_3(A, B) (Quarter(A) + Half(B) + Quarter(B) + Corr1_3(A, B))
+#define Weight3_1(A, B) (Half(A) + Quarter(A) + Quarter(B) + Corr3_1(A, B))
+
+// Halves
+#define Weight1_1(A, B) (Half(A) + Half(B) + Corr1_1(A, B))
+
+
+void upscale_256x240_to_320x240_bilinearish(uint32_t* restrict dst, uint32_t* restrict src, uint_fast16_t width, uint_fast16_t height)
+{
+ uint16_t* Src16 = (uint16_t*) src;
+ uint16_t* Dst16 = (uint16_t*) dst;
+ // There are 64 blocks of 4 pixels horizontally, and 239 of 1 vertically.
+ // Each block of 4x1 becomes 5x1.
+ uint32_t BlockX, BlockY;
+ uint16_t* BlockSrc;
+ uint16_t* BlockDst;
+ for (BlockY = 0; BlockY < height; BlockY++)
+ {
+ BlockSrc = Src16 + BlockY * 512 * 1;
+ BlockDst = Dst16 + BlockY * 320 * 1;
+ for (BlockX = 0; BlockX < 64; BlockX++)
+ {
+ /* Horizontally:
+ * Before(4):
+ * (a)(b)(c)(d)
+ * After(5):
+ * (a)(abbb)(bc)(cccd)(d)
+ */
+
+ // -- Row 1 --
+ uint16_t _1 = *(BlockSrc );
+ *(BlockDst ) = _1;
+ uint16_t _2 = *(BlockSrc + 1);
+ *(BlockDst + 1) = Weight1_3( _1, _2);
+ uint16_t _3 = *(BlockSrc + 2);
+ *(BlockDst + 2) = Weight1_1( _2, _3);
+ uint16_t _4 = *(BlockSrc + 3);
+ *(BlockDst + 3) = Weight3_1( _3, _4);
+ *(BlockDst + 4) = _4;
+
+ BlockSrc += 4;
+ BlockDst += 5;
+ }
+ }
+}
+
+void upscale_256xXXX_to_320x240(uint32_t* restrict dst, uint32_t* restrict src, uint_fast16_t width, uint_fast16_t height)
+{
+ uint_fast16_t midh = 240;
+ uint_fast16_t Eh = 0;
+ uint_fast16_t source = 0;
+ uint_fast16_t dh = 0;
+ uint_fast8_t y, x;
+
+ for (y = 0; y < 240; y++)
+ {
+ source = dh * width;
+
+ for (x = 0; x < 320/10; x++)
+ {
+ register uint32_t ab, cd, ef, gh;
+
+ __builtin_prefetch(dst + 4, 1);
+ __builtin_prefetch(src + source + 4, 0);
+
+ ab = src[source] & 0xF7DEF7DE;
+ cd = src[source + 1] & 0xF7DEF7DE;
+ ef = src[source + 2] & 0xF7DEF7DE;
+ gh = src[source + 3] & 0xF7DEF7DE;
+
+ if(Eh >= midh)
+ {
+ ab = AVERAGE(ab, src[source + width/2]) & 0xF7DEF7DE; // to prevent overflow
+ cd = AVERAGE(cd, src[source + width/2 + 1]) & 0xF7DEF7DE; // to prevent overflow
+ ef = AVERAGE(ef, src[source + width/2 + 2]) & 0xF7DEF7DE; // to prevent overflow
+ gh = AVERAGE(gh, src[source + width/2 + 3]) & 0xF7DEF7DE; // to prevent overflow
+ }
+
+ *dst++ = ab;
+ *dst++ = ((ab >> 17) + ((cd & 0xFFFF) >> 1)) + (cd << 16);
+ *dst++ = (cd >> 16) + (ef << 16);
+ *dst++ = (ef >> 16) + (((ef & 0xFFFF0000) >> 1) + ((gh & 0xFFFF) << 15));
+ *dst++ = gh;
+
+ source += 4;
+
+ }
+ Eh += height; if(Eh >= 240) { Eh -= 240; dh++; }
+ }
+}
+
+
+/* alekmaul's scaler taken from mame4all */
+void bitmap_scale(uint32_t startx, uint32_t starty, uint32_t viswidth, uint32_t visheight, uint32_t newwidth, uint32_t newheight,uint32_t pitchsrc,uint32_t pitchdest, uint16_t* restrict src, uint16_t* restrict dst)
+{
+ uint32_t W,H,ix,iy,x,y;
+ x=startx<<16;
+ y=starty<<16;
+ W=newwidth;
+ H=newheight;
+ ix=(viswidth<<16)/W;
+ iy=(visheight<<16)/H;
+
+ do
+ {
+ uint16_t* restrict buffer_mem=&src[(y>>16)*pitchsrc];
+ W=newwidth; x=startx<<16;
+ do
+ {
+ *dst++=buffer_mem[x>>16];
+ x+=ix;
+ } while (--W);
+ dst+=pitchdest;
+ y+=iy;
+ } while (--H);
+}
diff --git a/shell/scalers/scaler.h b/shell/scalers/scaler.h new file mode 100644 index 0000000..f220800 --- /dev/null +++ b/shell/scalers/scaler.h @@ -0,0 +1,11 @@ +#ifndef SCALER_H
+#define SCALER_H
+
+#include <stdint.h>
+
+/* Generic */
+extern void bitmap_scale(uint32_t startx, uint32_t starty, uint32_t viswidth, uint32_t visheight, uint32_t newwidth, uint32_t newheight,uint32_t pitchsrc,uint32_t pitchdest, uint16_t* restrict src, uint16_t* restrict dst);
+extern void upscale_256xXXX_to_320x240(uint32_t* restrict dst, uint32_t* restrict src, uint_fast16_t width, uint_fast16_t height);
+extern void upscale_256x240_to_320x240_bilinearish(uint32_t* restrict dst, uint32_t* restrict src, uint_fast16_t width, uint_fast16_t height);
+
+#endif
diff --git a/shell/video/retrostone/video_blit.c b/shell/video/retrostone/video_blit.c new file mode 100644 index 0000000..be84dd1 --- /dev/null +++ b/shell/video/retrostone/video_blit.c @@ -0,0 +1,155 @@ +/* Cygne + * + * Copyright notice for this file: + * Copyright (C) 2002 Dox dox@space.pl + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <SDL/SDL.h> +#include <sys/time.h> +#include <sys/types.h> +#include "mednafen.h" +#include "mempatcher.h" +#include "wswan/gfx.h" +#include "wswan/wswan-memory.h" +#include "wswan/sound.h" +#include "wswan/interrupt.h" +#include "wswan/v30mz.h" +#include "wswan/rtc.h" +#include "wswan/gfx.h" +#include "wswan/eeprom.h" + +#include "video_blit.h" +#include "scaler.h" +#include "config.h" + +SDL_Surface *sdl_screen, *backbuffer, *wswan_vs, *wswan_vs_rot; + +uint32_t width_of_surface; +uint32_t* Draw_to_Virtual_Screen; + +void Init_Video() +{ + SDL_Init( SDL_INIT_VIDEO ); + + SDL_ShowCursor(0); + + sdl_screen = SDL_SetVideoMode(0, 0, 16, SDL_HWSURFACE); + + backbuffer = SDL_CreateRGBSurface(SDL_SWSURFACE, HOST_WIDTH_RESOLUTION, HOST_HEIGHT_RESOLUTION, 16, 0,0,0,0); + + wswan_vs = SDL_CreateRGBSurface(SDL_SWSURFACE, INTERNAL_WSWAN_WIDTH, INTERNAL_WSWAN_HEIGHT, 16, 0,0,0,0); + + wswan_vs_rot = SDL_CreateRGBSurface(SDL_SWSURFACE, INTERNAL_WSWAN_HEIGHT, INTERNAL_WSWAN_WIDTH, 16, 0,0,0,0); + + Set_Video_InGame(); +} + +void Set_Video_Menu() +{ + if (sdl_screen->w != HOST_WIDTH_RESOLUTION) + { + memcpy(wswan_vs->pixels, sdl_screen->pixels, (INTERNAL_WSWAN_WIDTH * INTERNAL_WSWAN_HEIGHT)*2); + sdl_screen = SDL_SetVideoMode(HOST_WIDTH_RESOLUTION, HOST_HEIGHT_RESOLUTION, 16, SDL_HWSURFACE); + } +} + +void Set_Video_InGame() +{ + if (sdl_screen->w != HOST_WIDTH_RESOLUTION) sdl_screen = SDL_SetVideoMode(HOST_WIDTH_RESOLUTION, HOST_HEIGHT_RESOLUTION, 16, SDL_HWSURFACE); + Draw_to_Virtual_Screen = wswan_vs->pixels; + width_of_surface = INTERNAL_WSWAN_WIDTH; +} + +void Video_Close() +{ + if (sdl_screen) SDL_FreeSurface(sdl_screen); + if (backbuffer) SDL_FreeSurface(backbuffer); + if (wswan_vs) SDL_FreeSurface(wswan_vs); + if (wswan_vs_rot) SDL_FreeSurface(wswan_vs_rot); + SDL_Quit(); +} + +void Update_Video_Menu() +{ + SDL_Flip(sdl_screen); +} + +static void rotate_90_ccw(uint16_t* restrict dst, uint16_t* restrict src) +{ + int32_t h = 224, w = 144; + src += w * h - 1; + for (int32_t col = w - 1; col >= 0; --col) + { + uint16_t *outcol = dst + col; + for(int32_t row = 0; row < h; ++row, outcol += w) + { + *outcol = *src--; + } + } +} + +void Update_Video_Ingame() +{ + uint32_t internal_width, internal_height, keep_aspect_width, keep_aspect_height; + uint16_t* restrict source_graph; + + if ((Wswan_IsVertical() == 1 && option.orientation_settings != 2) || option.orientation_settings == 1) + { + rotate_90_ccw((uint16_t* restrict)wswan_vs_rot->pixels, (uint16_t* restrict)wswan_vs->pixels); + internal_width = INTERNAL_WSWAN_HEIGHT; + internal_height = INTERNAL_WSWAN_WIDTH; + source_graph = (uint16_t* restrict)wswan_vs_rot->pixels; + keep_aspect_width = ((HOST_HEIGHT_RESOLUTION / INTERNAL_WSWAN_HEIGHT) * INTERNAL_WSWAN_WIDTH) / 2; + if (keep_aspect_width > HOST_WIDTH_RESOLUTION) keep_aspect_width -= HOST_WIDTH_RESOLUTION/2; + keep_aspect_height = HOST_HEIGHT_RESOLUTION; + } + else + { + internal_width = INTERNAL_WSWAN_WIDTH; + internal_height = INTERNAL_WSWAN_HEIGHT; + source_graph = (uint16_t* restrict)wswan_vs->pixels; + keep_aspect_width = HOST_WIDTH_RESOLUTION; + keep_aspect_height = ((HOST_WIDTH_RESOLUTION / INTERNAL_WSWAN_WIDTH) * INTERNAL_WSWAN_HEIGHT); + if (keep_aspect_height > HOST_HEIGHT_RESOLUTION) keep_aspect_height -= HOST_HEIGHT_RESOLUTION/4; + } + + if (SDL_LockSurface(sdl_screen) == 0) + { + switch(option.fullscreen) + { + // Fullscreen + case 0: + bitmap_scale(0,0,internal_width,internal_height,internal_width*2,internal_height*2,internal_width, HOST_WIDTH_RESOLUTION - (internal_width*2),(uint16_t* restrict)source_graph,(uint16_t* restrict)sdl_screen->pixels+(HOST_WIDTH_RESOLUTION-(internal_width*2))/2+(HOST_HEIGHT_RESOLUTION-(internal_height*2))/2*HOST_WIDTH_RESOLUTION); + break; + // Fullscreen + case 1: + bitmap_scale(0, 0, internal_width, internal_height, HOST_WIDTH_RESOLUTION, HOST_HEIGHT_RESOLUTION, internal_width, 0, (uint16_t* restrict)source_graph, (uint16_t* restrict)sdl_screen->pixels); + break; + case 2: + bitmap_scale(0,0,internal_width,internal_height,keep_aspect_width,keep_aspect_height,internal_width, HOST_WIDTH_RESOLUTION - keep_aspect_width,(uint16_t* restrict)source_graph,(uint16_t* restrict)sdl_screen->pixels+(HOST_WIDTH_RESOLUTION-keep_aspect_width)/2+(HOST_HEIGHT_RESOLUTION-keep_aspect_height)/2*HOST_WIDTH_RESOLUTION); + break; + // Hqx + case 3: + break; + } + SDL_UnlockSurface(sdl_screen); + } + SDL_Flip(sdl_screen); +} diff --git a/shell/video/retrostone/video_blit.h b/shell/video/retrostone/video_blit.h new file mode 100644 index 0000000..8e1c81c --- /dev/null +++ b/shell/video/retrostone/video_blit.h @@ -0,0 +1,24 @@ +#ifndef VIDEO_BLIT_H +#define VIDEO_BLIT_H + +#include <SDL/SDL.h> + +#define HOST_WIDTH_RESOLUTION (sdl_screen->w) +#define HOST_HEIGHT_RESOLUTION (sdl_screen->h) + +#define INTERNAL_WSWAN_WIDTH 224 +#define INTERNAL_WSWAN_HEIGHT 144 + +extern SDL_Surface *screen, *wswan_vs, *backbuffer; + +extern uint32_t width_of_surface; +extern uint32_t* Draw_to_Virtual_Screen; + +void Init_Video(); +void Set_Video_Menu(); +void Set_Video_InGame(); +void Close_Video(); +void Update_Video_Menu(); +void Update_Video_Ingame(); + +#endif diff --git a/shell/video/sdl/video_blit.c b/shell/video/sdl/video_blit.c new file mode 100644 index 0000000..9778039 --- /dev/null +++ b/shell/video/sdl/video_blit.c @@ -0,0 +1,132 @@ +/* Cygne + * + * Copyright notice for this file: + * Copyright (C) 2002 Dox dox@space.pl + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <SDL/SDL.h> +#include <sys/time.h> +#include <sys/types.h> +#include "main.h" +#include "snes9x.h" +#include "soundux.h" +#include "memmap.h" +#include "apu.h" +#include "cheats.h" +#include "display.h" +#include "gfx.h" +#include "cpuexec.h" +#include "spc7110.h" +#include "srtc.h" +#include "sa1.h" +#include "scaler.h" + +#include "video_blit.h" +#include "scaler.h" +#include "config.h" + + +SDL_Surface *sdl_screen, *backbuffer; + +uint32_t width_of_surface; +uint32_t* Draw_to_Virtual_Screen; + +void Init_Video() +{ + SDL_Init( SDL_INIT_VIDEO ); + + SDL_ShowCursor(0); + + sdl_screen = SDL_SetVideoMode(HOST_WIDTH_RESOLUTION, HOST_HEIGHT_RESOLUTION, 16, SDL_HWSURFACE); + + backbuffer = SDL_CreateRGBSurface(SDL_SWSURFACE, HOST_WIDTH_RESOLUTION, HOST_HEIGHT_RESOLUTION, 16, 0,0,0,0); + + Set_Video_InGame(); +} + +void Set_Video_Menu() +{ + /*if (sdl_screen->w != HOST_WIDTH_RESOLUTION) + { + sdl_screen = SDL_SetVideoMode(HOST_WIDTH_RESOLUTION, HOST_HEIGHT_RESOLUTION, 16, SDL_HWSURFACE); + }*/ +} + +void Set_Video_InGame() +{ + /*switch(option.fullscreen) + { + // Native + #ifdef SUPPORT_NATIVE_RESOLUTION + case 0: + if (sdl_screen->w != INTERNAL_WSWAN_WIDTH) sdl_screen = SDL_SetVideoMode(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, 16, SDL_HWSURFACE); + Draw_to_Virtual_Screen = sdl_screen->pixels; + width_of_surface = sdl_screen->w; + break; + #endif + default: + if (sdl_screen->w != HOST_WIDTH_RESOLUTION) sdl_screen = SDL_SetVideoMode(HOST_WIDTH_RESOLUTION, HOST_HEIGHT_RESOLUTION, 16, SDL_HWSURFACE); + Draw_to_Virtual_Screen = wswan_vs->pixels; + width_of_surface = INTERNAL_WSWAN_WIDTH; + break; + }*/ +} + +void Video_Close() +{ + if (sdl_screen) SDL_FreeSurface(sdl_screen); + if (backbuffer) SDL_FreeSurface(backbuffer); + SDL_Quit(); +} + +void Update_Video_Menu() +{ + SDL_Flip(sdl_screen); +} + +void Update_Video_Ingame() +{ + uint32_t *s, *d; + uint32_t h, w; + uint8_t PAL = !!(Memory.FillRAM[0x2133] & 4); + + SDL_LockSurface(sdl_screen); + + switch(option.fullscreen) + { + case 0: + s = (uint32_t*) GFX.Screen; + d = (uint32_t*) sdl_screen->pixels + ((sdl_screen->w - IPPU.RenderedScreenWidth)/4 + (sdl_screen->h - IPPU.RenderedScreenHeight) * 160) - (PAL ? 0 : 4*320); + for(uint8_t y = 0; y < IPPU.RenderedScreenHeight; y++, s += IPPU.RenderedScreenWidth, d += sdl_screen->w/2) memmove(d, s, IPPU.RenderedScreenWidth * 2); + + break; + case 1: + upscale_256xXXX_to_320x240((uint32_t*) sdl_screen->pixels, (uint32_t*) GFX.Screen, SNES_WIDTH, PAL ? 240 : 224); + break; + case 2: + if (IPPU.RenderedScreenHeight == 240) upscale_256x240_to_320x240_bilinearish((uint32_t*) sdl_screen->pixels, (uint32_t*) GFX.Screen, SNES_WIDTH, 239); + else upscale_256x240_to_320x240_bilinearish((uint32_t*) sdl_screen->pixels + (160*8), (uint32_t*) GFX.Screen, SNES_WIDTH, 224); + break; + } + //bitmap_scale(0, 0, IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, sdl_screen->w, sdl_screen->h, SNES_WIDTH*2, 0, GFX.Screen, sdl_screen->pixels); + + SDL_UnlockSurface(sdl_screen); + SDL_Flip(sdl_screen); +} diff --git a/shell/video/sdl/video_blit.h b/shell/video/sdl/video_blit.h new file mode 100644 index 0000000..ea28ba9 --- /dev/null +++ b/shell/video/sdl/video_blit.h @@ -0,0 +1,24 @@ +#ifndef VIDEO_BLIT_H +#define VIDEO_BLIT_H + +#include <SDL/SDL.h> + +#define HOST_WIDTH_RESOLUTION 320 +#define HOST_HEIGHT_RESOLUTION 240 + +#define INTERNAL_SNES_WIDTH_NTSC 256 +#define INTERNAL_SNES_HEIGHT_NTSC 224 + +extern SDL_Surface *screen, *backbuffer; + +extern uint32_t width_of_surface; +extern uint32_t* Draw_to_Virtual_Screen; + +void Init_Video(); +void Set_Video_Menu(); +void Set_Video_InGame(); +void Video_Close(); +void Update_Video_Menu(); +void Update_Video_Ingame(); + +#endif diff --git a/source/dsp1.c b/source/dsp1.c index f8a0713..5d8204c 100644 --- a/source/dsp1.c +++ b/source/dsp1.c @@ -3,8 +3,8 @@ #include "snes9x.h" #include "dsp1.h" #include "memmap.h" -#include "dsp1emu.c" -#include "dsp2emu.c" +#include "dsp1emu.h" +#include "dsp2emu.h" void (*SetDSP)(uint8_t, uint16_t) = &DSP1SetByte; uint8_t(*GetDSP)(uint16_t) = &DSP1GetByte; @@ -723,7 +723,7 @@ typedef struct SDSP4 DSP4; -#include "dsp4emu.c" +#include "dsp4emu.h" bool DSP4_init = false; diff --git a/source/dsp1emu.c b/source/dsp1emu.h index e7c3f7d..e7c3f7d 100644 --- a/source/dsp1emu.c +++ b/source/dsp1emu.h diff --git a/source/dsp2emu.c b/source/dsp2emu.h index 48e06c2..48e06c2 100644 --- a/source/dsp2emu.c +++ b/source/dsp2emu.h diff --git a/source/dsp4emu.c b/source/dsp4emu.h index da6e80f..da6e80f 100644 --- a/source/dsp4emu.c +++ b/source/dsp4emu.h diff --git a/source/port.h b/source/port.h index fcfe836..06c5f5e 100644 --- a/source/port.h +++ b/source/port.h @@ -3,6 +3,12 @@ #ifndef _PORT_H_ #define _PORT_H_ +#include <stdio.h> +#include <stddef.h> +#include <stdlib.h> +#include <stdint.h> + +#include <boolean.h> #include <limits.h> #include <string.h> #include <sys/types.h> @@ -62,8 +68,6 @@ void _splitpath(const char* path, char* drive, char* dir, char* fname, char* ext #define FAST_ALIGNED_LSB_WORD_ACCESS #endif -#include <libretro.h> - #define ABS(X) ((X) < 0 ? -(X) : (X)) #define MIN(A,B) ((A) < (B) ? (A) : (B)) #define MAX(A,B) ((A) > (B) ? (A) : (B)) diff --git a/source/snes9x.h b/source/snes9x.h index ad410e1..6f6caf5 100644 --- a/source/snes9x.h +++ b/source/snes9x.h @@ -4,10 +4,11 @@ #define _SNES9X_H_ #include <stdio.h> +#include <stddef.h> #include <stdlib.h> #include <stdint.h> -#include <libretro.h> +#include <boolean.h> #include "port.h" #include "65c816.h" diff --git a/source/srtc.c b/source/srtc.c index 0bfa7d9..3f4f257 100644 --- a/source/srtc.c +++ b/source/srtc.c @@ -371,7 +371,7 @@ void S9xSRTCPreSaveState() Memory.SRAM [s + 12 + MAX_RTC_INDEX] = (uint8_t)(rtc.system_timestamp >> 56); #else /* memmove converted: Different mallocs [Neb] */ - memcpy(&Memory.SRAM [s + 5 + MAX_RTC_INDEX], &rtc.system_timestamp, 8); + memcpy(&Memory.SRAM [s + 5 + MAX_RTC_INDEX], &rtc.system_timestamp, sizeof(time_t)); #endif } } @@ -402,7 +402,7 @@ void S9xSRTCPostLoadState() rtc.system_timestamp |= (Memory.SRAM [s + 12 + MAX_RTC_INDEX] << 56); #else /* memmove converted: Different mallocs [Neb] */ - memcpy(&rtc.system_timestamp, &Memory.SRAM [s + 5 + MAX_RTC_INDEX], 8); + memcpy(&rtc.system_timestamp, &Memory.SRAM [s + 5 + MAX_RTC_INDEX], sizeof(time_t)); #endif S9xUpdateSrtcTime(); } |