Merge branch 'master' into fh/gles-dynload
This commit is contained in:
commit
0dd555c5c8
|
|
@ -0,0 +1,311 @@
|
|||
cmake_minimum_required(VERSION 3.5.0 FATAL_ERROR)
|
||||
|
||||
set(TNAME reicast)
|
||||
|
||||
project(${TNAME})
|
||||
|
||||
enable_language(ASM)
|
||||
|
||||
set(DEBUG_CMAKE ON)
|
||||
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
|
||||
set(reicast_root_path "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
set(reicast_core_path "${reicast_root_path}/core")
|
||||
set(reicast_shell_path "${reicast_root_path}/shell")
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${reicast_shell_path}/cmake")
|
||||
|
||||
|
||||
include(GetGitRevisionDescription)
|
||||
git_describe(GIT_VERSION --tags)
|
||||
configure_file(${reicast_core_path}/version.h.in ${reicast_core_path}/version.h @ONLY)
|
||||
|
||||
|
||||
|
||||
|
||||
## reicast build modules #
|
||||
#
|
||||
|
||||
set(reicast_SRCS "")
|
||||
|
||||
include(config) # configure build settings, must be first
|
||||
|
||||
|
||||
|
||||
### libdreamcast.cmake #########################################################################
|
||||
|
||||
set(d_core ${reicast_core_path})
|
||||
|
||||
file(GLOB_RECURSE hw_SRCS ${d_core}/hw/*.cpp ${d_core}/hw/*.h)
|
||||
|
||||
file(GLOB cfg_SRCS ${d_core}/cfg/*.cpp ${d_core}/cfg/*.h)
|
||||
file(GLOB rend_SRCS ${d_core}/rend/*.cpp ${d_core}/rend/*.h)
|
||||
file(GLOB input_SRCS ${d_core}/input/*.cpp ${d_core}/input/*.h)
|
||||
file(GLOB reios_SRCS ${d_core}/reios/*.cpp ${d_core}/reios/*.h)
|
||||
file(GLOB imgread_SRCS ${d_core}/imgread/*.cpp ${d_core}/imgread/*.h)
|
||||
file(GLOB profiler_SRCS ${d_core}/profiler/*.cpp ${d_core}/profiler/*.h)
|
||||
file(GLOB archive_SRCS ${d_core}/archive/*.cpp ${d_core}/archive/*.h)
|
||||
|
||||
#### option(rend)
|
||||
file(GLOB gl4_SRCS ${d_core}/rend/gl4/*.cpp ${d_core}/rend/gl4/*.h)
|
||||
file(GLOB gles_SRCS ${d_core}/rend/gles/*.cpp ${d_core}/rend/gles/*.h)
|
||||
|
||||
set(core_SRCS
|
||||
${hw_SRCS}
|
||||
${cfg_SRCS}
|
||||
${rend_SRCS}
|
||||
${gl4_SRCS}
|
||||
${gles_SRCS}
|
||||
${input_SRCS}
|
||||
${reios_SRCS}
|
||||
${imgread_SRCS}
|
||||
${profiler_SRCS}
|
||||
${d_core}/archive/archive.cpp ${d_core}/archive/archive.h
|
||||
${d_core}/nullDC.cpp
|
||||
${d_core}/stdclass.cpp
|
||||
${d_core}/dispframe.cpp
|
||||
${d_core}/serialize.cpp
|
||||
)
|
||||
|
||||
|
||||
if(${BUILD_COMPILER} EQUAL ${COMPILER_GCC}) # Add Clang if NOT WIN32 *FIXME*
|
||||
list(APPEND core_SRCS ${archive_SRCS})
|
||||
endif()
|
||||
|
||||
if(${FEAT_SHREC} EQUAL ${DYNAREC_JIT})
|
||||
#
|
||||
if(${HOST_CPU} EQUAL ${CPU_X86})
|
||||
list(APPEND core_SRCS
|
||||
${d_core}/rec-x86/rec_x86_driver.cpp
|
||||
${d_core}/rec-x86/rec_x86_il.cpp
|
||||
${d_core}/rec-x86/rec_x86_asm.cpp # change for linux , rec_lin86_asm.S
|
||||
${d_core}/rec-x86/rec_x86_ngen.h
|
||||
)
|
||||
elseif(${HOST_CPU} EQUAL ${CPU_ARM})
|
||||
list(APPEND core_SRCS
|
||||
${d_core}/rec-ARM/ngen_arm.S
|
||||
${d_core}/rec-ARM/rec_arm.cpp
|
||||
)
|
||||
elseif(${HOST_CPU} EQUAL ${CPU_X64})
|
||||
|
||||
### FIXME: asm with cmake ninja+VC
|
||||
if(${BUILD_COMPILER} EQUAL ${COMPILER_VC})
|
||||
list(APPEND core_SRCS ${d_core}/rec-x64/msvc.asm)
|
||||
endif()
|
||||
|
||||
list(APPEND core_SRCS ${d_core}/rec-x64/rec_x64.cpp ${d_core}/rec-x64/x64_regalloc.h)
|
||||
|
||||
elseif(${HOST_CPU} EQUAL ${CPU_A64})
|
||||
list(APPEND core_SRCS ${d_core}/rec-ARM64/rec_arm64.cpp ${d_core}/rec-ARM64/arm64_regalloc.h)
|
||||
|
||||
else()
|
||||
message(" FEAT_SHREC==DYNAREC_JIT && HOST_CPU Unknown Default add arch or disable rec if not avail.")
|
||||
error()
|
||||
endif()
|
||||
#
|
||||
elseif(${FEAT_SHREC} EQUAL ${DYNAREC_CPP})
|
||||
list(APPEND core_SRCS ${d_core}/rec-cpp/rec_cpp.cpp)
|
||||
endif()
|
||||
|
||||
add_definitions(/DFEAT_HAS_SOFTREND=0)
|
||||
|
||||
|
||||
### deps.cmake #################################################################################
|
||||
|
||||
set(d_deps ${reicast_core_path}/deps)
|
||||
include_directories ("${d_deps}")
|
||||
include_directories ("${d_deps}/picotcp/include")
|
||||
include_directories ("${d_deps}/picotcp/modules")
|
||||
|
||||
file(GLOB xbyak_H ${d_deps}/xbyak/*.h) # include headers into cmake target/project view
|
||||
|
||||
file(GLOB chdr_SRCS ${d_deps}/chdr/*.c)
|
||||
file(GLOB lzma_SRCS ${d_deps}/lzma/*.c)
|
||||
file(GLOB lz_SRCS ${d_deps}/zlib/*.c)
|
||||
file(GLOB lzip_SRCS ${d_deps}/libzip/*.c)
|
||||
file(GLOB lpng_SRCS ${d_deps}/libpng/*.c)
|
||||
file(GLOB lelf_SRCS ${d_deps}/libelf/el*.cpp)
|
||||
file(GLOB crypt_SRCS ${d_deps}/crypto/*.cpp)
|
||||
file(GLOB imgui_SRCS ${d_deps}/imgui/*.cpp)
|
||||
file(GLOB lws_SRCS ${d_deps}/libwebsocket/*.c)
|
||||
|
||||
file(GLOB picoModS ${d_deps}/picotcp/modules/*.c)
|
||||
file(GLOB picoStkS ${d_deps}/picotcp/stack/*.c)
|
||||
set(pico_SRCS ${picoModS} ${picoStkS})
|
||||
|
||||
set(deps_SRCS
|
||||
${lz_SRCS}
|
||||
${lpng_SRCS}
|
||||
${lelf_SRCS}
|
||||
${chdr_SRCS}
|
||||
${crypt_SRCS}
|
||||
${imgui_SRCS}
|
||||
${d_deps}/xbrz/xbrz.cpp
|
||||
${d_deps}/dirent/dirent.c
|
||||
${d_deps}/xxhash/xxhash.c
|
||||
${d_deps}/chdpsr/cdipsr.cpp # sigh, this dir is named chdpsr for some reason ...
|
||||
${d_deps}/coreio/coreio.cpp
|
||||
# ${d_deps}/ifaddrs/ifaddrs.c
|
||||
${xbyak_H}
|
||||
)
|
||||
|
||||
if(${BUILD_COMPILER} EQUAL ${COMPILER_GCC}) # Add Clang if NOT WIN32 *FIXME*
|
||||
list(APPEND deps_SRCS
|
||||
${lzip_SRCS}
|
||||
${lzma_SRCS}
|
||||
${pico_SRCS}
|
||||
)
|
||||
add_definitions(-D_7ZIP_ST -DCHD5_LZMA)
|
||||
endif()
|
||||
|
||||
### libosd.cmake ################################################################################
|
||||
|
||||
|
||||
set(d_aout ${reicast_core_path}/oslib)
|
||||
|
||||
include_directories ("${d_core}/khronos")
|
||||
|
||||
## I really should just glob all of the dirs and ;shrug; if guards don't do it all ##
|
||||
|
||||
set(osd_SRCS "")
|
||||
|
||||
list(APPEND osd_SRCS ${d_aout}/audiostream.cpp)
|
||||
|
||||
if (${HOST_OS} EQUAL ${OS_WINDOWS})
|
||||
|
||||
list(APPEND osd_SRCS ${d_core}/windows/winmain.cpp)
|
||||
list(APPEND osd_SRCS ${d_aout}/audiobackend_directsound.cpp)
|
||||
|
||||
|
||||
link_libraries(dsound.lib winmm.lib xinput.lib wsock32.lib opengl32.lib)
|
||||
|
||||
|
||||
elseif (${HOST_OS} EQUAL ${OS_LINUX} OR ${HOST_OS} EQUAL ${OS_ANDROID})
|
||||
|
||||
list(APPEND osd_SRCS
|
||||
${d_core}/linux/common.cpp
|
||||
${d_core}/linux/context.cpp
|
||||
${d_core}/linux/nixprof/nixprof.cpp
|
||||
|
||||
${d_aout}/audiobackend_oss.cpp # add option
|
||||
) # todo: configure linux audio lib options
|
||||
|
||||
if(NOT ANDROID)
|
||||
list(APPEND osd_SRCS
|
||||
${d_core}/linux-dist/x11.cpp
|
||||
${d_core}/linux-dist/main.cpp
|
||||
${d_core}/linux-dist/evdev.cpp)
|
||||
|
||||
add_definitions(-DSUPPORT_X11) ## don't use GLES ?
|
||||
link_libraries(X11)
|
||||
else()
|
||||
list(APPEND osd_SRCS
|
||||
.//android-studio/reicast/src/main/jni/src/Android.cpp
|
||||
.//android-studio/reicast/src/main/jni/src/utils.cpp
|
||||
# .//android-studio/reicast/src/main/jni/src/XperiaPlay.c
|
||||
)
|
||||
endif() # ANDROID
|
||||
|
||||
add_definitions(-DGLES -DUSE_EVDEV)
|
||||
|
||||
link_libraries(pthread dl rt asound Xext GLESv2 EGL)
|
||||
|
||||
elseif(${HOST_OS} EQUAL ${OS_DARWIN})
|
||||
#
|
||||
list(APPEND objc_SRCS
|
||||
./shell/apple/emulator-osx/emulator-osx/osx-main.mm
|
||||
./shell/apple/emulator-osx/emulator-osx/AppDelegate.swift
|
||||
./shell/apple/emulator-osx/emulator-osx/EmuGLView.swift
|
||||
)
|
||||
|
||||
set_source_files_properties(${objc_SRCS} PROPERTIES COMPILE_FLAGS "-x objective-c++")
|
||||
|
||||
list(APPEND osd_SRCS ${objc_SRCS}
|
||||
${d_osd}/linux/common.cpp
|
||||
${d_osd}/linux/context.cpp
|
||||
${d_osd}/audiobackend/audiobackend_coreaudio.cpp
|
||||
# if NOT USE_SWIFT / ObjC
|
||||
#${d_osd}/apple/osx_osd.cpp
|
||||
)
|
||||
|
||||
else()
|
||||
#
|
||||
message("OS Unhandled")
|
||||
error()
|
||||
#
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
##
|
||||
|
||||
include_directories ("${reicast_core_path}")
|
||||
|
||||
|
||||
|
||||
|
||||
set(reicast_SRCS ${core_SRCS} ${deps_SRCS} ${osd_SRCS})
|
||||
|
||||
add_executable(${TNAME}${binSuffix} ${reicast_SRCS} ${deps_SRCS})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if(APPLE)
|
||||
enable_language(Swift)
|
||||
set_property(TARGET ${TNAME} PROPERTY XCODE_ATTRIBUTE_SWIFT_OBJC_BRIDGING_HEADER "./shell/apple/emulator-osx/emulator-osx/emulator-osx-Bridging-Header.h")
|
||||
|
||||
target_link_libraries(${TNAME}
|
||||
# "-framework Cocoa"
|
||||
# "-framework AppKit"
|
||||
"-framework CoreData"
|
||||
"-framework CoreAudio"
|
||||
"-framework AudioUnit"
|
||||
"-framework AudioToolbox"
|
||||
"-framework Foundation"
|
||||
)
|
||||
|
||||
#### OSX Notes, when not using xcode you have to make app bundle, edit plist and copy, convert MainMenu.xib to nib and copy,
|
||||
#null@devpc:~$ /Users/null/Documents/projects/reicast-emulator/bin/RelWithDebInfo/Reicast.app/Contents/MacOS/reicast ; exit;
|
||||
#2019-03-18 14:28:44.842 reicast[11468:131797] Unknown class _TtC12emulator_osx9EmuGLView in Interface Builder file at path /Users/null/Documents/projects/reicast-emulator/bin/RelWithDebInfo/Reicast.app/Contents/Resources/MainMenu.nib.
|
||||
#2019-03-18 14:28:44.842 reicast[11468:131797] Unknown class _TtC12emulator_osx11AppDelegate in Interface Builder file at path /Users/null/Documents/projects/reicast-emulator/bin/RelWithDebInfo/Reicast.app/Contents/Resources/MainMenu.nib.
|
||||
#2019-03-18 14:28:44.860 reicast[11468:131797] Failed to connect (window) outlet from (NSObject) to (NSWindow): missing setter or instance variable
|
||||
#
|
||||
|
||||
endif() #APPLE
|
||||
|
||||
|
||||
if(DEBUG_CMAKE)
|
||||
message(" ------------------------------------------------")
|
||||
message(" - HOST_OS: ${HOST_OS} - HOST_CPU: ${HOST_CPU} ")
|
||||
message(" - host_os: ${host_os} - host_arch: ${host_arch} ")
|
||||
message(" ------------------------------------------------")
|
||||
message(" C Flags: ${CMAKE_C_FLAGS} ")
|
||||
message(" CXX Flags: ${CMAKE_CXX_FLAGS} ")
|
||||
message(" LINK_DIRS: ${LINK_DIRECTORIES}")
|
||||
message("LINK_FLAGS: ${CMAKE_EXE_LINKER_FLAGS}")
|
||||
message(" ------------------------------------------------\n")
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,220 @@
|
|||
{
|
||||
"environments": [
|
||||
{
|
||||
"environment": "toolchain.generic",
|
||||
"TOOLCHAIN_FILE": "ps4sdk.cmake"
|
||||
}
|
||||
],
|
||||
"configurations": [
|
||||
{
|
||||
"name": "win-x86-Debug",
|
||||
"generator": "Ninja",
|
||||
"description": "TemplateDescription_Localize_x86Debug",
|
||||
"configurationType": "Debug",
|
||||
"inheritEnvironments": [
|
||||
"msvc_x86"
|
||||
],
|
||||
"buildRoot": "${projectDir}\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\build\\${name}\\install",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "-v",
|
||||
"ctestCommandArgs": ""
|
||||
},
|
||||
{
|
||||
"name": "win-x86-Release",
|
||||
"generator": "Ninja",
|
||||
"description": "TemplateDescription_Localize_x86Release",
|
||||
"configurationType": "RelWithDebInfo",
|
||||
"inheritEnvironments": [
|
||||
"msvc_x86"
|
||||
],
|
||||
"buildRoot": "${projectDir}\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\build\\${name}\\install",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "-v",
|
||||
"ctestCommandArgs": ""
|
||||
},
|
||||
{
|
||||
"name": "win-x64-Debug",
|
||||
"generator": "Ninja",
|
||||
"description": "TemplateDescription_Localize_x64Debug",
|
||||
"configurationType": "Debug",
|
||||
"inheritEnvironments": [
|
||||
"msvc_x64_x64"
|
||||
],
|
||||
"buildRoot": "${projectDir}\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\build\\${name}\\install",
|
||||
"cmakeCommandArgs": "-DNINJA=1",
|
||||
"buildCommandArgs": "-v",
|
||||
"ctestCommandArgs": ""
|
||||
},
|
||||
{
|
||||
"name": "win-x64-Release",
|
||||
"generator": "Ninja",
|
||||
"description": "TemplateDescription_Localize_x64Release",
|
||||
"configurationType": "RelWithDebInfo",
|
||||
"inheritEnvironments": [
|
||||
"msvc_x64_x64"
|
||||
],
|
||||
"buildRoot": "${projectDir}\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\build\\${name}\\install",
|
||||
"cmakeCommandArgs": "-DNINJA=1",
|
||||
"buildCommandArgs": "-v",
|
||||
"ctestCommandArgs": ""
|
||||
},
|
||||
{
|
||||
"name": "win-x64-Clang-RelWithDebInfo",
|
||||
"generator": "Ninja",
|
||||
"description": "TemplateDescription_Localize_x64Release",
|
||||
"configurationType": "RelWithDebInfo",
|
||||
"inheritEnvironments": [
|
||||
"msvc_x64_x64"
|
||||
],
|
||||
"buildRoot": "${projectDir}\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\build\\${name}\\install",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "-v",
|
||||
"ctestCommandArgs": "",
|
||||
"variables": [
|
||||
{
|
||||
"name": "CMAKE_C_COMPILER",
|
||||
"value": "clang-cl.exe"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_CXX_COMPILER",
|
||||
"value": "clang-cl.exe"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
// Console SDK's
|
||||
{
|
||||
"name": "PS4 SDK",
|
||||
"generator": "Ninja",
|
||||
"description": "TemplateDescription_Localize_PS4SDK",
|
||||
"configurationType": "RelWithDebInfo",
|
||||
"inheritEnvironments": [
|
||||
"toolchain.generic"
|
||||
],
|
||||
"buildRoot": "${projectDir}\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\build\\${name}\\install",
|
||||
"cmakeCommandArgs": "-DCMAKE_TOOLCHAIN_FILE=${projectDir}\\cmake\\ps4sdk.cmake",
|
||||
"buildCommandArgs": "-v",
|
||||
"ctestCommandArgs": ""
|
||||
},
|
||||
{
|
||||
"name": "NSW SDK",
|
||||
"generator": "Ninja",
|
||||
"description": "TemplateDescription_Localize_PS4SDK",
|
||||
"configurationType": "RelWithDebInfo",
|
||||
"inheritEnvironments": [
|
||||
"toolchain.generic"
|
||||
],
|
||||
"buildRoot": "${projectDir}\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\build\\${name}\\install",
|
||||
"cmakeCommandArgs": "-DCMAKE_TOOLCHAIN_FILE=${projectDir}\\cmake\\devkitA64.cmake",
|
||||
"buildCommandArgs": "-v",
|
||||
"ctestCommandArgs": ""
|
||||
},
|
||||
|
||||
// UWP and VS Gen (temp?)
|
||||
{
|
||||
"name": "uwp-x64-Release",
|
||||
"generator": "Visual Studio 15 2017 Win64",
|
||||
"description": "TemplateDescription_Localize_x64Release",
|
||||
"configurationType": "RelWithDebInfo",
|
||||
"inheritEnvironments": [
|
||||
"msvc_x64_x64"
|
||||
],
|
||||
"buildRoot": "${projectDir}\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\build\\${name}\\install",
|
||||
"cmakeCommandArgs": "-DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=10",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": ""
|
||||
},
|
||||
{
|
||||
"name": "win-x64-MSBuild-Release",
|
||||
"generator": "Visual Studio 15 2017 Win64",
|
||||
"description": "TemplateDescription_Localize_x64Release",
|
||||
"configurationType": "RelWithDebInfo",
|
||||
"inheritEnvironments": [
|
||||
"msvc_x64_x64"
|
||||
],
|
||||
"buildRoot": "${projectDir}\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\build\\${name}\\install",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": ""
|
||||
},
|
||||
{
|
||||
"environments": [
|
||||
{
|
||||
//"MINGW64_ROOT": "C:\\msys64\\mingw64",
|
||||
"BIN_ROOT": "${env.MINGW64_ROOT}\\bin",
|
||||
"FLAVOR": "x86_64-w64-mingw32",
|
||||
"TOOLSET_VERSION": "7.3.0",
|
||||
"PATH": "${env.MINGW64_ROOT}\\bin;${env.MINGW64_ROOT}\\..\\usr\\local\\bin;${env.MINGW64_ROOT}\\..\\usr\\bin;${env.MINGW64_ROOT}\\..\\bin;${env.PATH}",
|
||||
"INCLUDE": "${env.INCLUDE};${env.MINGW64_ROOT}\\include\\c++\\${env.TOOLSET_VERSION};${env.MINGW64_ROOT}\\include\\c++\\${env.TOOLSET_VERSION}\\tr1;${env.MINGW64_ROOT}\\include\\c++\\${env.TOOLSET_VERSION}\\${env.FLAVOR}",
|
||||
"environment": "mingw_64"
|
||||
}
|
||||
],
|
||||
"name": "Mingw64-Release",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "RelWithDebInfo",
|
||||
"inheritEnvironments": [
|
||||
"mingw_64"
|
||||
],
|
||||
"buildRoot": "${projectDir}\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\build\\${name}\\install",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "-v",
|
||||
"ctestCommandArgs": "",
|
||||
"intelliSenseMode": "linux-gcc-x64",
|
||||
"variables": [
|
||||
{
|
||||
"name": "CMAKE_C_COMPILER",
|
||||
"value": "${env.BIN_ROOT}\\gcc.exe"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_CXX_COMPILER",
|
||||
"value": "${env.BIN_ROOT}\\g++.exe"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"environments": [
|
||||
{
|
||||
//"MINGW64_ROOT": "C:\\msys64\\mingw64",
|
||||
"BIN_ROOT": "${env.MINGW64_ROOT}\\bin",
|
||||
"FLAVOR": "x86_64-w64-mingw32",
|
||||
"TOOLSET_VERSION": "7.3.0",
|
||||
"PATH": "${env.MINGW64_ROOT}\\bin;${env.MINGW64_ROOT}\\..\\usr\\local\\bin;${env.MINGW64_ROOT}\\..\\usr\\bin;${env.MINGW64_ROOT}\\..\\bin;${env.PATH}",
|
||||
"INCLUDE": "${env.INCLUDE};${env.MINGW64_ROOT}\\include\\c++\\${env.TOOLSET_VERSION};${env.MINGW64_ROOT}\\include\\c++\\${env.TOOLSET_VERSION}\\tr1;${env.MINGW64_ROOT}\\include\\c++\\${env.TOOLSET_VERSION}\\${env.FLAVOR}",
|
||||
"environment": "mingw_64"
|
||||
}
|
||||
],
|
||||
"name": "Mingw64-Debug",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Debug",
|
||||
"inheritEnvironments": [
|
||||
"mingw_64"
|
||||
],
|
||||
"buildRoot": "${projectDir}\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\build\\${name}\\install",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "-v",
|
||||
"ctestCommandArgs": "",
|
||||
"intelliSenseMode": "linux-gcc-x64",
|
||||
"variables": [
|
||||
{
|
||||
"name": "CMAKE_C_COMPILER",
|
||||
"value": "${env.BIN_ROOT}\\gcc.exe"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_CXX_COMPILER",
|
||||
"value": "${env.BIN_ROOT}\\g++.exe"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
/version.h
|
||||
|
|
@ -21,12 +21,15 @@
|
|||
|
||||
#include "archive.h"
|
||||
#include "7zArchive.h"
|
||||
#ifndef _MSC_VER
|
||||
#include "ZipArchive.h"
|
||||
#endif
|
||||
|
||||
Archive *OpenArchive(const char *path)
|
||||
{
|
||||
std::string base_path(path);
|
||||
|
||||
#ifndef _MSC_VER
|
||||
Archive *sz_archive = new SzArchive();
|
||||
if (sz_archive->Open(base_path.c_str()) || sz_archive->Open((base_path + ".7z").c_str()) || sz_archive->Open((base_path + ".7Z").c_str()))
|
||||
return sz_archive;
|
||||
|
|
@ -36,6 +39,7 @@ Archive *OpenArchive(const char *path)
|
|||
if (zip_archive->Open(base_path.c_str()) || zip_archive->Open((base_path + ".zip").c_str()) || zip_archive->Open((base_path + ".ZIP").c_str()))
|
||||
return zip_archive;
|
||||
delete zip_archive;
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
38
core/build.h
38
core/build.h
|
|
@ -127,10 +127,18 @@
|
|||
#define DC_PLATFORM_AURORA 6 /* Needs to be done, Uses newer 300 mhz sh4 + 150 mhz pvr mbx SoC */
|
||||
|
||||
|
||||
|
||||
//HOST_OS
|
||||
#define OS_WINDOWS 0x10000001
|
||||
#define OS_LINUX 0x10000002
|
||||
#define OS_DARWIN 0x10000003
|
||||
#define OS_IOS 0x10000004
|
||||
#define OS_ANDROID 0x10000005
|
||||
|
||||
#define OS_UWP 0x10000011
|
||||
#define OS_NSW_HOS 0x80000001
|
||||
#define OS_PS4_BSD 0x80000002
|
||||
|
||||
|
||||
//HOST_CPU
|
||||
#define CPU_X86 0x20000001
|
||||
|
|
@ -138,11 +146,16 @@
|
|||
#define CPU_MIPS 0x20000003
|
||||
#define CPU_X64 0x20000004
|
||||
#define CPU_GENERIC 0x20000005 //used for pnacl, emscripten, etc
|
||||
#define CPU_ARM64 0x20000006
|
||||
#define CPU_PPC 0x20000006
|
||||
#define CPU_PPC64 0x20000007
|
||||
#define CPU_A64 0x20000008
|
||||
#define CPU_MIPS64 0x20000009
|
||||
|
||||
//BUILD_COMPILER
|
||||
#define COMPILER_VC 0x30000001
|
||||
#define COMPILER_GCC 0x30000002
|
||||
#define COMPILER_VC 0x30000001
|
||||
#define COMPILER_GCC 0x30000002
|
||||
#define COMPILER_CLANG 0x30000003
|
||||
#define COMPILER_INTEL 0x30000004
|
||||
|
||||
//FEAT_SHREC, FEAT_AREC, FEAT_DSPREC
|
||||
#define DYNAREC_NONE 0x40000001
|
||||
|
|
@ -152,6 +165,8 @@
|
|||
|
||||
//automatic
|
||||
|
||||
#ifndef CMAKE_BUILD
|
||||
|
||||
#if defined(_WIN32) && !defined(TARGET_WIN86) && !defined(TARGET_WIN64)
|
||||
#if !defined(_M_AMD64) && !defined(__x86_64__)
|
||||
#define TARGET_WIN86
|
||||
|
|
@ -233,6 +248,8 @@
|
|||
#define FEAT_DSPREC DYNAREC_NONE
|
||||
#endif
|
||||
|
||||
#endif // !CMAKE_BUILD
|
||||
|
||||
|
||||
#if defined(TARGET_NO_NIXPROF)
|
||||
#define FEAT_HAS_NIXPROF 0
|
||||
|
|
@ -295,6 +312,21 @@
|
|||
#error Dont use HOST_NO_AREC
|
||||
#endif
|
||||
|
||||
|
||||
// Compiler Related
|
||||
|
||||
#define COMPILER_VC_OR_CLANG_WIN32 ((BUILD_COMPILER == COMPILER_VC) || (BUILD_COMPILER == COMPILER_CLANG) && defined(WIN32))
|
||||
|
||||
#if BUILD_COMPILER!=COMPILER_VC
|
||||
#define ATTR_USED __attribute__((used))
|
||||
#define ATTR_UNUSED __attribute__((used))
|
||||
#else
|
||||
#define ATTR_USED
|
||||
#define ATTR_UNUSED
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// TARGET PLATFORM
|
||||
|
||||
#define RAM_SIZE_MAX (32*1024*1024)
|
||||
|
|
|
|||
62
core/core.mk
62
core/core.mk
|
|
@ -5,22 +5,13 @@
|
|||
#LDFLAGS := -Wl,-Map,$(notdir $@).map,--gc-sections -Wl,-O3 -Wl,--sort-common
|
||||
|
||||
RZDCY_SRC_DIR ?= $(call my-dir)
|
||||
VERSION_SRC := $(RZDCY_SRC_DIR)/version/version.cpp
|
||||
VERSION_HEADER := $(RZDCY_SRC_DIR)/version.h
|
||||
|
||||
RZDCY_MODULES := cfg/ hw/arm7/ hw/aica/ hw/holly/ hw/ hw/gdrom/ hw/maple/ hw/modem/ \
|
||||
RZDCY_MODULES := cfg/ hw/arm7/ hw/aica/ hw/holly/ hw/ hw/gdrom/ hw/maple/ \
|
||||
hw/mem/ hw/pvr/ hw/sh4/ hw/sh4/interpr/ hw/sh4/modules/ plugins/ profiler/ oslib/ \
|
||||
hw/extdev/ hw/arm/ hw/naomi/ imgread/ ./ deps/coreio/ deps/zlib/ deps/chdr/ deps/crypto/ \
|
||||
deps/libelf/ deps/chdpsr/ arm_emitter/ rend/ reios/ deps/libpng/ deps/xbrz/ \
|
||||
deps/picotcp/modules/ deps/picotcp/stack/ deps/xxhash/ deps/libzip/ deps/imgui/ \
|
||||
archive/ input/
|
||||
|
||||
ifdef CHD5_LZMA
|
||||
RZDCY_MODULES += deps/lzma/
|
||||
endif
|
||||
|
||||
ifdef CHD5_FLAC
|
||||
RZDCY_MODULES += deps/flac/src/libFLAC/
|
||||
endif
|
||||
deps/xxhash/ deps/libzip/ deps/imgui/ archive/ input/
|
||||
|
||||
ifdef WEBUI
|
||||
RZDCY_MODULES += webui/
|
||||
|
|
@ -31,10 +22,6 @@ ifdef WEBUI
|
|||
endif
|
||||
endif
|
||||
|
||||
ifndef NO_REC
|
||||
RZDCY_MODULES += hw/sh4/dyna/
|
||||
endif
|
||||
|
||||
ifndef NOT_ARM
|
||||
RZDCY_MODULES += rec-ARM/
|
||||
endif
|
||||
|
|
@ -66,10 +53,6 @@ else
|
|||
RZDCY_MODULES += rend/norend/
|
||||
endif
|
||||
|
||||
ifdef HAS_SOFTREND
|
||||
RZDCY_MODULES += rend/soft/
|
||||
endif
|
||||
|
||||
ifndef NO_NIXPROF
|
||||
RZDCY_MODULES += linux/nixprof/
|
||||
endif
|
||||
|
|
@ -90,12 +73,6 @@ ifdef FOR_WINDOWS
|
|||
RZDCY_MODULES += windows/
|
||||
endif
|
||||
|
||||
RZDCY_FILES := $(foreach dir,$(addprefix $(RZDCY_SRC_DIR)/,$(RZDCY_MODULES)),$(wildcard $(dir)*.cpp))
|
||||
RZDCY_FILES += $(foreach dir,$(addprefix $(RZDCY_SRC_DIR)/,$(RZDCY_MODULES)),$(wildcard $(dir)*.cc))
|
||||
RZDCY_FILES += $(foreach dir,$(addprefix $(RZDCY_SRC_DIR)/,$(RZDCY_MODULES)),$(wildcard $(dir)*.c))
|
||||
RZDCY_FILES += $(foreach dir,$(addprefix $(RZDCY_SRC_DIR)/,$(RZDCY_MODULES)),$(wildcard $(dir)*.S))
|
||||
RZDCY_FILES += $(VERSION_SRC)
|
||||
|
||||
ifdef FOR_PANDORA
|
||||
RZDCY_CFLAGS := \
|
||||
$(CFLAGS) -c -O3 \
|
||||
|
|
@ -134,11 +111,17 @@ RZDCY_CFLAGS :=
|
|||
endif
|
||||
|
||||
RZDCY_CFLAGS += -I$(RZDCY_SRC_DIR) -I$(RZDCY_SRC_DIR)/rend/gles -I$(RZDCY_SRC_DIR)/deps \
|
||||
-I$(RZDCY_SRC_DIR)/deps/picotcp/include -I$(RZDCY_SRC_DIR)/deps/picotcp/modules \
|
||||
-I$(RZDCY_SRC_DIR)/deps/vixl -I$(RZDCY_SRC_DIR)/khronos
|
||||
|
||||
ifdef USE_MODEM
|
||||
RZDCY_CFLAGS += -DENABLE_MODEM -I$(RZDCY_SRC_DIR)/deps/picotcp/include -I$(RZDCY_SRC_DIR)/deps/picotcp/modules
|
||||
RZDCY_MODULES += hw/modem/ deps/picotcp/modules/ deps/picotcp/stack/
|
||||
endif
|
||||
|
||||
ifdef NO_REC
|
||||
RZDCY_CFLAGS += -DTARGET_NO_REC
|
||||
RZDCY_CFLAGS += -DTARGET_NO_REC
|
||||
else
|
||||
RZDCY_MODULES += hw/sh4/dyna/
|
||||
endif
|
||||
|
||||
ifdef USE_GLES
|
||||
|
|
@ -147,17 +130,30 @@ endif
|
|||
|
||||
ifdef HAS_SOFTREND
|
||||
RZDCY_CFLAGS += -DTARGET_SOFTREND
|
||||
RZDCY_MODULES += rend/soft/
|
||||
endif
|
||||
|
||||
ifdef CHD5_FLAC
|
||||
RZDCY_CFLAGS += -I$(RZDCY_SRC_DIR)/deps/flac/src/libFLAC/include/ -I$(RZDCY_SRC_DIR)/deps/flac/include
|
||||
RZDCY_CFLAGS += -DCHD5_FLAC -I$(RZDCY_SRC_DIR)/deps/flac/src/libFLAC/include/ -I$(RZDCY_SRC_DIR)/deps/flac/include
|
||||
RZDCY_CFLAGS += -DPACKAGE_VERSION=\"1.3.2\" -DFLAC__HAS_OGG=0 -DFLAC__NO_DLL -DHAVE_LROUND -DHAVE_STDINT_H -DHAVE_STDLIB_H -DHAVE_SYS_PARAM_H
|
||||
RZDCY_MODULES += deps/flac/src/libFLAC/
|
||||
endif
|
||||
|
||||
# 7-Zip/LZMA settings (CHDv5)
|
||||
ifdef CHD5_LZMA
|
||||
RZDCY_MODULES += deps/lzma/
|
||||
RZDCY_CFLAGS += -D_7ZIP_ST -DCHD5_LZMA
|
||||
endif
|
||||
|
||||
RZDCY_CXXFLAGS := $(RZDCY_CFLAGS) -fno-exceptions -fno-rtti -std=gnu++11
|
||||
|
||||
$(VERSION_SRC):
|
||||
echo "const char *version = \"`git describe --tags --always`\";" > $(VERSION_SRC)
|
||||
echo "const char *git_hash = \"`git rev-parse --short HEAD`\";" >> $(VERSION_SRC)
|
||||
echo "const char *build_date = \"`date '+%Y-%m-%d %H:%M:%S %Z'`\";" >> $(VERSION_SRC)
|
||||
RZDCY_FILES := $(foreach dir,$(addprefix $(RZDCY_SRC_DIR)/,$(RZDCY_MODULES)),$(wildcard $(dir)*.cpp))
|
||||
RZDCY_FILES += $(foreach dir,$(addprefix $(RZDCY_SRC_DIR)/,$(RZDCY_MODULES)),$(wildcard $(dir)*.cc))
|
||||
RZDCY_FILES += $(foreach dir,$(addprefix $(RZDCY_SRC_DIR)/,$(RZDCY_MODULES)),$(wildcard $(dir)*.c))
|
||||
RZDCY_FILES += $(foreach dir,$(addprefix $(RZDCY_SRC_DIR)/,$(RZDCY_MODULES)),$(wildcard $(dir)*.S))
|
||||
|
||||
$(VERSION_HEADER):
|
||||
echo "#define REICAST_VERSION \"`git describe --tags --always`\"" > $(VERSION_HEADER)
|
||||
echo "#define GIT_HASH \"`git rev-parse --short HEAD`\"" >> $(VERSION_HEADER)
|
||||
echo "#define BUILD_DATE \"`date '+%Y-%m-%d %H:%M:%S %Z'`\"" >> $(VERSION_HEADER)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
|
||||
Implementation of POSIX directory browsing functions and types for Win32.
|
||||
|
||||
Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com)
|
||||
History: Created March 1997. Updated June 2003 and July 2012.
|
||||
Rights: See end of file.
|
||||
|
||||
*/
|
||||
|
||||
#include "dirent.h"
|
||||
#include <errno.h>
|
||||
#include <io.h> /* _findfirst and _findnext set errno iff they return -1 */
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef ptrdiff_t handle_type; /* C99's intptr_t not sufficiently portable */
|
||||
|
||||
struct DIR
|
||||
{
|
||||
handle_type handle; /* -1 for failed rewind */
|
||||
struct _finddata_t info;
|
||||
struct dirent result; /* d_name null iff first time */
|
||||
char *name; /* null-terminated char string */
|
||||
};
|
||||
|
||||
DIR *opendir(const char *name)
|
||||
{
|
||||
DIR *dir = 0;
|
||||
|
||||
if (name && name[0])
|
||||
{
|
||||
size_t base_length = strlen(name);
|
||||
const char *all = /* search pattern must end with suitable wildcard */
|
||||
strchr("/\\", name[base_length - 1]) ? "*" : "/*";
|
||||
|
||||
if ((dir = (DIR *)malloc(sizeof *dir)) != 0 &&
|
||||
(dir->name = (char *)malloc(base_length + strlen(all) + 1)) != 0)
|
||||
{
|
||||
strcat(strcpy(dir->name, name), all);
|
||||
|
||||
if ((dir->handle =
|
||||
(handle_type)_findfirst(dir->name, &dir->info)) != -1)
|
||||
{
|
||||
dir->result.d_name = 0;
|
||||
}
|
||||
else /* rollback */
|
||||
{
|
||||
free(dir->name);
|
||||
free(dir);
|
||||
dir = 0;
|
||||
}
|
||||
}
|
||||
else /* rollback */
|
||||
{
|
||||
free(dir);
|
||||
dir = 0;
|
||||
errno = ENOMEM;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errno = EINVAL;
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
int closedir(DIR *dir)
|
||||
{
|
||||
int result = -1;
|
||||
|
||||
if (dir)
|
||||
{
|
||||
if (dir->handle != -1)
|
||||
{
|
||||
result = _findclose(dir->handle);
|
||||
}
|
||||
|
||||
free(dir->name);
|
||||
free(dir);
|
||||
}
|
||||
|
||||
if (result == -1) /* map all errors to EBADF */
|
||||
{
|
||||
errno = EBADF;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct dirent *readdir(DIR *dir)
|
||||
{
|
||||
struct dirent *result = 0;
|
||||
|
||||
if (dir && dir->handle != -1)
|
||||
{
|
||||
if (!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1)
|
||||
{
|
||||
result = &dir->result;
|
||||
result->d_name = dir->info.name;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errno = EBADF;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void rewinddir(DIR *dir)
|
||||
{
|
||||
if (dir && dir->handle != -1)
|
||||
{
|
||||
_findclose(dir->handle);
|
||||
dir->handle = (handle_type)_findfirst(dir->name, &dir->info);
|
||||
dir->result.d_name = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
errno = EBADF;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
Copyright Kevlin Henney, 1997, 2003, 2012. All rights reserved.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose is hereby granted without fee, provided
|
||||
that this copyright and permissions notice appear in all copies and
|
||||
derivatives.
|
||||
|
||||
This software is supplied "as is" without express or implied warranty.
|
||||
|
||||
But that said, if there are any problems please get in touch.
|
||||
|
||||
*/
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
#ifndef DIRENT_INCLUDED
|
||||
#define DIRENT_INCLUDED
|
||||
|
||||
/*
|
||||
|
||||
Declaration of POSIX directory browsing functions and types for Win32.
|
||||
|
||||
Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com)
|
||||
History: Created March 1997. Updated June 2003.
|
||||
Rights: See end of file.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct DIR DIR;
|
||||
|
||||
struct dirent
|
||||
{
|
||||
char *d_name;
|
||||
};
|
||||
|
||||
DIR *opendir(const char *);
|
||||
int closedir(DIR *);
|
||||
struct dirent *readdir(DIR *);
|
||||
void rewinddir(DIR *);
|
||||
|
||||
/*
|
||||
|
||||
Copyright Kevlin Henney, 1997, 2003. All rights reserved.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose is hereby granted without fee, provided
|
||||
that this copyright and permissions notice appear in all copies and
|
||||
derivatives.
|
||||
|
||||
This software is supplied "as is" without express or implied warranty.
|
||||
|
||||
But that said, if there are any problems please get in touch.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
#include "aica.h"
|
||||
#include "aica_if.h"
|
||||
#include "sgc_if.h"
|
||||
#include "aica_mem.h"
|
||||
#include <math.h>
|
||||
|
|
@ -180,6 +181,7 @@ template void WriteAicaReg<2>(u32 reg,u32 data);
|
|||
s32 libAICA_Init()
|
||||
{
|
||||
init_mem();
|
||||
aica_Init();
|
||||
|
||||
verify(sizeof(*CommonData)==0x508);
|
||||
verify(sizeof(*DSPData)==0x15C8);
|
||||
|
|
@ -203,9 +205,12 @@ s32 libAICA_Init()
|
|||
return rv_ok;
|
||||
}
|
||||
|
||||
void libAICA_Reset(bool m)
|
||||
void libAICA_Reset(bool manual)
|
||||
{
|
||||
if (!manual)
|
||||
init_mem();
|
||||
sgc_Init();
|
||||
aica_Reset(manual);
|
||||
}
|
||||
|
||||
void libAICA_Term()
|
||||
|
|
|
|||
|
|
@ -13,11 +13,12 @@
|
|||
|
||||
#include <time.h>
|
||||
|
||||
VArray2 aica_ram;
|
||||
VLockedMemory aica_ram;
|
||||
u32 VREG;//video reg =P
|
||||
u32 ARMRST;//arm reset reg
|
||||
u32 rtc_EN=0;
|
||||
int dma_sched_id;
|
||||
u32 RealTimeClock;
|
||||
|
||||
u32 GetRTC_now()
|
||||
{
|
||||
|
|
@ -39,9 +40,9 @@ u32 ReadMem_aica_rtc(u32 addr,u32 sz)
|
|||
switch( addr & 0xFF )
|
||||
{
|
||||
case 0:
|
||||
return settings.dreamcast.RTC>>16;
|
||||
return RealTimeClock>>16;
|
||||
case 4:
|
||||
return settings.dreamcast.RTC &0xFFFF;
|
||||
return RealTimeClock &0xFFFF;
|
||||
case 8:
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -57,16 +58,16 @@ void WriteMem_aica_rtc(u32 addr,u32 data,u32 sz)
|
|||
case 0:
|
||||
if (rtc_EN)
|
||||
{
|
||||
settings.dreamcast.RTC&=0xFFFF;
|
||||
settings.dreamcast.RTC|=(data&0xFFFF)<<16;
|
||||
RealTimeClock&=0xFFFF;
|
||||
RealTimeClock|=(data&0xFFFF)<<16;
|
||||
rtc_EN=0;
|
||||
}
|
||||
return;
|
||||
case 4:
|
||||
if (rtc_EN)
|
||||
{
|
||||
settings.dreamcast.RTC&=0xFFFF0000;
|
||||
settings.dreamcast.RTC|= data&0xFFFF;
|
||||
RealTimeClock&=0xFFFF0000;
|
||||
RealTimeClock|= data&0xFFFF;
|
||||
//TODO: Clean the internal timer ?
|
||||
}
|
||||
return;
|
||||
|
|
@ -153,15 +154,12 @@ void WriteMem_aica_reg(u32 addr,u32 data,u32 sz)
|
|||
//Init/res/term
|
||||
void aica_Init()
|
||||
{
|
||||
//mmnnn ? gotta fill it w/ something
|
||||
RealTimeClock = GetRTC_now();
|
||||
}
|
||||
|
||||
void aica_Reset(bool Manual)
|
||||
{
|
||||
if (!Manual)
|
||||
{
|
||||
aica_ram.Zero();
|
||||
}
|
||||
aica_Init();
|
||||
}
|
||||
|
||||
void aica_Term()
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
#include "types.h"
|
||||
|
||||
extern u32 VREG;
|
||||
extern VArray2 aica_ram;
|
||||
extern VLockedMemory aica_ram;
|
||||
extern u32 RealTimeClock;
|
||||
u32 ReadMem_aica_rtc(u32 addr,u32 sz);
|
||||
void WriteMem_aica_rtc(u32 addr,u32 data,u32 sz);
|
||||
u32 ReadMem_aica_reg(u32 addr,u32 sz);
|
||||
|
|
@ -17,4 +18,4 @@ void aica_Term();
|
|||
|
||||
void aica_sb_Init();
|
||||
void aica_sb_Reset(bool Manual);
|
||||
void aica_sb_Term();
|
||||
void aica_sb_Term();
|
||||
|
|
|
|||
|
|
@ -783,7 +783,7 @@ void sb_Init()
|
|||
maple_Init();
|
||||
aica_sb_Init();
|
||||
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST && defined(ENABLE_MODEM)
|
||||
ModemInit();
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -217,8 +217,10 @@ T DYNACALL ReadMem_area0(u32 addr)
|
|||
{
|
||||
#if DC_PLATFORM == DC_PLATFORM_NAOMI || DC_PLATFORM == DC_PLATFORM_ATOMISWAVE
|
||||
return (T)libExtDevice_ReadMem_A0_006(addr, sz);
|
||||
#else
|
||||
#elif defined(ENABLE_MODEM)
|
||||
return (T)ModemReadMem_A0_006(addr, sz);
|
||||
#else
|
||||
return (T)0;
|
||||
#endif
|
||||
}
|
||||
//map 0x0060 to 0x006F
|
||||
|
|
@ -302,7 +304,7 @@ void DYNACALL WriteMem_area0(u32 addr,T data)
|
|||
{
|
||||
#if DC_PLATFORM == DC_PLATFORM_NAOMI || DC_PLATFORM == DC_PLATFORM_ATOMISWAVE
|
||||
libExtDevice_WriteMem_A0_006(addr, data, sz);
|
||||
#else
|
||||
#elif defined(ENABLE_MODEM)
|
||||
ModemWriteMem_A0_006(addr, data, sz);
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "maple_devs.h"
|
||||
#include "maple_cfg.h"
|
||||
#include "cfg/cfg.h"
|
||||
#include "hw/naomi/naomi_cart.h"
|
||||
|
||||
#define HAS_VMU
|
||||
/*
|
||||
|
|
@ -28,13 +29,31 @@ extern u16 kcode[4];
|
|||
extern u32 vks[4];
|
||||
extern s8 joyx[4],joyy[4];
|
||||
extern u8 rt[4],lt[4];
|
||||
extern bool naomi_test_button;
|
||||
|
||||
u8 GetBtFromSgn(s8 val)
|
||||
{
|
||||
return val+128;
|
||||
}
|
||||
|
||||
u32 awave_button_mapping[] = {
|
||||
AWAVE_SERVICE_KEY, // DC_BTN_C
|
||||
AWAVE_BTN1_KEY, // DC_BTN_B
|
||||
AWAVE_BTN0_KEY, // DC_BTN_A
|
||||
AWAVE_START_KEY, // DC_BTN_START
|
||||
AWAVE_UP_KEY, // DC_DPAD_UP
|
||||
AWAVE_DOWN_KEY, // DC_DPAD_DOWN
|
||||
AWAVE_LEFT_KEY, // DC_DPAD_LEFT
|
||||
AWAVE_RIGHT_KEY, // DC_DPAD_RIGHT
|
||||
AWAVE_TEST_KEY, // DC_BTN_Z
|
||||
AWAVE_BTN3_KEY, // DC_BTN_Y
|
||||
AWAVE_BTN2_KEY, // DC_BTN_X
|
||||
AWAVE_COIN_KEY, // DC_BTN_D
|
||||
// DC_DPAD2_UP
|
||||
// DC_DPAD2_DOWN
|
||||
// DC_DPAD2_LEFT
|
||||
// DC_DPAD2_RIGHT
|
||||
};
|
||||
|
||||
struct MapleConfigMap : IMapleConfigMap
|
||||
{
|
||||
maple_device* dev;
|
||||
|
|
@ -59,17 +78,32 @@ struct MapleConfigMap : IMapleConfigMap
|
|||
|
||||
pjs->kcode=kcode[player_num];
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
pjs->kcode |= 0xF901;
|
||||
#elif DC_PLATFORM == DC_PLATFORM_ATOMISWAVE
|
||||
if (naomi_test_button)
|
||||
pjs->kcode &= ~(1 << 14);
|
||||
// if (!(pjs->kcode & (1 << 9))) // Hack (Y -> service btn)
|
||||
// pjs->kcode &= ~(1 << 13);
|
||||
#endif
|
||||
pjs->kcode |= 0xF901; // mask off DPad2, C, D and Z
|
||||
pjs->joy[PJAI_X1]=GetBtFromSgn(joyx[player_num]);
|
||||
pjs->joy[PJAI_Y1]=GetBtFromSgn(joyy[player_num]);
|
||||
pjs->trigger[PJTI_R]=rt[player_num];
|
||||
pjs->trigger[PJTI_L]=lt[player_num];
|
||||
#elif DC_PLATFORM == DC_PLATFORM_ATOMISWAVE
|
||||
pjs->kcode = 0xFFFF;
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
if ((kcode[player_num] & (1 << i)) == 0)
|
||||
pjs->kcode &= ~awave_button_mapping[i];
|
||||
}
|
||||
pjs->joy[PJAI_X1] = GetBtFromSgn(joyx[player_num]);
|
||||
if (NaomiGameInputs != NULL && NaomiGameInputs->axes[1].name != NULL && NaomiGameInputs->axes[1].type == Half)
|
||||
{
|
||||
// Driving games: put axis 2 on RT (accel) and axis 3 on LT (brake)
|
||||
pjs->joy[PJAI_Y1] = rt[player_num];
|
||||
pjs->joy[PJAI_X2] = lt[player_num];
|
||||
}
|
||||
else
|
||||
{
|
||||
pjs->joy[PJAI_Y1] = GetBtFromSgn(joyy[player_num]);
|
||||
pjs->joy[PJAI_X2] = rt[player_num];
|
||||
pjs->joy[PJAI_Y2] = lt[player_num];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void SetImage(void* img)
|
||||
{
|
||||
|
|
@ -77,6 +111,16 @@ struct MapleConfigMap : IMapleConfigMap
|
|||
}
|
||||
};
|
||||
|
||||
bool maple_atomiswave_coin_chute(int slot)
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
if ((kcode[slot] & (1 << i)) == 0 && awave_button_mapping[i] == AWAVE_COIN_KEY)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void mcfg_Create(MapleDeviceType type, u32 bus, u32 port, s32 player_num = -1)
|
||||
{
|
||||
if (MapleDevices[bus][port] != NULL)
|
||||
|
|
@ -100,17 +144,32 @@ void mcfg_CreateAtomisWaveControllers()
|
|||
// Then other devices on port 2 and 3 for analog axes, light guns, ...
|
||||
mcfg_Create(MDT_SegaController, 0, 5);
|
||||
mcfg_Create(MDT_SegaController, 1, 5);
|
||||
// mcfg_Create(MDT_SegaController, 2, 5, 0);
|
||||
// mcfg_Create(MDT_SegaController, 3, 5, 1);
|
||||
// mcfg_Create(MDT_LightGun, 2, 5, 0);
|
||||
// mcfg_Create(MDT_LightGun, 3, 5, 1);
|
||||
// mcfg_Create(MDT_Mouse, 2, 5, 0);
|
||||
// Guilty Gear Isuka (4P) needs 4 std controllers
|
||||
// Faster Than Speed needs 1 std controller on port 0 (digital inputs) and one on port 2 (analog axes)
|
||||
// Maximum Speed same
|
||||
// Clay Challenge needs 2 std controllers on port 0 & 1 (digital in) and light guns on port 2 & 3
|
||||
// Sports Shooting same
|
||||
// Sega Bass Fishing Challenge needs a mouse (track-ball) on port 3
|
||||
if (NaomiGameInputs != NULL && NaomiGameInputs->axes[0].name != NULL)
|
||||
{
|
||||
// Game needs analog axes
|
||||
mcfg_Create(MDT_SegaController, 2, 5, 0);
|
||||
mcfg_Create(MDT_SegaController, 3, 5, 1);
|
||||
// Faster Than Speed needs 1 std controller on port 0 (digital inputs) and one on port 2 (analog axes)
|
||||
// Maximum Speed same
|
||||
}
|
||||
else if (settings.input.JammaSetup == 1)
|
||||
{
|
||||
// 4 players
|
||||
mcfg_Create(MDT_SegaController, 2, 5);
|
||||
mcfg_Create(MDT_SegaController, 3, 5);
|
||||
}
|
||||
else if (settings.input.JammaSetup == 5)
|
||||
{
|
||||
// Clay Challenge needs 2 std controllers on port 0 & 1 (digital in) and light guns on port 2 & 3
|
||||
// Sports Shooting same
|
||||
mcfg_Create(MDT_LightGun, 2, 5, 0);
|
||||
mcfg_Create(MDT_LightGun, 3, 5, 1);
|
||||
}
|
||||
else if (settings.input.JammaSetup == 3)
|
||||
{
|
||||
// Sega Bass Fishing Challenge needs a mouse (track-ball) on port 2
|
||||
mcfg_Create(MDT_Mouse, 2, 5, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void mcfg_CreateDevices()
|
||||
|
|
|
|||
|
|
@ -68,3 +68,5 @@ void mcfg_CreateAtomisWaveControllers();
|
|||
void mcfg_DestroyDevices();
|
||||
void mcfg_SerializeDevices(void **data, unsigned int *total_size);
|
||||
void mcfg_UnserializeDevices(void **data, unsigned int *total_size);
|
||||
|
||||
bool maple_atomiswave_coin_chute(int slot);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "hw/naomi/naomi.h"
|
||||
#include "hw/naomi/naomi_cart.h"
|
||||
#include "hw/pvr/spg.h"
|
||||
#include "input/gamepad.h"
|
||||
#include <time.h>
|
||||
|
||||
#include "deps/zlib/zlib.h"
|
||||
|
|
@ -198,6 +199,35 @@ struct maple_base: maple_device
|
|||
*/
|
||||
struct maple_sega_controller: maple_base
|
||||
{
|
||||
virtual u32 get_capabilities() {
|
||||
// byte 0: 0 0 0 0 0 0 0 0
|
||||
// byte 1: 0 0 a5 a4 a3 a2 a1 a0
|
||||
// byte 2: R2 L2 D2 U2 D X Y Z
|
||||
// byte 3: R L D U St A B C
|
||||
|
||||
return 0xfe060f00; // 4 analog axes (0-3) X Y A B Start U D L R
|
||||
}
|
||||
|
||||
virtual u32 transform_kcode(u32 kcode) {
|
||||
return kcode;
|
||||
}
|
||||
|
||||
virtual u32 get_analog_axis(int index, const PlainJoystickState &pjs) {
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return pjs.trigger[PJTI_R]; // Right trigger
|
||||
case 1:
|
||||
return pjs.trigger[PJTI_L]; // Left trigger
|
||||
case 2:
|
||||
return pjs.joy[PJAI_X1]; // Stick X
|
||||
case 3:
|
||||
return pjs.joy[PJAI_Y1]; // Stick Y
|
||||
default:
|
||||
return 0x80; // unused
|
||||
}
|
||||
}
|
||||
|
||||
virtual MapleDeviceType get_device_type()
|
||||
{
|
||||
return MDT_SegaController;
|
||||
|
|
@ -215,9 +245,9 @@ struct maple_sega_controller: maple_base
|
|||
|
||||
//struct data
|
||||
//3*4
|
||||
w32( 0xfe060f00);
|
||||
w32( 0);
|
||||
w32( 0);
|
||||
w32(get_capabilities());
|
||||
w32(0);
|
||||
w32(0);
|
||||
|
||||
//1 area code
|
||||
w8(0xFF);
|
||||
|
|
@ -250,26 +280,26 @@ struct maple_sega_controller: maple_base
|
|||
|
||||
//state data
|
||||
//2 key code
|
||||
w16(pjs.kcode);
|
||||
w16(transform_kcode(pjs.kcode));
|
||||
|
||||
//triggers
|
||||
//1 R
|
||||
w8(pjs.trigger[PJTI_R]);
|
||||
w8(get_analog_axis(0, pjs));
|
||||
//1 L
|
||||
w8(pjs.trigger[PJTI_L]);
|
||||
w8(get_analog_axis(1, pjs));
|
||||
|
||||
//joyx
|
||||
//1
|
||||
w8(pjs.joy[PJAI_X1]);
|
||||
w8(get_analog_axis(2, pjs));
|
||||
//joyy
|
||||
//1
|
||||
w8(pjs.joy[PJAI_Y1]);
|
||||
w8(get_analog_axis(3, pjs));
|
||||
|
||||
//not used
|
||||
//1
|
||||
w8(0x80);
|
||||
w8(get_analog_axis(4, pjs));
|
||||
//1
|
||||
w8(0x80);
|
||||
w8(get_analog_axis(5, pjs));
|
||||
}
|
||||
|
||||
return MDRS_DataTransfer;
|
||||
|
|
@ -281,6 +311,38 @@ struct maple_sega_controller: maple_base
|
|||
}
|
||||
};
|
||||
|
||||
struct maple_atomiswave_controller: maple_sega_controller
|
||||
{
|
||||
virtual u32 get_capabilities() override {
|
||||
// byte 0: 0 0 0 0 0 0 0 0
|
||||
// byte 1: 0 0 a5 a4 a3 a2 a1 a0
|
||||
// byte 2: R2 L2 D2 U2 D X Y Z
|
||||
// byte 3: R L D U St A B C
|
||||
|
||||
return 0xff663f00; // 6 analog axes, X Y L2/D2(?) A B C Start U D L R
|
||||
}
|
||||
|
||||
virtual u32 transform_kcode(u32 kcode) override {
|
||||
return kcode | AWAVE_TRIGGER_KEY;
|
||||
}
|
||||
|
||||
virtual u32 get_analog_axis(int index, const PlainJoystickState &pjs) override {
|
||||
switch (index)
|
||||
{
|
||||
case 2:
|
||||
return pjs.joy[PJAI_X1];
|
||||
case 3:
|
||||
return pjs.joy[PJAI_Y1];
|
||||
case 4:
|
||||
return pjs.joy[PJAI_X2];
|
||||
case 5:
|
||||
return pjs.joy[PJAI_Y2];
|
||||
default:
|
||||
return 0x80;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Sega Dreamcast Visual Memory Unit
|
||||
This is pretty much done (?)
|
||||
|
|
@ -1267,6 +1329,10 @@ struct maple_mouse : maple_base
|
|||
|
||||
struct maple_lightgun : maple_base
|
||||
{
|
||||
virtual u32 transform_kcode(u32 kcode) {
|
||||
return kcode | 0xFF01;
|
||||
}
|
||||
|
||||
virtual MapleDeviceType get_device_type()
|
||||
{
|
||||
return MDT_LightGun;
|
||||
|
|
@ -1315,21 +1381,13 @@ struct maple_lightgun : maple_base
|
|||
PlainJoystickState pjs;
|
||||
config->GetInput(&pjs);
|
||||
|
||||
// Also use the mouse buttons
|
||||
if (!(mo_buttons & 4)) // Left button
|
||||
pjs.kcode &= ~4; // A
|
||||
if (!(mo_buttons & 2)) // Right button
|
||||
pjs.kcode &= ~2; // B
|
||||
if (!(mo_buttons & 8)) // Wheel button
|
||||
pjs.kcode &= ~8; // Start
|
||||
|
||||
//caps
|
||||
//4
|
||||
w32(MFID_0_Input);
|
||||
|
||||
//state data
|
||||
//2 key code
|
||||
w16(pjs.kcode | 0xFF01);
|
||||
w16(transform_kcode(pjs.kcode));
|
||||
|
||||
//not used
|
||||
//2
|
||||
|
|
@ -1355,6 +1413,13 @@ struct maple_lightgun : maple_base
|
|||
}
|
||||
};
|
||||
|
||||
struct atomiswave_lightgun : maple_lightgun
|
||||
{
|
||||
virtual u32 transform_kcode(u32 kcode) override {
|
||||
return (kcode & AWAVE_TRIGGER_KEY) == 0 ? ~AWAVE_BTN0_KEY : ~0;
|
||||
}
|
||||
};
|
||||
|
||||
extern u16 kcode[4];
|
||||
extern s8 joyx[4],joyy[4];
|
||||
extern u8 rt[4], lt[4];
|
||||
|
|
@ -1381,20 +1446,29 @@ static u16 getRightTriggerAxis()
|
|||
return rt[0] << 8;
|
||||
}
|
||||
|
||||
NaomiInputMapping Naomi_Mapping = {
|
||||
{ getJoystickXAxis, getJoystickYAxis, getRightTriggerAxis, getLeftTriggerAxis },
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 },
|
||||
{ 0x40, 0x01, 0x02, 0x80, 0x20, 0x10, 0x08, 0x04, 0, 0x80, 0x40, 0, 0 },
|
||||
// SERVICE BTN1 BTN0 START UP DOWN LEFT RIGHT BTN2 BTN3
|
||||
u32 naomi_button_mapping[] = {
|
||||
NAOMI_SERVICE_KEY, // DC_BTN_C
|
||||
NAOMI_BTN1_KEY, // DC_BTN_B
|
||||
NAOMI_BTN0_KEY, // DC_BTN_A
|
||||
NAOMI_START_KEY, // DC_BTN_START
|
||||
NAOMI_UP_KEY, // DC_DPAD_UP
|
||||
NAOMI_DOWN_KEY, // DC_DPAD_DOWN
|
||||
NAOMI_LEFT_KEY, // DC_DPAD_LEFT
|
||||
NAOMI_RIGHT_KEY, // DC_DPAD_RIGHT
|
||||
NAOMI_TEST_KEY, // DC_BTN_Z
|
||||
NAOMI_BTN3_KEY, // DC_BTN_Y
|
||||
NAOMI_BTN2_KEY, // DC_BTN_X
|
||||
NAOMI_COIN_KEY, // DC_BTN_D
|
||||
// DC_DPAD2_UP
|
||||
// DC_DPAD2_DOWN
|
||||
// DC_DPAD2_LEFT
|
||||
// DC_DPAD2_RIGHT
|
||||
};
|
||||
|
||||
/*
|
||||
* Sega JVS I/O board
|
||||
*/
|
||||
bool coin_chute;
|
||||
static bool old_coin_chute;
|
||||
static int coin_count;
|
||||
bool naomi_test_button = false;
|
||||
static bool old_coin_chute[4];
|
||||
static int coin_count[4];
|
||||
|
||||
struct maple_naomi_jamma;
|
||||
|
||||
|
|
@ -2313,63 +2387,56 @@ u32 jvs_io_board::handle_jvs_message(u8 *buffer_in, u32 length_in, u8 *buffer_ou
|
|||
{
|
||||
JVS_STATUS1(); // report byte
|
||||
|
||||
LOGJVS("btns ");
|
||||
JVS_OUT(naomi_test_button ? 0x80 : 0x00); // test, tilt1, tilt2, tilt3, unused, unused, unused, unused
|
||||
// FIXME in-lst mapping
|
||||
u8 buttons[8] = { 0 };
|
||||
u32 keycode = ~kcode[0];
|
||||
for (int i = 0; i < 16; i++)
|
||||
if ((keycode & (1 << i)) != 0)
|
||||
{
|
||||
buttons[Naomi_Mapping.button_mapping_byte[i]] |= Naomi_Mapping.button_mapping_mask[i];
|
||||
}
|
||||
for (int player = 0; player < buffer_in[cmdi + 1]; player++)
|
||||
u16 buttons[4] = { 0 };
|
||||
for (int player = 0; player < buffer_in[cmdi + 1] && first_player + player < ARRAY_SIZE(kcode); player++)
|
||||
{
|
||||
u8 *cur_btns = &buttons[(first_player + player) * 2];
|
||||
LOGJVS("P%d %02x ", player + 1 + first_player, cur_btns[0]);
|
||||
JVS_OUT(cur_btns[0]);
|
||||
if (buffer_in[cmdi + 2] == 2)
|
||||
u32 keycode = ~kcode[first_player + player];
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
LOGJVS("%02x ", cur_btns[1]);
|
||||
JVS_OUT(cur_btns[1]);
|
||||
if ((keycode & (1 << i)) != 0)
|
||||
buttons[player] |= naomi_button_mapping[i];
|
||||
}
|
||||
}
|
||||
|
||||
LOGJVS("btns ");
|
||||
JVS_OUT((buttons[0] & NAOMI_TEST_KEY) ? 0x80 : 0x00); // test, tilt1, tilt2, tilt3, unused, unused, unused, unused
|
||||
for (int player = 0; player < buffer_in[cmdi + 1]; player++)
|
||||
{
|
||||
u16 cur_btns = first_player + player < ARRAY_SIZE(buttons) ? buttons[first_player + player] : 0;
|
||||
LOGJVS("P%d %02x ", player + 1 + first_player, cur_btns >> 8);
|
||||
JVS_OUT(cur_btns >> 8);
|
||||
if (buffer_in[cmdi + 2] == 2)
|
||||
{
|
||||
LOGJVS("%02x ", cur_btns & 0xFF);
|
||||
JVS_OUT(cur_btns);
|
||||
}
|
||||
}
|
||||
// for (int player = 0; player < jvs_request[channel][cmdi + 1]; player++)
|
||||
// {
|
||||
// u32 keycode = ~kcode[player];
|
||||
// if (keycode & DC_BTN_C)
|
||||
// keycode |= 0xFFff;
|
||||
//
|
||||
// if (jvs_request[channel][cmdi + 2] == 1)
|
||||
// JVS_OUT(keycode);
|
||||
// else
|
||||
// w16(keycode);
|
||||
// }
|
||||
cmdi += 3;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x21: // Read coins
|
||||
{
|
||||
if (coin_chute && !old_coin_chute)
|
||||
coin_count++;
|
||||
old_coin_chute = coin_chute;
|
||||
JVS_STATUS1(); // report byte
|
||||
LOGJVS("coins ");
|
||||
for (int slot = 0; slot < buffer_in[cmdi + 1]; slot++)
|
||||
{
|
||||
if (slot == 0)
|
||||
bool coin_chute = false;
|
||||
u32 keycode = ~kcode[first_player + slot];
|
||||
for (int i = 0; i < 16 && !coin_chute; i++)
|
||||
{
|
||||
LOGJVS("0:%d ", coin_count);
|
||||
JVS_OUT((coin_count >> 8) & 0x3F); // status (2 highest bits, 0: normal), coin count MSB
|
||||
JVS_OUT(coin_count); // coin count LSB
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGJVS("%d:0 ", slot);
|
||||
JVS_OUT(0);
|
||||
JVS_OUT(0);
|
||||
if (naomi_button_mapping[i] == NAOMI_COIN_KEY && (keycode & (1 << i)) != 0)
|
||||
coin_chute = true;
|
||||
}
|
||||
if (coin_chute && !old_coin_chute[first_player + slot])
|
||||
coin_count[first_player + slot] += 1;
|
||||
old_coin_chute[first_player + slot] = coin_chute;
|
||||
|
||||
LOGJVS("%d:%d ", slot + 1 + first_player, coin_count[first_player + slot]);
|
||||
// status (2 highest bits, 0: normal), coin count MSB
|
||||
JVS_OUT((coin_count[first_player + slot] >> 8) & 0x3F);
|
||||
// coin count LSB
|
||||
JVS_OUT(coin_count[first_player + slot]);
|
||||
}
|
||||
cmdi += 2;
|
||||
}
|
||||
|
|
@ -2393,34 +2460,50 @@ u32 jvs_io_board::handle_jvs_message(u8 *buffer_in, u32 length_in, u8 *buffer_ou
|
|||
}
|
||||
LOGJVS("x,y:%4x,%4x ", x, y);
|
||||
JVS_OUT(x >> 8); // X, MSB
|
||||
JVS_OUT(x); // X, LSB
|
||||
JVS_OUT(x); // X, LSB
|
||||
JVS_OUT(y >> 8); // Y, MSB
|
||||
JVS_OUT(y); // Y, LSB
|
||||
JVS_OUT(y); // Y, LSB
|
||||
axis = 2;
|
||||
}
|
||||
|
||||
int full_axis_count = 0;
|
||||
int half_axis_count = 0;
|
||||
for (; axis < buffer_in[cmdi + 1]; axis++)
|
||||
{
|
||||
// FIXME Need to know how many axes per player for proper mapping
|
||||
u16 axis_value;
|
||||
if (axis + first_player * 4 < 8 && Naomi_Mapping.axis[axis + first_player * 4] != NULL)
|
||||
axis_value = Naomi_Mapping.axis[axis + first_player * 4]();
|
||||
if (NaomiGameInputs != NULL
|
||||
&& axis < ARRAY_SIZE(NaomiGameInputs->axes)
|
||||
&& NaomiGameInputs->axes[axis].name != NULL
|
||||
&& NaomiGameInputs->axes[axis].type == Half)
|
||||
{
|
||||
if (half_axis_count == 0)
|
||||
axis_value = rt[first_player] << 8;
|
||||
else if (half_axis_count == 1)
|
||||
axis_value = lt[first_player] << 8;
|
||||
else
|
||||
axis_value = 0;
|
||||
half_axis_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (axis) {
|
||||
switch (full_axis_count) {
|
||||
case 0:
|
||||
axis_value = (joyx[first_player + axis / 4] + 128) << 8;
|
||||
axis_value = (joyx[first_player] + 128) << 8;
|
||||
break;
|
||||
case 1:
|
||||
axis_value = (joyy[first_player + axis / 4] + 128) << 8;
|
||||
break;
|
||||
case 2:
|
||||
axis_value = rt[first_player + axis / 4] << 8;
|
||||
break;
|
||||
case 3:
|
||||
axis_value = lt[first_player + axis / 4] << 8;
|
||||
axis_value = (joyy[first_player] + 128) << 8;
|
||||
break;
|
||||
// TODO right analog stick
|
||||
// case 2:
|
||||
// axis_value = (joyrx[first_player] + 128) << 8;
|
||||
// break;
|
||||
// case 3:
|
||||
// axis_value = (joyry[first_player] + 128) << 8;
|
||||
// break;
|
||||
default:
|
||||
axis_value = 128;
|
||||
}
|
||||
full_axis_count++;
|
||||
}
|
||||
LOGJVS("%d:%4x ", axis, axis_value);
|
||||
JVS_OUT(axis_value >> 8);
|
||||
|
|
@ -2493,8 +2576,8 @@ u32 jvs_io_board::handle_jvs_message(u8 *buffer_in, u32 length_in, u8 *buffer_ou
|
|||
break;
|
||||
|
||||
case 0x30: // substract coin
|
||||
if (buffer_in[cmdi + 1] == 1)
|
||||
coin_count -= (buffer_in[cmdi + 2] << 8) + buffer_in[cmdi + 3];
|
||||
if (buffer_in[cmdi + 1] > 0 && first_player + buffer_in[cmdi + 1] - 1 < ARRAY_SIZE(coin_count))
|
||||
coin_count[first_player + buffer_in[cmdi + 1] - 1] -= (buffer_in[cmdi + 2] << 8) + buffer_in[cmdi + 3];
|
||||
JVS_STATUS1(); // report byte
|
||||
cmdi += 4;
|
||||
break;
|
||||
|
|
@ -2542,7 +2625,11 @@ maple_device* maple_Create(MapleDeviceType type)
|
|||
switch(type)
|
||||
{
|
||||
case MDT_SegaController:
|
||||
rv=new maple_sega_controller();
|
||||
#if DC_PLATFORM != DC_PLATFORM_ATOMISWAVE
|
||||
rv = new maple_sega_controller();
|
||||
#else
|
||||
rv = new maple_atomiswave_controller();
|
||||
#endif
|
||||
break;
|
||||
|
||||
case MDT_Microphone:
|
||||
|
|
@ -2566,7 +2653,11 @@ maple_device* maple_Create(MapleDeviceType type)
|
|||
break;
|
||||
|
||||
case MDT_LightGun:
|
||||
#if DC_PLATFORM != DC_PLATFORM_ATOMISWAVE
|
||||
rv = new maple_lightgun();
|
||||
#else
|
||||
rv = new atomiswave_lightgun();
|
||||
#endif
|
||||
break;
|
||||
|
||||
case MDT_NaomiJamma:
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ _vmem_WriteMem32FP* _vmem_WF32[HANDLER_COUNT];
|
|||
//upper 8b of the address
|
||||
void* _vmem_MemInfo_ptr[0x100];
|
||||
|
||||
|
||||
void _vmem_get_ptrs(u32 sz,bool write,void*** vmap,void*** func)
|
||||
{
|
||||
*vmap=_vmem_MemInfo_ptr;
|
||||
|
|
@ -385,10 +384,7 @@ void _vmem_reset()
|
|||
verify(_vmem_register_handler(0,0,0,0,0,0)==0);
|
||||
}
|
||||
|
||||
void _vmem_term()
|
||||
{
|
||||
|
||||
}
|
||||
void _vmem_term() {}
|
||||
|
||||
#include "hw/pvr/pvr_mem.h"
|
||||
#include "hw/sh4/sh4_mem.h"
|
||||
|
|
@ -409,414 +405,119 @@ void* malloc_pages(size_t size) {
|
|||
#endif
|
||||
}
|
||||
|
||||
bool _vmem_reserve_nonvmem()
|
||||
{
|
||||
virt_ram_base = 0;
|
||||
|
||||
p_sh4rcb=(Sh4RCB*)malloc_pages(sizeof(Sh4RCB));
|
||||
|
||||
mem_b.size=RAM_SIZE;
|
||||
mem_b.data=(u8*)malloc_pages(RAM_SIZE);
|
||||
|
||||
vram.size=VRAM_SIZE;
|
||||
vram.data=(u8*)malloc_pages(VRAM_SIZE);
|
||||
|
||||
aica_ram.size=ARAM_SIZE;
|
||||
aica_ram.data=(u8*)malloc_pages(ARAM_SIZE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void _vmem_bm_reset_nvmem();
|
||||
|
||||
// Resets the FPCB table (by either clearing it to the default val
|
||||
// or by flushing it and making it fault on access again.
|
||||
void _vmem_bm_reset() {
|
||||
if (virt_ram_base) {
|
||||
#if !defined(TARGET_NO_NVMEM)
|
||||
_vmem_bm_reset_nvmem();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef TARGET_IPHONE
|
||||
if (!virt_ram_base)
|
||||
#endif
|
||||
{
|
||||
bm_vmem_pagefill((void**)p_sh4rcb->fpcb, FPCB_SIZE);
|
||||
}
|
||||
// If we allocated it via vmem:
|
||||
if (virt_ram_base)
|
||||
vmem_platform_reset_mem(p_sh4rcb->fpcb, sizeof(p_sh4rcb->fpcb));
|
||||
else
|
||||
// We allocated it via a regular malloc/new/whatever on the heap
|
||||
bm_vmem_pagefill((void**)p_sh4rcb->fpcb, sizeof(p_sh4rcb->fpcb));
|
||||
}
|
||||
|
||||
static void _vmem_release_nonvmem()
|
||||
{
|
||||
free(p_sh4rcb);
|
||||
free(vram.data);
|
||||
free(aica_ram.data);
|
||||
free(mem_b.data);
|
||||
}
|
||||
// This gets called whenever there is a pagefault, it is possible that it lands
|
||||
// on the fpcb memory range, which is allocated on miss. Returning true tells the
|
||||
// fault handler this was us, and that the page is resolved and can continue the execution.
|
||||
bool BM_LockedWrite(u8* address) {
|
||||
if (!virt_ram_base)
|
||||
return false; // No vmem, therefore not us who caused this.
|
||||
|
||||
#if !defined(TARGET_NO_NVMEM)
|
||||
uintptr_t ptrint = (uintptr_t)address;
|
||||
uintptr_t start = (uintptr_t)p_sh4rcb->fpcb;
|
||||
uintptr_t end = start + sizeof(p_sh4rcb->fpcb);
|
||||
|
||||
#define MAP_RAM_START_OFFSET 0
|
||||
#define MAP_VRAM_START_OFFSET (MAP_RAM_START_OFFSET+RAM_SIZE)
|
||||
#define MAP_ARAM_START_OFFSET (MAP_VRAM_START_OFFSET+VRAM_SIZE)
|
||||
|
||||
#if HOST_OS==OS_WINDOWS
|
||||
#include <Windows.h>
|
||||
HANDLE mem_handle;
|
||||
|
||||
void* _nvmem_map_buffer(u32 dst,u32 addrsz,u32 offset,u32 size, bool w)
|
||||
{
|
||||
void* ptr;
|
||||
void* rv;
|
||||
|
||||
u32 map_times=addrsz/size;
|
||||
verify((addrsz%size)==0);
|
||||
verify(map_times>=1);
|
||||
|
||||
rv= MapViewOfFileEx(mem_handle,FILE_MAP_READ | (w?FILE_MAP_WRITE:0),0,offset,size,&virt_ram_base[dst]);
|
||||
if (!rv)
|
||||
return 0;
|
||||
|
||||
for (u32 i=1;i<map_times;i++)
|
||||
{
|
||||
dst+=size;
|
||||
ptr=MapViewOfFileEx(mem_handle,FILE_MAP_READ | (w?FILE_MAP_WRITE:0),0,offset,size,&virt_ram_base[dst]);
|
||||
if (!ptr) return 0;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
void* _nvmem_unused_buffer(u32 start,u32 end)
|
||||
{
|
||||
void* ptr=VirtualAlloc(&virt_ram_base[start],end-start,MEM_RESERVE,PAGE_NOACCESS);
|
||||
|
||||
if (ptr == 0)
|
||||
return 0;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void* _nvmem_alloc_mem()
|
||||
{
|
||||
mem_handle = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, RAM_SIZE_MAX + VRAM_SIZE_MAX + ARAM_SIZE_MAX, 0);
|
||||
|
||||
void* rv= (u8*)VirtualAlloc(0, 512*1024*1024 + sizeof(Sh4RCB) + ARAM_SIZE_MAX, MEM_RESERVE, PAGE_NOACCESS);
|
||||
if (rv) VirtualFree(rv,0,MEM_RELEASE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef MAP_NOSYNC
|
||||
#define MAP_NOSYNC 0 //missing from linux :/ -- could be the cause of android slowness ?
|
||||
#endif
|
||||
|
||||
#ifdef _ANDROID
|
||||
#include <linux/ashmem.h>
|
||||
|
||||
#ifndef ASHMEM_DEVICE
|
||||
#define ASHMEM_DEVICE "/dev/ashmem"
|
||||
#endif
|
||||
int ashmem_create_region(const char *name, size_t size)
|
||||
{
|
||||
int fd, ret;
|
||||
|
||||
fd = open(ASHMEM_DEVICE, O_RDWR);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
if (name) {
|
||||
char buf[ASHMEM_NAME_LEN];
|
||||
|
||||
strlcpy(buf, name, sizeof(buf));
|
||||
ret = ioctl(fd, ASHMEM_SET_NAME, buf);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = ioctl(fd, ASHMEM_SET_SIZE, size);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
return fd;
|
||||
|
||||
error:
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
int fd;
|
||||
void* _nvmem_unused_buffer(u32 start,u32 end)
|
||||
{
|
||||
void* ptr=mmap(&virt_ram_base[start], end-start, PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
if (MAP_FAILED==ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
void* _nvmem_map_buffer(u32 dst,u32 addrsz,u32 offset,u32 size, bool w)
|
||||
{
|
||||
void* ptr;
|
||||
void* rv;
|
||||
|
||||
printf("MAP %08X w/ %d\n",dst,offset);
|
||||
u32 map_times=addrsz/size;
|
||||
verify((addrsz%size)==0);
|
||||
verify(map_times>=1);
|
||||
u32 prot=PROT_READ|(w?PROT_WRITE:0);
|
||||
rv= mmap(&virt_ram_base[dst], size, prot, MAP_SHARED | MAP_NOSYNC | MAP_FIXED, fd, offset);
|
||||
if (MAP_FAILED==rv || rv!=(void*)&virt_ram_base[dst] || (mprotect(rv,size,prot)!=0))
|
||||
{
|
||||
printf("MAP1 failed %d\n",errno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (u32 i=1;i<map_times;i++)
|
||||
{
|
||||
dst+=size;
|
||||
ptr=mmap(&virt_ram_base[dst], size, prot , MAP_SHARED | MAP_NOSYNC | MAP_FIXED, fd, offset);
|
||||
if (MAP_FAILED==ptr || ptr!=(void*)&virt_ram_base[dst] || (mprotect(rv,size,prot)!=0))
|
||||
{
|
||||
printf("MAP2 failed %d\n",errno);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void* _nvmem_alloc_mem()
|
||||
{
|
||||
|
||||
#if HOST_OS == OS_DARWIN
|
||||
string path = get_writable_data_path("/dcnzorz_mem");
|
||||
fd = open(path.c_str(),O_CREAT|O_RDWR|O_TRUNC,S_IRWXU|S_IRWXG|S_IRWXO);
|
||||
unlink(path.c_str());
|
||||
verify(ftruncate(fd, RAM_SIZE_MAX + VRAM_SIZE_MAX + ARAM_SIZE_MAX) == 0);
|
||||
#elif !defined(_ANDROID)
|
||||
fd = shm_open("/dcnzorz_mem", O_CREAT | O_EXCL | O_RDWR,S_IREAD | S_IWRITE);
|
||||
shm_unlink("/dcnzorz_mem");
|
||||
if (fd==-1)
|
||||
{
|
||||
fd = open("dcnzorz_mem",O_CREAT|O_RDWR|O_TRUNC,S_IRWXU|S_IRWXG|S_IRWXO);
|
||||
unlink("dcnzorz_mem");
|
||||
}
|
||||
|
||||
verify(ftruncate(fd, RAM_SIZE_MAX + VRAM_SIZE_MAX + ARAM_SIZE_MAX) == 0);
|
||||
#else
|
||||
|
||||
fd = ashmem_create_region(0, RAM_SIZE_MAX + VRAM_SIZE_MAX + ARAM_SIZE_MAX);
|
||||
if (false)//this causes writebacks to flash -> slow and stuttery
|
||||
{
|
||||
fd = open("/data/data/com.reicast.emulator/files/dcnzorz_mem",O_CREAT|O_RDWR|O_TRUNC,S_IRWXU|S_IRWXG|S_IRWXO);
|
||||
unlink("/data/data/com.reicast.emulator/files/dcnzorz_mem");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
u32 sz = 512*1024*1024 + sizeof(Sh4RCB) + ARAM_SIZE_MAX + 0x10000;
|
||||
void* rv=mmap(0, sz, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
verify(rv != NULL);
|
||||
munmap(rv,sz);
|
||||
return (u8*)rv + 0x10000 - unat(rv)%0x10000;//align to 64 KB (Needed for linaro mmap not to extend to next region)
|
||||
}
|
||||
#endif
|
||||
|
||||
#define map_buffer(dsts,dste,offset,sz,w) {ptr=_nvmem_map_buffer(dsts,dste-dsts,offset,sz,w);if (!ptr) return false;}
|
||||
#define unused_buffer(start,end) {ptr=_nvmem_unused_buffer(start,end);if (!ptr) return false;}
|
||||
|
||||
u32 pagecnt;
|
||||
void _vmem_bm_reset_nvmem()
|
||||
{
|
||||
#if defined(TARGET_NO_NVMEM)
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_IPHONE
|
||||
//On iOS & nacl we allways allocate all of the mapping table
|
||||
mprotect(p_sh4rcb, sizeof(p_sh4rcb->fpcb), PROT_READ | PROT_WRITE);
|
||||
return;
|
||||
#endif
|
||||
pagecnt=0;
|
||||
|
||||
#if HOST_OS==OS_WINDOWS
|
||||
VirtualFree(p_sh4rcb,sizeof(p_sh4rcb->fpcb),MEM_DECOMMIT);
|
||||
#else
|
||||
mprotect(p_sh4rcb, sizeof(p_sh4rcb->fpcb), PROT_NONE);
|
||||
madvise(p_sh4rcb,sizeof(p_sh4rcb->fpcb),MADV_DONTNEED);
|
||||
#ifdef MADV_REMOVE
|
||||
madvise(p_sh4rcb,sizeof(p_sh4rcb->fpcb),MADV_REMOVE);
|
||||
#else
|
||||
//OSX, IOS
|
||||
madvise(p_sh4rcb,sizeof(p_sh4rcb->fpcb),MADV_FREE);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
printf("Freeing fpcb\n");
|
||||
}
|
||||
|
||||
bool BM_LockedWrite(u8* address)
|
||||
{
|
||||
if (!_nvmem_enabled())
|
||||
return false;
|
||||
|
||||
#if FEAT_SHREC != DYNAREC_NONE
|
||||
u32 addr=address-(u8*)p_sh4rcb->fpcb;
|
||||
|
||||
address=(u8*)p_sh4rcb->fpcb+ (addr&~PAGE_MASK);
|
||||
|
||||
if (addr<sizeof(p_sh4rcb->fpcb))
|
||||
{
|
||||
//printf("Allocated %d PAGES [%08X]\n",++pagecnt,addr);
|
||||
|
||||
#if HOST_OS==OS_WINDOWS
|
||||
verify(VirtualAlloc(address,PAGE_SIZE,MEM_COMMIT,PAGE_READWRITE));
|
||||
#else
|
||||
mprotect (address, PAGE_SIZE, PROT_READ | PROT_WRITE);
|
||||
#endif
|
||||
|
||||
bm_vmem_pagefill((void**)address,PAGE_SIZE);
|
||||
|
||||
if (ptrint >= start && ptrint < end) {
|
||||
// Alloc the page then and initialize it to default values
|
||||
void *aligned_addr = (void*)(ptrint & (~PAGE_MASK));
|
||||
vmem_platform_ondemand_page(aligned_addr, PAGE_SIZE);
|
||||
bm_vmem_pagefill((void**)aligned_addr, PAGE_SIZE);
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
die("BM_LockedWrite and NO REC");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
bool _vmem_reserve()
|
||||
{
|
||||
void* ptr=0;
|
||||
|
||||
bool _vmem_reserve() {
|
||||
// TODO: Static assert?
|
||||
verify((sizeof(Sh4RCB)%PAGE_SIZE)==0);
|
||||
|
||||
if (settings.dynarec.disable_nvmem)
|
||||
return _vmem_reserve_nonvmem();
|
||||
VMemType vmemstatus = MemTypeError;
|
||||
|
||||
virt_ram_base=(u8*)_nvmem_alloc_mem();
|
||||
// Use vmem only if settings mandate so, and if we have proper exception handlers.
|
||||
#ifndef TARGET_NO_EXCEPTIONS
|
||||
if (!settings.dynarec.disable_nvmem)
|
||||
vmemstatus = vmem_platform_init((void**)&virt_ram_base, (void**)&p_sh4rcb);
|
||||
#endif
|
||||
|
||||
if (virt_ram_base==0)
|
||||
return _vmem_reserve_nonvmem();
|
||||
|
||||
p_sh4rcb=(Sh4RCB*)virt_ram_base;
|
||||
// Fallback to statically allocated buffers, this results in slow-ops being generated.
|
||||
if (vmemstatus == MemTypeError) {
|
||||
printf("Warning! nvmem is DISABLED (due to failure or not being built-in\n");
|
||||
virt_ram_base = 0;
|
||||
|
||||
// Map the sh4 context but protect access to Sh4RCB.fpcb[]
|
||||
#if HOST_OS==OS_WINDOWS
|
||||
//verify(p_sh4rcb==VirtualAlloc(p_sh4rcb,sizeof(Sh4RCB),MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE));
|
||||
verify(p_sh4rcb==VirtualAlloc(p_sh4rcb,sizeof(Sh4RCB),MEM_RESERVE,PAGE_NOACCESS));
|
||||
// Allocate it all and initialize it.
|
||||
p_sh4rcb = (Sh4RCB*)malloc_pages(sizeof(Sh4RCB));
|
||||
bm_vmem_pagefill((void**)p_sh4rcb->fpcb, sizeof(p_sh4rcb->fpcb));
|
||||
|
||||
verify(VirtualAlloc((u8*)p_sh4rcb + sizeof(p_sh4rcb->fpcb),sizeof(Sh4RCB)-sizeof(p_sh4rcb->fpcb),MEM_COMMIT,PAGE_READWRITE));
|
||||
#else
|
||||
verify(p_sh4rcb==mmap(p_sh4rcb,sizeof(Sh4RCB),PROT_NONE,MAP_PRIVATE | MAP_ANON, -1, 0));
|
||||
mprotect((u8*)p_sh4rcb + sizeof(p_sh4rcb->fpcb),sizeof(Sh4RCB)-sizeof(p_sh4rcb->fpcb),PROT_READ|PROT_WRITE);
|
||||
#endif
|
||||
virt_ram_base+=sizeof(Sh4RCB);
|
||||
mem_b.size = RAM_SIZE;
|
||||
mem_b.data = (u8*)malloc_pages(RAM_SIZE);
|
||||
|
||||
//Area 0
|
||||
//[0x00000000 ,0x00800000) -> unused
|
||||
unused_buffer(0x00000000,0x00800000);
|
||||
vram.size = VRAM_SIZE;
|
||||
vram.data = (u8*)malloc_pages(VRAM_SIZE);
|
||||
|
||||
//I wonder, aica ram warps here ?.?
|
||||
//I really should check teh docs before codin ;p
|
||||
//[0x00800000,0x00A00000);
|
||||
map_buffer(0x00800000,0x01000000,MAP_ARAM_START_OFFSET,ARAM_SIZE,false);
|
||||
map_buffer(0x20000000,0x20000000+ARAM_SIZE,MAP_ARAM_START_OFFSET,ARAM_SIZE,true);
|
||||
aica_ram.size = ARAM_SIZE;
|
||||
aica_ram.data = (u8*)malloc_pages(ARAM_SIZE);
|
||||
}
|
||||
else {
|
||||
printf("Info: nvmem is enabled, with addr space of size %s\n", vmemstatus == MemType4GB ? "4GB" : "512MB");
|
||||
// Map the different parts of the memory file into the new memory range we got.
|
||||
#define MAP_RAM_START_OFFSET 0
|
||||
#define MAP_VRAM_START_OFFSET (MAP_RAM_START_OFFSET+RAM_SIZE)
|
||||
#define MAP_ARAM_START_OFFSET (MAP_VRAM_START_OFFSET+VRAM_SIZE)
|
||||
const vmem_mapping mem_mappings[] = {
|
||||
{0x00000000, 0x00800000, 0, 0, false}, // Area 0 -> unused
|
||||
{0x00800000, 0x01000000, MAP_ARAM_START_OFFSET, ARAM_SIZE, false}, // Aica, wraps too
|
||||
{0x20000000, 0x20000000+ARAM_SIZE, MAP_ARAM_START_OFFSET, ARAM_SIZE, true},
|
||||
{0x01000000, 0x04000000, 0, 0, false}, // More unused
|
||||
{0x04000000, 0x05000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // Area 1 (vram, 16MB, wrapped on DC as 2x8MB)
|
||||
{0x05000000, 0x06000000, 0, 0, false}, // 32 bit path (unused)
|
||||
{0x06000000, 0x07000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // VRAM mirror
|
||||
{0x07000000, 0x08000000, 0, 0, false}, // 32 bit path (unused) mirror
|
||||
{0x08000000, 0x0C000000, 0, 0, false}, // Area 2
|
||||
{0x0C000000, 0x10000000, MAP_RAM_START_OFFSET, RAM_SIZE, true}, // Area 3 (main RAM + 3 mirrors)
|
||||
{0x10000000, 0x20000000, 0, 0, false}, // Area 4-7 (unused)
|
||||
};
|
||||
vmem_platform_create_mappings(&mem_mappings[0], sizeof(mem_mappings) / sizeof(mem_mappings[0]));
|
||||
|
||||
aica_ram.size=ARAM_SIZE;
|
||||
aica_ram.data=(u8*)ptr;
|
||||
//[0x01000000 ,0x04000000) -> unused
|
||||
unused_buffer(0x01000000,0x04000000);
|
||||
|
||||
// Point buffers to actual data pointers
|
||||
aica_ram.size = ARAM_SIZE;
|
||||
aica_ram.data = &virt_ram_base[0x20000000]; // Points to the writtable AICA addrspace
|
||||
|
||||
//Area 1
|
||||
//[0x04000000,0x05000000) -> vram (16mb, warped on dc)
|
||||
map_buffer(0x04000000,0x05000000,MAP_VRAM_START_OFFSET,VRAM_SIZE,true);
|
||||
|
||||
vram.size=VRAM_SIZE;
|
||||
vram.data=(u8*)ptr;
|
||||
vram.size = VRAM_SIZE;
|
||||
vram.data = &virt_ram_base[0x04000000]; // Points to first vram mirror (writtable and lockable)
|
||||
|
||||
//[0x05000000,0x06000000) -> unused (32b path)
|
||||
unused_buffer(0x05000000,0x06000000);
|
||||
|
||||
//[0x06000000,0x07000000) -> vram mirror
|
||||
map_buffer(0x06000000,0x07000000,MAP_VRAM_START_OFFSET,VRAM_SIZE,true);
|
||||
|
||||
|
||||
//[0x07000000,0x08000000) -> unused (32b path) mirror
|
||||
unused_buffer(0x07000000,0x08000000);
|
||||
|
||||
//Area 2
|
||||
//[0x08000000,0x0C000000) -> unused
|
||||
unused_buffer(0x08000000,0x0C000000);
|
||||
|
||||
//Area 3
|
||||
//[0x0C000000,0x0D000000) -> main ram
|
||||
//[0x0D000000,0x0E000000) -> main ram mirror
|
||||
//[0x0E000000,0x0F000000) -> main ram mirror
|
||||
//[0x0F000000,0x10000000) -> main ram mirror
|
||||
map_buffer(0x0C000000,0x10000000,MAP_RAM_START_OFFSET,RAM_SIZE,true);
|
||||
|
||||
mem_b.size=RAM_SIZE;
|
||||
mem_b.data=(u8*)ptr;
|
||||
|
||||
//Area 4
|
||||
//Area 5
|
||||
//Area 6
|
||||
//Area 7
|
||||
//all -> Unused
|
||||
//[0x10000000,0x20000000) -> unused
|
||||
unused_buffer(0x10000000,0x20000000);
|
||||
|
||||
printf("vmem reserve: base: %08X, aram: %08x, vram: %08X, ram: %08X\n",virt_ram_base,aica_ram.data,vram.data,mem_b.data);
|
||||
mem_b.size = RAM_SIZE;
|
||||
mem_b.data = &virt_ram_base[0x0C000000]; // Main memory, first mirror
|
||||
}
|
||||
|
||||
// Clear out memory
|
||||
aica_ram.Zero();
|
||||
vram.Zero();
|
||||
mem_b.Zero();
|
||||
|
||||
printf("Mem alloc successful!\n");
|
||||
|
||||
return virt_ram_base!=0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void _vmem_release()
|
||||
{
|
||||
if (!_nvmem_enabled())
|
||||
_vmem_release_nonvmem();
|
||||
else
|
||||
{
|
||||
if (virt_ram_base != NULL)
|
||||
{
|
||||
#if HOST_OS == OS_WINDOWS
|
||||
VirtualFree(virt_ram_base, 0, MEM_RELEASE);
|
||||
#else
|
||||
munmap(virt_ram_base, 0x20000000);
|
||||
#endif
|
||||
virt_ram_base = NULL;
|
||||
}
|
||||
#if HOST_OS != OS_WINDOWS
|
||||
close(fd);
|
||||
#endif
|
||||
#define freedefptr(x) \
|
||||
if (x) { free(x); x = NULL; }
|
||||
|
||||
void _vmem_release() {
|
||||
if (virt_ram_base)
|
||||
vmem_platform_destroy();
|
||||
else {
|
||||
freedefptr(p_sh4rcb);
|
||||
freedefptr(vram.data);
|
||||
freedefptr(aica_ram.data);
|
||||
freedefptr(mem_b.data);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
bool _vmem_reserve()
|
||||
{
|
||||
return _vmem_reserve_nonvmem();
|
||||
}
|
||||
void _vmem_release()
|
||||
{
|
||||
_vmem_release_nonvmem();
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,6 +1,33 @@
|
|||
#pragma once
|
||||
#include "types.h"
|
||||
|
||||
enum VMemType {
|
||||
MemType4GB,
|
||||
MemType512MB,
|
||||
MemTypeError
|
||||
};
|
||||
|
||||
struct vmem_mapping {
|
||||
u32 start_address, end_address;
|
||||
unsigned memoffset, memsize;
|
||||
bool allow_writes;
|
||||
};
|
||||
|
||||
// Platform specific vmemory API
|
||||
// To initialize (maybe) the vmem subsystem
|
||||
VMemType vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr);
|
||||
// To reset the on-demand allocated pages.
|
||||
void vmem_platform_reset_mem(void *ptr, unsigned size_bytes);
|
||||
// To handle a fault&allocate an ondemand page.
|
||||
void vmem_platform_ondemand_page(void *address, unsigned size_bytes);
|
||||
// To create the mappings in the address space.
|
||||
void vmem_platform_create_mappings(const vmem_mapping *vmem_maps, unsigned nummaps);
|
||||
// Just tries to wipe as much as possible in the relevant area.
|
||||
void vmem_platform_destroy();
|
||||
|
||||
// Note: if you want to disable vmem magic in any given platform, implement the
|
||||
// above functions as empty functions and make vmem_platform_init return MemTypeError.
|
||||
|
||||
//Typedef's
|
||||
//ReadMem
|
||||
typedef u8 DYNACALL _vmem_ReadMem8FP(u32 Address);
|
||||
|
|
@ -70,4 +97,4 @@ static inline bool _nvmem_enabled() {
|
|||
return virt_ram_base != 0;
|
||||
}
|
||||
|
||||
void _vmem_bm_reset();
|
||||
void _vmem_bm_reset();
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@
|
|||
You should have received a copy of the GNU General Public License
|
||||
along with reicast. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "types.h"
|
||||
|
||||
#if BUILD_COMPILER!=COMPILER_VC && (BUILD_COMPILER!=COMPILER_CLANG || !defined(WIN32))
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
|
@ -145,3 +148,5 @@ char *read_name(char *reader, char *buffer, int *count)
|
|||
|
||||
return name;
|
||||
}
|
||||
|
||||
#endif // !COMPILER_VC_OR_CLANG_WIN32
|
||||
|
|
@ -162,6 +162,11 @@ ROM board internal layouts:
|
|||
*/
|
||||
#include "awcartridge.h"
|
||||
#include "awave_regs.h"
|
||||
#ifdef _MSC_VER
|
||||
#undef min
|
||||
#undef max
|
||||
#include <algorithm>
|
||||
#endif
|
||||
|
||||
u32 AWCartridge::ReadMem(u32 address, u32 size) {
|
||||
verify(size != 1);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "hw/holly/sb.h"
|
||||
#include "hw/sh4/sh4_mem.h"
|
||||
#include "hw/holly/holly_intc.h"
|
||||
#include "hw/maple/maple_cfg.h"
|
||||
|
||||
#include "naomi.h"
|
||||
#include "naomi_cart.h"
|
||||
|
|
@ -634,7 +635,6 @@ void Update_naomi()
|
|||
}
|
||||
|
||||
static u8 aw_maple_devs;
|
||||
extern bool coin_chute;
|
||||
|
||||
u32 libExtDevice_ReadMem_A0_006(u32 addr,u32 size) {
|
||||
addr &= 0x7ff;
|
||||
|
|
@ -653,12 +653,13 @@ u32 libExtDevice_ReadMem_A0_006(u32 addr,u32 size) {
|
|||
aw_ram_test_skipped = true;
|
||||
return 0;
|
||||
}
|
||||
if (coin_chute)
|
||||
{
|
||||
// FIXME Coin Error if coin_chute is set for too long
|
||||
return 0xE;
|
||||
u8 coin_input = 0xF;
|
||||
for (int slot = 0; slot < 4; slot++)
|
||||
if (maple_atomiswave_coin_chute(slot))
|
||||
coin_input &= ~(1 << slot);
|
||||
return coin_input;
|
||||
}
|
||||
return 0xF;
|
||||
|
||||
case 0x284: // Atomiswave maple devices
|
||||
// ddcc0000 where cc/dd are the types of devices on maple bus 2 and 3:
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ fd_t* RomCacheMap = NULL;
|
|||
u32 RomCacheMapCount;
|
||||
|
||||
char naomi_game_id[33];
|
||||
InputDescriptors *naomi_game_inputs;
|
||||
InputDescriptors *NaomiGameInputs;
|
||||
u8 *naomi_default_eeprom;
|
||||
|
||||
extern RomChip sys_rom;
|
||||
|
|
@ -246,7 +246,7 @@ static bool naomi_cart_LoadZip(char *filename)
|
|||
break;
|
||||
}
|
||||
CurrentCartridge->SetKey(game->key);
|
||||
naomi_game_inputs = game->inputs;
|
||||
NaomiGameInputs = game->inputs;
|
||||
|
||||
for (int romid = 0; game->blobs[romid].filename != NULL; romid++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -110,6 +110,6 @@ struct InputDescriptors
|
|||
AxisDescriptor axes[8];
|
||||
};
|
||||
|
||||
extern InputDescriptors *naomi_game_inputs;
|
||||
extern InputDescriptors *NaomiGameInputs;
|
||||
|
||||
#endif //NAOMI_CART_H
|
||||
|
|
|
|||
|
|
@ -82,8 +82,7 @@ bool renderer_enabled = true; // Signals the renderer thread to exit
|
|||
bool renderer_changed = false; // Signals the renderer thread to switch renderer
|
||||
|
||||
#if !defined(TARGET_NO_THREADS)
|
||||
cResetEvent rs(false,true);
|
||||
cResetEvent re(false,true);
|
||||
cResetEvent rs, re;
|
||||
#endif
|
||||
|
||||
int max_idx,max_mvo,max_op,max_pt,max_tr,max_vtx,max_modt, ovrn;
|
||||
|
|
@ -99,6 +98,7 @@ TA_context* _pvrrc;
|
|||
void SetREP(TA_context* cntx);
|
||||
void killtex();
|
||||
bool render_output_framebuffer();
|
||||
static void rend_create_renderer();
|
||||
|
||||
void dump_frame(const char* file, TA_context* ctx, u8* vram, u8* vram_ref = NULL) {
|
||||
FILE* fw = fopen(file, "wb");
|
||||
|
|
@ -267,6 +267,13 @@ bool rend_frame(TA_context* ctx, bool draw_osd) {
|
|||
|
||||
bool rend_single_frame()
|
||||
{
|
||||
if (renderer_changed)
|
||||
{
|
||||
renderer_changed = false;
|
||||
rend_term_renderer();
|
||||
rend_create_renderer();
|
||||
rend_init_renderer();
|
||||
}
|
||||
//wait render start only if no frame pending
|
||||
do
|
||||
{
|
||||
|
|
@ -363,6 +370,7 @@ void rend_init_renderer()
|
|||
}
|
||||
printf("Selected renderer initialization failed. Falling back to default renderer.\n");
|
||||
renderer = fallback_renderer;
|
||||
fallback_renderer = NULL; // avoid double-free
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -378,7 +386,6 @@ void rend_term_renderer()
|
|||
delete fallback_renderer;
|
||||
fallback_renderer = NULL;
|
||||
}
|
||||
tactx_Term();
|
||||
}
|
||||
|
||||
void* rend_thread(void* p)
|
||||
|
|
@ -392,13 +399,6 @@ void* rend_thread(void* p)
|
|||
{
|
||||
if (rend_single_frame())
|
||||
renderer->Present();
|
||||
if (renderer_changed)
|
||||
{
|
||||
renderer_changed = false;
|
||||
rend_term_renderer();
|
||||
rend_create_renderer();
|
||||
rend_init_renderer();
|
||||
}
|
||||
}
|
||||
|
||||
rend_term_renderer();
|
||||
|
|
@ -539,6 +539,7 @@ void rend_end_render()
|
|||
void rend_stop_renderer()
|
||||
{
|
||||
renderer_enabled = false;
|
||||
tactx_Term();
|
||||
}
|
||||
|
||||
void rend_vblank()
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ f32 vrf(u32 addr);
|
|||
u32 vri(u32 addr);
|
||||
|
||||
//vram 32-64b
|
||||
extern VArray2 vram;
|
||||
extern VLockedMemory vram;
|
||||
//read
|
||||
u8 DYNACALL pvr_read_area1_8(u32 addr);
|
||||
u16 DYNACALL pvr_read_area1_16(u32 addr);
|
||||
|
|
@ -36,4 +36,4 @@ extern "C" void DYNACALL TAWriteSQ(u32 address,u8* sqb);
|
|||
|
||||
void YUV_init();
|
||||
//registers
|
||||
#define PVR_BASE 0x005F8000
|
||||
#define PVR_BASE 0x005F8000
|
||||
|
|
|
|||
|
|
@ -88,6 +88,8 @@ double full_rps;
|
|||
static u32 lightgun_line = 0xffff;
|
||||
static u32 lightgun_hpos;
|
||||
|
||||
double mspdf;
|
||||
|
||||
u32 fskip=0;
|
||||
//called from sh4 context , should update pvr/ta state and everything else
|
||||
int spg_line_sched(int tag, int cycl, int jit)
|
||||
|
|
@ -174,7 +176,7 @@ int spg_line_sched(int tag, int cycl, int jit)
|
|||
}
|
||||
|
||||
double frames_done=spd_cpu/2;
|
||||
double mspdf=1/frames_done*1000;
|
||||
mspdf=1/frames_done*1000;
|
||||
|
||||
full_rps=(spd_fps+fskip/ts);
|
||||
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ void VDecEnd()
|
|||
|
||||
cMutex mtx_rqueue;
|
||||
TA_context* rqueue;
|
||||
cResetEvent frame_finished(false, true);
|
||||
cResetEvent frame_finished;
|
||||
|
||||
double last_frame = 0;
|
||||
u64 last_cyces = 0;
|
||||
|
|
|
|||
|
|
@ -339,9 +339,9 @@ void bm_Rebuild()
|
|||
rebuild_counter=30;
|
||||
}
|
||||
|
||||
void bm_vmem_pagefill(void** ptr,u32 PAGE_SZ)
|
||||
void bm_vmem_pagefill(void** ptr, u32 size_bytes)
|
||||
{
|
||||
for (size_t i=0; i<PAGE_SZ/sizeof(ptr[0]); i++)
|
||||
for (size_t i=0; i < size_bytes / sizeof(ptr[0]); i++)
|
||||
{
|
||||
ptr[i]=(void*)ngen_FailedToFindBlock;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ void bm_WriteBlockMap(const string& file);
|
|||
DynarecCodeEntryPtr DYNACALL bm_GetCode(u32 addr);
|
||||
|
||||
extern "C" {
|
||||
__attribute__((used)) DynarecCodeEntryPtr DYNACALL bm_GetCode2(u32 addr);
|
||||
ATTR_USED DynarecCodeEntryPtr DYNACALL bm_GetCode2(u32 addr);
|
||||
}
|
||||
|
||||
RuntimeBlockInfo* bm_GetBlock(void* dynarec_code);
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ int AicaUpdate(int tag, int c, int j)
|
|||
|
||||
int DreamcastSecond(int tag, int c, int j)
|
||||
{
|
||||
settings.dreamcast.RTC++;
|
||||
RealTimeClock++;
|
||||
|
||||
#if 1 //HOST_OS==OS_WINDOWS
|
||||
prof_periodical();
|
||||
|
|
|
|||
|
|
@ -314,7 +314,7 @@ struct Sh4RCB
|
|||
Sh4Context cntx;
|
||||
};
|
||||
|
||||
extern Sh4RCB* p_sh4rcb;
|
||||
extern "C" Sh4RCB* p_sh4rcb;
|
||||
extern u8* sh4_dyna_rcb;
|
||||
|
||||
INLINE u32 sh4_sr_GetFull()
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ void ExecuteDelayslot_RTE();
|
|||
extern "C" {
|
||||
|
||||
int UpdateSystem();
|
||||
__attribute__((used)) int UpdateSystem_INTC();
|
||||
|
||||
ATTR_USED int UpdateSystem_INTC();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
|
||||
//main system mem
|
||||
VArray2 mem_b;
|
||||
VLockedMemory mem_b;
|
||||
|
||||
void _vmem_init();
|
||||
void _vmem_reset();
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#include "types.h"
|
||||
|
||||
//main system mem
|
||||
extern VArray2 mem_b;
|
||||
extern VLockedMemory mem_b;
|
||||
|
||||
#include "hw/mem/_vmem.h"
|
||||
#include "modules/mmu.h"
|
||||
|
|
|
|||
|
|
@ -25,15 +25,15 @@ u64 sh4_sched_ffb;
|
|||
u32 sh4_sched_intr;
|
||||
|
||||
|
||||
vector<sched_list> list;
|
||||
vector<sched_list> sch_list; // using list as external inside a macro confuses clang and msc
|
||||
|
||||
int sh4_sched_next_id=-1;
|
||||
|
||||
u32 sh4_sched_remaining(int id, u32 reference)
|
||||
{
|
||||
if (list[id].end != -1)
|
||||
if (sch_list[id].end != -1)
|
||||
{
|
||||
return list[id].end - reference;
|
||||
return sch_list[id].end - reference;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -51,7 +51,7 @@ void sh4_sched_ffts()
|
|||
u32 diff=-1;
|
||||
int slot=-1;
|
||||
|
||||
for (size_t i=0;i<list.size();i++)
|
||||
for (size_t i=0;i<sch_list.size();i++)
|
||||
{
|
||||
if (sh4_sched_remaining(i)<diff)
|
||||
{
|
||||
|
|
@ -79,9 +79,9 @@ int sh4_sched_register(int tag, sh4_sched_callback* ssc)
|
|||
{
|
||||
sched_list t={ssc,tag,-1,-1};
|
||||
|
||||
list.push_back(t);
|
||||
sch_list.push_back(t);
|
||||
|
||||
return list.size()-1;
|
||||
return sch_list.size()-1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -103,16 +103,16 @@ void sh4_sched_request(int id, int cycles)
|
|||
{
|
||||
verify(cycles== -1 || (cycles >= 0 && cycles <= SH4_MAIN_CLOCK));
|
||||
|
||||
list[id].start=sh4_sched_now();
|
||||
sch_list[id].start=sh4_sched_now();
|
||||
|
||||
if (cycles == -1) {
|
||||
list[id].end = -1;
|
||||
sch_list[id].end = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
list[id].end = list[id].start + cycles;
|
||||
if (list[id].end == -1)
|
||||
list[id].end++;
|
||||
sch_list[id].end = sch_list[id].start + cycles;
|
||||
if (sch_list[id].end == -1)
|
||||
sch_list[id].end++;
|
||||
}
|
||||
|
||||
sh4_sched_ffts();
|
||||
|
|
@ -120,10 +120,10 @@ void sh4_sched_request(int id, int cycles)
|
|||
|
||||
int sh4_sched_elapsed(int id)
|
||||
{
|
||||
if (list[id].end!=-1)
|
||||
if (sch_list[id].end!=-1)
|
||||
{
|
||||
int rv=sh4_sched_now()-list[id].start;
|
||||
list[id].start=sh4_sched_now();
|
||||
int rv=sh4_sched_now()-sch_list[id].start;
|
||||
sch_list[id].start=sh4_sched_now();
|
||||
return rv;
|
||||
}
|
||||
else
|
||||
|
|
@ -132,12 +132,12 @@ int sh4_sched_elapsed(int id)
|
|||
|
||||
void handle_cb(int id)
|
||||
{
|
||||
int remain=list[id].end-list[id].start;
|
||||
int remain=sch_list[id].end-sch_list[id].start;
|
||||
int elapsd=sh4_sched_elapsed(id);
|
||||
int jitter=elapsd-remain;
|
||||
|
||||
list[id].end=-1;
|
||||
int re_sch=list[id].cb(list[id].tag,remain,jitter);
|
||||
sch_list[id].end=-1;
|
||||
int re_sch=sch_list[id].cb(sch_list[id].tag,remain,jitter);
|
||||
|
||||
if (re_sch > 0)
|
||||
sh4_sched_request(id, max(0, re_sch - jitter));
|
||||
|
|
@ -156,7 +156,7 @@ void sh4_sched_tick(int cycles)
|
|||
sh4_sched_intr++;
|
||||
if (sh4_sched_next_id!=-1)
|
||||
{
|
||||
for (int i=0;i<list.size();i++)
|
||||
for (int i=0;i<sch_list.size();i++)
|
||||
{
|
||||
int remaining = sh4_sched_remaining(i, fztime);
|
||||
verify(remaining >= 0 || remaining == -1);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include "common.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <Windows.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <ntddscsi.h>
|
||||
#include "SCSIDEFS.H"
|
||||
|
|
@ -388,4 +388,4 @@ Disc* ioctl_parse(const wchar* file)
|
|||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -51,7 +51,39 @@ bool GamepadDevice::gamepad_btn_input(u32 code, bool pressed)
|
|||
if (key < 0x10000)
|
||||
{
|
||||
if (pressed)
|
||||
{
|
||||
kcode[_maple_port] &= ~(u16)key;
|
||||
// Avoid two opposite dpad keys being pressed simultaneously
|
||||
switch (key)
|
||||
{
|
||||
case DC_DPAD_UP:
|
||||
kcode[_maple_port] |= (u16)DC_DPAD_DOWN;
|
||||
break;
|
||||
case DC_DPAD_DOWN:
|
||||
kcode[_maple_port] |= (u16)DC_DPAD_UP;
|
||||
break;
|
||||
case DC_DPAD_LEFT:
|
||||
kcode[_maple_port] |= (u16)DC_DPAD_RIGHT;
|
||||
break;
|
||||
case DC_DPAD_RIGHT:
|
||||
kcode[_maple_port] |= (u16)DC_DPAD_LEFT;
|
||||
break;
|
||||
case DC_DPAD2_UP:
|
||||
kcode[_maple_port] |= (u16)DC_DPAD2_DOWN;
|
||||
break;
|
||||
case DC_DPAD2_DOWN:
|
||||
kcode[_maple_port] |= (u16)DC_DPAD2_UP;
|
||||
break;
|
||||
case DC_DPAD2_LEFT:
|
||||
kcode[_maple_port] |= (u16)DC_DPAD2_RIGHT;
|
||||
break;
|
||||
case DC_DPAD2_RIGHT:
|
||||
kcode[_maple_port] |= (u16)DC_DPAD2_LEFT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
kcode[_maple_port] |= (u16)key;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,8 +84,6 @@ Atom wmDeleteMessage;
|
|||
void* x11_vis;
|
||||
|
||||
extern bool dump_frame_switch;
|
||||
extern bool naomi_test_button;
|
||||
extern bool coin_chute;
|
||||
|
||||
void dc_exit(void);
|
||||
|
||||
|
|
@ -275,16 +273,6 @@ void input_x11_handle()
|
|||
x11_fullscreen = !x11_fullscreen;
|
||||
x11_window_set_fullscreen(x11_fullscreen);
|
||||
}
|
||||
#if DC_PLATFORM == DC_PLATFORM_NAOMI || DC_PLATFORM == DC_PLATFORM_ATOMISWAVE
|
||||
else if (e.xkey.keycode == KEY_F8)
|
||||
{
|
||||
coin_chute = e.type == KeyPress;
|
||||
}
|
||||
else if (e.xkey.keycode == KEY_F7)
|
||||
{
|
||||
naomi_test_button = e.type == KeyPress;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -373,6 +361,11 @@ void input_x11_init()
|
|||
printf("X11 Keyboard input disabled by config.\n");
|
||||
}
|
||||
|
||||
static int x11_error_handler(Display *, XErrorEvent *)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void x11_window_create()
|
||||
{
|
||||
if (cfgLoadInt("pvr", "nox11", 0) == 0)
|
||||
|
|
@ -531,20 +524,22 @@ void x11_window_create()
|
|||
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
|
||||
None
|
||||
};
|
||||
int (*old_handler)(Display *, XErrorEvent *) = XSetErrorHandler(&x11_error_handler);
|
||||
|
||||
x11_glc = glXCreateContextAttribsARB(x11Display, bestFbc, 0, True, context_attribs);
|
||||
if (!x11_glc)
|
||||
{
|
||||
printf("Open GL 4.3 not supported\n");
|
||||
// Try GL 3.1
|
||||
// Try GL 3.0
|
||||
context_attribs[1] = 3;
|
||||
context_attribs[3] = 1;
|
||||
context_attribs[3] = 0;
|
||||
x11_glc = glXCreateContextAttribsARB(x11Display, bestFbc, 0, True, context_attribs);
|
||||
if (!x11_glc)
|
||||
{
|
||||
die("Open GL 3.1 not supported\n");
|
||||
die("Open GL 3.0 not supported\n");
|
||||
}
|
||||
}
|
||||
XSetErrorHandler(old_handler);
|
||||
XSync(x11Display, False);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -23,10 +23,6 @@
|
|||
#include <sys/personality.h>
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
#if HOST_OS == OS_DARWIN
|
||||
#include <mach/clock.h>
|
||||
#include <mach/mach.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#include "hw/sh4/dyna/blockmanager.h"
|
||||
|
||||
|
|
@ -57,7 +53,6 @@ void sigill_handler(int sn, siginfo_t * si, void *segfault_ctx) {
|
|||
}
|
||||
#endif
|
||||
|
||||
#if !defined(TARGET_NO_EXCEPTIONS)
|
||||
void fault_handler (int sn, siginfo_t * si, void *segfault_ctx)
|
||||
{
|
||||
rei_host_context_t ctx;
|
||||
|
|
@ -108,12 +103,9 @@ void fault_handler (int sn, siginfo_t * si, void *segfault_ctx)
|
|||
signal(SIGSEGV, SIG_DFL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
void install_fault_handler (void)
|
||||
void install_fault_handler(void)
|
||||
{
|
||||
#if !defined(TARGET_NO_EXCEPTIONS)
|
||||
struct sigaction act, segv_oact;
|
||||
memset(&act, 0, sizeof(act));
|
||||
act.sa_sigaction = fault_handler;
|
||||
|
|
@ -127,180 +119,14 @@ void install_fault_handler (void)
|
|||
act.sa_sigaction = sigill_handler;
|
||||
sigaction(SIGILL, &act, &segv_oact);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(TARGET_NO_THREADS)
|
||||
|
||||
//Thread class
|
||||
cThread::cThread(ThreadEntryFP* function,void* prm)
|
||||
{
|
||||
Entry=function;
|
||||
param=prm;
|
||||
}
|
||||
|
||||
void cThread::Start()
|
||||
{
|
||||
verify(hThread == NULL);
|
||||
if (pthread_create( (pthread_t*)&hThread, NULL, Entry, param))
|
||||
{
|
||||
die("Thread creation failed");
|
||||
}
|
||||
}
|
||||
|
||||
void cThread::WaitToEnd()
|
||||
{
|
||||
if (hThread != NULL)
|
||||
{
|
||||
pthread_join((pthread_t)hThread,0);
|
||||
hThread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//End thread class
|
||||
#endif
|
||||
|
||||
//cResetEvent Calss
|
||||
cResetEvent::cResetEvent(bool State,bool Auto)
|
||||
{
|
||||
//sem_init((sem_t*)hEvent, 0, State?1:0);
|
||||
verify(State==false&&Auto==true);
|
||||
pthread_mutex_init(&mutx, NULL);
|
||||
pthread_cond_init(&cond, NULL);
|
||||
}
|
||||
cResetEvent::~cResetEvent()
|
||||
{
|
||||
//Destroy the event object ?
|
||||
|
||||
}
|
||||
void cResetEvent::Set()//Signal
|
||||
{
|
||||
pthread_mutex_lock( &mutx );
|
||||
state=true;
|
||||
pthread_cond_signal( &cond);
|
||||
pthread_mutex_unlock( &mutx );
|
||||
}
|
||||
void cResetEvent::Reset()//reset
|
||||
{
|
||||
pthread_mutex_lock( &mutx );
|
||||
state=false;
|
||||
pthread_mutex_unlock( &mutx );
|
||||
}
|
||||
bool cResetEvent::Wait(u32 msec)//Wait for signal , then reset
|
||||
{
|
||||
pthread_mutex_lock( &mutx );
|
||||
if (!state)
|
||||
{
|
||||
struct timespec ts;
|
||||
#if HOST_OS == OS_DARWIN
|
||||
// OSX doesn't have clock_gettime.
|
||||
clock_serv_t cclock;
|
||||
mach_timespec_t mts;
|
||||
|
||||
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
|
||||
clock_get_time(cclock, &mts);
|
||||
mach_port_deallocate(mach_task_self(), cclock);
|
||||
ts.tv_sec = mts.tv_sec;
|
||||
ts.tv_nsec = mts.tv_nsec;
|
||||
#else
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
#endif
|
||||
ts.tv_sec += msec / 1000;
|
||||
ts.tv_nsec += (msec % 1000) * 1000000;
|
||||
while (ts.tv_nsec > 1000000000)
|
||||
{
|
||||
ts.tv_nsec -= 1000000000;
|
||||
ts.tv_sec++;
|
||||
}
|
||||
pthread_cond_timedwait( &cond, &mutx, &ts );
|
||||
}
|
||||
bool rc = state;
|
||||
state=false;
|
||||
pthread_mutex_unlock( &mutx );
|
||||
|
||||
return rc;
|
||||
}
|
||||
void cResetEvent::Wait()//Wait for signal , then reset
|
||||
{
|
||||
pthread_mutex_lock( &mutx );
|
||||
if (!state)
|
||||
{
|
||||
pthread_cond_wait( &cond, &mutx );
|
||||
}
|
||||
state=false;
|
||||
pthread_mutex_unlock( &mutx );
|
||||
}
|
||||
|
||||
//End AutoResetEvent
|
||||
#else // !defined(TARGET_NO_EXCEPTIONS)
|
||||
// No exceptions/nvmem dummy handlers.
|
||||
void install_fault_handler(void) {}
|
||||
#endif // !defined(TARGET_NO_EXCEPTIONS)
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
void VArray2::LockRegion(u32 offset,u32 size)
|
||||
{
|
||||
#if !defined(TARGET_NO_EXCEPTIONS)
|
||||
u32 inpage=offset & PAGE_MASK;
|
||||
u32 rv=mprotect (data+offset-inpage, size+inpage, PROT_READ );
|
||||
if (rv!=0)
|
||||
{
|
||||
printf("mprotect(%8s,%08X,R) failed: %d | %d\n",data+offset-inpage,size+inpage,rv,errno);
|
||||
die("mprotect failed ..\n");
|
||||
}
|
||||
|
||||
#else
|
||||
//printf("VA2: LockRegion\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void print_mem_addr()
|
||||
{
|
||||
FILE *ifp, *ofp;
|
||||
|
||||
char outputFilename[] = "/data/data/com.reicast.emulator/files/mem_alloc.txt";
|
||||
|
||||
ifp = fopen("/proc/self/maps", "r");
|
||||
|
||||
if (ifp == NULL) {
|
||||
fprintf(stderr, "Can't open input file /proc/self/maps!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ofp = fopen(outputFilename, "w");
|
||||
|
||||
if (ofp == NULL) {
|
||||
fprintf(stderr, "Can't open output file %s!\n",
|
||||
outputFilename);
|
||||
#if HOST_OS == OS_LINUX
|
||||
ofp = stderr;
|
||||
#else
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
char line [ 512 ];
|
||||
while (fgets(line, sizeof line, ifp) != NULL) {
|
||||
fprintf(ofp, "%s", line);
|
||||
}
|
||||
|
||||
fclose(ifp);
|
||||
if (ofp != stderr)
|
||||
fclose(ofp);
|
||||
}
|
||||
|
||||
void VArray2::UnLockRegion(u32 offset,u32 size)
|
||||
{
|
||||
#if !defined(TARGET_NO_EXCEPTIONS)
|
||||
u32 inpage=offset & PAGE_MASK;
|
||||
u32 rv=mprotect (data+offset-inpage, size+inpage, PROT_READ | PROT_WRITE);
|
||||
if (rv!=0)
|
||||
{
|
||||
print_mem_addr();
|
||||
printf("mprotect(%8p,%08X,RW) failed: %d | %d\n",data+offset-inpage,size+inpage,rv,errno);
|
||||
die("mprotect failed ..\n");
|
||||
}
|
||||
#else
|
||||
//printf("VA2: UnLockRegion\n");
|
||||
#endif
|
||||
}
|
||||
double os_GetSeconds()
|
||||
{
|
||||
timeval a;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,178 @@
|
|||
|
||||
// Implementation of the vmem related function for POSIX-like platforms.
|
||||
// There's some minimal amount of platform specific hacks to support
|
||||
// Android and OSX since they are slightly different in some areas.
|
||||
|
||||
// This implements the VLockedMemory interface, as defined in _vmem.h
|
||||
// The implementation allows it to be empty (that is, to not lock memory).
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "hw/mem/_vmem.h"
|
||||
#include "stdclass.h"
|
||||
|
||||
#ifndef MAP_NOSYNC
|
||||
#define MAP_NOSYNC 0 //missing from linux :/ -- could be the cause of android slowness ?
|
||||
#endif
|
||||
|
||||
#ifdef _ANDROID
|
||||
#include <linux/ashmem.h>
|
||||
#ifndef ASHMEM_DEVICE
|
||||
#define ASHMEM_DEVICE "/dev/ashmem"
|
||||
#undef PAGE_MASK
|
||||
#define PAGE_MASK (PAGE_SIZE-1)
|
||||
#else
|
||||
#define PAGE_SIZE 4096
|
||||
#define PAGE_MASK (PAGE_SIZE-1)
|
||||
#endif
|
||||
|
||||
// Android specific ashmem-device stuff for creating shared memory regions
|
||||
int ashmem_create_region(const char *name, size_t size) {
|
||||
int fd = open(ASHMEM_DEVICE, O_RDWR);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
if (ioctl(fd, ASHMEM_SET_SIZE, size) < 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
#endif // #ifdef _ANDROID
|
||||
|
||||
void VLockedMemory::LockRegion(unsigned offset, unsigned size_bytes) {
|
||||
size_t inpage = offset & PAGE_MASK;
|
||||
if (mprotect(&data[offset - inpage], size_bytes + inpage, PROT_READ)) {
|
||||
die("mprotect failed ..\n");
|
||||
}
|
||||
}
|
||||
|
||||
void VLockedMemory::UnLockRegion(unsigned offset, unsigned size_bytes) {
|
||||
size_t inpage = offset & PAGE_MASK;
|
||||
if (mprotect(&data[offset - inpage], size_bytes + inpage, PROT_READ|PROT_WRITE)) {
|
||||
// Add some way to see why it failed? gdb> info proc mappings
|
||||
die("mprotect failed ..\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Allocates memory via a fd on shmem/ahmem or even a file on disk
|
||||
static int allocate_shared_filemem() {
|
||||
int fd = -1;
|
||||
#if defined(_ANDROID)
|
||||
// Use Android's specific shmem stuff.
|
||||
fd = ashmem_create_region(0, RAM_SIZE_MAX + VRAM_SIZE_MAX + ARAM_SIZE_MAX);
|
||||
#else
|
||||
#if HOST_OS != OS_DARWIN
|
||||
fd = shm_open("/dcnzorz_mem", O_CREAT | O_EXCL | O_RDWR,S_IREAD | S_IWRITE);
|
||||
shm_unlink("/dcnzorz_mem");
|
||||
#endif
|
||||
|
||||
// if shmem does not work (or using OSX) fallback to a regular file on disk
|
||||
if (fd < 0) {
|
||||
string path = get_writable_data_path("/dcnzorz_mem");
|
||||
fd = open(path.c_str(), O_CREAT|O_RDWR|O_TRUNC, S_IRWXU|S_IRWXG|S_IRWXO);
|
||||
unlink(path.c_str());
|
||||
}
|
||||
// If we can't open the file, fallback to slow mem.
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
// Finally make the file as big as we need!
|
||||
if (ftruncate(fd, RAM_SIZE_MAX + VRAM_SIZE_MAX + ARAM_SIZE_MAX)) {
|
||||
// Can't get as much memory as needed, fallback.
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
// Implement vmem initialization for RAM, ARAM, VRAM and SH4 context, fpcb etc.
|
||||
// The function supports allocating 512MB or 4GB addr spaces.
|
||||
|
||||
static int shmem_fd = -1;
|
||||
|
||||
// vmem_base_addr points to an address space of 512MB (or 4GB) that can be used for fast memory ops.
|
||||
// In negative offsets of the pointer (up to FPCB size, usually 65/129MB) the context and jump table
|
||||
// can be found. If the platform init returns error, the user is responsible for initializing the
|
||||
// memory using a fallback (that is, regular mallocs and falling back to slow memory JIT).
|
||||
VMemType vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr) {
|
||||
// Firt let's try to allocate the shm-backed memory
|
||||
shmem_fd = allocate_shared_filemem();
|
||||
if (shmem_fd < 0)
|
||||
return MemTypeError;
|
||||
|
||||
// Now try to allocate a contiguous piece of memory.
|
||||
unsigned memsize = 512*1024*1024 + sizeof(Sh4RCB) + ARAM_SIZE_MAX + 0x10000;
|
||||
void *first_ptr = mmap(0, memsize, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
if (!first_ptr) {
|
||||
close(shmem_fd);
|
||||
return MemTypeError;
|
||||
}
|
||||
|
||||
// Align pointer to 64KB too, some Linaro bug (no idea but let's just be safe I guess).
|
||||
uintptr_t ptrint = (uintptr_t)first_ptr;
|
||||
ptrint = (ptrint + 0x10000 - 1) & (~0xffff);
|
||||
*sh4rcb_addr = (void*)ptrint;
|
||||
*vmem_base_addr = (void*)(ptrint + sizeof(Sh4RCB));
|
||||
void *sh4rcb_base_ptr = (void*)(ptrint + FPCB_SIZE);
|
||||
|
||||
// Now map the memory for the SH4 context, do not include FPCB on purpose (paged on demand).
|
||||
mprotect(sh4rcb_base_ptr, sizeof(Sh4RCB) - FPCB_SIZE, PROT_READ | PROT_WRITE);
|
||||
|
||||
return MemType512MB;
|
||||
}
|
||||
|
||||
// Just tries to wipe as much as possible in the relevant area.
|
||||
void vmem_platform_destroy() {
|
||||
munmap(virt_ram_base, 0x20000000);
|
||||
}
|
||||
|
||||
// Resets a chunk of memory by deleting its data and setting its protection back.
|
||||
void vmem_platform_reset_mem(void *ptr, unsigned size_bytes) {
|
||||
// Mark them as non accessible.
|
||||
mprotect(ptr, size_bytes, PROT_NONE);
|
||||
// Tell the kernel to flush'em all (FIXME: perhaps unmap+mmap 'd be better?)
|
||||
madvise(ptr, size_bytes, MADV_DONTNEED);
|
||||
#if defined(MADV_REMOVE)
|
||||
madvise(ptr, size_bytes, MADV_REMOVE);
|
||||
#elif defined(MADV_FREE)
|
||||
madvise(ptr, size_bytes, MADV_FREE);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Allocates a bunch of memory (page aligned and page-sized)
|
||||
void vmem_platform_ondemand_page(void *address, unsigned size_bytes) {
|
||||
verify(!mprotect(address, size_bytes, PROT_READ | PROT_WRITE));
|
||||
}
|
||||
|
||||
// Creates mappings to the underlying file including mirroring sections
|
||||
void vmem_platform_create_mappings(const vmem_mapping *vmem_maps, unsigned nummaps) {
|
||||
for (unsigned i = 0; i < nummaps; i++) {
|
||||
// Ignore unmapped stuff, it is already reserved as PROT_NONE
|
||||
if (!vmem_maps[i].memsize)
|
||||
continue;
|
||||
|
||||
// Calculate the number of mirrors
|
||||
unsigned address_range_size = vmem_maps[i].end_address - vmem_maps[i].start_address;
|
||||
unsigned num_mirrors = (address_range_size) / vmem_maps[i].memsize;
|
||||
int protection = vmem_maps[i].allow_writes ? (PROT_READ | PROT_WRITE) : PROT_READ;
|
||||
verify((address_range_size % vmem_maps[i].memsize) == 0 && num_mirrors >= 1);
|
||||
|
||||
for (unsigned j = 0; j < num_mirrors; j++) {
|
||||
unsigned offset = vmem_maps[i].start_address + j * vmem_maps[i].memsize;
|
||||
verify(!munmap(&virt_ram_base[offset], vmem_maps[i].memsize));
|
||||
verify(MAP_FAILED != mmap(&virt_ram_base[offset], vmem_maps[i].memsize, protection,
|
||||
MAP_SHARED | MAP_NOSYNC | MAP_FIXED, shmem_fd, vmem_maps[i].memoffset));
|
||||
// ??? (mprotect(rv,size,prot)!=0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -134,7 +134,7 @@ void LoadSpecialSettings()
|
|||
safemode_game = false;
|
||||
tr_poly_depth_mask_game = false;
|
||||
extra_depth_game = false;
|
||||
|
||||
|
||||
if (reios_windows_ce)
|
||||
{
|
||||
printf("Enabling Extra depth scaling for Windows CE games\n");
|
||||
|
|
@ -190,7 +190,7 @@ void LoadSpecialSettings()
|
|||
}
|
||||
#elif DC_PLATFORM == DC_PLATFORM_NAOMI || DC_PLATFORM == DC_PLATFORM_ATOMISWAVE
|
||||
printf("Game ID is [%s]\n", naomi_game_id);
|
||||
|
||||
|
||||
if (!strcmp("METAL SLUG 6", naomi_game_id) || !strcmp("WAVE RUNNER GP", naomi_game_id))
|
||||
{
|
||||
printf("Enabling Dynarec safe mode for game %s\n", naomi_game_id);
|
||||
|
|
@ -213,12 +213,14 @@ void LoadSpecialSettings()
|
|||
printf("Enabling JVS rotary encoders for game %s\n", naomi_game_id);
|
||||
settings.input.JammaSetup = 2;
|
||||
}
|
||||
else if (!strcmp("POWER STONE 2 JAPAN", naomi_game_id))
|
||||
else if (!strcmp("POWER STONE 2 JAPAN", naomi_game_id) // Naomi
|
||||
|| !strcmp("GUILTY GEAR isuka", naomi_game_id)) // AW
|
||||
{
|
||||
printf("Enabling 4-player setup for game %s\n", naomi_game_id);
|
||||
settings.input.JammaSetup = 1;
|
||||
}
|
||||
else if (!strcmp("SEGA MARINE FISHING JAPAN", naomi_game_id))
|
||||
else if (!strcmp("SEGA MARINE FISHING JAPAN", naomi_game_id)
|
||||
|| !strcmp(naomi_game_id, "BASS FISHING SIMULATOR VER.A")) // AW
|
||||
{
|
||||
printf("Enabling specific JVS setup for game %s\n", naomi_game_id);
|
||||
settings.input.JammaSetup = 3;
|
||||
|
|
@ -228,9 +230,11 @@ void LoadSpecialSettings()
|
|||
printf("Enabling specific JVS setup for game %s\n", naomi_game_id);
|
||||
settings.input.JammaSetup = 4;
|
||||
}
|
||||
else if (!strcmp("NINJA ASSAULT", naomi_game_id))
|
||||
else if (!strcmp("NINJA ASSAULT", naomi_game_id)
|
||||
|| !strcmp(naomi_game_id, "Sports Shooting USA") // AW
|
||||
|| !strcmp(naomi_game_id, "SEGA CLAY CHALLENGE")) // AW
|
||||
{
|
||||
printf("Enabling specific JVS setup for game %s\n", naomi_game_id);
|
||||
printf("Enabling lightgun setup for game %s\n", naomi_game_id);
|
||||
settings.input.JammaSetup = 5;
|
||||
}
|
||||
else if (!strcmp(" BIOHAZARD GUN SURVIVOR2", naomi_game_id))
|
||||
|
|
@ -309,11 +313,12 @@ int dc_start_game(const char *path)
|
|||
{
|
||||
InitSettings();
|
||||
LoadSettings(false);
|
||||
settings.dreamcast.RTC = GetRTC_now(); // FIXME This shouldn't be in settings anymore
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
if (!settings.bios.UseReios)
|
||||
#endif
|
||||
LoadRomFiles(get_readonly_data_path(DATA_PATH));
|
||||
if (!LoadRomFiles(get_readonly_data_path(DATA_PATH)))
|
||||
return -5;
|
||||
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
if (path == NULL)
|
||||
{
|
||||
|
|
@ -345,7 +350,6 @@ int dc_start_game(const char *path)
|
|||
return 0;
|
||||
}
|
||||
|
||||
settings.dreamcast.RTC = GetRTC_now(); // FIXME This shouldn't be in settings anymore
|
||||
if (settings.bios.UseReios || !LoadRomFiles(get_readonly_data_path(DATA_PATH)))
|
||||
{
|
||||
#ifdef USE_REIOS
|
||||
|
|
@ -485,7 +489,6 @@ void dc_exit()
|
|||
|
||||
void InitSettings()
|
||||
{
|
||||
settings.dreamcast.RTC = GetRTC_now();
|
||||
settings.dynarec.Enable = true;
|
||||
settings.dynarec.idleskip = true;
|
||||
settings.dynarec.unstable_opt = false;
|
||||
|
|
@ -499,6 +502,7 @@ void InitSettings()
|
|||
settings.aica.LimitFPS = true;
|
||||
settings.aica.NoBatch = false; // This also controls the DSP. Disabled by default
|
||||
settings.aica.NoSound = false;
|
||||
settings.audio.backend = "auto";
|
||||
settings.rend.UseMipmaps = true;
|
||||
settings.rend.WideScreen = false;
|
||||
settings.rend.ShowFPS = false;
|
||||
|
|
@ -513,6 +517,10 @@ void InitSettings()
|
|||
settings.rend.CustomTextures = false;
|
||||
settings.rend.DumpTextures = false;
|
||||
settings.rend.ScreenScaling = 100;
|
||||
settings.rend.ScreenStretching = 100;
|
||||
settings.rend.Fog = true;
|
||||
settings.rend.FloatVMUs = false;
|
||||
settings.rend.Rotate90 = false;
|
||||
|
||||
settings.pvr.ta_skip = 0;
|
||||
settings.pvr.rend = 0;
|
||||
|
|
@ -559,6 +567,7 @@ void LoadSettings(bool game_specific)
|
|||
{
|
||||
const char *config_section = game_specific ? cfgGetGameId() : "config";
|
||||
const char *input_section = game_specific ? cfgGetGameId() : "input";
|
||||
const char *audio_section = game_specific ? cfgGetGameId() : "audio";
|
||||
|
||||
settings.dynarec.Enable = cfgLoadBool(config_section, "Dynarec.Enabled", settings.dynarec.Enable);
|
||||
settings.dynarec.idleskip = cfgLoadBool(config_section, "Dynarec.idleskip", settings.dynarec.idleskip);
|
||||
|
|
@ -574,6 +583,7 @@ void LoadSettings(bool game_specific)
|
|||
settings.aica.LimitFPS = cfgLoadBool(config_section, "aica.LimitFPS", settings.aica.LimitFPS);
|
||||
settings.aica.NoBatch = cfgLoadBool(config_section, "aica.NoBatch", settings.aica.NoBatch);
|
||||
settings.aica.NoSound = cfgLoadBool(config_section, "aica.NoSound", settings.aica.NoSound);
|
||||
settings.audio.backend = cfgLoadStr(audio_section, "backend", settings.audio.backend.c_str());
|
||||
settings.rend.UseMipmaps = cfgLoadBool(config_section, "rend.UseMipmaps", settings.rend.UseMipmaps);
|
||||
settings.rend.WideScreen = cfgLoadBool(config_section, "rend.WideScreen", settings.rend.WideScreen);
|
||||
settings.rend.ShowFPS = cfgLoadBool(config_section, "rend.ShowFPS", settings.rend.ShowFPS);
|
||||
|
|
@ -595,6 +605,10 @@ void LoadSettings(bool game_specific)
|
|||
settings.rend.DumpTextures = cfgLoadBool(config_section, "rend.DumpTextures", settings.rend.DumpTextures);
|
||||
settings.rend.ScreenScaling = cfgLoadInt(config_section, "rend.ScreenScaling", settings.rend.ScreenScaling);
|
||||
settings.rend.ScreenScaling = min(max(1, settings.rend.ScreenScaling), 100);
|
||||
settings.rend.ScreenStretching = cfgLoadInt(config_section, "rend.ScreenStretching", settings.rend.ScreenStretching);
|
||||
settings.rend.Fog = cfgLoadBool(config_section, "rend.Fog", settings.rend.Fog);
|
||||
settings.rend.FloatVMUs = cfgLoadBool(config_section, "rend.FloatVMUs", settings.rend.FloatVMUs);
|
||||
settings.rend.Rotate90 = cfgLoadBool(config_section, "rend.Rotate90", settings.rend.Rotate90);
|
||||
|
||||
settings.pvr.ta_skip = cfgLoadInt(config_section, "ta.skip", settings.pvr.ta_skip);
|
||||
settings.pvr.rend = cfgLoadInt(config_section, "pvr.rend", settings.pvr.rend);
|
||||
|
|
@ -706,6 +720,27 @@ void SaveSettings()
|
|||
cfgSaveBool("config", "aica.LimitFPS", settings.aica.LimitFPS);
|
||||
cfgSaveBool("config", "aica.NoBatch", settings.aica.NoBatch);
|
||||
cfgSaveBool("config", "aica.NoSound", settings.aica.NoSound);
|
||||
cfgSaveStr("audio", "backend", settings.audio.backend.c_str());
|
||||
|
||||
// Write backend specific settings
|
||||
// std::map<std::string, std::map<std::string, std::string>>
|
||||
for (std::map<std::string, std::map<std::string, std::string>>::iterator it = settings.audio.options.begin(); it != settings.audio.options.end(); ++it)
|
||||
{
|
||||
|
||||
std::pair<std::string, std::map<std::string, std::string>> p = (std::pair<std::string, std::map<std::string, std::string>>)*it;
|
||||
std::string section = p.first;
|
||||
std::map<std::string, std::string> options = p.second;
|
||||
|
||||
for (std::map<std::string, std::string>::iterator it2 = options.begin(); it2 != options.end(); ++it2)
|
||||
{
|
||||
std::pair<std::string, std::string> p2 = (std::pair<std::string, std::string>)*it2;
|
||||
std::string key = p2.first;
|
||||
std::string val = p2.second;
|
||||
|
||||
cfgSaveStr(section.c_str(), key.c_str(), val.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
cfgSaveBool("config", "rend.WideScreen", settings.rend.WideScreen);
|
||||
cfgSaveBool("config", "rend.ShowFPS", settings.rend.ShowFPS);
|
||||
if (!rtt_to_buffer_game || !settings.rend.RenderToTextureBuffer)
|
||||
|
|
@ -718,6 +753,10 @@ void SaveSettings()
|
|||
cfgSaveBool("config", "rend.CustomTextures", settings.rend.CustomTextures);
|
||||
cfgSaveBool("config", "rend.DumpTextures", settings.rend.DumpTextures);
|
||||
cfgSaveInt("config", "rend.ScreenScaling", settings.rend.ScreenScaling);
|
||||
cfgSaveInt("config", "rend.ScreenStretching", settings.rend.ScreenStretching);
|
||||
cfgSaveBool("config", "rend.Fog", settings.rend.Fog);
|
||||
cfgSaveBool("config", "rend.FloatVMUs", settings.rend.FloatVMUs);
|
||||
cfgSaveBool("config", "rend.Rotate90", settings.rend.Rotate90);
|
||||
cfgSaveInt("config", "ta.skip", settings.pvr.ta_skip);
|
||||
cfgSaveInt("config", "pvr.rend", settings.pvr.rend);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#include "oslib/audiobackend_alsa.h"
|
||||
#include "oslib/audiostream.h"
|
||||
#if USE_ALSA
|
||||
#include <alsa/asoundlib.h>
|
||||
#include "cfg/cfg.h"
|
||||
|
|
@ -18,30 +18,43 @@ static void alsa_init()
|
|||
string device = cfgLoadStr("alsa", "device", "");
|
||||
|
||||
int rc = -1;
|
||||
if (device == "")
|
||||
if (device == "" || device == "auto")
|
||||
{
|
||||
printf("ALSA: trying to determine audio device\n");
|
||||
/* Open PCM device for playback. */
|
||||
|
||||
// trying default device
|
||||
device = "default";
|
||||
rc = snd_pcm_open(&handle, device.c_str(), SND_PCM_STREAM_PLAYBACK, 0);
|
||||
|
||||
// "default" didn't work, try first device
|
||||
if (rc < 0)
|
||||
{
|
||||
device = "plughw:0,0,0";
|
||||
rc = snd_pcm_open(&handle, device.c_str(), SND_PCM_STREAM_PLAYBACK, 0);
|
||||
|
||||
if (rc < 0)
|
||||
{
|
||||
device = "plughw:0,0";
|
||||
rc = snd_pcm_open(&handle, device.c_str(), SND_PCM_STREAM_PLAYBACK, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// first didn't work, try second
|
||||
if (rc < 0)
|
||||
{
|
||||
device = "plughw:0,0";
|
||||
device = "plughw:1,0";
|
||||
rc = snd_pcm_open(&handle, device.c_str(), SND_PCM_STREAM_PLAYBACK, 0);
|
||||
}
|
||||
|
||||
if (rc >= 0)
|
||||
// try pulse audio backend
|
||||
if (rc < 0)
|
||||
{
|
||||
// init successfull, write value back to config
|
||||
cfgSaveStr("alsa", "device", device.c_str());
|
||||
device = "pulse";
|
||||
rc = snd_pcm_open(&handle, device.c_str(), SND_PCM_STREAM_PLAYBACK, 0);
|
||||
}
|
||||
|
||||
if (rc < 0)
|
||||
printf("ALSA: unable to automatically determine audio device.\n");
|
||||
}
|
||||
else {
|
||||
rc = snd_pcm_open(&handle, device.c_str(), SND_PCM_STREAM_PLAYBACK, 0);
|
||||
|
|
@ -49,7 +62,7 @@ static void alsa_init()
|
|||
|
||||
if (rc < 0)
|
||||
{
|
||||
fprintf(stderr, "unable to open PCM device %s: %s\n", device.c_str(), snd_strerror(rc));
|
||||
fprintf(stderr, "ALSA: unable to open PCM device %s: %s\n", device.c_str(), snd_strerror(rc));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -62,7 +75,7 @@ static void alsa_init()
|
|||
rc=snd_pcm_hw_params_any(handle, params);
|
||||
if (rc < 0)
|
||||
{
|
||||
fprintf(stderr, "Error:snd_pcm_hw_params_any %s\n", snd_strerror(rc));
|
||||
fprintf(stderr, "ALSA: Error:snd_pcm_hw_params_any %s\n", snd_strerror(rc));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -72,7 +85,7 @@ static void alsa_init()
|
|||
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));
|
||||
fprintf(stderr, "ALSA: Error:snd_pcm_hw_params_set_access %s\n", snd_strerror(rc));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -80,7 +93,7 @@ static void alsa_init()
|
|||
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));
|
||||
fprintf(stderr, "ALSA: Error:snd_pcm_hw_params_set_format %s\n", snd_strerror(rc));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -88,7 +101,7 @@ static void alsa_init()
|
|||
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));
|
||||
fprintf(stderr, "ALSA: Error:snd_pcm_hw_params_set_channels %s\n", snd_strerror(rc));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -97,7 +110,7 @@ static void alsa_init()
|
|||
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));
|
||||
fprintf(stderr, "ALSA: Error:snd_pcm_hw_params_set_rate_near %s\n", snd_strerror(rc));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -106,26 +119,31 @@ static void alsa_init()
|
|||
rc=snd_pcm_hw_params_set_period_size_near(handle, params, &period_size, &dir);
|
||||
if (rc < 0)
|
||||
{
|
||||
fprintf(stderr, "Error:snd_pcm_hw_params_set_buffer_size_near %s\n", snd_strerror(rc));
|
||||
fprintf(stderr, "ALSA: Error:snd_pcm_hw_params_set_buffer_size_near %s\n", snd_strerror(rc));
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("ALSA: period size set to %ld\n", period_size);
|
||||
}
|
||||
|
||||
buffer_size = (44100 * 100 /* settings.omx.Audio_Latency */ / 1000 / period_size + 1) * period_size;
|
||||
rc=snd_pcm_hw_params_set_buffer_size_near(handle, params, &buffer_size);
|
||||
if (rc < 0)
|
||||
{
|
||||
fprintf(stderr, "Error:snd_pcm_hw_params_set_buffer_size_near %s\n", snd_strerror(rc));
|
||||
fprintf(stderr, "ALSA: Error:snd_pcm_hw_params_set_buffer_size_near %s\n", snd_strerror(rc));
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("ALSA: buffer size set to %ld\n", buffer_size);
|
||||
}
|
||||
|
||||
/* 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));
|
||||
fprintf(stderr, "ALSA: Unable to set hw parameters: %s\n", snd_strerror(rc));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -175,11 +193,84 @@ static void alsa_term()
|
|||
snd_pcm_close(handle);
|
||||
}
|
||||
|
||||
audiobackend_t audiobackend_alsa = {
|
||||
std::vector<std::string> alsa_get_devicelist()
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
|
||||
char **hints;
|
||||
int err = snd_device_name_hint(-1, "pcm", (void***)&hints);
|
||||
|
||||
// Error initializing ALSA
|
||||
if (err != 0)
|
||||
return result;
|
||||
|
||||
// special value to automatically detect on initialization
|
||||
result.push_back("auto");
|
||||
|
||||
char** n = hints;
|
||||
while (*n != NULL)
|
||||
{
|
||||
// Get the type (NULL/Input/Output)
|
||||
char *type = snd_device_name_get_hint(*n, "IOID");
|
||||
char *name = snd_device_name_get_hint(*n, "NAME");
|
||||
|
||||
if (name != NULL)
|
||||
{
|
||||
// We only want output or special devices (like "default" or "pulse")
|
||||
// TODO Only those with type == NULL?
|
||||
if (type == NULL || strcmp(type, "Output") == 0)
|
||||
{
|
||||
// TODO Check if device works (however we need to hash the resulting list then)
|
||||
/*snd_pcm_t *handle;
|
||||
int rc = snd_pcm_open(&handle, name, SND_PCM_STREAM_PLAYBACK, 0);
|
||||
|
||||
if (rc == 0)
|
||||
{
|
||||
result.push_back(name);
|
||||
snd_pcm_close(handle);
|
||||
}
|
||||
*/
|
||||
|
||||
result.push_back(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (type != NULL)
|
||||
free(type);
|
||||
|
||||
if (name != NULL)
|
||||
free(name);
|
||||
|
||||
n++;
|
||||
}
|
||||
|
||||
snd_device_name_free_hint((void**)hints);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static audio_option_t* alsa_audio_options(int* option_count)
|
||||
{
|
||||
*option_count = 1;
|
||||
static audio_option_t result[1];
|
||||
|
||||
result[0].cfg_name = "device";
|
||||
result[0].caption = "Device";
|
||||
result[0].type = list;
|
||||
result[0].list_callback = alsa_get_devicelist;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static audiobackend_t audiobackend_alsa = {
|
||||
"alsa", // Slug
|
||||
"Advanced Linux Sound Architecture", // Name
|
||||
&alsa_init,
|
||||
&alsa_push,
|
||||
&alsa_term
|
||||
&alsa_term,
|
||||
&alsa_audio_options
|
||||
};
|
||||
|
||||
static bool alsa = RegisterAudioBackend(&audiobackend_alsa);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
#pragma once
|
||||
#include "oslib/audiostream.h"
|
||||
|
||||
extern audiobackend_t audiobackend_alsa;
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
#pragma once
|
||||
#include "oslib/audiostream.h"
|
||||
|
||||
extern audiobackend_t audiobackend_android;
|
||||
|
|
@ -1,18 +1,18 @@
|
|||
/*
|
||||
Simple Core Audio backend for osx (and maybe ios?)
|
||||
Based off various audio core samples and dolphin's code
|
||||
|
||||
|
||||
This is part of the Reicast project, please consult the
|
||||
LICENSE file for licensing & related information
|
||||
|
||||
|
||||
This could do with some locking logic to avoid
|
||||
race conditions, and some variable length buffer
|
||||
logic to support chunk sizes other than 512 bytes
|
||||
|
||||
|
||||
It does work on my macmini though
|
||||
*/
|
||||
|
||||
#include "oslib/audiobackend_coreaudio.h"
|
||||
#include "oslib/audiostream.h"
|
||||
|
||||
#if HOST_OS == OS_DARWIN
|
||||
#include <atomic>
|
||||
|
|
@ -28,7 +28,7 @@ static u8 samples_temp[BUFSIZE];
|
|||
|
||||
static std::atomic<int> samples_wptr;
|
||||
static std::atomic<int> samples_rptr;
|
||||
static cResetEvent bufferEmpty(false, true);
|
||||
static cResetEvent bufferEmpty;
|
||||
|
||||
static OSStatus coreaudio_callback(void* ctx, AudioUnitRenderActionFlags* flags, const AudioTimeStamp* ts,
|
||||
UInt32 bus, UInt32 frames, AudioBufferList* abl)
|
||||
|
|
@ -49,9 +49,9 @@ static OSStatus coreaudio_callback(void* ctx, AudioUnitRenderActionFlags* flags,
|
|||
samples_rptr = (samples_rptr + buf_size) % BUFSIZE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bufferEmpty.Set();
|
||||
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ static void coreaudio_init()
|
|||
AudioStreamBasicDescription format;
|
||||
AudioComponentDescription desc;
|
||||
AudioComponent component;
|
||||
|
||||
|
||||
desc.componentType = kAudioUnitType_Output;
|
||||
#if !defined(TARGET_IPHONE)
|
||||
desc.componentSubType = kAudioUnitSubType_DefaultOutput;
|
||||
|
|
@ -75,12 +75,12 @@ static void coreaudio_init()
|
|||
desc.componentFlagsMask = 0;
|
||||
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
component = AudioComponentFindNext(nullptr, &desc);
|
||||
|
||||
|
||||
verify(component != nullptr);
|
||||
|
||||
|
||||
err = AudioComponentInstanceNew(component, &audioUnit);
|
||||
verify(err == noErr);
|
||||
|
||||
|
||||
FillOutASBDForLPCM(format, 44100,
|
||||
2, 16, 16, false, false, false);
|
||||
err = AudioUnitSetProperty(audioUnit,
|
||||
|
|
@ -88,7 +88,7 @@ static void coreaudio_init()
|
|||
kAudioUnitScope_Input, 0, &format,
|
||||
sizeof(AudioStreamBasicDescription));
|
||||
verify(err == noErr);
|
||||
|
||||
|
||||
callback_struct.inputProc = coreaudio_callback;
|
||||
callback_struct.inputProcRefCon = 0;
|
||||
err = AudioUnitSetProperty(audioUnit,
|
||||
|
|
@ -96,24 +96,24 @@ static void coreaudio_init()
|
|||
kAudioUnitScope_Input, 0, &callback_struct,
|
||||
sizeof callback_struct);
|
||||
verify(err == noErr);
|
||||
|
||||
|
||||
/*
|
||||
err = AudioUnitSetParameter(audioUnit,
|
||||
kHALOutputParam_Volume,
|
||||
kAudioUnitParameterFlag_Output, 0,
|
||||
1, 0);
|
||||
verify(err == noErr);
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
err = AudioUnitInitialize(audioUnit);
|
||||
|
||||
|
||||
verify(err == noErr);
|
||||
|
||||
|
||||
err = AudioOutputUnitStart(audioUnit);
|
||||
|
||||
verify(err == noErr);
|
||||
|
||||
|
||||
bufferEmpty.Set();
|
||||
}
|
||||
|
||||
|
|
@ -134,23 +134,23 @@ static u32 coreaudio_push(void* frame, u32 samples, bool wait)
|
|||
samples_wptr = (samples_wptr + byte_size) % BUFSIZE;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void coreaudio_term()
|
||||
{
|
||||
OSStatus err;
|
||||
|
||||
|
||||
err = AudioOutputUnitStop(audioUnit);
|
||||
verify(err == noErr);
|
||||
|
||||
|
||||
err = AudioUnitUninitialize(audioUnit);
|
||||
verify(err == noErr);
|
||||
|
||||
|
||||
err = AudioComponentInstanceDispose(audioUnit);
|
||||
verify(err == noErr);
|
||||
|
||||
|
||||
bufferEmpty.Set();
|
||||
}
|
||||
|
||||
|
|
@ -159,6 +159,10 @@ audiobackend_t audiobackend_coreaudio = {
|
|||
"Core Audio", // Name
|
||||
&coreaudio_init,
|
||||
&coreaudio_push,
|
||||
&coreaudio_term
|
||||
&coreaudio_term,
|
||||
NULL
|
||||
};
|
||||
|
||||
static bool core = RegisterAudioBackend(&audiobackend_coreaudio);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
#pragma once
|
||||
#include "oslib/audiostream.h"
|
||||
|
||||
extern audiobackend_t audiobackend_coreaudio;
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#include "oslib/audiobackend_directsound.h"
|
||||
#include "oslib/audiostream.h"
|
||||
#if HOST_OS==OS_WINDOWS
|
||||
#include "oslib.h"
|
||||
#include <initguid.h>
|
||||
|
|
@ -19,31 +19,31 @@ static void directsound_init()
|
|||
verifyc(dsound->SetCooperativeLevel((HWND)libPvr_GetRenderTarget(),DSSCL_PRIORITY));
|
||||
IDirectSoundBuffer* buffer_;
|
||||
|
||||
WAVEFORMATEX wfx;
|
||||
DSBUFFERDESC desc;
|
||||
WAVEFORMATEX wfx;
|
||||
DSBUFFERDESC desc;
|
||||
|
||||
// Set up WAV format structure.
|
||||
// Set up WAV format structure.
|
||||
|
||||
memset(&wfx, 0, sizeof(WAVEFORMATEX));
|
||||
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wfx.nChannels = 2;
|
||||
wfx.nSamplesPerSec = 44100;
|
||||
wfx.nBlockAlign = 4;
|
||||
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
|
||||
wfx.wBitsPerSample = 16;
|
||||
memset(&wfx, 0, sizeof(WAVEFORMATEX));
|
||||
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wfx.nChannels = 2;
|
||||
wfx.nSamplesPerSec = 44100;
|
||||
wfx.nBlockAlign = 4;
|
||||
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
|
||||
wfx.wBitsPerSample = 16;
|
||||
|
||||
// Set up DSBUFFERDESC structure.
|
||||
// Set up DSBUFFERDESC structure.
|
||||
|
||||
ds_ring_size=8192*wfx.nBlockAlign;
|
||||
|
||||
memset(&desc, 0, sizeof(DSBUFFERDESC));
|
||||
desc.dwSize = sizeof(DSBUFFERDESC);
|
||||
desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY;// _CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
|
||||
|
||||
desc.dwBufferBytes = ds_ring_size;
|
||||
desc.lpwfxFormat = &wfx;
|
||||
memset(&desc, 0, sizeof(DSBUFFERDESC));
|
||||
desc.dwSize = sizeof(DSBUFFERDESC);
|
||||
desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY;// _CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
|
||||
|
||||
desc.dwBufferBytes = ds_ring_size;
|
||||
desc.lpwfxFormat = &wfx;
|
||||
|
||||
|
||||
|
||||
|
||||
if (settings.aica.HW_mixing==0)
|
||||
{
|
||||
|
|
@ -71,7 +71,7 @@ static void directsound_init()
|
|||
|
||||
//Play the buffer !
|
||||
verifyc(buffer->Play(0,0,DSBPLAY_LOOPING));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -159,7 +159,7 @@ static u32 directsound_push(void* frame, u32 samples, bool wait)
|
|||
wait &= w;
|
||||
*/
|
||||
int ffs=1;
|
||||
|
||||
|
||||
/*
|
||||
while (directsound_IsAudioBufferedLots() && wait)
|
||||
if (ffs == 0)
|
||||
|
|
@ -175,7 +175,7 @@ static u32 directsound_push(void* frame, u32 samples, bool wait)
|
|||
static void directsound_term()
|
||||
{
|
||||
buffer->Stop();
|
||||
|
||||
|
||||
buffer->Release();
|
||||
dsound->Release();
|
||||
}
|
||||
|
|
@ -185,6 +185,9 @@ audiobackend_t audiobackend_directsound = {
|
|||
"Microsoft DirectSound", // Name
|
||||
&directsound_init,
|
||||
&directsound_push,
|
||||
&directsound_term
|
||||
&directsound_term,
|
||||
NULL
|
||||
};
|
||||
|
||||
static bool ds = RegisterAudioBackend(&audiobackend_directsound);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
#pragma once
|
||||
#include "oslib/audiostream.h"
|
||||
|
||||
extern audiobackend_t audiobackend_directsound;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#include "oslib/audiobackend_libao.h"
|
||||
#include "oslib/audiostream.h"
|
||||
#ifdef USE_LIBAO
|
||||
|
||||
#include <ao/ao.h>
|
||||
|
|
@ -10,12 +10,12 @@ static void libao_init()
|
|||
{
|
||||
ao_initialize();
|
||||
memset(&aoformat, 0, sizeof(aoformat));
|
||||
|
||||
|
||||
aoformat.bits = 16;
|
||||
aoformat.channels = 2;
|
||||
aoformat.rate = 44100;
|
||||
aoformat.byte_format = AO_FMT_LITTLE;
|
||||
|
||||
|
||||
aodevice = ao_open_live(ao_default_driver_id(), &aoformat, NULL); // Live output
|
||||
if (!aodevice)
|
||||
aodevice = ao_open_live(ao_driver_id("null"), &aoformat, NULL);
|
||||
|
|
@ -23,13 +23,13 @@ static void libao_init()
|
|||
|
||||
static u32 libao_push(void* frame, u32 samples, bool wait)
|
||||
{
|
||||
if (aodevice)
|
||||
if (aodevice)
|
||||
ao_play(aodevice, (char*)frame, samples * 4);
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void libao_term()
|
||||
static void libao_term()
|
||||
{
|
||||
if (aodevice)
|
||||
{
|
||||
|
|
@ -43,7 +43,9 @@ audiobackend_t audiobackend_libao = {
|
|||
"libao", // Name
|
||||
&libao_init,
|
||||
&libao_push,
|
||||
&libao_term
|
||||
&libao_term,
|
||||
NULL
|
||||
};
|
||||
|
||||
static bool ao = RegisterAudioBackend(&audiobackend_libao);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
#pragma once
|
||||
#include "oslib/audiostream.h"
|
||||
|
||||
extern audiobackend_t audiobackend_libao;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#include "oslib/audiobackend_omx.h"
|
||||
#include "oslib/audiostream.h"
|
||||
#if USE_OMX
|
||||
|
||||
#include <IL/OMX_Broadcom.h>
|
||||
|
|
@ -313,7 +313,9 @@ audiobackend_t audiobackend_omx = {
|
|||
"OpenMAX IL", // Name
|
||||
&omx_init,
|
||||
&omx_push,
|
||||
&omx_term
|
||||
&omx_term,
|
||||
NULL
|
||||
};
|
||||
|
||||
static bool omx = RegisterAudioBackend(&audiobackend_omx);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
#pragma once
|
||||
#include "oslib/audiostream.h"
|
||||
|
||||
extern audiobackend_t audiobackend_omx;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#include "oslib/audiobackend_oss.h"
|
||||
#include "oslib/audiostream.h"
|
||||
#ifdef USE_OSS
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/fcntl.h>
|
||||
|
|
@ -48,7 +48,9 @@ audiobackend_t audiobackend_oss = {
|
|||
"Open Sound System", // Name
|
||||
&oss_init,
|
||||
&oss_push,
|
||||
&oss_term
|
||||
&oss_term,
|
||||
NULL
|
||||
};
|
||||
|
||||
static bool oss = RegisterAudioBackend(&audiobackend_oss);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
#pragma once
|
||||
#include "oslib/audiostream.h"
|
||||
|
||||
extern audiobackend_t audiobackend_oss;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#include "oslib/audiobackend_pulseaudio.h"
|
||||
#include "oslib/audiostream.h"
|
||||
#ifdef USE_PULSEAUDIO
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/fcntl.h>
|
||||
|
|
@ -43,6 +43,9 @@ audiobackend_t audiobackend_pulseaudio = {
|
|||
"PulseAudio", // Name
|
||||
&pulseaudio_init,
|
||||
&pulseaudio_push,
|
||||
&pulseaudio_term
|
||||
&pulseaudio_term,
|
||||
NULL
|
||||
};
|
||||
|
||||
static bool pulse = RegisterAudioBackend(&audiobackend_pulseaudio);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
#pragma once
|
||||
#include "oslib/audiostream.h"
|
||||
|
||||
extern audiobackend_t audiobackend_pulseaudio;
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
|
||||
#if defined(USE_SDL_AUDIO)
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include "oslib/audiostream.h"
|
||||
#include "stdclass.h"
|
||||
|
||||
static SDL_AudioDeviceID audiodev;
|
||||
static bool needs_resampling;
|
||||
static cResetEvent read_wait;
|
||||
static cMutex stream_mutex;
|
||||
static struct {
|
||||
uint32_t prevs;
|
||||
uint32_t sample_buffer[2048];
|
||||
} audiobuf;
|
||||
static unsigned sample_count = 0;
|
||||
|
||||
// To easily access samples.
|
||||
union Sample { int16_t s[2]; uint32_t l; };
|
||||
|
||||
static float InterpolateCatmull4pt3oX(float x0, float x1, float x2, float x3, float t) {
|
||||
return 0.45 * ((2 * x1) + t * ((-x0 + x2) + t * ((2 * x0 - 5 * x1 + 4 * x2 - x3) + t * (-x0 + 3 * x1 - 3 * x2 + x3))));
|
||||
}
|
||||
|
||||
static void sdl2_audiocb(void* userdata, Uint8* stream, int len) {
|
||||
stream_mutex.Lock();
|
||||
// Wait until there's enough samples to feed the kraken
|
||||
unsigned oslen = len / sizeof(uint32_t);
|
||||
unsigned islen = needs_resampling ? oslen * 16 / 17 : oslen;
|
||||
unsigned minlen = needs_resampling ? islen + 2 : islen; // Resampler looks ahead by 2 samples.
|
||||
|
||||
if (sample_count < minlen) {
|
||||
// No data, just output a bit of silence for the underrun
|
||||
memset(stream, 0, len);
|
||||
stream_mutex.Unlock();
|
||||
read_wait.Set();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!needs_resampling) {
|
||||
// Just copy bytes for this case.
|
||||
memcpy(stream, &audiobuf.sample_buffer[0], len);
|
||||
}
|
||||
else {
|
||||
// 44.1KHz to 48KHz (actually 46.86KHz) resampling
|
||||
uint32_t *outbuf = (uint32_t*)stream;
|
||||
const float ra = 1.0f / 17;
|
||||
Sample *sbuf = (Sample*)&audiobuf.sample_buffer[0]; // [-1] stores the previous iteration last sample output
|
||||
for (int i = 0; i < islen/16; i++) {
|
||||
*outbuf++ = sbuf[i*16+ 0].l; // First sample stays at the same location.
|
||||
for (int k = 1; k < 17; k++) {
|
||||
Sample r;
|
||||
// Note we access offset -1 on first iteration, as to access prevs
|
||||
r.s[0] = InterpolateCatmull4pt3oX(sbuf[i*16+k-2].s[0], sbuf[i*16+k-1].s[0], sbuf[i*16+k].s[0], sbuf[i*16+k+1].s[0], 1 - ra*k);
|
||||
r.s[1] = InterpolateCatmull4pt3oX(sbuf[i*16+k-2].s[1], sbuf[i*16+k-1].s[1], sbuf[i*16+k].s[1], sbuf[i*16+k+1].s[1], 1 - ra*k);
|
||||
*outbuf++ = r.l;
|
||||
}
|
||||
}
|
||||
audiobuf.prevs = audiobuf.sample_buffer[islen-1];
|
||||
}
|
||||
|
||||
// Move samples in the buffer and consume them
|
||||
memmove(&audiobuf.sample_buffer[0], &audiobuf.sample_buffer[islen], (sample_count-islen)*sizeof(uint32_t));
|
||||
sample_count -= islen;
|
||||
|
||||
stream_mutex.Unlock();
|
||||
read_wait.Set();
|
||||
}
|
||||
|
||||
static void sdl2_audio_init() {
|
||||
if (!SDL_WasInit(SDL_INIT_AUDIO))
|
||||
SDL_InitSubSystem(SDL_INIT_AUDIO);
|
||||
|
||||
// Support 44.1KHz (native) but also upsampling to 48KHz
|
||||
SDL_AudioSpec wav_spec, out_spec;
|
||||
memset(&wav_spec, 0, sizeof(wav_spec));
|
||||
wav_spec.freq = 44100;
|
||||
wav_spec.format = AUDIO_S16;
|
||||
wav_spec.channels = 2;
|
||||
wav_spec.samples = 1024; // Must be power of two
|
||||
wav_spec.callback = sdl2_audiocb;
|
||||
|
||||
// Try 44.1KHz which should be faster since it's native.
|
||||
audiodev = SDL_OpenAudioDevice(NULL, 0, &wav_spec, &out_spec, 0);
|
||||
if (!audiodev) {
|
||||
needs_resampling = true;
|
||||
wav_spec.freq = 48000;
|
||||
audiodev = SDL_OpenAudioDevice(NULL, 0, &wav_spec, &out_spec, 0);
|
||||
verify(audiodev);
|
||||
}
|
||||
}
|
||||
|
||||
static u32 sdl2_audio_push(void* frame, u32 samples, bool wait) {
|
||||
// Unpause the device shall it be paused.
|
||||
if (SDL_GetAudioDeviceStatus(audiodev) != SDL_AUDIO_PLAYING)
|
||||
SDL_PauseAudioDevice(audiodev, 0);
|
||||
|
||||
// If wait, then wait for the buffer to be smaller than a certain size.
|
||||
stream_mutex.Lock();
|
||||
if (wait) {
|
||||
while (sample_count + samples > sizeof(audiobuf.sample_buffer)/sizeof(audiobuf.sample_buffer[0])) {
|
||||
stream_mutex.Unlock();
|
||||
read_wait.Wait();
|
||||
read_wait.Reset();
|
||||
stream_mutex.Lock();
|
||||
}
|
||||
}
|
||||
|
||||
// Copy as many samples as possible, drop any remaining (this should not happen usually)
|
||||
unsigned free_samples = sizeof(audiobuf.sample_buffer) / sizeof(audiobuf.sample_buffer[0]) - sample_count;
|
||||
unsigned tocopy = samples < free_samples ? samples : free_samples;
|
||||
memcpy(&audiobuf.sample_buffer[sample_count], frame, tocopy * sizeof(uint32_t));
|
||||
sample_count += tocopy;
|
||||
stream_mutex.Unlock();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void sdl2_audio_term() {
|
||||
// Stop audio playback.
|
||||
SDL_PauseAudioDevice(audiodev, 1);
|
||||
read_wait.Set();
|
||||
}
|
||||
|
||||
audiobackend_t audiobackend_sdl2audio = {
|
||||
"sdl2", // Slug
|
||||
"Simple DirectMedia Layer 2 Audio", // Name
|
||||
&sdl2_audio_init,
|
||||
&sdl2_audio_push,
|
||||
&sdl2_audio_term
|
||||
};
|
||||
|
||||
static bool sdl2audiobe = RegisterAudioBackend(&audiobackend_sdl2audio);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -2,14 +2,6 @@
|
|||
#include "cfg/cfg.h"
|
||||
#include "oslib/oslib.h"
|
||||
#include "audiostream.h"
|
||||
#include "oslib/audiobackend_directsound.h"
|
||||
#include "oslib/audiobackend_android.h"
|
||||
#include "oslib/audiobackend_alsa.h"
|
||||
#include "oslib/audiobackend_oss.h"
|
||||
#include "oslib/audiobackend_pulseaudio.h"
|
||||
#include "oslib/audiobackend_coreaudio.h"
|
||||
#include "oslib/audiobackend_omx.h"
|
||||
#include "oslib/audiobackend_libao.h"
|
||||
|
||||
struct SoundFrame { s16 l;s16 r; };
|
||||
#define SAMPLE_COUNT 512
|
||||
|
|
@ -25,16 +17,27 @@ u32 gen_samples=0;
|
|||
|
||||
double time_diff = 128/44100.0;
|
||||
double time_last;
|
||||
|
||||
#ifdef LOG_SOUND
|
||||
// TODO Only works on Windows!
|
||||
WaveWriter rawout("d:\\aica_out.wav");
|
||||
#endif
|
||||
|
||||
static bool audiobackends_registered = false;
|
||||
static unsigned int audiobackends_num_max = 1;
|
||||
static unsigned int audiobackends_num_registered = 0;
|
||||
static audiobackend_t **audiobackends = static_cast<audiobackend_t**>(calloc(audiobackends_num_max, sizeof(audiobackend_t*)));
|
||||
static audiobackend_t **audiobackends = NULL;
|
||||
static audiobackend_t *audiobackend_current = NULL;
|
||||
|
||||
u32 GetAudioBackendCount()
|
||||
{
|
||||
return audiobackends_num_registered;
|
||||
}
|
||||
|
||||
audiobackend_t* GetAudioBackend(int num)
|
||||
{
|
||||
return audiobackends[num];
|
||||
}
|
||||
|
||||
bool RegisterAudioBackend(audiobackend_t *backend)
|
||||
{
|
||||
/* This function announces the availability of an audio backend to reicast. */
|
||||
|
|
@ -44,10 +47,16 @@ bool RegisterAudioBackend(audiobackend_t *backend)
|
|||
printf("ERROR: Tried to register invalid audio backend (NULL pointer).\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (backend->slug == "auto" || backend->slug == "none") {
|
||||
printf("ERROR: Tried to register invalid audio backend (slug \"%s\" is a reserved keyword).\n", backend->slug.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// First call to RegisterAudioBackend(), create the backend structure;
|
||||
if (audiobackends == NULL)
|
||||
audiobackends = static_cast<audiobackend_t**>(calloc(audiobackends_num_max, sizeof(audiobackend_t*)));
|
||||
|
||||
// Check if we need to allocate addition memory for storing the pointers and allocate if neccessary
|
||||
if (audiobackends_num_registered == audiobackends_num_max)
|
||||
{
|
||||
|
|
@ -67,46 +76,19 @@ bool RegisterAudioBackend(audiobackend_t *backend)
|
|||
}
|
||||
audiobackends = new_ptr;
|
||||
}
|
||||
|
||||
audiobackends[audiobackends_num_registered] = backend;
|
||||
audiobackends_num_registered++;
|
||||
return true;
|
||||
}
|
||||
|
||||
void RegisterAllAudioBackends() {
|
||||
#if HOST_OS==OS_WINDOWS
|
||||
RegisterAudioBackend(&audiobackend_directsound);
|
||||
#endif
|
||||
#if ANDROID
|
||||
RegisterAudioBackend(&audiobackend_android);
|
||||
#endif
|
||||
#if USE_OMX
|
||||
RegisterAudioBackend(&audiobackend_omx);
|
||||
#endif
|
||||
#if USE_ALSA
|
||||
RegisterAudioBackend(&audiobackend_alsa);
|
||||
#endif
|
||||
#if USE_OSS
|
||||
RegisterAudioBackend(&audiobackend_oss);
|
||||
#endif
|
||||
#if USE_PULSEAUDIO
|
||||
RegisterAudioBackend(&audiobackend_pulseaudio);
|
||||
#endif
|
||||
#if USE_LIBAO
|
||||
RegisterAudioBackend(&audiobackend_libao);
|
||||
#endif
|
||||
#if HOST_OS == OS_DARWIN
|
||||
RegisterAudioBackend(&audiobackend_coreaudio);
|
||||
#endif
|
||||
audiobackends_registered = true;
|
||||
}
|
||||
|
||||
static audiobackend_t* GetAudioBackend(std::string slug)
|
||||
audiobackend_t* GetAudioBackend(std::string slug)
|
||||
{
|
||||
if (slug == "none")
|
||||
{
|
||||
printf("WARNING: Audio backend set to \"none\"!\n");
|
||||
}
|
||||
else if(audiobackends_num_registered > 0)
|
||||
else if (audiobackends_num_registered > 0)
|
||||
{
|
||||
if (slug == "auto")
|
||||
{
|
||||
|
|
@ -135,7 +117,8 @@ static audiobackend_t* GetAudioBackend(std::string slug)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
u32 PushAudio(void* frame, u32 amt, bool wait) {
|
||||
u32 PushAudio(void* frame, u32 amt, bool wait)
|
||||
{
|
||||
if (audiobackend_current != NULL) {
|
||||
return audiobackend_current->push(frame, amt, wait);
|
||||
}
|
||||
|
|
@ -151,11 +134,13 @@ u32 asRingUsedCount()
|
|||
//s32 sz=(WritePtr+1)%RingBufferSampleCount-ReadPtr;
|
||||
//return sz<0?sz+RingBufferSampleCount:sz;
|
||||
}
|
||||
|
||||
u32 asRingFreeCount()
|
||||
{
|
||||
return RingBufferSampleCount-asRingUsedCount();
|
||||
}
|
||||
|
||||
extern double mspdf;
|
||||
void WriteSample(s16 r, s16 l)
|
||||
{
|
||||
const u32 ptr=(WritePtr+1)%RingBufferSampleCount;
|
||||
|
|
@ -165,7 +150,30 @@ void WriteSample(s16 r, s16 l)
|
|||
|
||||
if (WritePtr==(SAMPLE_COUNT-1))
|
||||
{
|
||||
PushAudio(RingBuffer,SAMPLE_COUNT,settings.aica.LimitFPS);
|
||||
bool do_wait = settings.aica.LimitFPS && (mspdf <= 11);
|
||||
|
||||
PushAudio(RingBuffer,SAMPLE_COUNT, do_wait);
|
||||
}
|
||||
}
|
||||
|
||||
static bool backends_sorted = false;
|
||||
void SortAudioBackends()
|
||||
{
|
||||
if (backends_sorted)
|
||||
return;
|
||||
|
||||
// Sort backends by slug
|
||||
for (int n = audiobackends_num_registered; n > 0; n--)
|
||||
{
|
||||
for (int i = 0; i < n-1; i++)
|
||||
{
|
||||
if (audiobackends[i]->slug > audiobackends[i+1]->slug)
|
||||
{
|
||||
audiobackend_t* swap = audiobackends[i];
|
||||
audiobackends[i] = audiobackends[i+1];
|
||||
audiobackends[i+1] = swap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -176,26 +184,24 @@ void InitAudio()
|
|||
return;
|
||||
}
|
||||
|
||||
cfgSaveInt("audio","disable",0);
|
||||
|
||||
if (!audiobackends_registered) {
|
||||
//FIXME: There might some nicer way to do this.
|
||||
RegisterAllAudioBackends();
|
||||
}
|
||||
cfgSaveInt("audio", "disable", 0);
|
||||
|
||||
if (audiobackend_current != NULL) {
|
||||
printf("ERROR: The audio backend \"%s\" (%s) has already been initialized, you need to terminate it before you can call audio_init() again!\n", audiobackend_current->slug.c_str(), audiobackend_current->name.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
string audiobackend_slug = cfgLoadStr("audio", "backend", "auto"); // FIXME: This could be made a parameter
|
||||
SortAudioBackends();
|
||||
|
||||
string audiobackend_slug = settings.audio.backend;
|
||||
audiobackend_current = GetAudioBackend(audiobackend_slug);
|
||||
if (audiobackend_current == NULL) {
|
||||
printf("WARNING: Running without audio!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Initializing audio backend \"%s\" (%s)...\n", audiobackend_current->slug.c_str(), audiobackend_current->name.c_str());
|
||||
audiobackend_current->init();
|
||||
audiobackend_current->init();
|
||||
}
|
||||
|
||||
void TermAudio()
|
||||
|
|
@ -204,5 +210,5 @@ void TermAudio()
|
|||
audiobackend_current->term();
|
||||
printf("Terminating audio backend \"%s\" (%s)...\n", audiobackend_current->slug.c_str(), audiobackend_current->name.c_str());
|
||||
audiobackend_current = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "types.h"
|
||||
#include <tuple>
|
||||
|
||||
//Get used size in the ring buffer
|
||||
u32 asRingUsedCount();
|
||||
|
|
@ -10,6 +11,29 @@ u32 asRingFreeCount();
|
|||
bool asRingRead(u8* dst,u32 count=0);
|
||||
void UpdateBuff(u8* pos);
|
||||
|
||||
typedef std::vector<std::string> (*audio_option_callback_t)();
|
||||
enum audio_option_type
|
||||
{
|
||||
integer = 0
|
||||
, checkbox = 1
|
||||
, list = 2
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
std::string cfg_name;
|
||||
std::string caption;
|
||||
audio_option_type type;
|
||||
|
||||
// type int_value (spin edit)
|
||||
int min_value;
|
||||
int max_value;
|
||||
|
||||
// type list edit (string/char*)
|
||||
audio_option_callback_t list_callback;
|
||||
} audio_option_t;
|
||||
|
||||
typedef audio_option_t* (*audio_options_func_t)(int* option_count);
|
||||
|
||||
typedef void (*audio_backend_init_func_t)();
|
||||
typedef u32 (*audio_backend_push_func_t)(void*, u32, bool);
|
||||
typedef void (*audio_backend_term_func_t)();
|
||||
|
|
@ -19,8 +43,14 @@ typedef struct {
|
|||
audio_backend_init_func_t init;
|
||||
audio_backend_push_func_t push;
|
||||
audio_backend_term_func_t term;
|
||||
audio_options_func_t get_options;
|
||||
} audiobackend_t;
|
||||
extern bool RegisterAudioBackend(audiobackend_t* backend);
|
||||
extern void InitAudio();
|
||||
extern u32 PushAudio(void* frame, u32 amt, bool wait);
|
||||
extern void TermAudio();
|
||||
|
||||
u32 GetAudioBackendCount();
|
||||
void SortAudioBackends();
|
||||
audiobackend_t* GetAudioBackend(int num);
|
||||
audiobackend_t* GetAudioBackend(std::string slug);
|
||||
|
|
|
|||
|
|
@ -1420,9 +1420,12 @@ private:
|
|||
std::vector<const VRegister*> call_fregs;
|
||||
Arm64RegAlloc regalloc;
|
||||
RuntimeBlockInfo* block;
|
||||
const int write_memory_rewrite_size = 3; // same size (fast write) for any size: add, bfc, str
|
||||
#ifdef EXPLODE_SPANS
|
||||
const int read_memory_rewrite_size = 6; // worst case for u64: add, bfc, ldr, fmov, lsr, fmov
|
||||
// FIXME rewrite size per read/write size?
|
||||
const int write_memory_rewrite_size = 3;
|
||||
#else
|
||||
const int read_memory_rewrite_size = 4; // worst case for u64: add, bfc, ldr, str
|
||||
#endif
|
||||
};
|
||||
|
||||
static Arm64Assembler* compiler;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
_TEXT SEGMENT
|
||||
|
||||
SH4_TIMESLICE = 448
|
||||
CPU_RUNNING = 135266148
|
||||
PC = 135266120
|
||||
|
||||
EXTERN bm_GetCode2: PROC
|
||||
EXTERN UpdateSystem_INTC: PROC
|
||||
EXTERN cycle_counter: dword
|
||||
EXTERN p_sh4rcb: qword
|
||||
|
||||
PUBLIC ngen_mainloop
|
||||
ngen_mainloop PROC
|
||||
|
||||
push rbx
|
||||
push rbp
|
||||
push rdi
|
||||
push rsi
|
||||
push r12
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
sub rsp, 40 ; 32-byte shadow space + 8 for stack 16-byte alignment
|
||||
|
||||
mov dword ptr [cycle_counter], SH4_TIMESLICE
|
||||
|
||||
run_loop:
|
||||
mov rax, qword ptr [p_sh4rcb]
|
||||
mov edx, dword ptr[CPU_RUNNING + rax]
|
||||
test edx, edx
|
||||
je end_run_loop
|
||||
|
||||
slice_loop:
|
||||
mov rax, qword ptr [p_sh4rcb]
|
||||
mov ecx, dword ptr[PC + rax]
|
||||
call bm_GetCode2
|
||||
call rax
|
||||
mov ecx, dword ptr [cycle_counter]
|
||||
test ecx, ecx
|
||||
jg slice_loop
|
||||
|
||||
add ecx, SH4_TIMESLICE
|
||||
mov dword ptr [cycle_counter], ecx
|
||||
call UpdateSystem_INTC
|
||||
jmp run_loop
|
||||
|
||||
end_run_loop:
|
||||
|
||||
add rsp, 40
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop rsi
|
||||
pop rdi
|
||||
pop rbp
|
||||
pop rbx
|
||||
ret
|
||||
ngen_mainloop ENDP
|
||||
_TEXT ENDS
|
||||
END
|
||||
|
|
@ -32,7 +32,9 @@ struct DynaRBI : RuntimeBlockInfo
|
|||
}
|
||||
};
|
||||
|
||||
int cycle_counter;
|
||||
extern "C" {
|
||||
int cycle_counter;
|
||||
}
|
||||
|
||||
double host_cpu_time;
|
||||
u64 guest_cpu_cycles;
|
||||
|
|
@ -76,6 +78,8 @@ static __attribute((used)) void end_slice()
|
|||
#error RAM_SIZE_MAX unknown
|
||||
#endif
|
||||
|
||||
#ifndef _MSC_VER
|
||||
|
||||
#ifdef _WIN32
|
||||
// Fully naked function in win32 for proper SEH prologue
|
||||
__asm__ (
|
||||
|
|
@ -177,6 +181,7 @@ WIN32_ONLY( ".seh_pushreg %r14 \n\t")
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif // !_MSC_VER
|
||||
#undef _U
|
||||
#undef _S
|
||||
|
||||
|
|
|
|||
|
|
@ -326,8 +326,8 @@ void ngen_Compile(RuntimeBlockInfo* block, SmcCheckEnum smc_checks, bool reset,
|
|||
|
||||
if (prof.enable)
|
||||
{
|
||||
if (force_checks)
|
||||
x86e->Emit(op_add32,&prof.counters.blkrun.force_check,1);
|
||||
//if (force_checks)
|
||||
// x86e->Emit(op_add32,&prof.counters.blkrun.force_check,1);
|
||||
|
||||
x86e->Emit(op_add32,&prof.counters.blkrun.cycles[block->guest_cycles],1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,8 +124,7 @@ void palette_update()
|
|||
using namespace std;
|
||||
|
||||
vector<vram_block*> VramLocks[VRAM_SIZE/PAGE_SIZE];
|
||||
//vram 32-64b
|
||||
VArray2 vram;
|
||||
VLockedMemory vram; // vram 32-64b
|
||||
|
||||
//List functions
|
||||
//
|
||||
|
|
@ -207,7 +206,7 @@ vram_block* libCore_vramlock_Lock(u32 start_offset64,u32 end_offset64,void* user
|
|||
{
|
||||
vramlist_lock.Lock();
|
||||
|
||||
vram.LockRegion(block->start,block->len);
|
||||
vram.LockRegion(block->start, block->len);
|
||||
|
||||
//TODO: Fix this for 32M wrap as well
|
||||
if (_nvmem_enabled() && VRAM_SIZE == 0x800000) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include <d3d11.h>
|
||||
#include "hw\pvr\Renderer_if.h"
|
||||
#include "oslib\oslib.h"
|
||||
#include "hw/pvr/Renderer_if.h"
|
||||
#include "oslib/oslib.h"
|
||||
|
||||
#pragma comment(lib,"d3d11.lib")
|
||||
|
||||
|
|
@ -102,4 +102,4 @@ struct d3d11 : Renderer
|
|||
Renderer* rend_D3D11()
|
||||
{
|
||||
return new d3d11();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -331,23 +331,23 @@ void initABuffer()
|
|||
{
|
||||
char source[16384];
|
||||
sprintf(source, final_shader_source, 1);
|
||||
gl4CompilePipelineShader(&g_abuffer_final_shader, source);
|
||||
gl4CompilePipelineShader(&g_abuffer_final_shader, false, source);
|
||||
}
|
||||
if (g_abuffer_final_nosort_shader.program == 0)
|
||||
{
|
||||
char source[16384];
|
||||
sprintf(source, final_shader_source, 0);
|
||||
gl4CompilePipelineShader(&g_abuffer_final_nosort_shader, source);
|
||||
gl4CompilePipelineShader(&g_abuffer_final_nosort_shader, false, source);
|
||||
}
|
||||
if (g_abuffer_clear_shader.program == 0)
|
||||
gl4CompilePipelineShader(&g_abuffer_clear_shader, clear_shader_source);
|
||||
gl4CompilePipelineShader(&g_abuffer_clear_shader, false, clear_shader_source);
|
||||
if (g_abuffer_tr_modvol_shaders[0].program == 0)
|
||||
{
|
||||
char source[16384];
|
||||
for (int mode = 0; mode < ModeCount; mode++)
|
||||
{
|
||||
sprintf(source, tr_modvol_shader_source, mode);
|
||||
gl4CompilePipelineShader(&g_abuffer_tr_modvol_shaders[mode], source);
|
||||
gl4CompilePipelineShader(&g_abuffer_tr_modvol_shaders[mode], false, source);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -417,6 +417,17 @@ void termABuffer()
|
|||
glDeleteBuffers(1, &g_quadBuffer);
|
||||
g_quadBuffer = 0;
|
||||
}
|
||||
glcache.DeleteProgram(g_abuffer_final_shader.program);
|
||||
g_abuffer_final_shader.program = 0;
|
||||
glcache.DeleteProgram(g_abuffer_final_nosort_shader.program);
|
||||
g_abuffer_final_nosort_shader.program = 0;
|
||||
glcache.DeleteProgram(g_abuffer_clear_shader.program);
|
||||
g_abuffer_clear_shader.program = 0;
|
||||
for (int mode = 0; mode < ModeCount; mode++)
|
||||
{
|
||||
glcache.DeleteProgram(g_abuffer_tr_modvol_shaders[mode].program);
|
||||
g_abuffer_tr_modvol_shaders[mode].program = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void reshapeABuffer(int w, int h)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
#include "rend/gles/gles.h"
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
void gl4DrawStrips(GLuint output_fbo);
|
||||
|
||||
|
|
@ -44,7 +44,8 @@ struct gl4_ctx
|
|||
GLuint extra_depth_scale;
|
||||
} modvol_shader;
|
||||
|
||||
std::map<int, gl4PipelineShader *> shaders;
|
||||
std::unordered_map<u32, gl4PipelineShader> shaders;
|
||||
bool rotate90;
|
||||
|
||||
struct
|
||||
{
|
||||
|
|
@ -53,16 +54,6 @@ struct gl4_ctx
|
|||
GLuint modvol_vao;
|
||||
GLuint tr_poly_params;
|
||||
} vbo;
|
||||
|
||||
gl4PipelineShader *getShader(int programId) {
|
||||
gl4PipelineShader *shader = shaders[programId];
|
||||
if (shader == NULL) {
|
||||
shader = new gl4PipelineShader();
|
||||
shaders[programId] = shader;
|
||||
shader->program = -1;
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
};
|
||||
|
||||
extern gl4_ctx gl4;
|
||||
|
|
@ -76,7 +67,8 @@ bool gl4_render_output_framebuffer();
|
|||
void abufferDrawQuad(bool upsideDown = false, float x = 0.f, float y = 0.f, float w = 0.f, float h = 0.f);
|
||||
|
||||
extern const char *gl4PixelPipelineShader;
|
||||
bool gl4CompilePipelineShader(gl4PipelineShader* s, const char *source = gl4PixelPipelineShader);
|
||||
bool gl4CompilePipelineShader(gl4PipelineShader* s, bool rotate_90, const char *source = gl4PixelPipelineShader);
|
||||
void gl4_delete_shaders();
|
||||
|
||||
extern GLuint stencilTexId;
|
||||
extern GLuint depthTexId;
|
||||
|
|
|
|||
|
|
@ -45,10 +45,15 @@ static GLuint texSamplers[2];
|
|||
static GLuint depth_fbo;
|
||||
GLuint depthSaveTexId;
|
||||
|
||||
static int gl4GetProgramID(u32 cp_AlphaTest, u32 pp_ClipTestMode,
|
||||
static gl4PipelineShader *gl4GetProgram(u32 cp_AlphaTest, u32 pp_ClipTestMode,
|
||||
u32 pp_Texture, u32 pp_UseAlpha, u32 pp_IgnoreTexA, u32 pp_ShadInstr, u32 pp_Offset,
|
||||
u32 pp_FogCtrl, bool pp_TwoVolumes, u32 pp_DepthFunc, bool pp_Gouraud, bool pp_BumpMap, bool fog_clamping, int pass)
|
||||
{
|
||||
if (settings.rend.Rotate90 != gl4.rotate90)
|
||||
{
|
||||
gl4_delete_shaders();
|
||||
gl4.rotate90 = settings.rend.Rotate90;
|
||||
}
|
||||
u32 rv=0;
|
||||
|
||||
rv|=pp_ClipTestMode;
|
||||
|
|
@ -66,45 +71,27 @@ static int gl4GetProgramID(u32 cp_AlphaTest, u32 pp_ClipTestMode,
|
|||
rv <<= 1; rv |= fog_clamping;
|
||||
rv <<= 2; rv |= pass;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void setCurrentShader(u32 cp_AlphaTest, u32 pp_ClipTestMode,
|
||||
u32 pp_Texture, u32 pp_UseAlpha, u32 pp_IgnoreTexA, u32 pp_ShadInstr, u32 pp_Offset,
|
||||
u32 pp_FogCtrl, bool pp_TwoVolumes, u32 pp_DepthFunc, bool pp_Gouraud, bool pp_BumpMap, bool fog_clamping, int pass)
|
||||
{
|
||||
int shaderId = gl4GetProgramID(cp_AlphaTest,
|
||||
pp_ClipTestMode + 1,
|
||||
pp_Texture,
|
||||
pp_UseAlpha,
|
||||
pp_IgnoreTexA,
|
||||
pp_ShadInstr,
|
||||
pp_Offset,
|
||||
pp_FogCtrl,
|
||||
pp_TwoVolumes,
|
||||
pp_DepthFunc,
|
||||
pp_Gouraud,
|
||||
pp_BumpMap,
|
||||
fog_clamping,
|
||||
pass);
|
||||
CurrentShader = gl4.getShader(shaderId);
|
||||
if (CurrentShader->program == -1) {
|
||||
CurrentShader->cp_AlphaTest = cp_AlphaTest;
|
||||
CurrentShader->pp_ClipTestMode = pp_ClipTestMode;
|
||||
CurrentShader->pp_Texture = pp_Texture;
|
||||
CurrentShader->pp_UseAlpha = pp_UseAlpha;
|
||||
CurrentShader->pp_IgnoreTexA = pp_IgnoreTexA;
|
||||
CurrentShader->pp_ShadInstr = pp_ShadInstr;
|
||||
CurrentShader->pp_Offset = pp_Offset;
|
||||
CurrentShader->pp_FogCtrl = pp_FogCtrl;
|
||||
CurrentShader->pp_TwoVolumes = pp_TwoVolumes;
|
||||
CurrentShader->pp_DepthFunc = pp_DepthFunc;
|
||||
CurrentShader->pp_Gouraud = pp_Gouraud;
|
||||
CurrentShader->pp_BumpMap = pp_BumpMap;
|
||||
CurrentShader->fog_clamping = fog_clamping;
|
||||
CurrentShader->pass = pass;
|
||||
gl4CompilePipelineShader(CurrentShader);
|
||||
gl4PipelineShader *shader = &gl4.shaders[rv];
|
||||
if (shader->program == 0)
|
||||
{
|
||||
shader->cp_AlphaTest = cp_AlphaTest;
|
||||
shader->pp_ClipTestMode = pp_ClipTestMode;
|
||||
shader->pp_Texture = pp_Texture;
|
||||
shader->pp_UseAlpha = pp_UseAlpha;
|
||||
shader->pp_IgnoreTexA = pp_IgnoreTexA;
|
||||
shader->pp_ShadInstr = pp_ShadInstr;
|
||||
shader->pp_Offset = pp_Offset;
|
||||
shader->pp_FogCtrl = pp_FogCtrl;
|
||||
shader->pp_TwoVolumes = pp_TwoVolumes;
|
||||
shader->pp_DepthFunc = pp_DepthFunc;
|
||||
shader->pp_Gouraud = pp_Gouraud;
|
||||
shader->pp_BumpMap = pp_BumpMap;
|
||||
shader->fog_clamping = fog_clamping;
|
||||
shader->pass = pass;
|
||||
gl4CompilePipelineShader(shader, settings.rend.Rotate90);
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
static void SetTextureRepeatMode(int index, GLuint dir, u32 clamp, u32 mirror)
|
||||
|
|
@ -132,7 +119,7 @@ template <u32 Type, bool SortingEnabled>
|
|||
|
||||
if (pass == 0)
|
||||
{
|
||||
setCurrentShader(Type == ListType_Punch_Through ? 1 : 0,
|
||||
CurrentShader = gl4GetProgram(Type == ListType_Punch_Through ? 1 : 0,
|
||||
clipping,
|
||||
Type == ListType_Punch_Through ? gp->pcw.Texture : 0,
|
||||
1,
|
||||
|
|
@ -153,6 +140,8 @@ template <u32 Type, bool SortingEnabled>
|
|||
bool two_volumes_mode = (gp->tsp1.full != -1) && Type != ListType_Translucent;
|
||||
bool color_clamp = gp->tsp.ColorClamp && (pvrrc.fog_clamp_min != 0 || pvrrc.fog_clamp_max != 0xffffffff);
|
||||
|
||||
int fog_ctrl = settings.rend.Fog ? gp->tsp.FogCtrl : 2;
|
||||
|
||||
int depth_func = 0;
|
||||
if (Type == ListType_Translucent)
|
||||
{
|
||||
|
|
@ -162,14 +151,14 @@ template <u32 Type, bool SortingEnabled>
|
|||
depth_func = gp->isp.DepthMode;
|
||||
}
|
||||
|
||||
setCurrentShader(Type == ListType_Punch_Through ? 1 : 0,
|
||||
CurrentShader = gl4GetProgram(Type == ListType_Punch_Through ? 1 : 0,
|
||||
clipping,
|
||||
gp->pcw.Texture,
|
||||
gp->tsp.UseAlpha,
|
||||
gp->tsp.IgnoreTexA,
|
||||
gp->tsp.ShadInstr,
|
||||
gp->pcw.Offset,
|
||||
gp->tsp.FogCtrl,
|
||||
fog_ctrl,
|
||||
two_volumes_mode,
|
||||
depth_func,
|
||||
gp->pcw.Gouraud,
|
||||
|
|
@ -681,7 +670,7 @@ static void gl4_draw_quad_texture(GLuint texture, bool upsideDown, float x = 0.f
|
|||
|
||||
ShaderUniforms.trilinear_alpha = 1.0;
|
||||
|
||||
setCurrentShader(0,
|
||||
CurrentShader = gl4GetProgram(0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
|
|
@ -713,11 +702,15 @@ void gl4DrawFramebuffer(float w, float h)
|
|||
|
||||
bool gl4_render_output_framebuffer()
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glViewport(0, 0, screen_width, screen_height);
|
||||
if (gl.ofbo.tex == 0)
|
||||
glcache.Disable(GL_SCISSOR_TEST);
|
||||
if (gl.ofbo.fbo == 0)
|
||||
return false;
|
||||
|
||||
gl4_draw_quad_texture(gl.ofbo.tex, true);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, gl.ofbo.fbo);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glBlitFramebuffer(0, 0, gl.ofbo.width, gl.ofbo.height,
|
||||
0, 0, screen_width, screen_height,
|
||||
GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ static const char* VertexShaderSource =
|
|||
"\
|
||||
#version 140 \n\
|
||||
#define pp_Gouraud %d \n\
|
||||
#define ROTATE_90 %d \n\
|
||||
\n\
|
||||
#if pp_Gouraud == 0 \n\
|
||||
#define INTERPOLATION flat \n\
|
||||
|
|
@ -56,6 +57,9 @@ void main() \n\
|
|||
\n\
|
||||
vpos.w = extra_depth_scale / vpos.z; \n\
|
||||
vpos.z = vpos.w; \n\
|
||||
#if ROTATE_90 == 1 \n\
|
||||
vpos.xy = vec2(vpos.y, -vpos.x); \n\
|
||||
#endif \n\
|
||||
vpos.xy=vpos.xy*scale.xy-scale.zw; \n\
|
||||
vpos.xy*=vpos.w; \n\
|
||||
gl_Position = vpos; \n\
|
||||
|
|
@ -393,11 +397,11 @@ gl4_ctx gl4;
|
|||
|
||||
struct gl4ShaderUniforms_t gl4ShaderUniforms;
|
||||
|
||||
bool gl4CompilePipelineShader( gl4PipelineShader* s, const char *source /* = PixelPipelineShader */)
|
||||
bool gl4CompilePipelineShader( gl4PipelineShader* s, bool rotate_90, const char *source /* = PixelPipelineShader */)
|
||||
{
|
||||
char vshader[16384];
|
||||
|
||||
sprintf(vshader, VertexShaderSource, s->pp_Gouraud);
|
||||
sprintf(vshader, VertexShaderSource, s->pp_Gouraud, rotate_90);
|
||||
|
||||
char pshader[16384];
|
||||
|
||||
|
|
@ -478,28 +482,45 @@ bool gl4CompilePipelineShader( gl4PipelineShader* s, const char *source /* = Pix
|
|||
|
||||
void gl_term();
|
||||
|
||||
void gl4_delete_shaders()
|
||||
{
|
||||
for (auto it : gl4.shaders)
|
||||
{
|
||||
if (it.second.program != 0)
|
||||
glcache.DeleteProgram(it.second.program);
|
||||
}
|
||||
gl4.shaders.clear();
|
||||
glcache.DeleteProgram(gl4.modvol_shader.program);
|
||||
gl4.modvol_shader.program = 0;
|
||||
}
|
||||
|
||||
static void gles_term(void)
|
||||
{
|
||||
glDeleteProgram(gl4.modvol_shader.program);
|
||||
glDeleteBuffers(1, &gl4.vbo.geometry);
|
||||
gl4.vbo.geometry = 0;
|
||||
glDeleteBuffers(1, &gl4.vbo.modvols);
|
||||
glDeleteBuffers(1, &gl4.vbo.idxs);
|
||||
glDeleteBuffers(1, &gl4.vbo.idxs2);
|
||||
glDeleteBuffers(1, &gl4.vbo.tr_poly_params);
|
||||
for (auto it = gl4.shaders.begin(); it != gl4.shaders.end(); it++)
|
||||
{
|
||||
if (it->second->program != -1)
|
||||
glDeleteProgram(it->second->program);
|
||||
delete it->second;
|
||||
}
|
||||
gl4.shaders.clear();
|
||||
gl4_delete_shaders();
|
||||
glDeleteVertexArrays(1, &gl4.vbo.main_vao);
|
||||
glDeleteVertexArrays(1, &gl4.vbo.modvol_vao);
|
||||
|
||||
gl_term();
|
||||
}
|
||||
|
||||
static void create_modvol_shader()
|
||||
{
|
||||
if (gl4.modvol_shader.program != 0)
|
||||
return;
|
||||
char vshader[16384];
|
||||
sprintf(vshader, VertexShaderSource, 1, settings.rend.Rotate90);
|
||||
|
||||
gl4.modvol_shader.program=gl_CompileAndLink(vshader, ModifierVolumeShader);
|
||||
gl4.modvol_shader.scale = glGetUniformLocation(gl4.modvol_shader.program, "scale");
|
||||
gl4.modvol_shader.extra_depth_scale = glGetUniformLocation(gl4.modvol_shader.program, "extra_depth_scale");
|
||||
}
|
||||
|
||||
static bool gl_create_resources()
|
||||
{
|
||||
if (gl4.vbo.geometry != 0)
|
||||
|
|
@ -521,12 +542,7 @@ static bool gl_create_resources()
|
|||
gl4SetupMainVBO();
|
||||
gl4SetupModvolVBO();
|
||||
|
||||
char vshader[16384];
|
||||
sprintf(vshader, VertexShaderSource, 1);
|
||||
|
||||
gl4.modvol_shader.program=gl_CompileAndLink(vshader, ModifierVolumeShader);
|
||||
gl4.modvol_shader.scale = glGetUniformLocation(gl4.modvol_shader.program, "scale");
|
||||
gl4.modvol_shader.extra_depth_scale = glGetUniformLocation(gl4.modvol_shader.program, "extra_depth_scale");
|
||||
create_modvol_shader();
|
||||
|
||||
gl_load_osd_resources();
|
||||
|
||||
|
|
@ -604,6 +620,7 @@ static bool RenderFrame()
|
|||
old_screen_scaling = settings.rend.ScreenScaling;
|
||||
}
|
||||
DoCleanup();
|
||||
create_modvol_shader();
|
||||
|
||||
bool is_rtt=pvrrc.isRTT;
|
||||
|
||||
|
|
@ -639,6 +656,8 @@ static bool RenderFrame()
|
|||
{
|
||||
scale_x=fb_scale_x;
|
||||
scale_y=fb_scale_y;
|
||||
if (SCALER_CTL.interlace == 0 && SCALER_CTL.vscalefactor >= 0x400)
|
||||
scale_y *= SCALER_CTL.vscalefactor / 0x400;
|
||||
|
||||
//work out scaling parameters !
|
||||
//Pixel doubling is on VO, so it does not affect any pixel operations
|
||||
|
|
@ -662,16 +681,41 @@ static bool RenderFrame()
|
|||
/*
|
||||
Handle Dc to screen scaling
|
||||
*/
|
||||
float screen_scaling = is_rtt ? 1.f : settings.rend.ScreenScaling / 100.f;
|
||||
float dc2s_scale_h = is_rtt ? (screen_width / dc_width) : (screen_height / 480.0);
|
||||
dc2s_scale_h *= screen_scaling;
|
||||
float ds2s_offs_x = is_rtt ? 0 : (((screen_width * screen_scaling) - dc2s_scale_h * 640.0) / 2);
|
||||
float screen_scaling = settings.rend.ScreenScaling / 100.f;
|
||||
float screen_stretching = settings.rend.ScreenStretching / 100.f;
|
||||
|
||||
//-1 -> too much to left
|
||||
gl4ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width * screen_scaling / dc2s_scale_h * scale_x);
|
||||
gl4ShaderUniforms.scale_coefs[1] = (is_rtt ? 2 : -2) / dc_height; // FIXME CT2 needs 480 here instead of dc_height=512
|
||||
gl4ShaderUniforms.scale_coefs[2] = 1 - 2 * ds2s_offs_x / (screen_width * screen_scaling);
|
||||
gl4ShaderUniforms.scale_coefs[3] = (is_rtt ? 1 : -1);
|
||||
float dc2s_scale_h;
|
||||
float ds2s_offs_x;
|
||||
|
||||
if (is_rtt)
|
||||
{
|
||||
gl4ShaderUniforms.scale_coefs[0] = 2.0f / dc_width;
|
||||
gl4ShaderUniforms.scale_coefs[1] = 2.0f / dc_height; // FIXME CT2 needs 480 here instead of dc_height=512
|
||||
gl4ShaderUniforms.scale_coefs[2] = 1;
|
||||
gl4ShaderUniforms.scale_coefs[3] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (settings.rend.Rotate90)
|
||||
{
|
||||
dc2s_scale_h = screen_height / 640.0;
|
||||
ds2s_offs_x = (screen_width - dc2s_scale_h * 480.0 * screen_stretching) / 2;
|
||||
gl4ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching;
|
||||
gl4ShaderUniforms.scale_coefs[1] = -2.0f / dc_width;
|
||||
gl4ShaderUniforms.scale_coefs[2] = 1 - 2 * ds2s_offs_x / screen_width;
|
||||
gl4ShaderUniforms.scale_coefs[3] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
dc2s_scale_h = screen_height / 480.0;
|
||||
ds2s_offs_x = (screen_width - dc2s_scale_h * 640.0 * screen_stretching) / 2;
|
||||
//-1 -> too much to left
|
||||
gl4ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching;
|
||||
gl4ShaderUniforms.scale_coefs[1] = -2.0f / dc_height;
|
||||
gl4ShaderUniforms.scale_coefs[2] = 1 - 2 * ds2s_offs_x / screen_width;
|
||||
gl4ShaderUniforms.scale_coefs[3] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
gl4ShaderUniforms.extra_depth_scale = settings.rend.ExtraDepthScale;
|
||||
|
||||
|
|
@ -704,7 +748,7 @@ static bool RenderFrame()
|
|||
gl4ShaderUniforms.fog_clamp_max[2] = ((pvrrc.fog_clamp_max >> 0) & 0xFF) / 255.0f;
|
||||
gl4ShaderUniforms.fog_clamp_max[3] = ((pvrrc.fog_clamp_max >> 24) & 0xFF) / 255.0f;
|
||||
|
||||
if (fog_needs_update)
|
||||
if (fog_needs_update && settings.rend.Fog)
|
||||
{
|
||||
fog_needs_update = false;
|
||||
UpdateFogTexture((u8 *)FOG_TABLE, GL_TEXTURE5, GL_RED);
|
||||
|
|
@ -764,7 +808,7 @@ static bool RenderFrame()
|
|||
{
|
||||
if (settings.rend.ScreenScaling != 100 || gl.swap_buffer_not_preserved)
|
||||
{
|
||||
output_fbo = init_output_framebuffer(screen_width * screen_scaling, screen_height * screen_scaling);
|
||||
output_fbo = init_output_framebuffer(screen_width * screen_scaling + 0.5f, screen_height * screen_scaling + 0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -826,22 +870,37 @@ static bool RenderFrame()
|
|||
float min_y = pvrrc.fb_Y_CLIP.min / scale_y;
|
||||
if (!is_rtt)
|
||||
{
|
||||
if (SCALER_CTL.interlace && SCALER_CTL.vscalefactor >= 0x400)
|
||||
{
|
||||
// Clipping is done after scaling/filtering so account for that if enabled
|
||||
height *= SCALER_CTL.vscalefactor / 0x400;
|
||||
min_y *= SCALER_CTL.vscalefactor / 0x400;
|
||||
}
|
||||
if (settings.rend.Rotate90)
|
||||
{
|
||||
float t = width;
|
||||
width = height;
|
||||
height = t;
|
||||
t = min_x;
|
||||
min_x = min_y;
|
||||
min_y = 640 - t - height;
|
||||
}
|
||||
// Add x offset for aspect ratio > 4/3
|
||||
min_x = min_x * dc2s_scale_h + ds2s_offs_x;
|
||||
min_x = (min_x * dc2s_scale_h * screen_stretching + ds2s_offs_x) * screen_scaling;
|
||||
// Invert y coordinates when rendering to screen
|
||||
min_y = screen_height * screen_scaling - (min_y + height) * dc2s_scale_h;
|
||||
width *= dc2s_scale_h;
|
||||
height *= dc2s_scale_h;
|
||||
min_y = (screen_height - (min_y + height) * dc2s_scale_h) * screen_scaling;
|
||||
width *= dc2s_scale_h * screen_stretching * screen_scaling;
|
||||
height *= dc2s_scale_h * screen_scaling;
|
||||
|
||||
if (ds2s_offs_x > 0)
|
||||
{
|
||||
float rounded_offs_x = ds2s_offs_x + 0.5f;
|
||||
float scaled_offs_x = ds2s_offs_x * screen_scaling;
|
||||
|
||||
glcache.ClearColor(0.f, 0.f, 0.f, 0.f);
|
||||
glcache.Enable(GL_SCISSOR_TEST);
|
||||
glScissor(0, 0, rounded_offs_x, screen_height);
|
||||
glScissor(0, 0, scaled_offs_x + 0.5f, screen_height * screen_scaling + 0.5f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glScissor(screen_width - rounded_offs_x, 0, rounded_offs_x, screen_height);
|
||||
glScissor(screen_width * screen_scaling - scaled_offs_x + 0.5f, 0, scaled_offs_x + 1.f, screen_height * screen_scaling + 0.5f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#include "gl4.h"
|
||||
#include "glcache.h"
|
||||
#include "../gles/glcache.h"
|
||||
|
||||
GLuint gl4BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -22,7 +22,11 @@
|
|||
#include <sstream>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef _MSC_VER
|
||||
#include "dirent/dirent.h"
|
||||
#else
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
#include "deps/libpng/png.h"
|
||||
#include "reios/reios.h"
|
||||
|
|
@ -46,23 +50,28 @@ void CustomTexture::LoaderThread()
|
|||
|
||||
if (texture != NULL)
|
||||
{
|
||||
// FIXME texture may have been deleted. Need to detect this.
|
||||
texture->ComputeHash();
|
||||
int width, height;
|
||||
u8 *image_data = LoadCustomTexture(texture->texture_hash, width, height);
|
||||
if (image_data == NULL)
|
||||
if (texture->custom_image_data != NULL)
|
||||
{
|
||||
image_data = LoadCustomTexture(texture->old_texture_hash, width, height);
|
||||
delete [] texture->custom_image_data;
|
||||
texture->custom_image_data = NULL;
|
||||
}
|
||||
if (image_data != NULL)
|
||||
if (!texture->dirty)
|
||||
{
|
||||
if (texture->custom_image_data != NULL)
|
||||
delete [] texture->custom_image_data;
|
||||
texture->custom_width = width;
|
||||
texture->custom_height = height;
|
||||
texture->custom_image_data = image_data;
|
||||
int width, height;
|
||||
u8 *image_data = LoadCustomTexture(texture->texture_hash, width, height);
|
||||
if (image_data == NULL)
|
||||
{
|
||||
image_data = LoadCustomTexture(texture->old_texture_hash, width, height);
|
||||
}
|
||||
if (image_data != NULL)
|
||||
{
|
||||
texture->custom_width = width;
|
||||
texture->custom_height = height;
|
||||
texture->custom_image_data = image_data;
|
||||
}
|
||||
}
|
||||
texture->custom_load_in_progress = false;
|
||||
texture->custom_load_in_progress--;
|
||||
}
|
||||
|
||||
} while (texture != NULL);
|
||||
|
|
@ -140,10 +149,9 @@ u8* CustomTexture::LoadCustomTexture(u32 hash, int& width, int& height)
|
|||
void CustomTexture::LoadCustomTextureAsync(TextureCacheData *texture_data)
|
||||
{
|
||||
if (!Init())
|
||||
{
|
||||
texture_data->custom_load_in_progress = false;
|
||||
return;
|
||||
}
|
||||
|
||||
texture_data->custom_load_in_progress++;
|
||||
work_queue_mutex.Lock();
|
||||
work_queue.insert(work_queue.begin(), texture_data);
|
||||
work_queue_mutex.Unlock();
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@ public:
|
|||
CustomTexture()
|
||||
:
|
||||
#ifndef TARGET_NO_THREADS
|
||||
loader_thread(loader_thread_func, this),
|
||||
loader_thread(loader_thread_func, this)
|
||||
#endif
|
||||
wakeup_thread(false, true) {}
|
||||
{}
|
||||
~CustomTexture() { Terminate(); }
|
||||
u8* LoadCustomTexture(u32 hash, int& width, int& height);
|
||||
void LoadCustomTextureAsync(TextureCacheData *texture_data);
|
||||
|
|
@ -53,7 +53,7 @@ private:
|
|||
cThread loader_thread;
|
||||
#endif
|
||||
cResetEvent wakeup_thread;
|
||||
std::vector<struct TextureCacheData *> work_queue;
|
||||
std::vector<TextureCacheData *> work_queue;
|
||||
cMutex work_queue_mutex;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -149,6 +149,19 @@ public:
|
|||
return _texture_ids[--_texture_cache_size];
|
||||
}
|
||||
|
||||
void DeleteProgram(GLuint program)
|
||||
{
|
||||
GLsizei shader_count;
|
||||
GLuint shaders[2];
|
||||
glGetAttachedShaders(program, ARRAY_SIZE(shaders), &shader_count, shaders);
|
||||
for (int i = 0; i < shader_count; i++)
|
||||
glDeleteShader(shaders[i]);
|
||||
|
||||
glDeleteProgram(program);
|
||||
if (_program == program)
|
||||
_program = 0;
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
_texture = 0xFFFFFFFFu;
|
||||
_src_blend_factor = 0xFFFFFFFFu;
|
||||
|
|
@ -179,7 +192,7 @@ public:
|
|||
void DisableCache() { _disable_cache = true; }
|
||||
void EnableCache()
|
||||
{
|
||||
_disable_cache = true;
|
||||
_disable_cache = false;
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -114,13 +114,30 @@ s32 SetTileClip(u32 val, GLint uniform)
|
|||
csy /= scale_y;
|
||||
cex /= scale_x;
|
||||
cey /= scale_y;
|
||||
float t = cey;
|
||||
cey = 480 - csy;
|
||||
csy = 480 - t;
|
||||
float dc2s_scale_h = screen_height / 480.0f;
|
||||
float ds2s_offs_x = (screen_width - dc2s_scale_h * 640) / 2;
|
||||
csx = csx * dc2s_scale_h + ds2s_offs_x;
|
||||
cex = cex * dc2s_scale_h + ds2s_offs_x;
|
||||
float dc2s_scale_h;
|
||||
float ds2s_offs_x;
|
||||
float screen_stretching = settings.rend.ScreenStretching / 100.f;
|
||||
|
||||
if (settings.rend.Rotate90)
|
||||
{
|
||||
float t = cex;
|
||||
cex = cey;
|
||||
cey = 640 - csx;
|
||||
csx = csy;
|
||||
csy = 640 - t;
|
||||
dc2s_scale_h = screen_height / 640.0f;
|
||||
ds2s_offs_x = (screen_width - dc2s_scale_h * 480.0 * screen_stretching) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
float t = cey;
|
||||
cey = 480 - csy;
|
||||
csy = 480 - t;
|
||||
dc2s_scale_h = screen_height / 480.0f;
|
||||
ds2s_offs_x = (screen_width - dc2s_scale_h * 640.0 * screen_stretching) / 2;
|
||||
}
|
||||
csx = csx * dc2s_scale_h * screen_stretching + ds2s_offs_x;
|
||||
cex = cex * dc2s_scale_h * screen_stretching + ds2s_offs_x;
|
||||
csy = csy * dc2s_scale_h;
|
||||
cey = cey * dc2s_scale_h;
|
||||
}
|
||||
|
|
@ -173,28 +190,25 @@ __forceinline
|
|||
ShaderUniforms.trilinear_alpha = 1.f;
|
||||
|
||||
bool color_clamp = gp->tsp.ColorClamp && (pvrrc.fog_clamp_min != 0 || pvrrc.fog_clamp_max != 0xffffffff);
|
||||
int fog_ctrl = settings.rend.Fog ? gp->tsp.FogCtrl : 2;
|
||||
|
||||
CurrentShader = &gl.pogram_table[
|
||||
GetProgramID(Type == ListType_Punch_Through ? 1 : 0,
|
||||
SetTileClip(gp->tileclip, -1) + 1,
|
||||
gp->pcw.Texture,
|
||||
gp->tsp.UseAlpha,
|
||||
gp->tsp.IgnoreTexA,
|
||||
gp->tsp.ShadInstr,
|
||||
gp->pcw.Offset,
|
||||
gp->tsp.FogCtrl,
|
||||
gp->pcw.Gouraud,
|
||||
gp->tcw.PixelFmt == PixelBumpMap,
|
||||
color_clamp,
|
||||
ShaderUniforms.trilinear_alpha != 1.f)];
|
||||
CurrentShader = GetProgram(Type == ListType_Punch_Through ? 1 : 0,
|
||||
SetTileClip(gp->tileclip, -1) + 1,
|
||||
gp->pcw.Texture,
|
||||
gp->tsp.UseAlpha,
|
||||
gp->tsp.IgnoreTexA,
|
||||
gp->tsp.ShadInstr,
|
||||
gp->pcw.Offset,
|
||||
fog_ctrl,
|
||||
gp->pcw.Gouraud,
|
||||
gp->tcw.PixelFmt == PixelBumpMap,
|
||||
color_clamp,
|
||||
ShaderUniforms.trilinear_alpha != 1.f);
|
||||
|
||||
if (CurrentShader->program == -1)
|
||||
CompilePipelineShader(CurrentShader);
|
||||
else
|
||||
{
|
||||
glcache.UseProgram(CurrentShader->program);
|
||||
ShaderUniforms.Set(CurrentShader);
|
||||
}
|
||||
glcache.UseProgram(CurrentShader->program);
|
||||
if (CurrentShader->trilinear_alpha != -1)
|
||||
glUniform1f(CurrentShader->trilinear_alpha, ShaderUniforms.trilinear_alpha);
|
||||
|
||||
SetTileClip(gp->tileclip, CurrentShader->pp_ClipTest);
|
||||
|
||||
//This bit control which pixels are affected
|
||||
|
|
@ -1124,14 +1138,8 @@ static void DrawQuad(GLuint texId, float x, float y, float w, float h, float u0,
|
|||
|
||||
ShaderUniforms.trilinear_alpha = 1.0;
|
||||
|
||||
PipelineShader *shader = &gl.pogram_table[GetProgramID(0, 1, 1, 0, 1, 0, 0, 2, false, false, false, false)];
|
||||
if (shader->program == -1)
|
||||
CompilePipelineShader(shader);
|
||||
else
|
||||
{
|
||||
glcache.UseProgram(shader->program);
|
||||
ShaderUniforms.Set(shader);
|
||||
}
|
||||
PipelineShader *shader = GetProgram(0, 1, 1, 0, 1, 0, 0, 2, false, false, false, false);
|
||||
glcache.UseProgram(shader->program);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glcache.BindTexture(GL_TEXTURE_2D, texId);
|
||||
|
|
@ -1152,17 +1160,27 @@ void DrawFramebuffer(float w, float h)
|
|||
|
||||
bool render_output_framebuffer()
|
||||
{
|
||||
#if HOST_OS != OS_DARWIN
|
||||
//Fix this in a proper way
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
#endif
|
||||
glViewport(0, 0, screen_width, screen_height);
|
||||
if (gl.ofbo.tex == 0)
|
||||
return false;
|
||||
|
||||
float scl = 480.f / screen_height;
|
||||
float tx = (screen_width * scl - 640.f) / 2;
|
||||
DrawQuad(gl.ofbo.tex, -tx, 0, 640.f + tx * 2, 480.f, 0, 1, 1, 0);
|
||||
|
||||
glcache.Disable(GL_SCISSOR_TEST);
|
||||
if (gl.gl_major < 3)
|
||||
{
|
||||
glViewport(0, 0, screen_width, screen_height);
|
||||
if (gl.ofbo.tex == 0)
|
||||
return false;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
float scl = 480.f / screen_height;
|
||||
float tx = (screen_width * scl - 640.f) / 2;
|
||||
DrawQuad(gl.ofbo.tex, -tx, 0, 640.f + tx * 2, 480.f, 0, 1, 1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gl.ofbo.fbo == 0)
|
||||
return false;
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, gl.ofbo.fbo);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glBlitFramebuffer(0, 0, gl.ofbo.width, gl.ofbo.height,
|
||||
0, 0, screen_width, screen_height,
|
||||
GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ const char* VertexShaderSource =
|
|||
%s \n\
|
||||
#define TARGET_GL %s \n\
|
||||
#define pp_Gouraud %d \n\
|
||||
#define ROTATE_90 %d \n\
|
||||
\n\
|
||||
#define GLES2 0 \n\
|
||||
#define GLES3 1 \n\
|
||||
|
|
@ -136,6 +137,9 @@ void main() \n\
|
|||
vpos.z = vpos.w; \n\
|
||||
#else \n\
|
||||
vpos.z=depth_scale.x+depth_scale.y*vpos.w; \n\
|
||||
#endif \n\
|
||||
#if ROTATE_90 == 1 \n\
|
||||
vpos.xy = vec2(vpos.y, -vpos.x); \n\
|
||||
#endif \n\
|
||||
vpos.xy=vpos.xy*scale.xy-scale.zw; \n\
|
||||
vpos.xy*=vpos.w; \n\
|
||||
|
|
@ -782,7 +786,7 @@ GLuint fogTextureId;
|
|||
|
||||
return rv;
|
||||
}
|
||||
#include <Wingdi.h>
|
||||
#include <wingdi.h>
|
||||
void gl_swap()
|
||||
{
|
||||
wglSwapLayerBuffers(ourWindowHandleToDeviceContext,WGL_SWAP_MAIN_PLANE);
|
||||
|
|
@ -853,9 +857,20 @@ GLuint fogTextureId;
|
|||
extern void gl_term();
|
||||
#endif
|
||||
|
||||
static void gl_delete_shaders()
|
||||
{
|
||||
for (auto it : gl.shaders)
|
||||
{
|
||||
if (it.second.program != 0)
|
||||
glcache.DeleteProgram(it.second.program);
|
||||
}
|
||||
gl.shaders.clear();
|
||||
glcache.DeleteProgram(gl.modvol_shader.program);
|
||||
gl.modvol_shader.program = 0;
|
||||
}
|
||||
|
||||
static void gles_term()
|
||||
{
|
||||
glDeleteProgram(gl.modvol_shader.program);
|
||||
glDeleteBuffers(1, &gl.vbo.geometry);
|
||||
gl.vbo.geometry = 0;
|
||||
glDeleteBuffers(1, &gl.vbo.modvols);
|
||||
|
|
@ -868,7 +883,7 @@ static void gles_term()
|
|||
gl_free_osd_resources();
|
||||
free_output_framebuffer();
|
||||
|
||||
memset(gl.pogram_table, 0, sizeof(gl.pogram_table));
|
||||
gl_delete_shaders();
|
||||
gl_term();
|
||||
}
|
||||
|
||||
|
|
@ -1017,10 +1032,15 @@ GLuint gl_CompileAndLink(const char* VertexShader, const char* FragmentShader)
|
|||
return program;
|
||||
}
|
||||
|
||||
int GetProgramID(u32 cp_AlphaTest, u32 pp_ClipTestMode,
|
||||
PipelineShader *GetProgram(u32 cp_AlphaTest, u32 pp_ClipTestMode,
|
||||
u32 pp_Texture, u32 pp_UseAlpha, u32 pp_IgnoreTexA, u32 pp_ShadInstr, u32 pp_Offset,
|
||||
u32 pp_FogCtrl, bool pp_Gouraud, bool pp_BumpMap, bool fog_clamping, bool trilinear)
|
||||
{
|
||||
if (settings.rend.Rotate90 != gl.rotate90)
|
||||
{
|
||||
gl_delete_shaders();
|
||||
gl.rotate90 = settings.rend.Rotate90;
|
||||
}
|
||||
u32 rv=0;
|
||||
|
||||
rv|=pp_ClipTestMode;
|
||||
|
|
@ -1036,14 +1056,32 @@ int GetProgramID(u32 cp_AlphaTest, u32 pp_ClipTestMode,
|
|||
rv<<=1; rv|=fog_clamping;
|
||||
rv<<=1; rv|=trilinear;
|
||||
|
||||
return rv;
|
||||
PipelineShader *shader = &gl.shaders[rv];
|
||||
if (shader->program == 0)
|
||||
{
|
||||
shader->cp_AlphaTest = cp_AlphaTest;
|
||||
shader->pp_ClipTestMode = pp_ClipTestMode-1;
|
||||
shader->pp_Texture = pp_Texture;
|
||||
shader->pp_UseAlpha = pp_UseAlpha;
|
||||
shader->pp_IgnoreTexA = pp_IgnoreTexA;
|
||||
shader->pp_ShadInstr = pp_ShadInstr;
|
||||
shader->pp_Offset = pp_Offset;
|
||||
shader->pp_FogCtrl = pp_FogCtrl;
|
||||
shader->pp_Gouraud = pp_Gouraud;
|
||||
shader->pp_BumpMap = pp_BumpMap;
|
||||
shader->fog_clamping = fog_clamping;
|
||||
shader->trilinear = trilinear;
|
||||
CompilePipelineShader(shader);
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
bool CompilePipelineShader( PipelineShader* s)
|
||||
{
|
||||
char vshader[8192];
|
||||
|
||||
sprintf(vshader, VertexShaderSource, gl.glsl_version_header, gl.gl_version, s->pp_Gouraud);
|
||||
sprintf(vshader, VertexShaderSource, gl.glsl_version_header, gl.gl_version, s->pp_Gouraud, settings.rend.Rotate90);
|
||||
|
||||
char pshader[8192];
|
||||
|
||||
|
|
@ -1129,13 +1167,30 @@ void gl_load_osd_resources()
|
|||
|
||||
void gl_free_osd_resources()
|
||||
{
|
||||
glDeleteProgram(gl.OSD_SHADER.program);
|
||||
glcache.DeleteProgram(gl.OSD_SHADER.program);
|
||||
|
||||
if (osd_tex != 0) {
|
||||
glcache.DeleteTextures(1, &osd_tex);
|
||||
osd_tex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void create_modvol_shader()
|
||||
{
|
||||
if (gl.modvol_shader.program != 0)
|
||||
return;
|
||||
char vshader[8192];
|
||||
sprintf(vshader, VertexShaderSource, gl.glsl_version_header, gl.gl_version, 1, settings.rend.Rotate90);
|
||||
char fshader[8192];
|
||||
sprintf(fshader, ModifierVolumeShader, gl.glsl_version_header, gl.gl_version);
|
||||
|
||||
gl.modvol_shader.program=gl_CompileAndLink(vshader, fshader);
|
||||
gl.modvol_shader.scale = glGetUniformLocation(gl.modvol_shader.program, "scale");
|
||||
gl.modvol_shader.sp_ShaderColor = glGetUniformLocation(gl.modvol_shader.program, "sp_ShaderColor");
|
||||
gl.modvol_shader.depth_scale = glGetUniformLocation(gl.modvol_shader.program, "depth_scale");
|
||||
gl.modvol_shader.extra_depth_scale = glGetUniformLocation(gl.modvol_shader.program, "extra_depth_scale");
|
||||
}
|
||||
|
||||
bool gl_create_resources()
|
||||
{
|
||||
if (gl.vbo.geometry != 0)
|
||||
|
|
@ -1161,84 +1216,7 @@ bool gl_create_resources()
|
|||
glGenBuffers(1, &gl.vbo.idxs);
|
||||
glGenBuffers(1, &gl.vbo.idxs2);
|
||||
|
||||
memset(gl.pogram_table,0,sizeof(gl.pogram_table));
|
||||
|
||||
PipelineShader* dshader=0;
|
||||
u32 compile=0;
|
||||
#define forl(name,max) for(u32 name=0;name<=max;name++)
|
||||
forl(cp_AlphaTest,1)
|
||||
{
|
||||
forl(pp_ClipTestMode,2)
|
||||
{
|
||||
forl(pp_UseAlpha,1)
|
||||
{
|
||||
forl(pp_Texture,1)
|
||||
{
|
||||
forl(pp_FogCtrl,3)
|
||||
{
|
||||
forl(pp_IgnoreTexA,1)
|
||||
{
|
||||
forl(pp_ShadInstr,3)
|
||||
{
|
||||
forl(pp_Offset,1)
|
||||
{
|
||||
forl(pp_Gouraud,1)
|
||||
{
|
||||
forl(pp_BumpMap,1)
|
||||
{
|
||||
forl(fog_clamping,1)
|
||||
{
|
||||
forl(trilinear,1)
|
||||
{
|
||||
dshader=&gl.pogram_table[GetProgramID(cp_AlphaTest,pp_ClipTestMode,pp_Texture,pp_UseAlpha,pp_IgnoreTexA,
|
||||
pp_ShadInstr,pp_Offset,pp_FogCtrl, (bool)pp_Gouraud, (bool)pp_BumpMap, (bool)fog_clamping,
|
||||
(bool)trilinear)];
|
||||
|
||||
dshader->cp_AlphaTest = cp_AlphaTest;
|
||||
dshader->pp_ClipTestMode = pp_ClipTestMode-1;
|
||||
dshader->pp_Texture = pp_Texture;
|
||||
dshader->pp_UseAlpha = pp_UseAlpha;
|
||||
dshader->pp_IgnoreTexA = pp_IgnoreTexA;
|
||||
dshader->pp_ShadInstr = pp_ShadInstr;
|
||||
dshader->pp_Offset = pp_Offset;
|
||||
dshader->pp_FogCtrl = pp_FogCtrl;
|
||||
dshader->pp_Gouraud = pp_Gouraud;
|
||||
dshader->pp_BumpMap = pp_BumpMap;
|
||||
dshader->fog_clamping = fog_clamping;
|
||||
dshader->trilinear = trilinear;
|
||||
dshader->program = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char vshader[8192];
|
||||
sprintf(vshader, VertexShaderSource, gl.glsl_version_header, gl.gl_version, 1);
|
||||
char fshader[8192];
|
||||
sprintf(fshader, ModifierVolumeShader, gl.glsl_version_header, gl.gl_version);
|
||||
|
||||
gl.modvol_shader.program=gl_CompileAndLink(vshader, fshader);
|
||||
gl.modvol_shader.scale = glGetUniformLocation(gl.modvol_shader.program, "scale");
|
||||
gl.modvol_shader.sp_ShaderColor = glGetUniformLocation(gl.modvol_shader.program, "sp_ShaderColor");
|
||||
gl.modvol_shader.depth_scale = glGetUniformLocation(gl.modvol_shader.program, "depth_scale");
|
||||
gl.modvol_shader.extra_depth_scale = glGetUniformLocation(gl.modvol_shader.program, "extra_depth_scale");
|
||||
|
||||
//#define PRECOMPILE_SHADERS
|
||||
#ifdef PRECOMPILE_SHADERS
|
||||
for (u32 i=0;i<sizeof(gl.pogram_table)/sizeof(gl.pogram_table[0]);i++)
|
||||
{
|
||||
if (!CompilePipelineShader( &gl.pogram_table[i] ))
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
create_modvol_shader();
|
||||
|
||||
gl_load_osd_resources();
|
||||
|
||||
|
|
@ -1558,6 +1536,7 @@ static void upload_vertex_indices()
|
|||
bool RenderFrame()
|
||||
{
|
||||
DoCleanup();
|
||||
create_modvol_shader();
|
||||
|
||||
bool is_rtt=pvrrc.isRTT;
|
||||
|
||||
|
|
@ -1677,6 +1656,8 @@ bool RenderFrame()
|
|||
{
|
||||
scale_x=fb_scale_x;
|
||||
scale_y=fb_scale_y;
|
||||
if (SCALER_CTL.interlace == 0 && SCALER_CTL.vscalefactor >= 0x400)
|
||||
scale_y *= SCALER_CTL.vscalefactor / 0x400;
|
||||
|
||||
//work out scaling parameters !
|
||||
//Pixel doubling is on VO, so it does not affect any pixel operations
|
||||
|
|
@ -1724,17 +1705,41 @@ bool RenderFrame()
|
|||
/*
|
||||
Handle Dc to screen scaling
|
||||
*/
|
||||
float screen_scaling = is_rtt ? 1.f : settings.rend.ScreenScaling / 100.f;
|
||||
float dc2s_scale_h = is_rtt ? (screen_width / dc_width) : (screen_height / 480.0);
|
||||
dc2s_scale_h *= screen_scaling;
|
||||
float ds2s_offs_x = is_rtt ? 0 : (((screen_width * screen_scaling) - dc2s_scale_h * 640.0) / 2);
|
||||
float screen_stretching = settings.rend.ScreenStretching / 100.f;
|
||||
float screen_scaling = settings.rend.ScreenScaling / 100.f;
|
||||
|
||||
//-1 -> too much to left
|
||||
ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width * screen_scaling / dc2s_scale_h * scale_x);
|
||||
ShaderUniforms.scale_coefs[1]= (is_rtt ? 2 : -2) / dc_height; // FIXME CT2 needs 480 here instead of dc_height=512
|
||||
ShaderUniforms.scale_coefs[2]= 1 - 2 * ds2s_offs_x / (screen_width * screen_scaling);
|
||||
ShaderUniforms.scale_coefs[3]= (is_rtt ? 1 : -1);
|
||||
float dc2s_scale_h;
|
||||
float ds2s_offs_x;
|
||||
|
||||
if (is_rtt)
|
||||
{
|
||||
ShaderUniforms.scale_coefs[0] = 2.0f / dc_width;
|
||||
ShaderUniforms.scale_coefs[1] = 2.0f / dc_height; // FIXME CT2 needs 480 here instead of dc_height=512
|
||||
ShaderUniforms.scale_coefs[2] = 1;
|
||||
ShaderUniforms.scale_coefs[3] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (settings.rend.Rotate90)
|
||||
{
|
||||
dc2s_scale_h = screen_height / 640.0f;
|
||||
ds2s_offs_x = (screen_width - dc2s_scale_h * 480.0f * screen_stretching) / 2;
|
||||
ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching;
|
||||
ShaderUniforms.scale_coefs[1] = -2.0f / dc_width;
|
||||
ShaderUniforms.scale_coefs[2] = 1 - 2 * ds2s_offs_x / screen_width;
|
||||
ShaderUniforms.scale_coefs[3] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
dc2s_scale_h = screen_height / 480.0f;
|
||||
ds2s_offs_x = (screen_width - dc2s_scale_h * 640.0f * screen_stretching) / 2;
|
||||
ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching;
|
||||
ShaderUniforms.scale_coefs[1] = -2.0f / dc_height;
|
||||
ShaderUniforms.scale_coefs[2] = 1 - 2 * ds2s_offs_x / screen_width;
|
||||
ShaderUniforms.scale_coefs[3] = -1;
|
||||
}
|
||||
//-1 -> too much to left
|
||||
}
|
||||
|
||||
ShaderUniforms.depth_coefs[0]=2/(vtx_max_fZ-vtx_min_fZ);
|
||||
ShaderUniforms.depth_coefs[1]=-vtx_min_fZ-1;
|
||||
|
|
@ -1773,7 +1778,7 @@ bool RenderFrame()
|
|||
ShaderUniforms.fog_clamp_max[2] = ((pvrrc.fog_clamp_max >> 0) & 0xFF) / 255.0f;
|
||||
ShaderUniforms.fog_clamp_max[3] = ((pvrrc.fog_clamp_max >> 24) & 0xFF) / 255.0f;
|
||||
|
||||
if (fog_needs_update)
|
||||
if (fog_needs_update && settings.rend.Fog)
|
||||
{
|
||||
fog_needs_update = false;
|
||||
UpdateFogTexture((u8 *)FOG_TABLE, GL_TEXTURE1, gl.fog_image_format);
|
||||
|
|
@ -1787,16 +1792,12 @@ bool RenderFrame()
|
|||
|
||||
ShaderUniforms.PT_ALPHA=(PT_ALPHA_REF&0xFF)/255.0f;
|
||||
|
||||
// for (u32 i=0;i<sizeof(gl.pogram_table)/sizeof(gl.pogram_table[0]);i++)
|
||||
// {
|
||||
// PipelineShader* s=&gl.pogram_table[i];
|
||||
// if (s->program == -1)
|
||||
// continue;
|
||||
//
|
||||
// glcache.UseProgram(s->program);
|
||||
//
|
||||
// ShaderUniforms.Set(s);
|
||||
// }
|
||||
for (auto it : gl.shaders)
|
||||
{
|
||||
glcache.UseProgram(it.second.program);
|
||||
ShaderUniforms.Set(&it.second);
|
||||
}
|
||||
|
||||
//setup render target first
|
||||
if (is_rtt)
|
||||
{
|
||||
|
|
@ -1841,7 +1842,7 @@ bool RenderFrame()
|
|||
{
|
||||
if (settings.rend.ScreenScaling != 100 || gl.swap_buffer_not_preserved)
|
||||
{
|
||||
init_output_framebuffer(screen_width * screen_scaling, screen_height * screen_scaling);
|
||||
init_output_framebuffer(screen_width * screen_scaling + 0.5f, screen_height * screen_scaling + 0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1888,9 +1889,6 @@ bool RenderFrame()
|
|||
glBufferData(GL_ARRAY_BUFFER,pvrrc.modtrig.bytes(),pvrrc.modtrig.head(),GL_STREAM_DRAW); glCheck();
|
||||
}
|
||||
|
||||
int offs_x=ds2s_offs_x+0.5f;
|
||||
//this needs to be scaled
|
||||
|
||||
//not all scaling affects pixel operations, scale to adjust for that
|
||||
scale_x *= scissoring_scale_x;
|
||||
|
||||
|
|
@ -1909,22 +1907,37 @@ bool RenderFrame()
|
|||
float min_y = pvrrc.fb_Y_CLIP.min / scale_y;
|
||||
if (!is_rtt)
|
||||
{
|
||||
if (SCALER_CTL.interlace && SCALER_CTL.vscalefactor >= 0x400)
|
||||
{
|
||||
// Clipping is done after scaling/filtering so account for that if enabled
|
||||
height *= SCALER_CTL.vscalefactor / 0x400;
|
||||
min_y *= SCALER_CTL.vscalefactor / 0x400;
|
||||
}
|
||||
if (settings.rend.Rotate90)
|
||||
{
|
||||
float t = width;
|
||||
width = height;
|
||||
height = t;
|
||||
t = min_x;
|
||||
min_x = min_y;
|
||||
min_y = 640 - t - height;
|
||||
}
|
||||
// Add x offset for aspect ratio > 4/3
|
||||
min_x = min_x * dc2s_scale_h + ds2s_offs_x;
|
||||
min_x = (min_x * dc2s_scale_h * screen_stretching + ds2s_offs_x) * screen_scaling;
|
||||
// Invert y coordinates when rendering to screen
|
||||
min_y = screen_height * screen_scaling - (min_y + height) * dc2s_scale_h;
|
||||
width *= dc2s_scale_h;
|
||||
height *= dc2s_scale_h;
|
||||
min_y = (screen_height - (min_y + height) * dc2s_scale_h) * screen_scaling;
|
||||
width *= dc2s_scale_h * screen_stretching * screen_scaling;
|
||||
height *= dc2s_scale_h * screen_scaling;
|
||||
|
||||
if (ds2s_offs_x > 0)
|
||||
{
|
||||
float rounded_offs_x = ds2s_offs_x + 0.5f;
|
||||
float scaled_offs_x = ds2s_offs_x * screen_scaling;
|
||||
|
||||
glcache.ClearColor(0.f, 0.f, 0.f, 0.f);
|
||||
glcache.Enable(GL_SCISSOR_TEST);
|
||||
glScissor(0, 0, rounded_offs_x, screen_height);
|
||||
glScissor(0, 0, scaled_offs_x + 0.5f, screen_height * screen_scaling + 0.5f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glScissor(screen_width - rounded_offs_x, 0, rounded_offs_x, screen_height);
|
||||
glScissor(screen_width * screen_scaling - scaled_offs_x + 0.5f, 0, scaled_offs_x + 1.f, screen_height * screen_scaling + 0.5f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
#pragma once
|
||||
#include <unordered_map>
|
||||
#include <atomic>
|
||||
#include "rend/rend.h"
|
||||
|
||||
#if (defined(GLES) && !defined(TARGET_NACL32) && HOST_OS != OS_DARWIN && !defined(USE_SDL)) || defined(_ANDROID)
|
||||
|
|
@ -95,7 +97,9 @@ struct gl_ctx
|
|||
|
||||
} modvol_shader;
|
||||
|
||||
PipelineShader pogram_table[24576];
|
||||
std::unordered_map<u32, PipelineShader> shaders;
|
||||
bool rotate90;
|
||||
|
||||
struct
|
||||
{
|
||||
GLuint program;
|
||||
|
|
@ -119,6 +123,7 @@ struct gl_ctx
|
|||
struct
|
||||
{
|
||||
GLuint depthb;
|
||||
GLuint colorb;
|
||||
GLuint tex;
|
||||
GLuint fbo;
|
||||
int width;
|
||||
|
|
@ -178,7 +183,7 @@ void free_output_framebuffer();
|
|||
|
||||
void HideOSD();
|
||||
void OSD_DRAW(bool clear_screen);
|
||||
int GetProgramID(u32 cp_AlphaTest, u32 pp_ClipTestMode,
|
||||
PipelineShader *GetProgram(u32 cp_AlphaTest, u32 pp_ClipTestMode,
|
||||
u32 pp_Texture, u32 pp_UseAlpha, u32 pp_IgnoreTexA, u32 pp_ShadInstr, u32 pp_Offset,
|
||||
u32 pp_FogCtrl, bool pp_Gouraud, bool pp_BumpMap, bool fog_clamping, bool trilinear);
|
||||
|
||||
|
|
@ -225,9 +230,6 @@ extern struct ShaderUniforms_t
|
|||
if (s->sp_FOG_COL_VERT!=-1)
|
||||
glUniform3fv( s->sp_FOG_COL_VERT, 1, ps_FOG_COL_VERT);
|
||||
|
||||
if (s->trilinear_alpha != -1)
|
||||
glUniform1f(s->trilinear_alpha, trilinear_alpha);
|
||||
|
||||
if (s->fog_clamp_min != -1)
|
||||
glUniform4fv(s->fog_clamp_min, 1, fog_clamp_min);
|
||||
if (s->fog_clamp_max != -1)
|
||||
|
|
@ -274,10 +276,10 @@ struct TextureCacheData
|
|||
//a texture can't be both VQ and PAL at the same time
|
||||
u32 texture_hash; // xxhash of texture data, used for custom textures
|
||||
u32 old_texture_hash; // legacy hash
|
||||
u8* custom_image_data; // loaded custom image data
|
||||
u32 custom_width;
|
||||
u32 custom_height;
|
||||
bool custom_load_in_progress;
|
||||
u8* volatile custom_image_data; // loaded custom image data
|
||||
volatile u32 custom_width;
|
||||
volatile u32 custom_height;
|
||||
std::atomic_int custom_load_in_progress;
|
||||
|
||||
void PrintTextureName();
|
||||
|
||||
|
|
|
|||
|
|
@ -296,10 +296,7 @@ void TextureCacheData::Update()
|
|||
}
|
||||
}
|
||||
if (settings.rend.CustomTextures)
|
||||
{
|
||||
custom_load_in_progress = true;
|
||||
custom_texture.LoadCustomTextureAsync(this);
|
||||
}
|
||||
|
||||
void *temp_tex_buffer = NULL;
|
||||
u32 upscaled_w = w;
|
||||
|
|
@ -428,7 +425,7 @@ void TextureCacheData::UploadToGPU(GLuint textype, int width, int height, u8 *te
|
|||
|
||||
void TextureCacheData::CheckCustomTexture()
|
||||
{
|
||||
if (custom_image_data != NULL)
|
||||
if (custom_load_in_progress == 0 && custom_image_data != NULL)
|
||||
{
|
||||
UploadToGPU(GL_UNSIGNED_BYTE, custom_width, custom_height, custom_image_data);
|
||||
delete [] custom_image_data;
|
||||
|
|
@ -446,7 +443,7 @@ bool TextureCacheData::NeedsUpdate() {
|
|||
|
||||
bool TextureCacheData::Delete()
|
||||
{
|
||||
if (custom_load_in_progress)
|
||||
if (custom_load_in_progress > 0)
|
||||
return false;
|
||||
|
||||
if (pData) {
|
||||
|
|
@ -736,11 +733,7 @@ TextureCacheData *getTextureCacheData(TSP tsp, TCW tcw) {
|
|||
}
|
||||
else //create if not existing
|
||||
{
|
||||
TextureCacheData tfc={0};
|
||||
TexCache[key] = tfc;
|
||||
|
||||
tx=TexCache.find(key);
|
||||
tf=&tx->second;
|
||||
tf=&TexCache[key];
|
||||
|
||||
tf->tsp = tsp;
|
||||
tf->tcw = tcw;
|
||||
|
|
@ -800,11 +793,7 @@ text_info raw_GetTexture(TSP tsp, TCW tcw)
|
|||
}
|
||||
else //create if not existing
|
||||
{
|
||||
TextureCacheData tfc = { 0 };
|
||||
TexCache[key] = tfc;
|
||||
|
||||
tx = TexCache.find(key);
|
||||
tf = &tx->second;
|
||||
tf = &TexCache[key];
|
||||
|
||||
tf->tsp = tsp;
|
||||
tf->tcw = tcw;
|
||||
|
|
@ -1007,13 +996,7 @@ GLuint init_output_framebuffer(int width, int height)
|
|||
{
|
||||
if (width != gl.ofbo.width || height != gl.ofbo.height)
|
||||
{
|
||||
if (gl.ofbo.fbo != 0)
|
||||
{
|
||||
glDeleteFramebuffers(1, &gl.ofbo.fbo);
|
||||
gl.ofbo.fbo = 0;
|
||||
glDeleteRenderbuffers(1, &gl.ofbo.depthb);
|
||||
glcache.DeleteTextures(1, &gl.ofbo.tex);
|
||||
}
|
||||
free_output_framebuffer();
|
||||
gl.ofbo.width = width;
|
||||
gl.ofbo.height = height;
|
||||
}
|
||||
|
|
@ -1037,15 +1020,25 @@ GLuint init_output_framebuffer(int width, int height)
|
|||
else
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
|
||||
|
||||
// Create a texture for rendering to
|
||||
gl.ofbo.tex = glcache.GenTexture();
|
||||
glcache.BindTexture(GL_TEXTURE_2D, gl.ofbo.tex);
|
||||
if (gl.gl_major < 3)
|
||||
{
|
||||
// Create a texture for rendering to
|
||||
gl.ofbo.tex = glcache.GenTexture();
|
||||
glcache.BindTexture(GL_TEXTURE_2D, gl.ofbo.tex);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use a renderbuffer and glBlitFramebuffer
|
||||
glGenRenderbuffers(1, &gl.ofbo.colorb);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, gl.ofbo.colorb);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
|
||||
}
|
||||
|
||||
// Create the framebuffer
|
||||
glGenFramebuffers(1, &gl.ofbo.fbo);
|
||||
|
|
@ -1057,13 +1050,20 @@ GLuint init_output_framebuffer(int width, int height)
|
|||
if (!gl.is_gles || gl.GL_OES_packed_depth_stencil_supported)
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, gl.ofbo.depthb);
|
||||
|
||||
// Attach the texture to the FBO
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl.ofbo.tex, 0);
|
||||
// Attach the texture/renderbuffer to the FBO
|
||||
if (gl.gl_major < 3)
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl.ofbo.tex, 0);
|
||||
else
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, gl.ofbo.colorb);
|
||||
|
||||
// Check that our FBO creation was successful
|
||||
GLuint uStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
|
||||
verify(uStatus == GL_FRAMEBUFFER_COMPLETE);
|
||||
|
||||
glcache.Disable(GL_SCISSOR_TEST);
|
||||
glcache.ClearColor(0.f, 0.f, 0.f, 0.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
else
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, gl.ofbo.fbo);
|
||||
|
|
@ -1082,7 +1082,15 @@ void free_output_framebuffer()
|
|||
gl.ofbo.fbo = 0;
|
||||
glDeleteRenderbuffers(1, &gl.ofbo.depthb);
|
||||
gl.ofbo.depthb = 0;
|
||||
glcache.DeleteTextures(1, &gl.ofbo.tex);
|
||||
gl.ofbo.tex = 0;
|
||||
if (gl.ofbo.tex != 0)
|
||||
{
|
||||
glcache.DeleteTextures(1, &gl.ofbo.tex);
|
||||
gl.ofbo.tex = 0;
|
||||
}
|
||||
if (gl.ofbo.colorb != 0)
|
||||
{
|
||||
glDeleteRenderbuffers(1, &gl.ofbo.colorb);
|
||||
gl.ofbo.colorb = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@
|
|||
#endif
|
||||
|
||||
#include "gles.h"
|
||||
#include "glcache.h"
|
||||
|
||||
// OpenGL Data
|
||||
static char g_GlslVersionString[32] = "";
|
||||
|
|
@ -127,28 +128,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data, bool save_backgr
|
|||
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
|
||||
|
||||
// Backup GL state
|
||||
GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
GLint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
|
||||
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||
GLint last_sampler; glGetIntegerv(GL_SAMPLER_BINDING, &last_sampler);
|
||||
GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
|
||||
GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
|
||||
#ifdef GL_POLYGON_MODE
|
||||
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
|
||||
#endif
|
||||
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
|
||||
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
|
||||
GLenum last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, (GLint*)&last_blend_src_rgb);
|
||||
GLenum last_blend_dst_rgb; glGetIntegerv(GL_BLEND_DST_RGB, (GLint*)&last_blend_dst_rgb);
|
||||
GLenum last_blend_src_alpha; glGetIntegerv(GL_BLEND_SRC_ALPHA, (GLint*)&last_blend_src_alpha);
|
||||
GLenum last_blend_dst_alpha; glGetIntegerv(GL_BLEND_DST_ALPHA, (GLint*)&last_blend_dst_alpha);
|
||||
GLenum last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, (GLint*)&last_blend_equation_rgb);
|
||||
GLenum last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, (GLint*)&last_blend_equation_alpha);
|
||||
GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
|
||||
GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE);
|
||||
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
|
||||
GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
|
||||
bool clip_origin_lower_left = true;
|
||||
#ifdef GL_CLIP_ORIGIN
|
||||
if (gl.gl_major >= 4 && glClipControl != NULL)
|
||||
|
|
@ -167,13 +147,13 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data, bool save_backgr
|
|||
|
||||
// (Re-)create the background texture and reserve space for it
|
||||
if (g_BackgroundTexture != 0)
|
||||
glDeleteTextures(1, &g_BackgroundTexture);
|
||||
glGenTextures(1, &g_BackgroundTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, g_BackgroundTexture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glcache.DeleteTextures(1, &g_BackgroundTexture);
|
||||
g_BackgroundTexture = glcache.GenTexture();
|
||||
glcache.BindTexture(GL_TEXTURE_2D, g_BackgroundTexture);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fb_width, fb_height, 0, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)NULL);
|
||||
|
||||
// Copy the current framebuffer into it
|
||||
|
|
@ -182,12 +162,12 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data, bool save_backgr
|
|||
}
|
||||
|
||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
|
||||
glEnable(GL_BLEND);
|
||||
glcache.Enable(GL_BLEND);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glcache.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glcache.Disable(GL_CULL_FACE);
|
||||
glcache.Disable(GL_DEPTH_TEST);
|
||||
glcache.Enable(GL_SCISSOR_TEST);
|
||||
#ifdef GL_POLYGON_MODE
|
||||
if (glPolygonMode != NULL)
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
|
|
@ -207,7 +187,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data, bool save_backgr
|
|||
{ 0.0f, 0.0f, -1.0f, 0.0f },
|
||||
{ (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f },
|
||||
};
|
||||
glUseProgram(g_ShaderHandle);
|
||||
glcache.UseProgram(g_ShaderHandle);
|
||||
glUniform1i(g_AttribLocationTex, 0);
|
||||
glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
|
||||
#if !defined(GLES) || defined(_ANDROID)
|
||||
|
|
@ -265,7 +245,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data, bool save_backgr
|
|||
glScissor((int)clip_rect.x, (int)clip_rect.y, (int)clip_rect.z, (int)clip_rect.w); // Support for GL 4.5's glClipControl(GL_UPPER_LEFT)
|
||||
|
||||
// Bind texture, Draw
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
|
||||
glcache.BindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
|
||||
}
|
||||
}
|
||||
|
|
@ -276,31 +256,6 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data, bool save_backgr
|
|||
if (vao_handle != 0)
|
||||
glDeleteVertexArrays(1, &vao_handle);
|
||||
#endif
|
||||
// Restore modified GL state
|
||||
glUseProgram(last_program);
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
#if !defined(GLES) || defined(_ANDROID)
|
||||
if (gl.gl_major >= 3 && glBindSampler != NULL)
|
||||
glBindSampler(0, last_sampler);
|
||||
#endif
|
||||
glActiveTexture(last_active_texture);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
||||
#if !defined(GLES) || defined(_ANDROID)
|
||||
if (gl.gl_major >= 3)
|
||||
glBindVertexArray(last_vertex_array);
|
||||
#endif
|
||||
glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha);
|
||||
glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha);
|
||||
if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND);
|
||||
if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE);
|
||||
if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);
|
||||
if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST);
|
||||
#ifdef GL_POLYGON_MODE
|
||||
if (glPolygonMode != NULL)
|
||||
glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]);
|
||||
#endif
|
||||
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
|
||||
glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
|
||||
}
|
||||
|
||||
bool ImGui_ImplOpenGL3_CreateFontsTexture()
|
||||
|
|
@ -312,21 +267,16 @@ bool ImGui_ImplOpenGL3_CreateFontsTexture()
|
|||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
|
||||
|
||||
// Upload texture to graphics system
|
||||
GLint last_texture;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||
glGenTextures(1, &g_FontTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, g_FontTexture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
g_FontTexture = glcache.GenTexture();
|
||||
glcache.BindTexture(GL_TEXTURE_2D, g_FontTexture);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->TexID = (ImTextureID)(intptr_t)g_FontTexture;
|
||||
|
||||
// Restore state
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -335,7 +285,7 @@ void ImGui_ImplOpenGL3_DestroyFontsTexture()
|
|||
if (g_FontTexture)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
glDeleteTextures(1, &g_FontTexture);
|
||||
glcache.DeleteTextures(1, &g_FontTexture);
|
||||
io.Fonts->TexID = 0;
|
||||
g_FontTexture = 0;
|
||||
}
|
||||
|
|
@ -377,14 +327,8 @@ static bool CheckProgram(GLuint handle, const char* desc)
|
|||
return (GLboolean)status == GL_TRUE;
|
||||
}
|
||||
|
||||
bool ImGui_ImplOpenGL3_CreateDeviceObjects()
|
||||
bool ImGui_ImplOpenGL3_CreateDeviceObjects()
|
||||
{
|
||||
// Backup GL state
|
||||
GLint last_texture, last_array_buffer, last_vertex_array;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
|
||||
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
|
||||
|
||||
// Parse GLSL version string
|
||||
int glsl_version = 130;
|
||||
sscanf(g_GlslVersionString, "#version %d", &glsl_version);
|
||||
|
|
@ -544,14 +488,6 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
|
|||
|
||||
ImGui_ImplOpenGL3_CreateFontsTexture();
|
||||
|
||||
// Restore modified GL state
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
||||
#if !defined(GLES) || defined(_ANDROID)
|
||||
if (gl.gl_major >= 3)
|
||||
glBindVertexArray(last_vertex_array);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -561,26 +497,23 @@ void ImGui_ImplOpenGL3_DestroyDeviceObjects()
|
|||
if (g_ElementsHandle) glDeleteBuffers(1, &g_ElementsHandle);
|
||||
g_VboHandle = g_ElementsHandle = 0;
|
||||
|
||||
if (g_ShaderHandle && g_VertHandle) glDetachShader(g_ShaderHandle, g_VertHandle);
|
||||
if (g_VertHandle) glDeleteShader(g_VertHandle);
|
||||
glcache.DeleteProgram(g_ShaderHandle);
|
||||
g_VertHandle = 0;
|
||||
|
||||
if (g_ShaderHandle && g_FragHandle) glDetachShader(g_ShaderHandle, g_FragHandle);
|
||||
if (g_FragHandle) glDeleteShader(g_FragHandle);
|
||||
g_FragHandle = 0;
|
||||
|
||||
if (g_ShaderHandle) glDeleteProgram(g_ShaderHandle);
|
||||
g_ShaderHandle = 0;
|
||||
|
||||
ImGui_ImplOpenGL3_DestroyFontsTexture();
|
||||
|
||||
if (g_BackgroundTexture != 0)
|
||||
glDeleteTextures(1, &g_BackgroundTexture);
|
||||
glcache.DeleteTextures(1, &g_BackgroundTexture);
|
||||
g_BackgroundTexture = 0;
|
||||
}
|
||||
|
||||
void ImGui_ImplOpenGL3_DrawBackground()
|
||||
{
|
||||
glcache.Disable(GL_SCISSOR_TEST);
|
||||
glcache.ClearColor(0, 0, 0, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
if (g_BackgroundTexture != 0)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
|
@ -591,20 +524,14 @@ void ImGui_ImplOpenGL3_DrawBackground()
|
|||
ImGui::GetWindowDrawList()->AddImage((ImTextureID)(uintptr_t)g_BackgroundTexture, ImVec2(0, 0), io.DisplaySize, ImVec2(0, 1), ImVec2(1, 0), 0xffffffff);
|
||||
ImGui::End();
|
||||
}
|
||||
else
|
||||
{
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
ImTextureID ImGui_ImplOpenGL3_CreateVmuTexture(const unsigned int *data)
|
||||
{
|
||||
GLuint tex_id;
|
||||
glGenTextures(1, &tex_id);
|
||||
glBindTexture(GL_TEXTURE_2D, tex_id);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
GLuint tex_id = glcache.GenTexture();
|
||||
glcache.BindTexture(GL_TEXTURE_2D, tex_id);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 48, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
|
||||
return reinterpret_cast<ImTextureID>(tex_id);
|
||||
|
|
@ -612,5 +539,5 @@ ImTextureID ImGui_ImplOpenGL3_CreateVmuTexture(const unsigned int *data)
|
|||
|
||||
void ImGui_ImplOpenGL3_DeleteVmuTexture(ImTextureID tex_id)
|
||||
{
|
||||
glDeleteTextures(1, &(GLuint &)tex_id);
|
||||
glcache.DeleteTextures(1, &(GLuint &)tex_id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,12 @@
|
|||
*/
|
||||
#include <algorithm>
|
||||
#include <math.h>
|
||||
#ifdef _MSC_VER
|
||||
#include "dirent/dirent.h"
|
||||
#define S_ISDIR(mode) (((mode) & _S_IFMT) == _S_IFDIR)
|
||||
#else
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "gui.h"
|
||||
|
|
@ -34,7 +39,10 @@
|
|||
#include "linux-dist/main.h" // FIXME for kcode[]
|
||||
#include "gui_util.h"
|
||||
#include "gui_android.h"
|
||||
#include "version/version.h"
|
||||
|
||||
#include "version.h"
|
||||
#include "oslib/audiostream.h"
|
||||
|
||||
|
||||
extern void dc_loadstate();
|
||||
extern void dc_savestate();
|
||||
|
|
@ -294,7 +302,9 @@ static void gui_display_commands()
|
|||
if (!settings_opening)
|
||||
ImGui_ImplOpenGL3_DrawBackground();
|
||||
|
||||
display_vmus();
|
||||
if (!settings.rend.FloatVMUs)
|
||||
// If floating VMUs, they are already visible on the background
|
||||
display_vmus();
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(screen_width / 2.f, screen_height / 2.f), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
|
||||
ImGui::SetNextWindowSize(ImVec2(330 * scaling, 0));
|
||||
|
|
@ -617,6 +627,8 @@ void directory_selected_callback(bool cancelled, std::string selection)
|
|||
|
||||
static void gui_display_settings()
|
||||
{
|
||||
static bool maple_devices_changed;
|
||||
|
||||
ImGui_Impl_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
|
|
@ -639,10 +651,14 @@ static void gui_display_settings()
|
|||
gui_state = Commands;
|
||||
else
|
||||
gui_state = Main;
|
||||
if (maple_devices_changed)
|
||||
{
|
||||
maple_devices_changed = false;
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
maple_ReconnectDevices();
|
||||
reset_vmus();
|
||||
maple_ReconnectDevices();
|
||||
reset_vmus();
|
||||
#endif
|
||||
}
|
||||
SaveSettings();
|
||||
}
|
||||
if (game_started)
|
||||
|
|
@ -796,13 +812,14 @@ static void gui_display_settings()
|
|||
if (ImGui::BeginTabItem("Controls"))
|
||||
{
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, normal_padding);
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST || DC_PLATFORM == DC_PLATFORM_ATOMISWAVE
|
||||
if (ImGui::CollapsingHeader("Dreamcast Devices", ImGuiTreeNodeFlags_DefaultOpen))
|
||||
{
|
||||
for (int bus = 0; bus < MAPLE_PORTS; bus++)
|
||||
{
|
||||
ImGui::Text("Device %c", bus + 'A');
|
||||
ImGui::SameLine();
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
char device_name[32];
|
||||
sprintf(device_name, "##device%d", bus);
|
||||
float w = ImGui::CalcItemWidth() / 3;
|
||||
|
|
@ -813,7 +830,10 @@ static void gui_display_settings()
|
|||
{
|
||||
bool is_selected = settings.input.maple_devices[bus] == maple_device_type_from_index(i);
|
||||
if (ImGui::Selectable(maple_device_types[i], &is_selected))
|
||||
{
|
||||
settings.input.maple_devices[bus] = maple_device_type_from_index(i);
|
||||
maple_devices_changed = true;
|
||||
}
|
||||
if (is_selected)
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
|
|
@ -831,7 +851,10 @@ static void gui_display_settings()
|
|||
{
|
||||
bool is_selected = settings.input.maple_expansion_devices[bus][port] == maple_expansion_device_type_from_index(i);
|
||||
if (ImGui::Selectable(maple_expansion_device_types[i], &is_selected))
|
||||
{
|
||||
settings.input.maple_expansion_devices[bus][port] = maple_expansion_device_type_from_index(i);
|
||||
maple_devices_changed = true;
|
||||
}
|
||||
if (is_selected)
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
|
|
@ -840,6 +863,10 @@ static void gui_display_settings()
|
|||
ImGui::PopID();
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
#elif DC_PLATFORM == DC_PLATFORM_ATOMISWAVE
|
||||
if (MapleDevices[bus][5] != NULL)
|
||||
ImGui::Text("%s", maple_device_name(MapleDevices[bus][5]->get_device_type()));
|
||||
#endif
|
||||
}
|
||||
ImGui::Spacing();
|
||||
}
|
||||
|
|
@ -940,15 +967,27 @@ static void gui_display_settings()
|
|||
ImGui::Checkbox("Shadows", &settings.rend.ModifierVolumes);
|
||||
ImGui::SameLine();
|
||||
ShowHelpMarker("Enable modifier volumes, usually used for shadows");
|
||||
ImGui::Checkbox("Fog", &settings.rend.Fog);
|
||||
ImGui::SameLine();
|
||||
ShowHelpMarker("Enable fog effects");
|
||||
ImGui::Checkbox("Widescreen", &settings.rend.WideScreen);
|
||||
ImGui::SameLine();
|
||||
ShowHelpMarker("Draw geometry outside of the normal 4:3 aspect ratio. May produce graphical glitches in the revealed areas");
|
||||
ImGui::Checkbox("Show FPS Counter", &settings.rend.ShowFPS);
|
||||
ImGui::SameLine();
|
||||
ShowHelpMarker("Show on-screen frame/sec counter");
|
||||
ImGui::Checkbox("Show VMU in game", &settings.rend.FloatVMUs);
|
||||
ImGui::SameLine();
|
||||
ShowHelpMarker("Show the VMU LCD screens while in game");
|
||||
ImGui::Checkbox("Rotate screen 90°", &settings.rend.Rotate90);
|
||||
ImGui::SameLine();
|
||||
ShowHelpMarker("Rotate the screen 90° counterclockwise");
|
||||
ImGui::SliderInt("Scaling", (int *)&settings.rend.ScreenScaling, 1, 100);
|
||||
ImGui::SameLine();
|
||||
ShowHelpMarker("Downscaling factor relative to native screen resolution. Higher is better");
|
||||
ImGui::SliderInt("Horizontal Stretching", (int *)&settings.rend.ScreenStretching, 100, 150);
|
||||
ImGui::SameLine();
|
||||
ShowHelpMarker("Stretch the screen horizontally");
|
||||
ImGui::SliderInt("Frame Skipping", (int *)&settings.pvr.ta_skip, 0, 6);
|
||||
ImGui::SameLine();
|
||||
ShowHelpMarker("Number of frames to skip between two actually rendered frames");
|
||||
|
|
@ -986,12 +1025,122 @@ static void gui_display_settings()
|
|||
ImGui::Checkbox("Disable Sound", &settings.aica.NoSound);
|
||||
ImGui::SameLine();
|
||||
ShowHelpMarker("Disable the emulator sound output");
|
||||
|
||||
ImGui::Checkbox("Enable DSP", &settings.aica.NoBatch);
|
||||
ImGui::SameLine();
|
||||
ShowHelpMarker("Enable the Dreamcast Digital Sound Processor. Only recommended on fast and arm64 platforms");
|
||||
ImGui::Checkbox("Limit FPS", &settings.aica.LimitFPS);
|
||||
ImGui::SameLine();
|
||||
ShowHelpMarker("Use the sound output to limit the speed of the emulator. Recommended in most cases");
|
||||
|
||||
audiobackend_t* backend = NULL;;
|
||||
std::string backend_name = settings.audio.backend;
|
||||
if (backend_name != "auto" && backend_name != "none")
|
||||
{
|
||||
backend = GetAudioBackend(settings.audio.backend);
|
||||
if (backend != NULL)
|
||||
backend_name = backend->slug;
|
||||
}
|
||||
|
||||
SortAudioBackends();
|
||||
|
||||
audiobackend_t* current_backend = backend;
|
||||
if (ImGui::BeginCombo("Audio Backend", backend_name.c_str(), ImGuiComboFlags_None))
|
||||
{
|
||||
bool is_selected = (settings.audio.backend == "auto");
|
||||
if (ImGui::Selectable("auto", &is_selected))
|
||||
settings.audio.backend = "auto";
|
||||
ImGui::SameLine(); ImGui::Text("-");
|
||||
ImGui::SameLine(); ImGui::Text("Autoselect audio backend");
|
||||
|
||||
is_selected = (settings.audio.backend == "none");
|
||||
if (ImGui::Selectable("none", &is_selected))
|
||||
settings.audio.backend = "none";
|
||||
ImGui::SameLine(); ImGui::Text("-");
|
||||
ImGui::SameLine(); ImGui::Text("No audio backend");
|
||||
|
||||
for (int i = 0; i < GetAudioBackendCount(); i++)
|
||||
{
|
||||
backend = GetAudioBackend(i);
|
||||
is_selected = (settings.audio.backend == backend->slug);
|
||||
|
||||
if (is_selected)
|
||||
current_backend = backend;
|
||||
|
||||
if (ImGui::Selectable(backend->slug.c_str(), &is_selected))
|
||||
settings.audio.backend = backend->slug;
|
||||
ImGui::SameLine(); ImGui::Text("-");
|
||||
ImGui::SameLine(); ImGui::Text(backend->name.c_str());
|
||||
if (is_selected)
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ShowHelpMarker("The audio backend to use");
|
||||
|
||||
if (current_backend != NULL && current_backend->get_options != NULL)
|
||||
{
|
||||
// get backend specific options
|
||||
int option_count;
|
||||
audio_option_t* options = current_backend->get_options(&option_count);
|
||||
|
||||
// initialize options if not already done
|
||||
std::map<std::string, std::string>* cfg_entries = &settings.audio.options[current_backend->slug];
|
||||
bool populate_entries = (cfg_entries->size() == 0);
|
||||
|
||||
for (int o = 0; o < option_count; o++)
|
||||
{
|
||||
std::string value;
|
||||
if (populate_entries)
|
||||
{
|
||||
value = cfgLoadStr(current_backend->slug.c_str(), options->cfg_name.c_str(), "");
|
||||
(*cfg_entries)[options->cfg_name] = value;
|
||||
}
|
||||
value = (*cfg_entries)[options->cfg_name];
|
||||
|
||||
if (options->type == integer)
|
||||
{
|
||||
int val = stoi(value);
|
||||
ImGui::SliderInt(options->caption.c_str(), &val, options->min_value, options->max_value);
|
||||
(*cfg_entries)[options->cfg_name] = to_string(val);
|
||||
}
|
||||
else if (options->type == checkbox)
|
||||
{
|
||||
bool check = (value == "1");
|
||||
ImGui::Checkbox(options->caption.c_str(), &check);
|
||||
std::string cur = check ? "1" : "0";
|
||||
(*cfg_entries)[options->cfg_name] = cur;
|
||||
}
|
||||
else if (options->type == list)
|
||||
{
|
||||
if (ImGui::BeginCombo(options->caption.c_str(), value.c_str(), ImGuiComboFlags_None))
|
||||
{
|
||||
bool is_selected = false;
|
||||
std::vector<std::string> list_items = options->list_callback();
|
||||
for (std::vector<std::string>::iterator it = list_items.begin() ; it != list_items.end(); ++it)
|
||||
{
|
||||
std::string cur = (std::string)*it;
|
||||
is_selected = (value == cur);
|
||||
if (ImGui::Selectable(cur.c_str(), &is_selected))
|
||||
{
|
||||
(*cfg_entries)[options->cfg_name] = cur;
|
||||
}
|
||||
|
||||
if (is_selected)
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("Unknown option\n");
|
||||
}
|
||||
|
||||
options++;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
|
@ -1064,9 +1213,9 @@ static void gui_display_settings()
|
|||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, normal_padding);
|
||||
if (ImGui::CollapsingHeader("Reicast", ImGuiTreeNodeFlags_DefaultOpen))
|
||||
{
|
||||
ImGui::Text("Version: %s", version);
|
||||
ImGui::Text("Git Hash: %s", git_hash);
|
||||
ImGui::Text("Build Date: %s", build_date);
|
||||
ImGui::Text("Version: %s", REICAST_VERSION);
|
||||
ImGui::Text("Git Hash: %s", GIT_HASH);
|
||||
ImGui::Text("Build Date: %s", BUILD_DATE);
|
||||
ImGui::Text("Target: %s",
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
"Dreamcast"
|
||||
|
|
@ -1248,6 +1397,7 @@ static void gui_start_game(const std::string& path)
|
|||
{
|
||||
gui_state = Main;
|
||||
game_started = false;
|
||||
cfgSetVirtual("config", "image", "");
|
||||
switch (rc) {
|
||||
case -3:
|
||||
error_msg = "Audio/video initialization failed";
|
||||
|
|
@ -1405,24 +1555,6 @@ void gui_display_ui()
|
|||
gui_state = Closed;
|
||||
}
|
||||
|
||||
void gui_display_fps(const char *string)
|
||||
{
|
||||
ImGui_Impl_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
ImGui::SetNextWindowBgAlpha(0);
|
||||
ImGui::SetNextWindowPos(ImVec2(0, screen_height), ImGuiCond_Always, ImVec2(0.f, 1.f)); // Lower left corner
|
||||
|
||||
ImGui::Begin("##fps", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoNav
|
||||
| ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoBackground);
|
||||
ImGui::SetWindowFontScale(2);
|
||||
ImGui::TextColored(ImVec4(1, 1, 0, 0.7), "%s", string);
|
||||
ImGui::End();
|
||||
|
||||
ImGui::Render();
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
}
|
||||
|
||||
static float LastFPSTime;
|
||||
static int lastFrameCount = 0;
|
||||
static float fps = -1;
|
||||
|
|
@ -1470,26 +1602,32 @@ void gui_display_osd()
|
|||
if (osd_message.empty())
|
||||
{
|
||||
message = getFPSNotification();
|
||||
if (message.empty())
|
||||
return;
|
||||
}
|
||||
else
|
||||
message = osd_message;
|
||||
|
||||
ImGui_Impl_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
if (!message.empty() || settings.rend.FloatVMUs)
|
||||
{
|
||||
ImGui_Impl_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
ImGui::SetNextWindowBgAlpha(0);
|
||||
ImGui::SetNextWindowPos(ImVec2(0, screen_height), ImGuiCond_Always, ImVec2(0.f, 1.f)); // Lower left corner
|
||||
if (!message.empty())
|
||||
{
|
||||
ImGui::SetNextWindowBgAlpha(0);
|
||||
ImGui::SetNextWindowPos(ImVec2(0, screen_height), ImGuiCond_Always, ImVec2(0.f, 1.f)); // Lower left corner
|
||||
|
||||
ImGui::Begin("##osd", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoNav
|
||||
| ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoBackground);
|
||||
ImGui::SetWindowFontScale(1.5);
|
||||
ImGui::TextColored(ImVec4(1, 1, 0, 0.7), "%s", message.c_str());
|
||||
ImGui::End();
|
||||
ImGui::Begin("##osd", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoNav
|
||||
| ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoBackground);
|
||||
ImGui::SetWindowFontScale(1.5);
|
||||
ImGui::TextColored(ImVec4(1, 1, 0, 0.7), "%s", message.c_str());
|
||||
ImGui::End();
|
||||
}
|
||||
if (settings.rend.FloatVMUs)
|
||||
display_vmus();
|
||||
|
||||
ImGui::Render();
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
ImGui::Render();
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
}
|
||||
}
|
||||
|
||||
void gui_open_onboarding()
|
||||
|
|
|
|||
|
|
@ -21,8 +21,16 @@
|
|||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <stdlib.h>
|
||||
#ifdef _MSC_VER
|
||||
#include <io.h>
|
||||
#include "dirent/dirent.h"
|
||||
#define S_ISDIR(mode) (((mode) & _S_IFMT) == _S_IFDIR)
|
||||
#define access _access
|
||||
#define R_OK 4
|
||||
#else
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "types.h"
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ extern AicaTimer timers[3];
|
|||
|
||||
|
||||
//./core/hw/aica/aica_if.o
|
||||
extern VArray2 aica_ram;
|
||||
extern VLockedMemory aica_ram;
|
||||
extern u32 VREG;//video reg =P
|
||||
extern u32 ARMRST;//arm reset reg
|
||||
extern u32 rtc_EN;
|
||||
|
|
@ -381,7 +381,7 @@ extern DECL_ALIGN(4) u32 SFaceOffsColor;
|
|||
//extern vector<vram_block*> VramLocks[/*VRAM_SIZE*/(16*1024*1024)/PAGE_SIZE];
|
||||
//maybe - probably not - just a locking mechanism
|
||||
//extern cMutex vramlist_lock;
|
||||
extern VArray2 vram;
|
||||
extern VLockedMemory vram;
|
||||
|
||||
|
||||
|
||||
|
|
@ -403,7 +403,7 @@ extern Array<RegisterStruct> SCIF; //SCIF : 10 registers
|
|||
|
||||
|
||||
//./core/hw/sh4/sh4_mem.o
|
||||
extern VArray2 mem_b;
|
||||
extern VLockedMemory mem_b;
|
||||
//one-time init
|
||||
//extern _vmem_handler area1_32b;
|
||||
//one-time init
|
||||
|
|
@ -441,7 +441,7 @@ extern u32 old_dn;
|
|||
//./core/hw/sh4/sh4_sched.o
|
||||
extern u64 sh4_sched_ffb;
|
||||
extern u32 sh4_sched_intr;
|
||||
extern vector<sched_list> list;
|
||||
extern vector<sched_list> sch_list;
|
||||
//extern int sh4_sched_next_id;
|
||||
|
||||
|
||||
|
|
@ -975,8 +975,6 @@ bool dc_serialize(void **data, unsigned int *total_size)
|
|||
REICAST_S(decoded_srimask);
|
||||
|
||||
|
||||
|
||||
|
||||
//default to nommu_full
|
||||
i = 3 ;
|
||||
if ( do_sqw_nommu == &do_sqw_nommu_area_3)
|
||||
|
|
@ -1008,61 +1006,63 @@ bool dc_serialize(void **data, unsigned int *total_size)
|
|||
|
||||
//extern vector<sched_list> list;
|
||||
|
||||
REICAST_S(list[aica_schid].tag) ;
|
||||
REICAST_S(list[aica_schid].start) ;
|
||||
REICAST_S(list[aica_schid].end) ;
|
||||
|
||||
REICAST_S(list[rtc_schid].tag) ;
|
||||
REICAST_S(list[rtc_schid].start) ;
|
||||
REICAST_S(list[rtc_schid].end) ;
|
||||
REICAST_S(sch_list[aica_schid].tag) ;
|
||||
REICAST_S(sch_list[aica_schid].start) ;
|
||||
REICAST_S(sch_list[aica_schid].end) ;
|
||||
|
||||
REICAST_S(list[gdrom_schid].tag) ;
|
||||
REICAST_S(list[gdrom_schid].start) ;
|
||||
REICAST_S(list[gdrom_schid].end) ;
|
||||
REICAST_S(sch_list[rtc_schid].tag) ;
|
||||
REICAST_S(sch_list[rtc_schid].start) ;
|
||||
REICAST_S(sch_list[rtc_schid].end) ;
|
||||
|
||||
REICAST_S(list[maple_schid].tag) ;
|
||||
REICAST_S(list[maple_schid].start) ;
|
||||
REICAST_S(list[maple_schid].end) ;
|
||||
REICAST_S(sch_list[gdrom_schid].tag) ;
|
||||
REICAST_S(sch_list[gdrom_schid].start) ;
|
||||
REICAST_S(sch_list[gdrom_schid].end) ;
|
||||
|
||||
REICAST_S(list[dma_sched_id].tag) ;
|
||||
REICAST_S(list[dma_sched_id].start) ;
|
||||
REICAST_S(list[dma_sched_id].end) ;
|
||||
REICAST_S(sch_list[maple_schid].tag) ;
|
||||
REICAST_S(sch_list[maple_schid].start) ;
|
||||
REICAST_S(sch_list[maple_schid].end) ;
|
||||
|
||||
REICAST_S(sch_list[dma_sched_id].tag) ;
|
||||
REICAST_S(sch_list[dma_sched_id].start) ;
|
||||
REICAST_S(sch_list[dma_sched_id].end) ;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
REICAST_S(list[tmu_sched[i]].tag) ;
|
||||
REICAST_S(list[tmu_sched[i]].start) ;
|
||||
REICAST_S(list[tmu_sched[i]].end) ;
|
||||
REICAST_S(sch_list[tmu_sched[i]].tag) ;
|
||||
REICAST_S(sch_list[tmu_sched[i]].start) ;
|
||||
REICAST_S(sch_list[tmu_sched[i]].end) ;
|
||||
}
|
||||
|
||||
REICAST_S(list[render_end_schid].tag) ;
|
||||
REICAST_S(list[render_end_schid].start) ;
|
||||
REICAST_S(list[render_end_schid].end) ;
|
||||
REICAST_S(sch_list[render_end_schid].tag) ;
|
||||
REICAST_S(sch_list[render_end_schid].start) ;
|
||||
REICAST_S(sch_list[render_end_schid].end) ;
|
||||
|
||||
REICAST_S(list[vblank_schid].tag) ;
|
||||
REICAST_S(list[vblank_schid].start) ;
|
||||
REICAST_S(list[vblank_schid].end) ;
|
||||
|
||||
REICAST_S(list[time_sync].tag) ;
|
||||
REICAST_S(list[time_sync].start) ;
|
||||
REICAST_S(list[time_sync].end) ;
|
||||
|
||||
REICAST_S(list[modem_sched].tag) ;
|
||||
REICAST_S(list[modem_sched].start) ;
|
||||
REICAST_S(list[modem_sched].end) ;
|
||||
REICAST_S(sch_list[vblank_schid].tag) ;
|
||||
REICAST_S(sch_list[vblank_schid].start) ;
|
||||
REICAST_S(sch_list[vblank_schid].end) ;
|
||||
|
||||
REICAST_S(sch_list[time_sync].tag) ;
|
||||
REICAST_S(sch_list[time_sync].start) ;
|
||||
REICAST_S(sch_list[time_sync].end) ;
|
||||
|
||||
#ifdef ENABLE_MODEM
|
||||
REICAST_S(sch_list[modem_sched].tag) ;
|
||||
REICAST_S(sch_list[modem_sched].start) ;
|
||||
REICAST_S(sch_list[modem_sched].end) ;
|
||||
#else
|
||||
int modem_dummy = 0;
|
||||
REICAST_S(modem_dummy);
|
||||
REICAST_S(modem_dummy);
|
||||
REICAST_S(modem_dummy);
|
||||
#endif
|
||||
|
||||
REICAST_S(SCIF_SCFSR2);
|
||||
REICAST_S(SCIF_SCFRDR2);
|
||||
REICAST_S(SCIF_SCFDR2);
|
||||
|
||||
|
||||
REICAST_S(BSC_PDTRA);
|
||||
|
||||
|
||||
|
||||
|
||||
REICAST_SA(tmu_shift,3);
|
||||
REICAST_SA(tmu_mask,3);
|
||||
REICAST_SA(tmu_mask64,3);
|
||||
|
|
@ -1070,14 +1070,8 @@ bool dc_serialize(void **data, unsigned int *total_size)
|
|||
REICAST_SA(tmu_ch_base,3);
|
||||
REICAST_SA(tmu_ch_base64,3);
|
||||
|
||||
|
||||
|
||||
|
||||
REICAST_SA(CCN_QACR_TR,2);
|
||||
|
||||
|
||||
|
||||
|
||||
REICAST_SA(UTLB,64);
|
||||
REICAST_SA(ITLB,4);
|
||||
#if defined(NO_MMU)
|
||||
|
|
@ -1087,8 +1081,6 @@ bool dc_serialize(void **data, unsigned int *total_size)
|
|||
REICAST_S(mmu_error_TT);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
REICAST_S(NullDriveDiscType);
|
||||
REICAST_SA(q_subchannel,96);
|
||||
|
||||
|
|
@ -1130,22 +1122,16 @@ bool dc_serialize(void **data, unsigned int *total_size)
|
|||
REICAST_S(div_som_reg2);
|
||||
REICAST_S(div_som_reg3);
|
||||
|
||||
|
||||
|
||||
REICAST_S(LastAddr);
|
||||
REICAST_S(LastAddr_min);
|
||||
REICAST_SA(block_hash,1024);
|
||||
|
||||
|
||||
REICAST_SA(RegisterWrite,sh4_reg_count);
|
||||
REICAST_SA(RegisterRead,sh4_reg_count);
|
||||
REICAST_S(fallback_blocks);
|
||||
REICAST_S(total_blocks);
|
||||
REICAST_S(REMOVED_OPS);
|
||||
|
||||
|
||||
|
||||
|
||||
REICAST_SA(kcode,4);
|
||||
REICAST_SA(rt,4);
|
||||
REICAST_SA(lt,4);
|
||||
|
|
@ -1246,12 +1232,7 @@ static bool dc_unserialize_libretro(void **data, unsigned int *total_size)
|
|||
//this is one-time init, no updates - don't need to serialize
|
||||
//extern _vmem_handler area0_handler;
|
||||
|
||||
|
||||
|
||||
|
||||
REICAST_USA(reply_11,16) ;
|
||||
|
||||
|
||||
REICAST_USA(reply_11,16);
|
||||
|
||||
REICAST_US(sns_asc);
|
||||
REICAST_US(sns_ascq);
|
||||
|
|
@ -1365,8 +1346,6 @@ static bool dc_unserialize_libretro(void **data, unsigned int *total_size)
|
|||
|
||||
REICAST_USA(mem_b.data, mem_b.size);
|
||||
|
||||
|
||||
|
||||
REICAST_US(IRLPriority);
|
||||
REICAST_USA(InterruptEnvId,32);
|
||||
REICAST_USA(InterruptBit,32);
|
||||
|
|
@ -1375,9 +1354,6 @@ static bool dc_unserialize_libretro(void **data, unsigned int *total_size)
|
|||
REICAST_US(interrupt_vmask);
|
||||
REICAST_US(decoded_srimask);
|
||||
|
||||
|
||||
|
||||
|
||||
REICAST_US(i) ;
|
||||
if ( i == 0 )
|
||||
do_sqw_nommu = &do_sqw_nommu_area_3 ;
|
||||
|
|
@ -1402,69 +1378,67 @@ static bool dc_unserialize_libretro(void **data, unsigned int *total_size)
|
|||
REICAST_US(old_rm);
|
||||
REICAST_US(old_dn);
|
||||
|
||||
|
||||
|
||||
|
||||
REICAST_US(sh4_sched_ffb);
|
||||
REICAST_US(sh4_sched_intr);
|
||||
|
||||
//extern vector<sched_list> list;
|
||||
//extern vector<sched_list> sch_list;
|
||||
|
||||
REICAST_US(list[aica_schid].tag) ;
|
||||
REICAST_US(list[aica_schid].start) ;
|
||||
REICAST_US(list[aica_schid].end) ;
|
||||
REICAST_US(sch_list[aica_schid].tag) ;
|
||||
REICAST_US(sch_list[aica_schid].start) ;
|
||||
REICAST_US(sch_list[aica_schid].end) ;
|
||||
|
||||
REICAST_US(list[rtc_schid].tag) ;
|
||||
REICAST_US(list[rtc_schid].start) ;
|
||||
REICAST_US(list[rtc_schid].end) ;
|
||||
REICAST_US(sch_list[rtc_schid].tag) ;
|
||||
REICAST_US(sch_list[rtc_schid].start) ;
|
||||
REICAST_US(sch_list[rtc_schid].end) ;
|
||||
|
||||
REICAST_US(list[gdrom_schid].tag) ;
|
||||
REICAST_US(list[gdrom_schid].start) ;
|
||||
REICAST_US(list[gdrom_schid].end) ;
|
||||
REICAST_US(sch_list[gdrom_schid].tag) ;
|
||||
REICAST_US(sch_list[gdrom_schid].start) ;
|
||||
REICAST_US(sch_list[gdrom_schid].end) ;
|
||||
|
||||
REICAST_US(list[maple_schid].tag) ;
|
||||
REICAST_US(list[maple_schid].start) ;
|
||||
REICAST_US(list[maple_schid].end) ;
|
||||
REICAST_US(sch_list[maple_schid].tag) ;
|
||||
REICAST_US(sch_list[maple_schid].start) ;
|
||||
REICAST_US(sch_list[maple_schid].end) ;
|
||||
|
||||
REICAST_US(list[dma_sched_id].tag) ;
|
||||
REICAST_US(list[dma_sched_id].start) ;
|
||||
REICAST_US(list[dma_sched_id].end) ;
|
||||
REICAST_US(sch_list[dma_sched_id].tag) ;
|
||||
REICAST_US(sch_list[dma_sched_id].start) ;
|
||||
REICAST_US(sch_list[dma_sched_id].end) ;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
REICAST_US(list[tmu_sched[i]].tag) ;
|
||||
REICAST_US(list[tmu_sched[i]].start) ;
|
||||
REICAST_US(list[tmu_sched[i]].end) ;
|
||||
REICAST_US(sch_list[tmu_sched[i]].tag) ;
|
||||
REICAST_US(sch_list[tmu_sched[i]].start) ;
|
||||
REICAST_US(sch_list[tmu_sched[i]].end) ;
|
||||
}
|
||||
|
||||
REICAST_US(list[render_end_schid].tag) ;
|
||||
REICAST_US(list[render_end_schid].start) ;
|
||||
REICAST_US(list[render_end_schid].end) ;
|
||||
REICAST_US(sch_list[render_end_schid].tag) ;
|
||||
REICAST_US(sch_list[render_end_schid].start) ;
|
||||
REICAST_US(sch_list[render_end_schid].end) ;
|
||||
|
||||
REICAST_US(list[vblank_schid].tag) ;
|
||||
REICAST_US(list[vblank_schid].start) ;
|
||||
REICAST_US(list[vblank_schid].end) ;
|
||||
|
||||
REICAST_US(list[time_sync].tag) ;
|
||||
REICAST_US(list[time_sync].start) ;
|
||||
REICAST_US(list[time_sync].end) ;
|
||||
|
||||
REICAST_US(list[modem_sched].tag) ;
|
||||
REICAST_US(list[modem_sched].start) ;
|
||||
REICAST_US(list[modem_sched].end) ;
|
||||
REICAST_US(sch_list[vblank_schid].tag) ;
|
||||
REICAST_US(sch_list[vblank_schid].start) ;
|
||||
REICAST_US(sch_list[vblank_schid].end) ;
|
||||
|
||||
REICAST_US(sch_list[time_sync].tag) ;
|
||||
REICAST_US(sch_list[time_sync].start) ;
|
||||
REICAST_US(sch_list[time_sync].end) ;
|
||||
|
||||
#ifdef ENABLE_MODEM
|
||||
REICAST_US(sch_list[modem_sched].tag) ;
|
||||
REICAST_US(sch_list[modem_sched].start) ;
|
||||
REICAST_US(sch_list[modem_sched].end) ;
|
||||
#else
|
||||
int modem_dummy;
|
||||
REICAST_US(modem_dummy);
|
||||
REICAST_US(modem_dummy);
|
||||
REICAST_US(modem_dummy);
|
||||
#endif
|
||||
|
||||
REICAST_US(SCIF_SCFSR2);
|
||||
REICAST_US(SCIF_SCFRDR2);
|
||||
REICAST_US(SCIF_SCFDR2);
|
||||
|
||||
|
||||
REICAST_US(BSC_PDTRA);
|
||||
|
||||
|
||||
|
||||
|
||||
REICAST_USA(tmu_shift,3);
|
||||
REICAST_USA(tmu_mask,3);
|
||||
REICAST_USA(tmu_mask64,3);
|
||||
|
|
@ -1472,14 +1446,8 @@ static bool dc_unserialize_libretro(void **data, unsigned int *total_size)
|
|||
REICAST_USA(tmu_ch_base,3);
|
||||
REICAST_USA(tmu_ch_base64,3);
|
||||
|
||||
|
||||
|
||||
|
||||
REICAST_USA(CCN_QACR_TR,2);
|
||||
|
||||
|
||||
|
||||
|
||||
REICAST_USA(UTLB,64);
|
||||
REICAST_USA(ITLB,4);
|
||||
#if defined(NO_MMU)
|
||||
|
|
@ -1489,9 +1457,6 @@ static bool dc_unserialize_libretro(void **data, unsigned int *total_size)
|
|||
REICAST_US(mmu_error_TT);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
REICAST_US(NullDriveDiscType);
|
||||
REICAST_USA(q_subchannel,96);
|
||||
|
||||
|
|
@ -1546,9 +1511,6 @@ static bool dc_unserialize_libretro(void **data, unsigned int *total_size)
|
|||
REICAST_US(div_som_reg2);
|
||||
REICAST_US(div_som_reg3);
|
||||
|
||||
|
||||
|
||||
|
||||
//REICAST_USA(CodeCache,CODE_SIZE) ;
|
||||
//REICAST_USA(SH4_TCB,CODE_SIZE+4096);
|
||||
REICAST_US(LastAddr);
|
||||
|
|
@ -1612,7 +1574,6 @@ bool dc_unserialize(void **data, unsigned int *total_size)
|
|||
REICAST_US(timers[i].m_step);
|
||||
}
|
||||
|
||||
|
||||
REICAST_USA(aica_ram.data,aica_ram.size) ;
|
||||
REICAST_US(VREG);
|
||||
REICAST_US(ARMRST);
|
||||
|
|
@ -1620,8 +1581,6 @@ bool dc_unserialize(void **data, unsigned int *total_size)
|
|||
|
||||
REICAST_USA(aica_reg,0x8000);
|
||||
|
||||
|
||||
|
||||
REICAST_USA(volume_lut,16);
|
||||
REICAST_USA(tl_lut,256 + 768);
|
||||
REICAST_USA(AEG_ATT_SPS,64);
|
||||
|
|
@ -1636,14 +1595,11 @@ bool dc_unserialize(void **data, unsigned int *total_size)
|
|||
REICAST_USA(mxlr,64);
|
||||
REICAST_US(samples_gen);
|
||||
|
||||
|
||||
register_unserialize(sb_regs, data, total_size) ;
|
||||
REICAST_US(SB_ISTNRM);
|
||||
REICAST_US(SB_FFST_rc);
|
||||
REICAST_US(SB_FFST);
|
||||
|
||||
|
||||
|
||||
//this is one-time init, no updates - don't need to serialize
|
||||
//extern RomChip sys_rom;
|
||||
REICAST_US(sys_nvmem.size);
|
||||
|
|
@ -1755,8 +1711,6 @@ bool dc_unserialize(void **data, unsigned int *total_size)
|
|||
|
||||
REICAST_USA(mem_b.data, mem_b.size);
|
||||
|
||||
|
||||
|
||||
REICAST_US(IRLPriority);
|
||||
REICAST_USA(InterruptEnvId,32);
|
||||
REICAST_USA(InterruptBit,32);
|
||||
|
|
@ -1765,9 +1719,6 @@ bool dc_unserialize(void **data, unsigned int *total_size)
|
|||
REICAST_US(interrupt_vmask);
|
||||
REICAST_US(decoded_srimask);
|
||||
|
||||
|
||||
|
||||
|
||||
REICAST_US(i) ;
|
||||
if ( i == 0 )
|
||||
do_sqw_nommu = &do_sqw_nommu_area_3 ;
|
||||
|
|
@ -1800,50 +1751,55 @@ bool dc_unserialize(void **data, unsigned int *total_size)
|
|||
|
||||
//extern vector<sched_list> list;
|
||||
|
||||
REICAST_US(list[aica_schid].tag) ;
|
||||
REICAST_US(list[aica_schid].start) ;
|
||||
REICAST_US(list[aica_schid].end) ;
|
||||
REICAST_US(sch_list[aica_schid].tag) ;
|
||||
REICAST_US(sch_list[aica_schid].start) ;
|
||||
REICAST_US(sch_list[aica_schid].end) ;
|
||||
|
||||
REICAST_US(list[rtc_schid].tag) ;
|
||||
REICAST_US(list[rtc_schid].start) ;
|
||||
REICAST_US(list[rtc_schid].end) ;
|
||||
REICAST_US(sch_list[rtc_schid].tag) ;
|
||||
REICAST_US(sch_list[rtc_schid].start) ;
|
||||
REICAST_US(sch_list[rtc_schid].end) ;
|
||||
|
||||
REICAST_US(list[gdrom_schid].tag) ;
|
||||
REICAST_US(list[gdrom_schid].start) ;
|
||||
REICAST_US(list[gdrom_schid].end) ;
|
||||
REICAST_US(sch_list[gdrom_schid].tag) ;
|
||||
REICAST_US(sch_list[gdrom_schid].start) ;
|
||||
REICAST_US(sch_list[gdrom_schid].end) ;
|
||||
|
||||
REICAST_US(list[maple_schid].tag) ;
|
||||
REICAST_US(list[maple_schid].start) ;
|
||||
REICAST_US(list[maple_schid].end) ;
|
||||
REICAST_US(sch_list[maple_schid].tag) ;
|
||||
REICAST_US(sch_list[maple_schid].start) ;
|
||||
REICAST_US(sch_list[maple_schid].end) ;
|
||||
|
||||
REICAST_US(list[dma_sched_id].tag) ;
|
||||
REICAST_US(list[dma_sched_id].start) ;
|
||||
REICAST_US(list[dma_sched_id].end) ;
|
||||
REICAST_US(sch_list[dma_sched_id].tag) ;
|
||||
REICAST_US(sch_list[dma_sched_id].start) ;
|
||||
REICAST_US(sch_list[dma_sched_id].end) ;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
REICAST_US(list[tmu_sched[i]].tag) ;
|
||||
REICAST_US(list[tmu_sched[i]].start) ;
|
||||
REICAST_US(list[tmu_sched[i]].end) ;
|
||||
REICAST_US(sch_list[tmu_sched[i]].tag) ;
|
||||
REICAST_US(sch_list[tmu_sched[i]].start) ;
|
||||
REICAST_US(sch_list[tmu_sched[i]].end) ;
|
||||
}
|
||||
|
||||
REICAST_US(list[render_end_schid].tag) ;
|
||||
REICAST_US(list[render_end_schid].start) ;
|
||||
REICAST_US(list[render_end_schid].end) ;
|
||||
REICAST_US(sch_list[render_end_schid].tag) ;
|
||||
REICAST_US(sch_list[render_end_schid].start) ;
|
||||
REICAST_US(sch_list[render_end_schid].end) ;
|
||||
|
||||
REICAST_US(list[vblank_schid].tag) ;
|
||||
REICAST_US(list[vblank_schid].start) ;
|
||||
REICAST_US(list[vblank_schid].end) ;
|
||||
|
||||
REICAST_US(list[time_sync].tag) ;
|
||||
REICAST_US(list[time_sync].start) ;
|
||||
REICAST_US(list[time_sync].end) ;
|
||||
|
||||
REICAST_US(list[modem_sched].tag) ;
|
||||
REICAST_US(list[modem_sched].start) ;
|
||||
REICAST_US(list[modem_sched].end) ;
|
||||
REICAST_US(sch_list[vblank_schid].tag) ;
|
||||
REICAST_US(sch_list[vblank_schid].start) ;
|
||||
REICAST_US(sch_list[vblank_schid].end) ;
|
||||
|
||||
REICAST_US(sch_list[time_sync].tag) ;
|
||||
REICAST_US(sch_list[time_sync].start) ;
|
||||
REICAST_US(sch_list[time_sync].end) ;
|
||||
|
||||
#ifdef ENABLE_MODEM
|
||||
REICAST_US(sch_list[modem_sched].tag) ;
|
||||
REICAST_US(sch_list[modem_sched].start) ;
|
||||
REICAST_US(sch_list[modem_sched].end) ;
|
||||
#else
|
||||
int modem_dummy;
|
||||
REICAST_US(modem_dummy);
|
||||
REICAST_US(modem_dummy);
|
||||
REICAST_US(modem_dummy);
|
||||
#endif
|
||||
|
||||
REICAST_US(SCIF_SCFSR2);
|
||||
REICAST_US(SCIF_SCFRDR2);
|
||||
|
|
@ -1880,8 +1836,6 @@ bool dc_unserialize(void **data, unsigned int *total_size)
|
|||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
REICAST_US(NullDriveDiscType);
|
||||
REICAST_USA(q_subchannel,96);
|
||||
|
||||
|
|
@ -1897,7 +1851,6 @@ bool dc_unserialize(void **data, unsigned int *total_size)
|
|||
// REICAST_US(i); // VRAM_MASK
|
||||
|
||||
|
||||
|
||||
REICAST_US(naomi_updates);
|
||||
REICAST_US(i); // BoardID
|
||||
REICAST_US(GSerialBuffer);
|
||||
|
|
@ -1936,25 +1889,18 @@ bool dc_unserialize(void **data, unsigned int *total_size)
|
|||
REICAST_US(div_som_reg2);
|
||||
REICAST_US(div_som_reg3);
|
||||
|
||||
|
||||
|
||||
|
||||
//REICAST_USA(CodeCache,CODE_SIZE) ;
|
||||
//REICAST_USA(SH4_TCB,CODE_SIZE+4096);
|
||||
REICAST_US(LastAddr);
|
||||
REICAST_US(LastAddr_min);
|
||||
REICAST_USA(block_hash,1024);
|
||||
|
||||
|
||||
REICAST_USA(RegisterWrite,sh4_reg_count);
|
||||
REICAST_USA(RegisterRead,sh4_reg_count);
|
||||
REICAST_US(fallback_blocks);
|
||||
REICAST_US(total_blocks);
|
||||
REICAST_US(REMOVED_OPS);
|
||||
|
||||
|
||||
|
||||
|
||||
REICAST_USA(kcode,4);
|
||||
REICAST_USA(rt,4);
|
||||
REICAST_USA(lt,4);
|
||||
|
|
|
|||
|
|
@ -4,9 +4,16 @@
|
|||
#include <sys/stat.h>
|
||||
#include "types.h"
|
||||
#include "cfg/cfg.h"
|
||||
#include "stdclass.h"
|
||||
#if HOST_OS == OS_DARWIN
|
||||
#include <mach/clock.h>
|
||||
#include <mach/mach.h>
|
||||
#endif
|
||||
|
||||
#if BUILD_COMPILER==COMPILER_VC
|
||||
|
||||
#if COMPILER_VC_OR_CLANG_WIN32
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
#define access _access
|
||||
#define R_OK 4
|
||||
#else
|
||||
|
|
@ -140,62 +147,156 @@ string get_game_dir()
|
|||
|
||||
bool make_directory(const string& path)
|
||||
{
|
||||
return mkdir(path.c_str()
|
||||
#ifndef _WIN32
|
||||
, 0755
|
||||
#if COMPILER_VC_OR_CLANG_WIN32
|
||||
#define mkdir _mkdir
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
return mkdir(path.c_str()) == 0;
|
||||
#else
|
||||
return mkdir(path.c_str(), 0755) == 0;
|
||||
#endif
|
||||
) == 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
//File Enumeration
|
||||
void FindAllFiles(FileFoundCB* callback,wchar* dir,void* param)
|
||||
{
|
||||
WIN32_FIND_DATA FindFileData;
|
||||
HANDLE hFind = INVALID_HANDLE_VALUE;
|
||||
wchar DirSpec[MAX_PATH + 1]; // directory specification
|
||||
DWORD dwError;
|
||||
// Thread & related platform dependant code
|
||||
#if !defined(HOST_NO_THREADS)
|
||||
|
||||
strncpy (DirSpec, dir, strlen(dir)+1);
|
||||
//strncat (DirSpec, "\\*", 3);
|
||||
|
||||
hFind = FindFirstFile( DirSpec, &FindFileData);
|
||||
|
||||
if (hFind == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)==0)
|
||||
{
|
||||
callback(FindFileData.cFileName,param);
|
||||
}
|
||||
u32 rv;
|
||||
while ( (rv=FindNextFile(hFind, &FindFileData)) != 0)
|
||||
{
|
||||
if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)==0)
|
||||
{
|
||||
callback(FindFileData.cFileName,param);
|
||||
}
|
||||
}
|
||||
dwError = GetLastError();
|
||||
FindClose(hFind);
|
||||
if (dwError != ERROR_NO_MORE_FILES)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
#if HOST_OS==OS_WINDOWS
|
||||
void cThread::Start() {
|
||||
verify(hThread == NULL);
|
||||
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)entry, param, 0, NULL);
|
||||
ResumeThread(hThread);
|
||||
}
|
||||
void cThread::WaitToEnd() {
|
||||
WaitForSingleObject(hThread,INFINITE);
|
||||
CloseHandle(hThread);
|
||||
hThread = NULL;
|
||||
}
|
||||
#else
|
||||
void cThread::Start() {
|
||||
verify(hThread == NULL);
|
||||
hThread = new pthread_t;
|
||||
if (pthread_create( hThread, NULL, entry, param))
|
||||
die("Thread creation failed");
|
||||
}
|
||||
void cThread::WaitToEnd() {
|
||||
if (hThread) {
|
||||
pthread_join(*hThread,0);
|
||||
delete hThread;
|
||||
hThread = NULL;
|
||||
}
|
||||
return ;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
#include "dc\sh4\rec_v1\compiledblock.h"
|
||||
#include "dc\sh4\rec_v1\blockmanager.h"
|
||||
#endif
|
||||
|
||||
|
||||
#if HOST_OS==OS_WINDOWS
|
||||
cResetEvent::cResetEvent() {
|
||||
hEvent = CreateEvent(
|
||||
NULL, // default security attributes
|
||||
FALSE, // auto-reset event?
|
||||
FALSE, // initial state is State
|
||||
NULL // unnamed object
|
||||
);
|
||||
}
|
||||
cResetEvent::~cResetEvent()
|
||||
{
|
||||
//Destroy the event object ?
|
||||
CloseHandle(hEvent);
|
||||
}
|
||||
void cResetEvent::Set()//Signal
|
||||
{
|
||||
#if defined(DEBUG_THREADS)
|
||||
Sleep(rand() % 10);
|
||||
#endif
|
||||
SetEvent(hEvent);
|
||||
}
|
||||
void cResetEvent::Reset()//reset
|
||||
{
|
||||
#if defined(DEBUG_THREADS)
|
||||
Sleep(rand() % 10);
|
||||
#endif
|
||||
ResetEvent(hEvent);
|
||||
}
|
||||
bool cResetEvent::Wait(u32 msec)//Wait for signal , then reset
|
||||
{
|
||||
#if defined(DEBUG_THREADS)
|
||||
Sleep(rand() % 10);
|
||||
#endif
|
||||
return WaitForSingleObject(hEvent,msec) == WAIT_OBJECT_0;
|
||||
}
|
||||
void cResetEvent::Wait()//Wait for signal , then reset
|
||||
{
|
||||
#if defined(DEBUG_THREADS)
|
||||
Sleep(rand() % 10);
|
||||
#endif
|
||||
WaitForSingleObject(hEvent,(u32)-1);
|
||||
}
|
||||
#else
|
||||
cResetEvent::cResetEvent() {
|
||||
pthread_mutex_init(&mutx, NULL);
|
||||
pthread_cond_init(&cond, NULL);
|
||||
}
|
||||
cResetEvent::~cResetEvent() {
|
||||
}
|
||||
void cResetEvent::Set()//Signal
|
||||
{
|
||||
pthread_mutex_lock( &mutx );
|
||||
state=true;
|
||||
pthread_cond_signal( &cond);
|
||||
pthread_mutex_unlock( &mutx );
|
||||
}
|
||||
void cResetEvent::Reset()//reset
|
||||
{
|
||||
pthread_mutex_lock( &mutx );
|
||||
state=false;
|
||||
pthread_mutex_unlock( &mutx );
|
||||
}
|
||||
bool cResetEvent::Wait(u32 msec)//Wait for signal , then reset
|
||||
{
|
||||
pthread_mutex_lock( &mutx );
|
||||
if (!state)
|
||||
{
|
||||
struct timespec ts;
|
||||
#if HOST_OS == OS_DARWIN
|
||||
// OSX doesn't have clock_gettime.
|
||||
clock_serv_t cclock;
|
||||
mach_timespec_t mts;
|
||||
|
||||
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
|
||||
clock_get_time(cclock, &mts);
|
||||
mach_port_deallocate(mach_task_self(), cclock);
|
||||
ts.tv_sec = mts.tv_sec;
|
||||
ts.tv_nsec = mts.tv_nsec;
|
||||
#else
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
#endif
|
||||
ts.tv_sec += msec / 1000;
|
||||
ts.tv_nsec += (msec % 1000) * 1000000;
|
||||
while (ts.tv_nsec > 1000000000)
|
||||
{
|
||||
ts.tv_nsec -= 1000000000;
|
||||
ts.tv_sec++;
|
||||
}
|
||||
pthread_cond_timedwait( &cond, &mutx, &ts );
|
||||
}
|
||||
bool rc = state;
|
||||
state=false;
|
||||
pthread_mutex_unlock( &mutx );
|
||||
|
||||
return rc;
|
||||
}
|
||||
void cResetEvent::Wait()//Wait for signal , then reset
|
||||
{
|
||||
pthread_mutex_lock( &mutx );
|
||||
if (!state)
|
||||
{
|
||||
pthread_cond_wait( &cond, &mutx );
|
||||
}
|
||||
state=false;
|
||||
pthread_mutex_unlock( &mutx );
|
||||
}
|
||||
#endif
|
||||
|
||||
bool VramLockedWrite(u8* address);
|
||||
bool RamLockedWrite(u8* address,u32* sp);
|
||||
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#if HOST_OS!=OS_WINDOWS
|
||||
#include <pthread.h>
|
||||
#else
|
||||
#include <Windows.h>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -166,38 +166,41 @@ public:
|
|||
#if !defined(HOST_NO_THREADS)
|
||||
typedef void* ThreadEntryFP(void* param);
|
||||
|
||||
typedef void* THREADHANDLE;
|
||||
|
||||
class cThread
|
||||
{
|
||||
class cThread {
|
||||
private:
|
||||
ThreadEntryFP* Entry;
|
||||
ThreadEntryFP* entry;
|
||||
void* param;
|
||||
public :
|
||||
THREADHANDLE hThread;
|
||||
cThread(ThreadEntryFP* function,void* param);
|
||||
|
||||
#if HOST_OS==OS_WINDOWS
|
||||
HANDLE hThread;
|
||||
#else
|
||||
pthread_t *hThread;
|
||||
#endif
|
||||
|
||||
cThread(ThreadEntryFP* function, void* param)
|
||||
:entry(function), param(param), hThread(NULL) {}
|
||||
~cThread() { WaitToEnd(); }
|
||||
void Start();
|
||||
void WaitToEnd();
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
//Wait Events
|
||||
typedef void* EVENTHANDLE;
|
||||
class cResetEvent
|
||||
{
|
||||
|
||||
private:
|
||||
#if HOST_OS==OS_WINDOWS
|
||||
EVENTHANDLE hEvent;
|
||||
#else
|
||||
pthread_mutex_t mutx;
|
||||
pthread_cond_t cond;
|
||||
|
||||
bool state;
|
||||
#endif
|
||||
|
||||
public :
|
||||
bool state;
|
||||
cResetEvent(bool State,bool Auto);
|
||||
cResetEvent();
|
||||
~cResetEvent();
|
||||
void Set(); //Set state to signaled
|
||||
void Reset(); //Set state to non signaled
|
||||
|
|
@ -276,29 +279,38 @@ string get_game_save_prefix();
|
|||
string get_game_basename();
|
||||
string get_game_dir();
|
||||
|
||||
class VArray2
|
||||
{
|
||||
|
||||
// Locked memory class, used for texture invalidation purposes.
|
||||
class VLockedMemory {
|
||||
public:
|
||||
|
||||
u8* data;
|
||||
u32 size;
|
||||
//void Init(void* data,u32 sz);
|
||||
//void Term();
|
||||
void LockRegion(u32 offset,u32 size);
|
||||
void UnLockRegion(u32 offset,u32 size);
|
||||
unsigned size;
|
||||
|
||||
void Zero()
|
||||
{
|
||||
UnLockRegion(0,size);
|
||||
memset(data,0,size);
|
||||
void SetRegion(void* ptr, unsigned size) {
|
||||
this->data = (u8*)ptr;
|
||||
this->size = size;
|
||||
}
|
||||
void *getPtr() const { return data; }
|
||||
unsigned getSize() const { return size; }
|
||||
|
||||
#ifdef TARGET_NO_EXCEPTIONS
|
||||
void LockRegion(unsigned offset, unsigned size_bytes) {}
|
||||
void UnLockRegion(unsigned offset, unsigned size_bytes) {}
|
||||
#else
|
||||
void LockRegion(unsigned offset, unsigned size_bytes);
|
||||
void UnLockRegion(unsigned offset, unsigned size_bytes);
|
||||
#endif
|
||||
|
||||
void Zero() {
|
||||
UnLockRegion(0, size);
|
||||
memset(data, 0, size);
|
||||
}
|
||||
|
||||
INLINE u8& operator [](const u32 i)
|
||||
{
|
||||
INLINE u8& operator [](unsigned i) {
|
||||
#ifdef MEM_BOUND_CHECK
|
||||
if (i>=size)
|
||||
if (i >= size)
|
||||
{
|
||||
printf("Error: VArray2 , index out of range (%d>%d)\n",i,size-1);
|
||||
printf("Error: VLockedMemory , index out of range (%d > %d)\n", i, size-1);
|
||||
MEM_DO_BREAK;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -306,6 +318,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
int msgboxf(const wchar* text,unsigned int type,...);
|
||||
|
||||
|
||||
|
|
|
|||
62
core/types.h
62
core/types.h
|
|
@ -39,7 +39,7 @@
|
|||
#undef _CRT_SECURE_NO_DEPRECATE
|
||||
#endif
|
||||
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
//unnamed struncts/unions
|
||||
#pragma warning( disable : 4201)
|
||||
|
||||
|
|
@ -123,7 +123,7 @@ enum HollyInterruptType
|
|||
};
|
||||
|
||||
enum HollyInterruptID
|
||||
{
|
||||
{
|
||||
// asic9a /sh4 external holly normal [internal]
|
||||
holly_RENDER_DONE_vd = holly_nrm | 0, //bit 0 = End of Render interrupt : Video
|
||||
holly_RENDER_DONE_isp = holly_nrm | 1, //bit 1 = End of Render interrupt : ISP
|
||||
|
|
@ -132,11 +132,11 @@ enum HollyInterruptID
|
|||
holly_SCANINT1 = holly_nrm | 3, //bit 3 = V Blank-in interrupt
|
||||
holly_SCANINT2 = holly_nrm | 4, //bit 4 = V Blank-out interrupt
|
||||
holly_HBLank = holly_nrm | 5, //bit 5 = H Blank-in interrupt
|
||||
|
||||
|
||||
holly_YUV_DMA = holly_nrm | 6, //bit 6 = End of Transferring interrupt : YUV
|
||||
holly_OPAQUE = holly_nrm | 7, //bit 7 = End of Transferring interrupt : Opaque List
|
||||
holly_OPAQUEMOD = holly_nrm | 8, //bit 8 = End of Transferring interrupt : Opaque Modifier Volume List
|
||||
|
||||
|
||||
holly_TRANS = holly_nrm | 9, //bit 9 = End of Transferring interrupt : Translucent List
|
||||
holly_TRANSMOD = holly_nrm | 10, //bit 10 = End of Transferring interrupt : Translucent Modifier Volume List
|
||||
holly_PVR_DMA = holly_nrm | 11, //bit 11 = End of DMA interrupt : PVR-DMA
|
||||
|
|
@ -145,12 +145,12 @@ enum HollyInterruptID
|
|||
holly_MAPLE_VBOI = holly_nrm | 13, //bit 13 = Maple V blank over interrupt
|
||||
holly_GDROM_DMA = holly_nrm | 14, //bit 14 = End of DMA interrupt : GD-DMA
|
||||
holly_SPU_DMA = holly_nrm | 15, //bit 15 = End of DMA interrupt : AICA-DMA
|
||||
|
||||
|
||||
holly_EXT_DMA1 = holly_nrm | 16, //bit 16 = End of DMA interrupt : Ext-DMA1(External 1)
|
||||
holly_EXT_DMA2 = holly_nrm | 17, //bit 17 = End of DMA interrupt : Ext-DMA2(External 2)
|
||||
holly_DEV_DMA = holly_nrm | 18, //bit 18 = End of DMA interrupt : Dev-DMA(Development tool DMA)
|
||||
|
||||
holly_CH2_DMA = holly_nrm | 19, //bit 19 = End of DMA interrupt : ch2-DMA
|
||||
|
||||
holly_CH2_DMA = holly_nrm | 19, //bit 19 = End of DMA interrupt : ch2-DMA
|
||||
holly_PVR_SortDMA = holly_nrm | 20, //bit 20 = End of DMA interrupt : Sort-DMA (Transferring for alpha sorting)
|
||||
holly_PUNCHTHRU = holly_nrm | 21, //bit 21 = End of Transferring interrupt : Punch Through List
|
||||
|
||||
|
|
@ -188,8 +188,8 @@ enum HollyInterruptID
|
|||
//bit 23 = G2 : AICA-DMA Time out
|
||||
//bit 24 = G2 : Ext-DMA1 Time out
|
||||
//bit 25 = G2 : Ext-DMA2 Time out
|
||||
//bit 26 = G2 : Dev-DMA Time out
|
||||
//bit 27 = G2 : Time out in CPU accessing
|
||||
//bit 26 = G2 : Dev-DMA Time out
|
||||
//bit 27 = G2 : Time out in CPU accessing
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -200,7 +200,7 @@ struct vram_block
|
|||
u32 end;
|
||||
u32 len;
|
||||
u32 type;
|
||||
|
||||
|
||||
void* userdata;
|
||||
};
|
||||
|
||||
|
|
@ -229,7 +229,7 @@ struct NDC_WINDOW_RECT
|
|||
//******************************************************
|
||||
//*********************** PowerVR **********************
|
||||
//******************************************************
|
||||
|
||||
|
||||
void libCore_vramlock_Unlock_block (vram_block* block);
|
||||
void libCore_vramlock_Unlock_block_wb (vram_block* block);
|
||||
vram_block* libCore_vramlock_Lock(u32 start_offset,u32 end_offset,void* userdata);
|
||||
|
|
@ -246,7 +246,7 @@ enum DiscType
|
|||
CdRom_XA=0x20,
|
||||
CdRom_Extra=0x30,
|
||||
CdRom_CDI=0x40,
|
||||
GdRom=0x80,
|
||||
GdRom=0x80,
|
||||
|
||||
NoDisk=0x1, //These are a bit hacky .. but work for now ...
|
||||
Open=0x2, //tray is open :)
|
||||
|
|
@ -344,6 +344,7 @@ int darw_printf(const wchar* Text,...);
|
|||
//includes from c++rt
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
using namespace std;
|
||||
|
||||
//used for asm-olny functions
|
||||
|
|
@ -385,9 +386,9 @@ using namespace std;
|
|||
#include "stdclass.h"
|
||||
|
||||
#ifndef RELEASE
|
||||
#define EMUERROR(format, ...) printf("Error in %s:%s:%d: " format "\n", \
|
||||
strlen(__FILE__) <= 20 ? __FILE__ : __FILE__ + strlen(__FILE__) - 20, \
|
||||
__FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
#define EMUERROR(format, ...) printf("Error in %20s:%s:%d: " format "\n", \
|
||||
__FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
//strlen(__FILE__) <= 20 ? __FILE__ : __FILE__ + strlen(__FILE__) - 20,
|
||||
#else
|
||||
#define EMUERROR(format, ...)
|
||||
#endif
|
||||
|
|
@ -518,7 +519,7 @@ typedef union
|
|||
|
||||
|
||||
|
||||
#if COMPILER_VC==BUILD_COMPILER
|
||||
#if COMPILER_VC_OR_CLANG_WIN32
|
||||
#pragma warning( disable : 4127 4996 /*4244*/)
|
||||
#else
|
||||
#define stricmp strcasecmp
|
||||
|
|
@ -576,7 +577,7 @@ enum RegIO
|
|||
RIO_RO = REG_RO | REG_WF,
|
||||
RIO_RO_FUNC = REG_RO | REG_RF | REG_WF,
|
||||
RIO_CONST = REG_RO | REG_WF,
|
||||
RIO_WO_FUNC = REG_WF | REG_RF | REG_WO,
|
||||
RIO_WO_FUNC = REG_WF | REG_RF | REG_WO,
|
||||
RIO_NO_ACCESS = REG_WF | REG_RF | REG_NO_ACCESS
|
||||
};
|
||||
|
||||
|
|
@ -632,7 +633,11 @@ struct settings_t
|
|||
f32 ExtraDepthScale;
|
||||
bool CustomTextures;
|
||||
bool DumpTextures;
|
||||
int ScreenScaling; // in percent. 50 means half the native resolution
|
||||
int ScreenScaling; // in percent. 50 means half the native resolution
|
||||
int ScreenStretching; // in percent. 150 means stretch from 4/3 to 6/3
|
||||
bool Fog;
|
||||
bool FloatVMUs;
|
||||
bool Rotate90; // Rotate the screen 90 deg CC
|
||||
} rend;
|
||||
|
||||
struct
|
||||
|
|
@ -644,7 +649,7 @@ struct settings_t
|
|||
bool disable_nvmem;
|
||||
SmcCheckEnum SmcCheckLevel;
|
||||
} dynarec;
|
||||
|
||||
|
||||
struct
|
||||
{
|
||||
u32 run_counts;
|
||||
|
|
@ -653,7 +658,6 @@ struct settings_t
|
|||
struct
|
||||
{
|
||||
u32 cable; // 0 -> VGA, 1 -> VGA, 2 -> RGB, 3 -> TV
|
||||
u32 RTC;
|
||||
u32 region; // 0 -> JP, 1 -> USA, 2 -> EU, 3 -> default
|
||||
u32 broadcast; // 0 -> NTSC, 1 -> PAL, 2 -> PAL/M, 3 -> PAL/N, 4 -> default
|
||||
u32 language; // 0 -> JP, 1 -> EN, 2 -> DE, 3 -> FR, 4 -> SP, 5 -> IT, 6 -> default
|
||||
|
|
@ -676,6 +680,14 @@ struct settings_t
|
|||
bool NoSound;
|
||||
} aica;
|
||||
|
||||
struct{
|
||||
std::string backend;
|
||||
|
||||
// slug<<key, value>>
|
||||
std::map<std::string, std::map<std::string, std::string>> options;
|
||||
} audio;
|
||||
|
||||
|
||||
#if USE_OMX
|
||||
struct
|
||||
{
|
||||
|
|
@ -705,7 +717,7 @@ struct settings_t
|
|||
{
|
||||
u32 ta_skip;
|
||||
u32 rend;
|
||||
|
||||
|
||||
u32 MaxThreads;
|
||||
bool SynchronousRender;
|
||||
} pvr;
|
||||
|
|
@ -748,7 +760,7 @@ static inline void do_nada(...) { }
|
|||
#ifdef _ANDROID
|
||||
#include <android/log.h>
|
||||
|
||||
#ifdef printf
|
||||
#ifdef printf
|
||||
#undef printf
|
||||
#endif
|
||||
|
||||
|
|
@ -855,7 +867,7 @@ void libARM_Update(u32 cycles);
|
|||
else if (sz==2) \
|
||||
return *(u16*)&arr[addr]; \
|
||||
else if (sz==4) \
|
||||
return *(u32*)&arr[addr];}
|
||||
return *(u32*)&arr[addr];}
|
||||
|
||||
#define WriteMemArr(arr,addr,data,sz) \
|
||||
{if(sz==1) \
|
||||
|
|
@ -863,7 +875,7 @@ void libARM_Update(u32 cycles);
|
|||
else if (sz==2) \
|
||||
{*(u16*)&arr[addr]=(u16)data;} \
|
||||
else if (sz==4) \
|
||||
{*(u32*)&arr[addr]=data;}}
|
||||
{*(u32*)&arr[addr]=data;}}
|
||||
|
||||
#define WriteMemArrRet(arr,addr,data,sz) \
|
||||
{if(sz==1) \
|
||||
|
|
@ -871,7 +883,7 @@ void libARM_Update(u32 cycles);
|
|||
else if (sz==2) \
|
||||
{*(u16*)&arr[addr]=(u16)data;return;} \
|
||||
else if (sz==4) \
|
||||
{*(u32*)&arr[addr]=data;return;}}
|
||||
{*(u32*)&arr[addr]=data;return;}}
|
||||
|
||||
struct OnLoad
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* reicast: version.h
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define REICAST_VERSION "@GIT_VERSION@"
|
||||
#define GIT_HASH "@GIT_HASH@"
|
||||
#define BUILD_DATE __DATE__
|
||||
|
|
@ -1 +0,0 @@
|
|||
/version.cpp
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
extern const char *version;
|
||||
extern const char *git_hash;
|
||||
extern const char *build_date;
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
|
||||
#define _WIN32_WINNT 0x0500
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
|
||||
#include "hw/mem/_vmem.h"
|
||||
|
||||
// Implementation of the vmem related function for Windows platforms.
|
||||
// For now this probably does some assumptions on the CPU/platform.
|
||||
|
||||
// This implements the VLockedMemory interface, as defined in _vmem.h
|
||||
// The implementation allows it to be empty (that is, to not lock memory).
|
||||
|
||||
void VLockedMemory::LockRegion(unsigned offset, unsigned size) {
|
||||
//verify(offset + size < this->size && size != 0);
|
||||
DWORD old;
|
||||
VirtualProtect(&data[offset], size, PAGE_READONLY, &old);
|
||||
}
|
||||
|
||||
void VLockedMemory::UnLockRegion(unsigned offset, unsigned size) {
|
||||
//verify(offset + size <= this->size && size != 0);
|
||||
DWORD old;
|
||||
VirtualProtect(&data[offset], size, PAGE_READWRITE, &old);
|
||||
}
|
||||
|
||||
static HANDLE mem_handle = INVALID_HANDLE_VALUE;
|
||||
static char * base_alloc = NULL;
|
||||
|
||||
// Implement vmem initialization for RAM, ARAM, VRAM and SH4 context, fpcb etc.
|
||||
// The function supports allocating 512MB or 4GB addr spaces.
|
||||
|
||||
// Plase read the POSIX implementation for more information. On Windows this is
|
||||
// rather straightforward.
|
||||
VMemType vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr) {
|
||||
// Firt let's try to allocate the in-memory file
|
||||
mem_handle = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, RAM_SIZE_MAX + VRAM_SIZE_MAX + ARAM_SIZE_MAX, 0);
|
||||
|
||||
// Now allocate the actual address space (it will be 64KB aligned on windows).
|
||||
unsigned memsize = 512*1024*1024 + sizeof(Sh4RCB) + ARAM_SIZE_MAX;
|
||||
base_alloc = (char*)VirtualAlloc(0, memsize, MEM_RESERVE, PAGE_NOACCESS);
|
||||
|
||||
// Calculate pointers now
|
||||
*sh4rcb_addr = &base_alloc[0];
|
||||
*vmem_base_addr = &base_alloc[sizeof(Sh4RCB)];
|
||||
|
||||
return MemType512MB;
|
||||
}
|
||||
|
||||
// Just tries to wipe as much as possible in the relevant area.
|
||||
void vmem_platform_destroy() {
|
||||
VirtualFree(base_alloc, 0, MEM_RELEASE);
|
||||
CloseHandle(mem_handle);
|
||||
}
|
||||
|
||||
// Resets a chunk of memory by deleting its data and setting its protection back.
|
||||
void vmem_platform_reset_mem(void *ptr, unsigned size_bytes) {
|
||||
VirtualFree(ptr, size_bytes, MEM_DECOMMIT);
|
||||
}
|
||||
|
||||
// Allocates a bunch of memory (page aligned and page-sized)
|
||||
void vmem_platform_ondemand_page(void *address, unsigned size_bytes) {
|
||||
verify(VirtualAlloc(address, size_bytes, MEM_COMMIT, PAGE_READWRITE));
|
||||
}
|
||||
|
||||
/// Creates mappings to the underlying file including mirroring sections
|
||||
void vmem_platform_create_mappings(const vmem_mapping *vmem_maps, unsigned nummaps) {
|
||||
// Since this is tricky to get right in Windows (in posix one can just unmap sections and remap later)
|
||||
// we unmap the whole thing only to remap it later.
|
||||
|
||||
// Unmap the whole section
|
||||
VirtualFree(base_alloc, 0, MEM_RELEASE);
|
||||
|
||||
// Map the SH4CB block too
|
||||
void *base_ptr = VirtualAlloc(base_alloc, sizeof(Sh4RCB), MEM_RESERVE, PAGE_NOACCESS);
|
||||
verify(base_ptr == base_alloc);
|
||||
void *cntx_ptr = VirtualAlloc((u8*)p_sh4rcb + sizeof(p_sh4rcb->fpcb), sizeof(Sh4RCB) - sizeof(p_sh4rcb->fpcb), MEM_COMMIT, PAGE_READWRITE);
|
||||
verify(cntx_ptr == (u8*)p_sh4rcb + sizeof(p_sh4rcb->fpcb));
|
||||
|
||||
for (unsigned i = 0; i < nummaps; i++) {
|
||||
unsigned address_range_size = vmem_maps[i].end_address - vmem_maps[i].start_address;
|
||||
DWORD protection = vmem_maps[i].allow_writes ? (FILE_MAP_READ | FILE_MAP_WRITE) : FILE_MAP_READ;
|
||||
|
||||
if (!vmem_maps[i].memsize) {
|
||||
// Unmapped stuff goes with a protected area or memory. Prevent anything from allocating here
|
||||
void *ptr = VirtualAlloc(&virt_ram_base[vmem_maps[i].start_address], address_range_size, MEM_RESERVE, PAGE_NOACCESS);
|
||||
verify(ptr == &virt_ram_base[vmem_maps[i].start_address]);
|
||||
}
|
||||
else {
|
||||
// Calculate the number of mirrors
|
||||
unsigned num_mirrors = (address_range_size) / vmem_maps[i].memsize;
|
||||
verify((address_range_size % vmem_maps[i].memsize) == 0 && num_mirrors >= 1);
|
||||
|
||||
// Remap the views one by one
|
||||
for (unsigned j = 0; j < num_mirrors; j++) {
|
||||
unsigned offset = vmem_maps[i].start_address + j * vmem_maps[i].memsize;
|
||||
|
||||
void *ptr = MapViewOfFileEx(mem_handle, protection, 0, vmem_maps[i].memoffset,
|
||||
vmem_maps[i].memsize, &virt_ram_base[offset]);
|
||||
verify(ptr == &virt_ram_base[offset]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#include "oslib\oslib.h"
|
||||
#include "oslib\audiostream.h"
|
||||
#include "imgread\common.h"
|
||||
#include "oslib/oslib.h"
|
||||
#include "oslib/audiostream.h"
|
||||
#include "imgread/common.h"
|
||||
#include "stdclass.h"
|
||||
#include "cfg/cfg.h"
|
||||
#include "xinput_gamepad.h"
|
||||
|
|
@ -10,8 +10,8 @@
|
|||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
|
||||
#include <Xinput.h>
|
||||
#include "hw\maple\maple_cfg.h"
|
||||
#include <xinput.h>
|
||||
#include "hw/maple/maple_cfg.h"
|
||||
#pragma comment(lib, "XInput9_1_0.lib")
|
||||
|
||||
PCHAR*
|
||||
|
|
@ -148,12 +148,10 @@ LONG ExeptionHandler(EXCEPTION_POINTERS *ExceptionInfo)
|
|||
{
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
#ifndef TARGET_NO_NVMEM
|
||||
else if (BM_LockedWrite(address))
|
||||
{
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
#endif
|
||||
#if FEAT_SHREC == DYNAREC_JIT && HOST_CPU == CPU_X86
|
||||
else if ( ngen_Rewrite((unat&)ep->ContextRecord->Eip,*(unat*)ep->ContextRecord->Esp,ep->ContextRecord->Eax) )
|
||||
{
|
||||
|
|
@ -188,8 +186,6 @@ u16 kcode[4] = { 0xffff, 0xffff, 0xffff, 0xffff };
|
|||
u32 vks[4];
|
||||
s8 joyx[4],joyy[4];
|
||||
u8 rt[4],lt[4];
|
||||
extern bool coin_chute;
|
||||
extern bool naomi_test_button;
|
||||
// Mouse
|
||||
extern s32 mo_x_abs;
|
||||
extern s32 mo_y_abs;
|
||||
|
|
@ -200,6 +196,10 @@ extern f32 mo_wheel_delta;
|
|||
// Keyboard
|
||||
static Win32KeyboardDevice keyboard(0);
|
||||
|
||||
|
||||
void ToggleFullscreen();
|
||||
|
||||
|
||||
void UpdateInputState(u32 port)
|
||||
{
|
||||
/*
|
||||
|
|
@ -220,12 +220,6 @@ void UpdateInputState(u32 port)
|
|||
std::shared_ptr<XInputGamepadDevice> gamepad = XInputGamepadDevice::GetXInputDevice(port);
|
||||
if (gamepad != NULL)
|
||||
gamepad->ReadInput();
|
||||
|
||||
#if DC_PLATFORM == DC_PLATFORM_NAOMI || DC_PLATFORM == DC_PLATFORM_ATOMISWAVE
|
||||
// FIXME
|
||||
coin_chute = GetAsyncKeyState(VK_F8);
|
||||
naomi_test_button = GetAsyncKeyState(VK_F7);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Windows class name to register
|
||||
|
|
@ -339,6 +333,14 @@ LRESULT CALLBACK WndProc2(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
keyboard.keyboard_input(keycode, message == WM_KEYDOWN);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_SYSKEYDOWN:
|
||||
if (wParam == VK_RETURN)
|
||||
if ((HIWORD(lParam) & KF_ALTDOWN))
|
||||
ToggleFullscreen();
|
||||
|
||||
break;
|
||||
|
||||
case WM_CHAR:
|
||||
keyboard.keyboard_character((char)wParam);
|
||||
return 0;
|
||||
|
|
@ -396,6 +398,45 @@ void* libPvr_GetRenderSurface()
|
|||
return GetDC((HWND)window_win);
|
||||
}
|
||||
|
||||
|
||||
void ToggleFullscreen()
|
||||
{
|
||||
static RECT rSaved;
|
||||
static bool fullscreen=false;
|
||||
HWND hWnd = (HWND)window_win;
|
||||
|
||||
fullscreen = !fullscreen;
|
||||
|
||||
|
||||
if (fullscreen)
|
||||
{
|
||||
GetWindowRect(hWnd, &rSaved);
|
||||
|
||||
MONITORINFO mi = { sizeof(mi) };
|
||||
HMONITOR hmon = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
|
||||
if (GetMonitorInfo(hmon, &mi)) {
|
||||
|
||||
SetWindowLongPtr(hWnd, GWL_EXSTYLE, WS_EX_APPWINDOW | WS_EX_TOPMOST);
|
||||
SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
|
||||
|
||||
SetWindowPos(hWnd, HWND_TOPMOST, mi.rcMonitor.left, mi.rcMonitor.top,
|
||||
mi.rcMonitor.right - mi.rcMonitor.left, mi.rcMonitor.bottom - mi.rcMonitor.top,
|
||||
SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_ASYNCWINDOWPOS);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
SetWindowLongPtr(hWnd, GWL_EXSTYLE, WS_EX_APPWINDOW | WS_EX_TOPMOST);
|
||||
SetWindowLongPtr(hWnd, GWL_STYLE, WS_VISIBLE | WS_OVERLAPPEDWINDOW | (window_maximized ? WS_MAXIMIZE : 0));
|
||||
|
||||
SetWindowPos(hWnd, NULL, rSaved.left, rSaved.top,
|
||||
rSaved.right - rSaved.left, rSaved.bottom - rSaved.top,
|
||||
SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_ASYNCWINDOWPOS|SWP_NOZORDER);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
BOOL CtrlHandler( DWORD fdwCtrlType )
|
||||
{
|
||||
switch( fdwCtrlType )
|
||||
|
|
@ -646,15 +687,31 @@ int CALLBACK WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine
|
|||
int argc=0;
|
||||
wchar* cmd_line=GetCommandLineA();
|
||||
wchar** argv=CommandLineToArgvA(cmd_line,&argc);
|
||||
if(strstr(cmd_line,"NoConsole")==0)
|
||||
for (int i = 0; i < argc; i++)
|
||||
{
|
||||
if (AllocConsole())
|
||||
if (!stricmp(argv[i], "-console"))
|
||||
{
|
||||
freopen("CON","w",stdout);
|
||||
freopen("CON","w",stderr);
|
||||
freopen("CON","r",stdin);
|
||||
if (AllocConsole())
|
||||
{
|
||||
freopen("CON", "w", stdout);
|
||||
freopen("CON", "w", stderr);
|
||||
freopen("CON", "r", stdin);
|
||||
}
|
||||
SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE);
|
||||
}
|
||||
else if (!stricmp(argv[i], "-log"))
|
||||
{
|
||||
const char *logfile;
|
||||
if (i < argc - 1)
|
||||
{
|
||||
logfile = argv[i + 1];
|
||||
i++;
|
||||
}
|
||||
else
|
||||
logfile = "reicast-log.txt";
|
||||
freopen(logfile, "w", stdout);
|
||||
freopen(logfile, "w", stderr);
|
||||
}
|
||||
SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -662,14 +719,13 @@ int CALLBACK WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine
|
|||
ReserveBottomMemory();
|
||||
SetupPath();
|
||||
|
||||
#ifndef __GNUC__
|
||||
__try
|
||||
#else
|
||||
#ifdef _WIN64
|
||||
AddVectoredExceptionHandler(1, ExeptionHandler);
|
||||
#else
|
||||
SetUnhandledExceptionFilter(&ExeptionHandler);
|
||||
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)&ExeptionHandler);
|
||||
#endif
|
||||
#ifndef __GNUC__
|
||||
__try
|
||||
#endif
|
||||
{
|
||||
int reicast_init(int argc, char* argv[]);
|
||||
|
|
@ -742,90 +798,5 @@ void os_DoEvents()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//Windoze Code implementation of commong classes from here and after ..
|
||||
|
||||
//Thread class
|
||||
cThread::cThread(ThreadEntryFP* function,void* prm)
|
||||
{
|
||||
Entry=function;
|
||||
param=prm;
|
||||
}
|
||||
|
||||
|
||||
void cThread::Start()
|
||||
{
|
||||
hThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Entry,param,0,NULL);
|
||||
ResumeThread(hThread);
|
||||
}
|
||||
|
||||
void cThread::WaitToEnd()
|
||||
{
|
||||
WaitForSingleObject(hThread,INFINITE);
|
||||
}
|
||||
//End thread class
|
||||
|
||||
//cResetEvent Calss
|
||||
cResetEvent::cResetEvent(bool State,bool Auto)
|
||||
{
|
||||
hEvent = CreateEvent(
|
||||
NULL, // default security attributes
|
||||
Auto?FALSE:TRUE, // auto-reset event?
|
||||
State?TRUE:FALSE, // initial state is State
|
||||
NULL // unnamed object
|
||||
);
|
||||
}
|
||||
cResetEvent::~cResetEvent()
|
||||
{
|
||||
//Destroy the event object ?
|
||||
CloseHandle(hEvent);
|
||||
}
|
||||
void cResetEvent::Set()//Signal
|
||||
{
|
||||
#if defined(DEBUG_THREADS)
|
||||
Sleep(rand() % 10);
|
||||
#endif
|
||||
SetEvent(hEvent);
|
||||
}
|
||||
void cResetEvent::Reset()//reset
|
||||
{
|
||||
#if defined(DEBUG_THREADS)
|
||||
Sleep(rand() % 10);
|
||||
#endif
|
||||
ResetEvent(hEvent);
|
||||
}
|
||||
bool cResetEvent::Wait(u32 msec)//Wait for signal , then reset
|
||||
{
|
||||
#if defined(DEBUG_THREADS)
|
||||
Sleep(rand() % 10);
|
||||
#endif
|
||||
return WaitForSingleObject(hEvent,msec) == WAIT_OBJECT_0;
|
||||
}
|
||||
void cResetEvent::Wait()//Wait for signal , then reset
|
||||
{
|
||||
#if defined(DEBUG_THREADS)
|
||||
Sleep(rand() % 10);
|
||||
#endif
|
||||
WaitForSingleObject(hEvent,(u32)-1);
|
||||
}
|
||||
//End AutoResetEvent
|
||||
|
||||
void VArray2::LockRegion(u32 offset,u32 size)
|
||||
{
|
||||
//verify(offset+size<this->size);
|
||||
verify(size!=0);
|
||||
DWORD old;
|
||||
VirtualProtect(((u8*)data)+offset , size, PAGE_READONLY,&old);
|
||||
}
|
||||
void VArray2::UnLockRegion(u32 offset,u32 size)
|
||||
{
|
||||
//verify(offset+size<=this->size);
|
||||
verify(size!=0);
|
||||
DWORD old;
|
||||
VirtualProtect(((u8*)data)+offset , size, PAGE_READWRITE,&old);
|
||||
}
|
||||
|
||||
int get_mic_data(u8* buffer) { return 0; }
|
||||
int push_vmu_screen(u8* buffer) { return 0; }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#include <Xinput.h>
|
||||
#include <xinput.h>
|
||||
#include "input/gamepad_device.h"
|
||||
#include "rend/gui.h"
|
||||
|
||||
|
|
@ -181,7 +181,6 @@ protected:
|
|||
private:
|
||||
void do_rumble(float power)
|
||||
{
|
||||
printf("do_rumble %f\n", power);
|
||||
XINPUT_VIBRATION vib;
|
||||
|
||||
vib.wLeftMotorSpeed = (u16)(65535 * power);
|
||||
|
|
|
|||
|
|
@ -3,54 +3,57 @@
|
|||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<application android:name="com.reicast.emulator.Emulator">
|
||||
<activity
|
||||
android:name="com.reicast.emulator.NativeGLActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.GDI"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.gdi"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.CHD"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.chd"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.CDI"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.cdi"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.CUE"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.cue"
|
||||
android:scheme="file" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
android:name="com.reicast.emulator.NativeGLActivity"/>
|
||||
<activity-alias
|
||||
android:name="com.reicast.emulator.MainActivity"
|
||||
android:targetActivity="com.reicast.emulator.NativeGLActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.GDI"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.gdi"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.CHD"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.chd"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.CDI"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.cdi"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.CUE"
|
||||
android:scheme="file" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.cue"
|
||||
android:scheme="file" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
</application>
|
||||
</manifest>
|
||||
</manifest>
|
||||
|
|
|
|||
|
|
@ -53,14 +53,18 @@
|
|||
<activity
|
||||
android:name="com.reicast.emulator.NativeGLActivity"
|
||||
android:configChanges="orientation|navigation|screenSize|screenLayout|uiMode|keyboard|keyboardHidden"
|
||||
android:screenOrientation="sensorLandscape">
|
||||
android:screenOrientation="sensorLandscape"
|
||||
android:exported="true"/>
|
||||
<activity-alias
|
||||
android:name="com.reicast.emulator.MainActivity"
|
||||
android:targetActivity="com.reicast.emulator.NativeGLActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<category android:name="tv.ouya.intent.category.GAME" />
|
||||
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</activity-alias>
|
||||
<provider
|
||||
android:name="android.support.v4.content.FileProvider"
|
||||
android:authorities="${applicationId}.provider"
|
||||
|
|
|
|||
|
|
@ -228,22 +228,24 @@ public abstract class BaseGLActivity extends Activity implements ActivityCompat.
|
|||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
if (!JNIdc.guiIsOpen()) {
|
||||
showMenu();
|
||||
return true;
|
||||
if (event.getRepeatCount() == 0) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
if (!JNIdc.guiIsOpen()) {
|
||||
showMenu();
|
||||
return true;
|
||||
}
|
||||
else if (JNIdc.guiIsContentBrowser()) {
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (JNIdc.guiIsContentBrowser()) {
|
||||
finish();
|
||||
if (InputDeviceManager.getInstance().joystickButtonEvent(event.getDeviceId(), keyCode, true))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (InputDeviceManager.getInstance().joystickButtonEvent(event.getDeviceId(), keyCode, true))
|
||||
return true;
|
||||
|
||||
if (ViewConfiguration.get(this).hasPermanentMenuKey()) {
|
||||
if (keyCode == KeyEvent.KEYCODE_MENU) {
|
||||
return showMenu();
|
||||
if (ViewConfiguration.get(this).hasPermanentMenuKey()) {
|
||||
if (keyCode == KeyEvent.KEYCODE_MENU) {
|
||||
return showMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
|
|
@ -296,7 +298,7 @@ public abstract class BaseGLActivity extends Activity implements ActivityCompat.
|
|||
}
|
||||
|
||||
// Called from native code
|
||||
private void generateErrorLog() {
|
||||
protected void generateErrorLog() {
|
||||
try {
|
||||
new GenerateLogs(this).execute(getFilesDir().getAbsolutePath());
|
||||
} catch (RuntimeException e) {
|
||||
|
|
|
|||
|
|
@ -21,8 +21,7 @@ public final class JNIdc
|
|||
public static native int send(int cmd, int opt);
|
||||
public static native int data(int cmd, byte[] data);
|
||||
|
||||
public static native void rendinitNative(Surface surface, int w, int h);
|
||||
public static native boolean rendframeNative();
|
||||
public static native void rendinitNative(Surface surface);
|
||||
public static native void rendinitJava(int w, int h);
|
||||
public static native boolean rendframeJava();
|
||||
public static native void rendtermJava();
|
||||
|
|
|
|||
|
|
@ -19,8 +19,6 @@ import com.reicast.emulator.NativeGLActivity;
|
|||
import com.reicast.emulator.config.Config;
|
||||
|
||||
public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback {
|
||||
private Handler handler = new Handler();
|
||||
|
||||
private boolean surfaceReady = false;
|
||||
private boolean paused = false;
|
||||
VirtualJoystickDelegate vjoyDelegate;
|
||||
|
|
@ -66,23 +64,6 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback
|
|||
|
||||
if (NativeGLActivity.syms != null)
|
||||
JNIdc.data(1, NativeGLActivity.syms);
|
||||
|
||||
startRendering();
|
||||
}
|
||||
|
||||
private void startRendering() {
|
||||
// Continuously render frames
|
||||
handler.removeCallbacksAndMessages(null);
|
||||
handler.postAtTime(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!paused)
|
||||
{
|
||||
JNIdc.rendframeNative();
|
||||
handler.post(this);
|
||||
}
|
||||
}
|
||||
}, SystemClock.uptimeMillis() + 500);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -111,7 +92,7 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback
|
|||
public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int w, int h) {
|
||||
//Log.i("reicast", "NativeGLView.surfaceChanged: " + w + "x" + h);
|
||||
surfaceReady = true;
|
||||
JNIdc.rendinitNative(surfaceHolder.getSurface(), w, h);
|
||||
JNIdc.rendinitNative(surfaceHolder.getSurface());
|
||||
Emulator.getCurrentActivity().handleStateChange(false);
|
||||
}
|
||||
|
||||
|
|
@ -119,7 +100,7 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback
|
|||
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
|
||||
//Log.i("reicast", "NativeGLView.surfaceDestroyed");
|
||||
surfaceReady = false;
|
||||
JNIdc.rendinitNative(null, 0, 0);
|
||||
JNIdc.rendinitNative(null);
|
||||
Emulator.getCurrentActivity().handleStateChange(true);
|
||||
}
|
||||
|
||||
|
|
@ -142,7 +123,6 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback
|
|||
requestFocus();
|
||||
JNIdc.resume();
|
||||
}
|
||||
startRendering();
|
||||
}
|
||||
|
||||
@TargetApi(19)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import com.reicast.emulator.periph.InputDeviceManager;
|
|||
import com.reicast.emulator.periph.VJoy;
|
||||
|
||||
public class VirtualJoystickDelegate {
|
||||
private Vibrator vib;
|
||||
private VibratorThread vibratorThread;
|
||||
|
||||
private boolean editVjoyMode = false;
|
||||
private int selectedVjoyElement = -1;
|
||||
|
|
@ -39,7 +39,10 @@ public class VirtualJoystickDelegate {
|
|||
public VirtualJoystickDelegate(View view) {
|
||||
this.view = view;
|
||||
this.context = view.getContext();
|
||||
vib = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
|
||||
|
||||
vibratorThread = new VibratorThread(context);
|
||||
vibratorThread.start();
|
||||
|
||||
readCustomVjoyValues();
|
||||
scaleGestureDetector = new ScaleGestureDetector(context, new OscOnScaleGestureListener());
|
||||
}
|
||||
|
|
@ -224,8 +227,9 @@ public class VirtualJoystickDelegate {
|
|||
if (y > vjoy[j][1] && y <= (vjoy[j][1] + vjoy[j][3])) {
|
||||
if (vjoy[j][4] >= -2) {
|
||||
if (vjoy[j][5] == 0)
|
||||
if (!editVjoyMode && Emulator.vibrationDuration > 0)
|
||||
vib.vibrate(Emulator.vibrationDuration);
|
||||
if (!editVjoyMode) {
|
||||
vibratorThread.vibrate();
|
||||
}
|
||||
vjoy[j][5] = 2;
|
||||
}
|
||||
|
||||
|
|
@ -397,4 +401,51 @@ public class VirtualJoystickDelegate {
|
|||
selectedVjoyElement = -1;
|
||||
}
|
||||
}
|
||||
|
||||
private class VibratorThread extends Thread
|
||||
{
|
||||
private Vibrator vibrator;
|
||||
private boolean vibrate = false;
|
||||
private boolean stopping = false;
|
||||
|
||||
VibratorThread(Context context) {
|
||||
vibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (!stopping) {
|
||||
boolean doVibrate;
|
||||
synchronized (this) {
|
||||
doVibrate = false;
|
||||
try {
|
||||
this.wait();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
if (vibrate) {
|
||||
doVibrate = true;
|
||||
vibrate = false;
|
||||
}
|
||||
}
|
||||
if (doVibrate)
|
||||
vibrator.vibrate(Emulator.vibrationDuration);
|
||||
}
|
||||
}
|
||||
|
||||
public void stopVibrator() {
|
||||
synchronized (this) {
|
||||
stopping = true;
|
||||
notify();
|
||||
}
|
||||
}
|
||||
|
||||
public void vibrate() {
|
||||
if (Emulator.vibrationDuration > 0) {
|
||||
synchronized (this) {
|
||||
vibrate = true;
|
||||
notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ WEBUI := 1
|
|||
USE_GLES := 1
|
||||
CHD5_LZMA := 1
|
||||
CHD5_FLAC := 1
|
||||
USE_MODEM := 1
|
||||
|
||||
ifneq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||
NOT_ARM := 1
|
||||
|
|
@ -112,6 +113,8 @@ else
|
|||
endif
|
||||
endif
|
||||
|
||||
$(LOCAL_SRC_FILES): $(VERSION_HEADER)
|
||||
|
||||
#
|
||||
# android has poor support for hardfp calling.
|
||||
# r9b+ is required, and it only works for internal calls
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
#include "hw/maple/maple_devs.h"
|
||||
#include "hw/maple/maple_if.h"
|
||||
#include "hw/naomi/naomi_cart.h"
|
||||
#include "oslib/audiobackend_android.h"
|
||||
#include "oslib/audiostream.h"
|
||||
#include "imgread/common.h"
|
||||
#include "rend/gui.h"
|
||||
#include "cfg/cfg.h"
|
||||
|
|
@ -91,8 +91,7 @@ JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_destroy(JNIEnv *env,j
|
|||
JNIEXPORT jint JNICALL Java_com_reicast_emulator_emu_JNIdc_send(JNIEnv *env,jobject obj,jint id, jint v) __attribute__((visibility("default")));
|
||||
JNIEXPORT jint JNICALL Java_com_reicast_emulator_emu_JNIdc_data(JNIEnv *env,jobject obj,jint id, jbyteArray d) __attribute__((visibility("default")));
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitNative(JNIEnv *env, jobject obj, jobject surface, jint w, jint h) __attribute__((visibility("default")));
|
||||
JNIEXPORT jboolean JNICALL Java_com_reicast_emulator_emu_JNIdc_rendframeNative(JNIEnv *env,jobject obj) __attribute__((visibility("default")));
|
||||
JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitNative(JNIEnv *env, jobject obj, jobject surface) __attribute__((visibility("default")));
|
||||
JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitJava(JNIEnv *env, jobject obj, jint w, jint h) __attribute__((visibility("default")));
|
||||
JNIEXPORT jboolean JNICALL Java_com_reicast_emulator_emu_JNIdc_rendframeJava(JNIEnv *env, jobject obj) __attribute__((visibility("default")));
|
||||
JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendtermJava(JNIEnv *env, jobject obj) __attribute__((visibility("default")));
|
||||
|
|
@ -404,35 +403,57 @@ JNIEXPORT jint JNICALL Java_com_reicast_emulator_emu_JNIdc_data(JNIEnv *env, job
|
|||
|
||||
extern void gl_swap();
|
||||
extern void egl_stealcntx();
|
||||
volatile static bool render_running;
|
||||
volatile static bool render_reinit;
|
||||
|
||||
JNIEXPORT jboolean JNICALL Java_com_reicast_emulator_emu_JNIdc_rendframeNative(JNIEnv *env,jobject obj)
|
||||
void *render_thread_func(void *)
|
||||
{
|
||||
if (g_window == NULL)
|
||||
return false;
|
||||
if (!egl_makecurrent())
|
||||
return false;
|
||||
jboolean ret = (jboolean)rend_single_frame();
|
||||
if (ret)
|
||||
gl_swap();
|
||||
return ret;
|
||||
render_running = true;
|
||||
|
||||
rend_init_renderer();
|
||||
|
||||
while (render_running) {
|
||||
if (render_reinit)
|
||||
{
|
||||
render_reinit = false;
|
||||
rend_init_renderer();
|
||||
}
|
||||
else
|
||||
if (!egl_makecurrent())
|
||||
break;;
|
||||
|
||||
bool ret = rend_single_frame();
|
||||
if (ret)
|
||||
gl_swap();
|
||||
}
|
||||
egl_makecurrent();
|
||||
rend_term_renderer();
|
||||
ANativeWindow_release(g_window);
|
||||
g_window = NULL;
|
||||
render_running = false;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitNative(JNIEnv * env, jobject obj, jobject surface, jint width, jint height)
|
||||
static cThread render_thread(render_thread_func, NULL);
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitNative(JNIEnv * env, jobject obj, jobject surface)
|
||||
{
|
||||
if (g_window != NULL)
|
||||
{
|
||||
egl_makecurrent();
|
||||
rend_term_renderer();
|
||||
ANativeWindow_release(g_window);
|
||||
g_window = NULL;
|
||||
}
|
||||
if (surface != NULL)
|
||||
{
|
||||
if (render_thread.hThread != NULL)
|
||||
{
|
||||
if (surface == NULL)
|
||||
{
|
||||
render_running = false;
|
||||
render_thread.WaitToEnd();
|
||||
}
|
||||
else
|
||||
render_reinit = true;
|
||||
}
|
||||
else if (surface != NULL)
|
||||
{
|
||||
g_window = ANativeWindow_fromSurface(env, surface);
|
||||
rend_init_renderer();
|
||||
screen_width = width;
|
||||
screen_height = height;
|
||||
}
|
||||
render_thread.Start();
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitJava(JNIEnv * env, jobject obj, jint width, jint height)
|
||||
|
|
@ -526,9 +547,13 @@ audiobackend_t audiobackend_android = {
|
|||
"Android Audio", // Name
|
||||
&androidaudio_init,
|
||||
&androidaudio_push,
|
||||
&androidaudio_term
|
||||
&androidaudio_term,
|
||||
NULL
|
||||
};
|
||||
|
||||
static bool android = RegisterAudioBackend(&audiobackend_android);
|
||||
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_AudioBackend_setInstance(JNIEnv *env, jobject obj, jobject instance)
|
||||
{
|
||||
if (g_audioBackend != NULL)
|
||||
|
|
@ -568,7 +593,7 @@ void os_DebugBreak()
|
|||
|
||||
raise(SIGABRT);
|
||||
//pthread_exit(NULL);
|
||||
|
||||
|
||||
// Attach debugger here to figure out what went wrong
|
||||
for(;;) ;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@
|
|||
android:name="com.reicast.emulator.Emulator">
|
||||
|
||||
<activity
|
||||
android:name="com.reicast.emulator.MainActivity">
|
||||
android:name="com.reicast.emulator.NativeGLActivity"/>
|
||||
<activity-alias
|
||||
android:name="com.reicast.emulator.MainActivity"
|
||||
android:targetActivity="com.reicast.emulator.NativeGLActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
|
|
@ -61,6 +64,6 @@
|
|||
android:pathPattern=".*\\.7z"
|
||||
android:scheme="file" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</activity-alias>
|
||||
</application>
|
||||
</manifest>
|
||||
|
|
|
|||
|
|
@ -266,6 +266,7 @@
|
|||
AEE6278E2224762000EC7E89 /* imgui_impl_opengl3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEE6278B2224762000EC7E89 /* imgui_impl_opengl3.cpp */; };
|
||||
AEE6279422247C0A00EC7E89 /* gui_util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEE6279222247C0A00EC7E89 /* gui_util.cpp */; };
|
||||
AEE6279622247C2B00EC7E89 /* keyboard_device.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEE6279522247C2B00EC7E89 /* keyboard_device.cpp */; };
|
||||
AEF2564822886A2E00348550 /* posix_vmem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEF2564722886A2E00348550 /* posix_vmem.cpp */; };
|
||||
AEFF7ECC214AEC810068CE11 /* modem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEFF7EC7214AEC800068CE11 /* modem.cpp */; };
|
||||
AEFF7F4D214D9D590068CE11 /* pico_arp.c in Sources */ = {isa = PBXBuildFile; fileRef = AEFF7EFA214D9D590068CE11 /* pico_arp.c */; };
|
||||
AEFF7F4E214D9D590068CE11 /* pico_dev_ppp.c in Sources */ = {isa = PBXBuildFile; fileRef = AEFF7EFE214D9D590068CE11 /* pico_dev_ppp.c */; };
|
||||
|
|
@ -803,6 +804,7 @@
|
|||
AEE6279222247C0A00EC7E89 /* gui_util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gui_util.cpp; sourceTree = "<group>"; };
|
||||
AEE6279322247C0A00EC7E89 /* gui_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gui_util.h; sourceTree = "<group>"; };
|
||||
AEE6279522247C2B00EC7E89 /* keyboard_device.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = keyboard_device.cpp; sourceTree = "<group>"; };
|
||||
AEF2564722886A2E00348550 /* posix_vmem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = posix_vmem.cpp; sourceTree = "<group>"; };
|
||||
AEFF7EC7214AEC800068CE11 /* modem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = modem.cpp; sourceTree = "<group>"; };
|
||||
AEFF7EC8214AEC800068CE11 /* modem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = modem.h; sourceTree = "<group>"; };
|
||||
AEFF7EC9214AEC800068CE11 /* modem_regs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = modem_regs.h; sourceTree = "<group>"; };
|
||||
|
|
@ -1556,6 +1558,7 @@
|
|||
84B7BE661B72720100F9733F /* context.cpp */,
|
||||
84B7BE671B72720100F9733F /* context.h */,
|
||||
84B7BE681B72720100F9733F /* nixprof */,
|
||||
AEF2564722886A2E00348550 /* posix_vmem.cpp */,
|
||||
84B7BE6A1B72720100F9733F /* typedefs.h */,
|
||||
);
|
||||
name = linux;
|
||||
|
|
@ -2199,7 +2202,7 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "echo \"const char *version = \\\"`git describe --tags --always`\\\";\" > $SRCROOT/../../../core/version/version.cpp\necho \"const char *git_hash = \\\"`git rev-parse --short HEAD`\\\";\" >> $SRCROOT/../../../core/version/version.cpp\necho \"const char *build_date = \\\"`date '+%Y-%m-%d %H:%M:%S %Z'`\\\";\" >> $SRCROOT/../../../core/version/version.cpp\n";
|
||||
shellScript = "echo \"#define REICAST_VERSION \\\"`git describe --tags --always`\\\"\" > $SRCROOT/../../../core/version.h\necho \"#define GIT_HASH \\\"`git rev-parse --short HEAD`\\\"\" >> $SRCROOT/../../../core/version.h\necho \"#define BUILD_DATE \\\"`date '+%Y-%m-%d %H:%M:%S %Z'`\\\"\" >> $SRCROOT/../../../core/version.h\n";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
|
|
@ -2310,6 +2313,7 @@
|
|||
84B7BF131B72720200F9733F /* zip_unchange_all.c in Sources */,
|
||||
84B7BF541B72720200F9733F /* sh4_interrupts.cpp in Sources */,
|
||||
AE2A2D7F21D6851E004B308D /* 7zFile.c in Sources */,
|
||||
AEF2564822886A2E00348550 /* posix_vmem.cpp in Sources */,
|
||||
84B7BF6B1B72720200F9733F /* audiostream.cpp in Sources */,
|
||||
84B7BEFB1B72720200F9733F /* zip_get_file_comment.c in Sources */,
|
||||
84B7BF301B72720200F9733F /* holly_intc.cpp in Sources */,
|
||||
|
|
@ -2546,6 +2550,7 @@
|
|||
TARGET_NO_AREC,
|
||||
XBYAK_NO_OP_NAMES,
|
||||
TARGET_NO_OPENMP,
|
||||
ENABLE_MODEM,
|
||||
CHD5_LZMA,
|
||||
_7ZIP_ST,
|
||||
CHD5_FLAC,
|
||||
|
|
@ -2602,6 +2607,7 @@
|
|||
TARGET_NO_AREC,
|
||||
XBYAK_NO_OP_NAMES,
|
||||
TARGET_NO_OPENMP,
|
||||
ENABLE_MODEM,
|
||||
CHD5_LZMA,
|
||||
_7ZIP_ST,
|
||||
CHD5_FLAC,
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue