mirror of https://github.com/mgba-emu/mgba.git
Merge branch 'master' (early part) into translations
This commit is contained in:
commit
261f46fb83
Binary file not shown.
23
CHANGES
23
CHANGES
|
@ -1,36 +1,57 @@
|
|||
0.11.0: (Future)
|
||||
Features:
|
||||
- New option to lock the maximum frame size
|
||||
- Scripting: New `input` API for getting raw keyboard/mouse/controller state
|
||||
- Scripting: New `storage` API for saving data for a script, e.g. settings
|
||||
- Scripting: Debugger integration to allow for breakpoints and watchpoints
|
||||
- New unlicensed GB mappers: NT (older types 1 and 2), Li Cheng, GGB-81
|
||||
- Debugger: Add range watchpoints
|
||||
Emulation fixes:
|
||||
- ARM: Add framework for coprocessor support
|
||||
- GB Audio: Fix audio envelope timing resetting too often (fixes mgba.io/i/3164)
|
||||
- GB I/O: Fix STAT writing IRQ trigger conditions (fixes mgba.io/i/2501)
|
||||
- GB Serialize: Add missing Pocket Cam state to savestates
|
||||
- GB Video: Implement DMG-style sprite ordering
|
||||
- GBA: Unhandled bkpt should be treated as an undefined exception
|
||||
- GBA GPIO: Fix tilt scale and orientation (fixes mgba.io/i/2703)
|
||||
- GBA: Add baseline CP0 (Wii U VC) and CP1 (DCC) implementations
|
||||
- GBA GPIO: Fix gyro read-out start (fixes mgba.io/i/3141)
|
||||
- GBA I/O: Fix HALTCNT access behavior (fixes mgba.io/i/2309)
|
||||
- GBA Serialize: Fix some minor save state edge cases
|
||||
- GBA SIO: Fix MULTI mode SIOCNT bit 7 writes on secondary GBAs (fixes mgba.io/i/3110)
|
||||
- GBA Video: Disable BG target 1 blending when OBJ blending (fixes mgba.io/i/2722)
|
||||
- GBA Video: Improve emulation of window start/end conditions (fixes mgba.io/i/1945)
|
||||
Other fixes:
|
||||
- Core: Fix inconsistencies with setting game-specific overrides (fixes mgba.io/i/2963)
|
||||
- Debugger: Fix writing to specific segment in command-line debugger
|
||||
- GB: Fix uninitialized save data when loading undersized temporary saves
|
||||
- GB, GBA Core: Fix memory leak if reloading debug symbols
|
||||
- GB Serialize: Prevent loading invalid states where LY >= 144 in modes other than 1
|
||||
- GBA: Fix getting game info for multiboot ROMs
|
||||
- GBA Audio: Fix crash if audio FIFOs and timers get out of sync
|
||||
- GBA Audio: Fix crash in audio subsampling if timing lockstep breaks
|
||||
- GBA Core: Fix loading symbols from ELF files if the file doesn't end with .elf
|
||||
- GBA Memory: Let raw access read high MMIO addresses
|
||||
- Qt: Fix savestate preview sizes with different scales (fixes mgba.io/i/2560)
|
||||
- Qt: Fix potential crash when configuring shortcuts
|
||||
- Qt: Fix crash when applying changes to GB I/O registers in I/O view
|
||||
- Qt: Fix LCDC background priority/enable bit being mis-mapped in I/O view
|
||||
- Updater: Fix updating appimage across filesystems
|
||||
Misc:
|
||||
- Core: Handle relative paths for saves, screenshots, etc consistently (fixes mgba.io/i/2826)
|
||||
- Core: Improve rumble emulation by averaging state over entire frame (fixes mgba.io/i/3232)
|
||||
- GB: Prevent incompatible BIOSes from being used on differing models
|
||||
- GB Serialize: Add missing savestate support for MBC6 and NT (newer)
|
||||
- GBA: Improve detection of valid ELF ROMs
|
||||
- GBA Audio: Remove broken XQ audio pending rewrite
|
||||
- GBA Memory: Improve VRAM access stall cycle estimation
|
||||
- GBA Video: Add special circlular window handling in OpenGL renderer
|
||||
- Libretro: Add Super Game Boy Color support (closes mgba.io/i/3188)
|
||||
- mGUI: Enable auto-softpatching (closes mgba.io/i/2899)
|
||||
- mGUI: Persist fast forwarding after closing menu (fixes mgba.io/i/2414)
|
||||
- Qt: Handle multiple save game files for disparate games separately (fixes mgba.io/i/2887)
|
||||
- Qt: Remove maligned double-click-to-fullscreen shortcut (closes mgba.io/i/2632)
|
||||
- Qt: Pass logging context through to video proxy thread (fixes mgba.io/i/3095)
|
||||
- Qt: Show maker code and game version in ROM info
|
||||
- Scripting: Add `callbacks:oneshot` for single-call callbacks
|
||||
- Switch: Add bilinear filtering option (closes mgba.io/i/3111)
|
||||
- Vita: Add imc0 and xmc0 mount point support
|
||||
|
|
113
CMakeLists.txt
113
CMakeLists.txt
|
@ -46,11 +46,11 @@ else()
|
|||
endif()
|
||||
|
||||
if(NOT LIBMGBA_ONLY)
|
||||
set(USE_DEBUGGERS ON CACHE BOOL "Whether or not to enable the debugging infrastructure")
|
||||
set(ENABLE_DEBUGGERS ON CACHE BOOL "Whether or not to enable the debugging infrastructure")
|
||||
if (NOT WIN32)
|
||||
set(USE_EDITLINE ON CACHE BOOL "Whether or not to enable the CLI-mode debugger")
|
||||
endif()
|
||||
set(USE_GDB_STUB ON CACHE BOOL "Whether or not to enable the GDB stub ARM debugger")
|
||||
set(ENABLE_GDB_STUB ON CACHE BOOL "Whether or not to enable the GDB stub ARM debugger")
|
||||
set(USE_FFMPEG ON CACHE BOOL "Whether or not to enable FFmpeg support")
|
||||
set(USE_ZLIB ON CACHE BOOL "Whether or not to enable zlib support")
|
||||
set(USE_MINIZIP ON CACHE BOOL "Whether or not to enable external minizip support")
|
||||
|
@ -68,9 +68,6 @@ if(NOT LIBMGBA_ONLY)
|
|||
set(BUILD_QT ON CACHE BOOL "Build Qt frontend")
|
||||
set(BUILD_SDL ON CACHE BOOL "Build SDL frontend")
|
||||
set(BUILD_LIBRETRO OFF CACHE BOOL "Build libretro core")
|
||||
if(APPLE)
|
||||
set(BUILD_OPENEMU OFF CACHE BOOL "Build OpenEmu core")
|
||||
endif()
|
||||
set(BUILD_PERF OFF CACHE BOOL "Build performance profiling tool")
|
||||
set(BUILD_TEST OFF CACHE BOOL "Build testing harness")
|
||||
set(BUILD_SUITE OFF CACHE BOOL "Build test suite")
|
||||
|
@ -80,7 +77,7 @@ if(NOT LIBMGBA_ONLY)
|
|||
set(BUILD_PYTHON OFF CACHE BOOL "Build Python bindings")
|
||||
set(BUILD_STATIC OFF CACHE BOOL "Build a static library")
|
||||
set(BUILD_SHARED ON CACHE BOOL "Build a shared library")
|
||||
set(SKIP_LIBRARY OFF CACHE BOOL "Skip building the library (useful for only building libretro or OpenEmu cores)")
|
||||
set(SKIP_LIBRARY OFF CACHE BOOL "Skip building the library (useful for only building libretro core)")
|
||||
set(BUILD_GL ON CACHE BOOL "Build with OpenGL")
|
||||
set(BUILD_GLES2 ON CACHE BOOL "Build with OpenGL|ES 2")
|
||||
set(BUILD_GLES3 ON CACHE BOOL "Build with OpenGL|ES 3")
|
||||
|
@ -144,11 +141,6 @@ if (BUILD_LIBRETRO)
|
|||
mark_as_advanced(LIBRETRO_LIBDIR)
|
||||
endif()
|
||||
|
||||
if (BUILD_OPENEMU)
|
||||
set(OE_LIBDIR "${LIBDIR}" CACHE PATH "Installed library directory (OpenEmu)")
|
||||
mark_as_advanced(OE_LIBDIR)
|
||||
endif()
|
||||
|
||||
if (DISTBUILD)
|
||||
set(EXTRA_LICENSES "" CACHE FILEPATH "Extra licenses to include in distribution packaages")
|
||||
mark_as_advanced(EXTRA_LICENSES)
|
||||
|
@ -215,6 +207,7 @@ elseif(BUILD_PGO AND PGO_STAGE_2)
|
|||
endif()
|
||||
|
||||
# Platform support
|
||||
set(OS_DEFINES)
|
||||
if(WIN32)
|
||||
set(WIN32_VERSION "${LIB_VERSION_MAJOR},${LIB_VERSION_MINOR},${LIB_VERSION_PATCH}")
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
|
||||
|
@ -228,7 +221,8 @@ if(WIN32)
|
|||
endif()
|
||||
endif()
|
||||
list(APPEND OS_LIB ws2_32 shlwapi)
|
||||
list(APPEND CORE_VFS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/util/vfs/vfs-fd.c ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/windows/vfs-w32.c)
|
||||
list(APPEND OS_DEFINES ENABLE_VFS_FD)
|
||||
list(APPEND VFS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/util/vfs/vfs-fd.c ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/windows/vfs-w32.c)
|
||||
file(GLOB OS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/windows/*.c)
|
||||
source_group("Windows-specific code" FILES ${OS_SRC})
|
||||
elseif(UNIX)
|
||||
|
@ -238,7 +232,8 @@ elseif(UNIX)
|
|||
add_definitions(-D_GNU_SOURCE)
|
||||
endif()
|
||||
|
||||
list(APPEND CORE_VFS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/util/vfs/vfs-fd.c ${CMAKE_CURRENT_SOURCE_DIR}/src/util/vfs/vfs-dirent.c)
|
||||
list(APPEND OS_DEFINES ENABLE_VFS_FD)
|
||||
list(APPEND VFS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/util/vfs/vfs-fd.c ${CMAKE_CURRENT_SOURCE_DIR}/src/util/vfs/vfs-dirent.c)
|
||||
file(GLOB OS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/posix/*.c)
|
||||
source_group("POSIX-specific code" FILES ${OS_SRC})
|
||||
endif()
|
||||
|
@ -277,20 +272,6 @@ if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang" OR
|
|||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELEASE} -gdwarf")
|
||||
endif()
|
||||
|
||||
if(BUILD_BBB OR BUILD_RASPI OR BUILD_PANDORA)
|
||||
if(NOT BUILD_EGL)
|
||||
add_definitions(-DCOLOR_16_BIT -DCOLOR_5_6_5)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(BUILD_RASPI)
|
||||
set(BUILD_GL OFF CACHE BOOL "OpenGL not supported" FORCE)
|
||||
endif()
|
||||
|
||||
if(BUILD_PANDORA)
|
||||
add_definitions(-DBUILD_PANDORA)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm.*")
|
||||
enable_language(ASM)
|
||||
endif()
|
||||
|
@ -301,7 +282,7 @@ endif()
|
|||
|
||||
if(DEFINED 3DS OR DEFINED PSP2 OR DEFINED WII OR DEFINED SWITCH)
|
||||
set(IS_EMBEDDED ON)
|
||||
set(USE_DEBUGGERS OFF)
|
||||
set(ENABLE_DEBUGGERS OFF)
|
||||
set(USE_SQLITE3 OFF)
|
||||
set(USE_DISCORD_RPC OFF)
|
||||
set(USE_LIBZIP OFF CACHE BOOL "")
|
||||
|
@ -313,12 +294,12 @@ if(DEFINED SWITCH)
|
|||
endif()
|
||||
|
||||
if(NOT M_CORE_GBA)
|
||||
set(USE_GDB_STUB OFF)
|
||||
set(ENABLE_GDB_STUB OFF)
|
||||
endif()
|
||||
|
||||
if(NOT USE_DEBUGGERS)
|
||||
if(NOT ENABLE_DEBUGGERS)
|
||||
set(USE_EDITLINE OFF)
|
||||
set(USE_GDB_STUB OFF)
|
||||
set(ENABLE_GDB_STUB OFF)
|
||||
endif()
|
||||
|
||||
if(WII)
|
||||
|
@ -345,22 +326,21 @@ find_function(popcount32)
|
|||
|
||||
find_function(futimens)
|
||||
find_function(futimes)
|
||||
find_function(localtime_r)
|
||||
|
||||
find_function(realpath)
|
||||
|
||||
if(ANDROID AND ANDROID_NDK_MAJOR GREATER 13)
|
||||
find_function(localtime_r)
|
||||
set(HAVE_STRTOF_L ON)
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
find_function(localtime_r)
|
||||
list(APPEND FUNCTION_DEFINES HAVE_STRTOF_L)
|
||||
elseif(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
# The strtof_l on Linux not actually exposed nor actually strtof_l
|
||||
set(HAVE_STRTOF_L OFF)
|
||||
else()
|
||||
find_function(localtime_r)
|
||||
find_function(strtof_l)
|
||||
endif()
|
||||
|
||||
check_include_files("xlocale.h" HAVE_XLOCALE)
|
||||
|
||||
set(ENABLE_VFS ON)
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Generic")
|
||||
if(NOT IS_EMBEDDED)
|
||||
set(DISABLE_DEPS ON CACHE BOOL "This platform cannot build with dependencies" FORCE)
|
||||
|
@ -493,7 +473,7 @@ if(NOT BUILD_GLES2 AND NOT BUILD_GLES3 AND NOT LIBMGBA_ONLY)
|
|||
endif()
|
||||
|
||||
if(DISABLE_DEPS)
|
||||
set(USE_GDB_STUB OFF)
|
||||
set(ENABLE_GDB_STUB OFF)
|
||||
set(USE_DISCORD_RPC OFF)
|
||||
set(USE_JSON_C OFF)
|
||||
set(USE_SQLITE3 OFF)
|
||||
|
@ -545,8 +525,8 @@ else()
|
|||
set(DEBUGGER_LIB "")
|
||||
endif()
|
||||
|
||||
if(USE_GDB_STUB)
|
||||
list(APPEND FEATURES GDB_STUB)
|
||||
if(ENABLE_GDB_STUB)
|
||||
list(APPEND ENABLES GDB_STUB)
|
||||
endif()
|
||||
source_group("Debugger" FILES ${DEBUGGER_SRC})
|
||||
|
||||
|
@ -590,8 +570,6 @@ if(USE_FFMPEG)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
list(APPEND THIRD_PARTY_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/third-party/blip_buf/blip_buf.c")
|
||||
|
||||
if(WANT_ZLIB AND NOT USE_ZLIB)
|
||||
set(SKIP_INSTALL_ALL ON)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/third-party/zlib zlib EXCLUDE_FROM_ALL)
|
||||
|
@ -855,10 +833,10 @@ if(M_CORE_GBA)
|
|||
list(APPEND TEST_SRC ${ARM_TEST_SRC} ${GBA_TEST_SRC})
|
||||
endif()
|
||||
|
||||
if(USE_DEBUGGERS)
|
||||
if(ENABLE_DEBUGGERS)
|
||||
list(APPEND FEATURE_SRC ${DEBUGGER_SRC})
|
||||
list(APPEND TEST_SRC ${DEBUGGER_TEST_SRC})
|
||||
list(APPEND FEATURES DEBUGGERS)
|
||||
list(APPEND ENABLES DEBUGGERS)
|
||||
endif()
|
||||
|
||||
if(ENABLE_SCRIPTING)
|
||||
|
@ -866,6 +844,10 @@ if(ENABLE_SCRIPTING)
|
|||
list(APPEND TEST_SRC ${SCRIPT_TEST_SRC})
|
||||
endif()
|
||||
|
||||
if(ENABLE_VFS)
|
||||
list(APPEND ENABLES VFS)
|
||||
endif()
|
||||
|
||||
foreach(FEATURE IN LISTS FEATURES)
|
||||
list(APPEND FEATURE_DEFINES "USE_${FEATURE}")
|
||||
endforeach()
|
||||
|
@ -879,7 +861,6 @@ source_group("Extra features" FILES ${FEATURE_SRC})
|
|||
source_group("Third-party code" FILES ${THIRD_PARTY_SRC})
|
||||
|
||||
# Platform binaries
|
||||
set(OS_DEFINES)
|
||||
if(DEFINED 3DS)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/platform/3ds ${CMAKE_CURRENT_BINARY_DIR}/3ds)
|
||||
endif()
|
||||
|
@ -904,7 +885,11 @@ list(APPEND CORE_SRC
|
|||
${THIRD_PARTY_SRC})
|
||||
list(APPEND TEST_SRC ${UTIL_TEST_SRC})
|
||||
|
||||
set(SRC ${CORE_SRC} ${VFS_SRC})
|
||||
set(SRC ${CORE_SRC})
|
||||
if(ENABLE_VFS)
|
||||
list(APPEND SRC ${VFS_SRC})
|
||||
endif()
|
||||
|
||||
if(NOT MINIMAL_CORE)
|
||||
set(ENABLE_EXTRA ON)
|
||||
if(M_CORE_GBA)
|
||||
|
@ -936,7 +921,7 @@ if(NOT SKIP_LIBRARY)
|
|||
endif()
|
||||
|
||||
if(BUILD_SHARED)
|
||||
add_library(${BINARY_NAME} SHARED ${SRC} ${VFS_SRC})
|
||||
add_library(${BINARY_NAME} SHARED ${SRC})
|
||||
set(EXPORT_DEFINES MGBA_DLL)
|
||||
if(BUILD_STATIC)
|
||||
add_library(${BINARY_NAME}-static STATIC ${SRC})
|
||||
|
@ -996,9 +981,9 @@ endif()
|
|||
|
||||
if(BUILD_LIBRETRO)
|
||||
file(GLOB RETRO_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/libretro/*.c)
|
||||
add_library(${BINARY_NAME}_libretro SHARED ${CORE_SRC} ${RETRO_SRC})
|
||||
add_library(${BINARY_NAME}_libretro SHARED ${CORE_SRC} ${RETRO_SRC} ${VFS_SRC})
|
||||
add_dependencies(${BINARY_NAME}_libretro ${BINARY_NAME}-version-info)
|
||||
set_target_properties(${BINARY_NAME}_libretro PROPERTIES PREFIX "" COMPILE_DEFINITIONS "__LIBRETRO__;COLOR_16_BIT;COLOR_5_6_5;DISABLE_THREADING;MGBA_STANDALONE;${OS_DEFINES};${FUNCTION_DEFINES};MINIMAL_CORE=2")
|
||||
set_target_properties(${BINARY_NAME}_libretro PROPERTIES PREFIX "" COMPILE_DEFINITIONS "__LIBRETRO__;COLOR_16_BIT;COLOR_5_6_5;DISABLE_THREADING;MGBA_STANDALONE;${OS_DEFINES};${FUNCTION_DEFINES};ENABLE_VFS;MINIMAL_CORE=2")
|
||||
target_link_libraries(${BINARY_NAME}_libretro ${OS_LIB})
|
||||
if(MSVC)
|
||||
install(TARGETS ${BINARY_NAME}_libretro RUNTIME DESTINATION ${LIBRETRO_LIBDIR} COMPONENT ${BINARY_NAME}_libretro)
|
||||
|
@ -1007,23 +992,7 @@ if(BUILD_LIBRETRO)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if(BUILD_OPENEMU)
|
||||
find_library(FOUNDATION Foundation)
|
||||
find_library(OPENEMUBASE OpenEmuBase)
|
||||
file(GLOB OE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/openemu/*.m)
|
||||
add_library(${BINARY_NAME}-openemu MODULE ${CORE_SRC} ${OS_SRC})
|
||||
set_target_properties(${BINARY_NAME}-openemu PROPERTIES
|
||||
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/openemu/Info.plist.in
|
||||
BUNDLE TRUE
|
||||
BUNDLE_EXTENSION oecoreplugin
|
||||
OUTPUT_NAME ${PROJECT_NAME}
|
||||
COMPILE_OPTIONS "-fobjc-arc"
|
||||
COMPILE_DEFINITIONS "DISABLE_THREADING;MGBA_STANDALONE;${OS_DEFINES};${FUNCTION_DEFINES};MINIMAL_CORE=1")
|
||||
target_link_libraries(${BINARY_NAME}-openemu ${OS_LIB} ${FOUNDATION} ${OPENEMUBASE})
|
||||
install(TARGETS ${BINARY_NAME}-openemu LIBRARY DESTINATION ${OE_LIBDIR} COMPONENT ${BINARY_NAME}.oecoreplugin NAMELINK_SKIP)
|
||||
endif()
|
||||
|
||||
if(BUILD_QT AND (WIN32 OR APPLE OR CMAKE_SYSTEM_NAME STREQUAL "Linux"))
|
||||
if(BUILD_QT AND (WIN32 OR APPLE OR CMAKE_SYSTEM_NAME STREQUAL "Linux") AND ENABLE_VFS)
|
||||
set(BUILD_UPDATER ON)
|
||||
endif()
|
||||
|
||||
|
@ -1045,6 +1014,7 @@ endif()
|
|||
if(ENABLE_SCRIPTING AND BUILD_DOCGEN)
|
||||
add_executable(docgen ${CMAKE_CURRENT_SOURCE_DIR}/src/tools/docgen.c)
|
||||
target_link_libraries(docgen ${OS_LIB} ${PLATFORM_LIBRARY} ${BINARY_NAME})
|
||||
set_target_properties(docgen PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FUNCTION_DEFINES};${FEATURE_DEFINES}")
|
||||
endif()
|
||||
|
||||
if(BUILD_MAINTAINER_TOOLS)
|
||||
|
@ -1089,7 +1059,7 @@ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/mgba-util DESTINATION ${CM
|
|||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/mgba/flags.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/mgba COMPONENT ${BINARY_NAME}-dev)
|
||||
|
||||
# Packaging
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/licenses/blip_buf.txt DESTINATION ${CMAKE_INSTALL_DOCDIR}/licenses COMPONENT ${BINARY_NAME})
|
||||
install(FILES DESTINATION ${CMAKE_INSTALL_DOCDIR}/licenses COMPONENT ${BINARY_NAME})
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/licenses/inih.txt DESTINATION ${CMAKE_INSTALL_DOCDIR}/licenses COMPONENT ${BINARY_NAME})
|
||||
if(USE_DISCORD_RPC)
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/licenses/discord-rpc.txt DESTINATION ${CMAKE_INSTALL_DOCDIR}/licenses COMPONENT ${BINARY_NAME})
|
||||
|
@ -1316,11 +1286,11 @@ if(NOT QUIET AND NOT LIBMGBA_ONLY)
|
|||
message(STATUS " Game Boy Advance: ${M_CORE_GBA}")
|
||||
message(STATUS " Game Boy: ${M_CORE_GB}")
|
||||
message(STATUS "Features:")
|
||||
message(STATUS " Debuggers: ${USE_DEBUGGERS}")
|
||||
message(STATUS " Debuggers: ${ENABLE_DEBUGGERS}")
|
||||
if(NOT WIN32)
|
||||
message(STATUS " CLI debugger: ${USE_EDITLINE}")
|
||||
endif()
|
||||
message(STATUS " GDB stub: ${USE_GDB_STUB}")
|
||||
message(STATUS " GDB stub: ${ENABLE_GDB_STUB}")
|
||||
message(STATUS " GIF/Video recording: ${USE_FFMPEG}")
|
||||
message(STATUS " Screenshot/advanced savestate support: ${USE_PNG}")
|
||||
message(STATUS " ZIP support: ${SUMMARY_ZIP}")
|
||||
|
@ -1351,9 +1321,6 @@ if(NOT QUIET AND NOT LIBMGBA_ONLY)
|
|||
message(STATUS " ROM tester: ${BUILD_ROM_TEST}")
|
||||
message(STATUS "Cores:")
|
||||
message(STATUS " Libretro core: ${BUILD_LIBRETRO}")
|
||||
if(APPLE)
|
||||
message(STATUS " OpenEmu core: ${BUILD_OPENEMU}")
|
||||
endif()
|
||||
message(STATUS "Libraries:")
|
||||
message(STATUS " Static: ${BUILD_STATIC}")
|
||||
message(STATUS " Shared: ${BUILD_SHARED}")
|
||||
|
|
|
@ -260,7 +260,6 @@ mGBA is Copyright © 2013 – 2023 Jeffrey Pfau. It is distributed under the [Mo
|
|||
mGBA contains the following third-party libraries:
|
||||
|
||||
- [inih](https://github.com/benhoyt/inih), which is copyright © 2009 – 2020 Ben Hoyt and used under a BSD 3-clause license.
|
||||
- [blip-buf](https://code.google.com/archive/p/blip-buf), which is copyright © 2003 – 2009 Shay Green and used under a Lesser GNU Public License.
|
||||
- [LZMA SDK](http://www.7-zip.org/sdk.html), which is public domain.
|
||||
- [MurmurHash3](https://github.com/aappleby/smhasher) implementation by Austin Appleby, which is public domain.
|
||||
- [getopt for MSVC](https://github.com/skandhurkat/Getopt-for-Visual-Studio/), which is public domain.
|
||||
|
|
|
@ -247,7 +247,6 @@ Copyright für mGBA © 2013 – 2021 Jeffrey Pfau. mGBA wird unter der [Mozilla
|
|||
mGBA beinhaltet die folgenden Bibliotheken von Drittanbietern:
|
||||
|
||||
- [inih](https://github.com/benhoyt/inih), Copyright © 2009 - 2020 Ben Hoyt, verwendet unter einer BSD 3-clause-Lizenz.
|
||||
- [blip-buf](https://code.google.com/archive/b/blip-buf), Copyright © 2003 - 2009 Shay Green, verwendet unter einer Lesser GNU Public License.
|
||||
- [LZMA SDK](http://www.7-zip.org/sdk.html), Public Domain.
|
||||
- [MurmurHash3](https://github.com/aappleby/smhasher), Implementierung von Austin Appleby, Public Domain.
|
||||
- [getopt fot MSVC](https://github.com/skandhurkat/Getopt-for-Visual-Studio/), Public Domain.
|
||||
|
|
|
@ -247,7 +247,6 @@ mGBA es Copyright © 2013 – 2021 Jeffrey Pfau. Es distribuído bajo la [licenc
|
|||
mGBA contiene las siguientes bibliotecas de terceros:
|
||||
|
||||
- [inih](https://github.com/benhoyt/inih), que es copyright © 2009 - 2020 Ben Hoyt y se utiliza bajo licencia de la cláusula 3 de BSD.
|
||||
- [blip-buf](https://code.google.com/archive/p/blip-buf), que es copyright © 2003 - 2009 Shay Green y se usa bajo LGPL.
|
||||
- [LZMA SDK](http://www.7-zip.org/sdk.html), la cual está en el dominio público.
|
||||
- [MurmurHash3](https://github.com/aappleby/smhasher), implementación por Austin Appleby, la cual está en el dominio público.
|
||||
- [getopt for MSVC](https://github.com/skandhurkat/Getopt-for-Visual-Studio/), la cual está en el dominio público.
|
||||
|
|
|
@ -5,7 +5,9 @@ mGBA 是一个运行 Game Boy Advance 游戏的模拟器。mGBA 的目标是比
|
|||
|
||||
可在以下网址找到最新新闻和下载:[mgba.io](https://mgba.io/)。
|
||||
|
||||
[![Build status](https://travis-ci.org/mgba-emu/mgba.svg?branch=master)](https://travis-ci.org/mgba-emu/mgba)
|
||||
[![Build status](https://buildbot.mgba.io/badges/build-win32.svg)](https://buildbot.mgba.io)
|
||||
[![Translation status](https://hosted.weblate.org/widgets/mgba/-/svg-badge.svg)](https://hosted.weblate.org/engage/mgba)
|
||||
|
||||
|
||||
功能
|
||||
--------
|
||||
|
@ -13,7 +15,7 @@ mGBA 是一个运行 Game Boy Advance 游戏的模拟器。mGBA 的目标是比
|
|||
- 支持高精确的 Game Boy Advance 硬件[<sup>[1]</sup>](#missing)。
|
||||
- 支持 Game Boy/Game Boy Color 硬件。
|
||||
- 快速模拟:已知即使在低端硬件(例如上网本)上也能够全速运行。
|
||||
- 用于重型和轻型前端的 Qt 和 SDL 端口。
|
||||
- 可用于重型和轻型前端的 Qt 和 SDL 移植。
|
||||
- 支持本地(同一台计算机)链接电缆。
|
||||
- 存档类型检测,即使是闪存大小也可检测[<sup>[2]</sup>](#flashdetect)。
|
||||
- 支持附带有运动传感器和振动机制的卡带(仅适用于游戏控制器)。
|
||||
|
@ -21,6 +23,7 @@ mGBA 是一个运行 Game Boy Advance 游戏的模拟器。mGBA 的目标是比
|
|||
- 支持《我们的太阳》系列游戏的太阳能传感器。
|
||||
- 支持 Game Boy 相机和 Game Boy 打印机。
|
||||
- 内置 BIOS 执行,并具有加载外部 BIOS 文件的功能。
|
||||
- 支持使用 Lua 编写脚本
|
||||
- 支持 Turbo/快进功能(按住 Tab 键)。
|
||||
- 支持倒带(按住反引号键)。
|
||||
- 支持跳帧,最多可配置 10 级。
|
||||
|
@ -32,10 +35,11 @@ mGBA 是一个运行 Game Boy Advance 游戏的模拟器。mGBA 的目标是比
|
|||
- 可重新映射键盘和游戏手柄的控制键。
|
||||
- 支持从 ZIP 和 7z 文件中加载。
|
||||
- 支持 IPS、UPS 和 BPS 补丁。
|
||||
- 支持通过命令行界面和 GDB 远程支持进行游戏调试,兼容 IDA Pro。
|
||||
- 支持通过命令行界面和 GDB 远程支持进行游戏调试,兼容 Ghidra 和 IDA Pro。
|
||||
- 支持可配置的模拟倒带。
|
||||
- 支持载入和导出 GameShark 和 Action Replay 快照。
|
||||
- 适用于 RetroArch/Libretro 和 OpenEmu 的内核。
|
||||
- 社区支持的多种语言翻译 [Weblate](https://hosted.weblate.org/engage/mgba).
|
||||
- 许许多多的小玩意。
|
||||
|
||||
#### Game Boy 映射器(mapper)
|
||||
|
@ -51,9 +55,10 @@ mGBA 是一个运行 Game Boy Advance 游戏的模拟器。mGBA 的目标是比
|
|||
- MBC5+振动
|
||||
- MBC7
|
||||
- Wisdom Tree(未授权)
|
||||
- NT "old type" 1 and 2 (未授权多合一卡带)
|
||||
- NT "new type" (未授权 MBC5-like)
|
||||
- Pokémon Jade/Diamond(未授权)
|
||||
- BBD(未授权、类 MBC5)
|
||||
- Hitek(未授权、类 MBC5)
|
||||
- Sachen MMC1 (未授权)
|
||||
|
||||
部分支持以下 mapper:
|
||||
|
||||
|
@ -63,6 +68,11 @@ mGBA 是一个运行 Game Boy Advance 游戏的模拟器。mGBA 的目标是比
|
|||
- TAMA5(缺少 RTC 支持)
|
||||
- HuC-1(缺少 IR 支持)
|
||||
- HuC-3(缺少 IR 和 RTC 支持)
|
||||
- Sachen MMC2 (缺少备用接线支持)
|
||||
- BBD (缺少图标切换)
|
||||
- Hitek (缺少图标切换)
|
||||
- GGB-81 (缺少图标切换)
|
||||
- Li Cheng (缺少图标切换)
|
||||
|
||||
### 计划加入的功能
|
||||
|
||||
|
@ -70,7 +80,6 @@ mGBA 是一个运行 Game Boy Advance 游戏的模拟器。mGBA 的目标是比
|
|||
- 支持 Dolphin/JOY 总线链接电缆。
|
||||
- MP2k 音频混合,获得比硬件更高质量的声音。
|
||||
- 支持针对工具辅助竞速(Tool-Assisted Speedrun)的重录功能。
|
||||
- 支持 Lua 脚本。
|
||||
- 全方位的调试套件。
|
||||
- 支持无线适配器。
|
||||
|
||||
|
@ -112,17 +121,19 @@ mGBA 是一个运行 Game Boy Advance 游戏的模拟器。mGBA 的目标是比
|
|||
编译
|
||||
---------
|
||||
|
||||
编译需要使用 CMake 3.1 或更新版本。已知 GCC 和 Clang 都可以编译 mGBA,而 Visual Studio 2013 和更旧的版本则无法编译。我们即将实现对 Visual Studio 2015 或更新版本的支持。
|
||||
编译需要使用 CMake 3.1 或更新版本。已知 GCC , Clang 和 Visual Studio 2013 都可以编译 mGBA。
|
||||
|
||||
#### Docker 构建
|
||||
|
||||
对于大多数平台来说,建议使用 Docker 进行构建。我们提供了多个 Docker 映像,其中包含在多个平台上构建 mGBA 所需的工具链和依赖项。
|
||||
|
||||
注意: 如果你是用的是 Widnows 10 之前的旧版本 Windows 系统, 你可能需要配置你的 Docker 使用 VirtualBox 共享文件夹以正确映射你当前 mGBA 检出目录到 Docker 镜像中的工作目录. 详细细节参见 issue [#1985](https://mgba.io/i/1985)
|
||||
|
||||
要使用 Docker 映像构建 mGBA,只需在 mGBA 的签出(checkout)根目录中运行以下命令:
|
||||
|
||||
docker run --rm -t -v $PWD:/home/mgba/src mgba/windows:w32
|
||||
|
||||
此命令将生成 `build-win32` 目录。将 `mgba/windows:w32` 替换为其他平台上的 Docker 映像,会生成相应的其他目录。Docker Hub 上提供了以下 Docker 映像:
|
||||
启动 Docker 容器之后, 此命令将生成 `build-win32` 目录, 此目录中包含编译产物。将 `mgba/windows:w32` 替换为其他平台上的 Docker 映像,会生成相应的其他目录。Docker Hub 上提供了以下 Docker 映像:
|
||||
|
||||
- mgba/3ds
|
||||
- mgba/switch
|
||||
|
@ -135,6 +146,8 @@ mGBA 是一个运行 Game Boy Advance 游戏的模拟器。mGBA 的目标是比
|
|||
- mgba/windows:w32
|
||||
- mgba/windows:w64
|
||||
|
||||
如果你希望加速编译过程, 可以考虑添加编译选项 `-e MAKEFLAGS=-jN`, 使用 `N` 个 CPU 核心来并行构建 mGBA
|
||||
|
||||
#### *nix 构建
|
||||
|
||||
要在基于 Unix 的系统上使用 CMake 进行构建,推荐执行以下命令:
|
||||
|
@ -147,7 +160,7 @@ mGBA 是一个运行 Game Boy Advance 游戏的模拟器。mGBA 的目标是比
|
|||
|
||||
这些命令将构建 mGBA 并将其安装到 `/usr/bin` 和 `/usr/lib` 中。系统会自动检测已安装的依赖项,如果未找到依赖项,则会在提示找不到依赖项的情况下运行 `cmake` 命令,并显示已被禁用的功能。
|
||||
|
||||
如果您使用的是 MacOS,则步骤略有不同。假设您使用的是自制软件包管理器,建议使用以下命令来获取依赖项并进行构建:
|
||||
如果您使用的是 MacOS,则步骤略有不同。假设您使用的 homebrew 软件包管理器,建议使用以下命令来获取依赖项并进行构建:
|
||||
|
||||
brew install cmake ffmpeg libzip qt5 sdl2 libedit pkg-config
|
||||
mkdir build
|
||||
|
@ -220,10 +233,12 @@ mGBA 没有硬性的依赖项,但是特定功能需要以下可选的依赖项
|
|||
- libzip 或 zlib:载入储存在 ZIP 文件中的 ROM 的所需依赖项。
|
||||
- SQLite3:游戏数据库的所需依赖项
|
||||
- libelf:ELF 载入的所需依赖项
|
||||
- Lua: 脚本支持
|
||||
- json-c: 脚本 `storage` API 支持
|
||||
|
||||
SQLite3、libpng 以及 zlib 已包含在模拟器中,因此不需要先对这些依赖项进行外部编译。
|
||||
|
||||
Footnotes
|
||||
脚注
|
||||
---------
|
||||
|
||||
<a name="missing">[1]</a> 目前缺失的功能有
|
||||
|
@ -232,7 +247,7 @@ Footnotes
|
|||
|
||||
<a name="flashdetect">[2]</a> 闪存大小检测在某些情况下不起作用。 这些可以在运行时中进行配置,但如果遇到此类情况,建议提交错误。
|
||||
|
||||
<a name="osxver">[3]</a> 仅 Qt 端口需要 10.9。应该可以在 10.7 或更早版本上构建或运行 Qt 端口,但这类操作不受官方支持。已知 SDL 端口可以在 10.5 上运行,并且可能能够在旧版本上运行。
|
||||
<a name="osxver">[3]</a> 仅 Qt 移植需要 10.9。应该可以在 10.7 或更早版本上构建或运行 Qt 移植,但这类操作不受官方支持。已知 SDL 移植可以在 10.5 上运行,并且可能能够在旧版本上运行。
|
||||
|
||||
[downloads]: http://mgba.io/downloads.html
|
||||
[source]: https://github.com/mgba-emu/mgba/
|
||||
|
@ -240,12 +255,11 @@ Footnotes
|
|||
版权
|
||||
---------
|
||||
|
||||
mGBA 版权 © 2013 – 2020 Jeffrey Pfau。基于 [Mozilla 公共许可证版本 2.0](https://www.mozilla.org/MPL/2.0/) 许可证分发。分发的 LICENSE 文件中提供了许可证的副本。
|
||||
mGBA 版权 © 2013 – 2023 Jeffrey Pfau。基于 [Mozilla 公共许可证版本 2.0](https://www.mozilla.org/MPL/2.0/) 许可证分发。分发的 LICENSE 文件中提供了许可证的副本。
|
||||
|
||||
mGBA 包含以下第三方库:
|
||||
|
||||
- [inih](https://github.com/benhoyt/inih):版权 © 2009 – 2020 Ben Hoyt,基于 BSD 3-clause 许可证使用。
|
||||
- [blip-buf](https://code.google.com/archive/p/blip-buf):版权 © 2003 – 2009 Shay Green,基于 Lesser GNU 公共许可证使用。
|
||||
- [LZMA SDK](http://www.7-zip.org/sdk.html):属公有领域使用。
|
||||
- [MurmurHash3](https://github.com/aappleby/smhasher):由 Austin Appleby 实施,属公有领域使用。
|
||||
- [getopt for MSVC](https://github.com/skandhurkat/Getopt-for-Visual-Studio/):属公有领域使用。
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/* Copyright (c) 2013-2024 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef M_AUDIO_BUFFER_H
|
||||
#define M_AUDIO_BUFFER_H
|
||||
|
||||
#include <mgba-util/common.h>
|
||||
|
||||
CXX_GUARD_START
|
||||
|
||||
#include <mgba-util/circle-buffer.h>
|
||||
|
||||
struct mAudioBuffer {
|
||||
struct mCircleBuffer data;
|
||||
unsigned channels;
|
||||
};
|
||||
|
||||
void mAudioBufferInit(struct mAudioBuffer* buffer, size_t capacity, unsigned channels);
|
||||
void mAudioBufferDeinit(struct mAudioBuffer* buffer);
|
||||
|
||||
size_t mAudioBufferAvailable(const struct mAudioBuffer* buffer);
|
||||
size_t mAudioBufferCapacity(const struct mAudioBuffer* buffer);
|
||||
|
||||
void mAudioBufferClear(struct mAudioBuffer* buffer);
|
||||
int16_t mAudioBufferPeek(const struct mAudioBuffer* buffer, unsigned channel, size_t offset);
|
||||
size_t mAudioBufferDump(const struct mAudioBuffer* buffer, int16_t* samples, size_t count, size_t offset);
|
||||
size_t mAudioBufferRead(struct mAudioBuffer* buffer, int16_t* samples, size_t count);
|
||||
size_t mAudioBufferWrite(struct mAudioBuffer* buffer, const int16_t* samples, size_t count);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
|
@ -0,0 +1,42 @@
|
|||
/* Copyright (c) 2013-2024 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef M_AUDIO_RESAMPLER_H
|
||||
#define M_AUDIO_RESAMPLER_H
|
||||
|
||||
#include <mgba-util/common.h>
|
||||
|
||||
CXX_GUARD_START
|
||||
|
||||
#include <mgba-util/interpolator.h>
|
||||
|
||||
struct mAudioBuffer;
|
||||
struct mAudioResampler {
|
||||
struct mAudioBuffer* source;
|
||||
struct mAudioBuffer* destination;
|
||||
double sourceRate;
|
||||
double destRate;
|
||||
double timestamp;
|
||||
double lowWaterMark;
|
||||
double highWaterMark;
|
||||
enum mInterpolatorType interpType;
|
||||
union {
|
||||
struct mInterpolator interp;
|
||||
struct mInterpolatorSinc sinc;
|
||||
struct mInterpolatorCosine cosine;
|
||||
};
|
||||
bool consume;
|
||||
};
|
||||
|
||||
void mAudioResamplerInit(struct mAudioResampler*, enum mInterpolatorType);
|
||||
void mAudioResamplerDeinit(struct mAudioResampler*);
|
||||
void mAudioResamplerSetSource(struct mAudioResampler*, struct mAudioBuffer* source, double rate, bool consume);
|
||||
void mAudioResamplerSetDestination(struct mAudioResampler*, struct mAudioBuffer* destination, double rate);
|
||||
size_t mAudioResamplerProcess(struct mAudioResampler*);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
CXX_GUARD_START
|
||||
|
||||
struct CircleBuffer {
|
||||
struct mCircleBuffer {
|
||||
void* data;
|
||||
size_t capacity;
|
||||
size_t size;
|
||||
|
@ -18,20 +18,21 @@ struct CircleBuffer {
|
|||
void* writePtr;
|
||||
};
|
||||
|
||||
void CircleBufferInit(struct CircleBuffer* buffer, unsigned capacity);
|
||||
void CircleBufferDeinit(struct CircleBuffer* buffer);
|
||||
size_t CircleBufferSize(const struct CircleBuffer* buffer);
|
||||
size_t CircleBufferCapacity(const struct CircleBuffer* buffer);
|
||||
void CircleBufferClear(struct CircleBuffer* buffer);
|
||||
int CircleBufferWrite8(struct CircleBuffer* buffer, int8_t value);
|
||||
int CircleBufferWrite16(struct CircleBuffer* buffer, int16_t value);
|
||||
int CircleBufferWrite32(struct CircleBuffer* buffer, int32_t value);
|
||||
size_t CircleBufferWrite(struct CircleBuffer* buffer, const void* input, size_t length);
|
||||
int CircleBufferRead8(struct CircleBuffer* buffer, int8_t* value);
|
||||
int CircleBufferRead16(struct CircleBuffer* buffer, int16_t* value);
|
||||
int CircleBufferRead32(struct CircleBuffer* buffer, int32_t* value);
|
||||
size_t CircleBufferRead(struct CircleBuffer* buffer, void* output, size_t length);
|
||||
size_t CircleBufferDump(const struct CircleBuffer* buffer, void* output, size_t length);
|
||||
void mCircleBufferInit(struct mCircleBuffer* buffer, unsigned capacity);
|
||||
void mCircleBufferDeinit(struct mCircleBuffer* buffer);
|
||||
size_t mCircleBufferSize(const struct mCircleBuffer* buffer);
|
||||
size_t mCircleBufferCapacity(const struct mCircleBuffer* buffer);
|
||||
void mCircleBufferClear(struct mCircleBuffer* buffer);
|
||||
int mCircleBufferWrite8(struct mCircleBuffer* buffer, int8_t value);
|
||||
int mCircleBufferWrite16(struct mCircleBuffer* buffer, int16_t value);
|
||||
int mCircleBufferWrite32(struct mCircleBuffer* buffer, int32_t value);
|
||||
size_t mCircleBufferWrite(struct mCircleBuffer* buffer, const void* input, size_t length);
|
||||
size_t mCircleBufferWriteTruncate(struct mCircleBuffer* buffer, const void* input, size_t length);
|
||||
int mCircleBufferRead8(struct mCircleBuffer* buffer, int8_t* value);
|
||||
int mCircleBufferRead16(struct mCircleBuffer* buffer, int16_t* value);
|
||||
int mCircleBufferRead32(struct mCircleBuffer* buffer, int32_t* value);
|
||||
size_t mCircleBufferRead(struct mCircleBuffer* buffer, void* output, size_t length);
|
||||
size_t mCircleBufferDump(const struct mCircleBuffer* buffer, void* output, size_t length, size_t offset);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
|
|
|
@ -314,6 +314,26 @@ typedef intptr_t ssize_t;
|
|||
|
||||
#define ROR(I, ROTATE) ((((uint32_t) (I)) >> ROTATE) | ((uint32_t) (I) << ((-ROTATE) & 31)))
|
||||
|
||||
#define mASSERT(COND) \
|
||||
if (!(COND)) { \
|
||||
abort(); \
|
||||
}
|
||||
#define mASSERT_DEBUG(COND) assert((COND))
|
||||
|
||||
#define mASSERT_LOG(CAT, COND, ...) \
|
||||
if (!(COND)) { \
|
||||
mLOG(CAT, FATAL, __VA_ARGS__); \
|
||||
}
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define mASSERT_DEBUG_LOG(...)
|
||||
#else
|
||||
#define mASSERT_DEBUG_LOG(CAT, COND, ...) \
|
||||
if (!(COND)) { \
|
||||
mLOG(CAT, FATAL, __VA_ARGS__); \
|
||||
}
|
||||
#endif
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
||||
|
|
|
@ -34,10 +34,12 @@ const char* ConfigurationGetValue(const struct Configuration*, const char* secti
|
|||
|
||||
void ConfigurationClearValue(struct Configuration*, const char* section, const char* key);
|
||||
|
||||
#ifdef ENABLE_VFS
|
||||
bool ConfigurationRead(struct Configuration*, const char* path);
|
||||
bool ConfigurationReadVFile(struct Configuration*, struct VFile* vf);
|
||||
bool ConfigurationWrite(const struct Configuration*, const char* path);
|
||||
bool ConfigurationWriteSection(const struct Configuration*, const char* path, const char* section);
|
||||
#endif
|
||||
bool ConfigurationReadVFile(struct Configuration*, struct VFile* vf);
|
||||
bool ConfigurationWriteVFile(const struct Configuration*, struct VFile* vf);
|
||||
|
||||
void ConfigurationEnumerateSections(const struct Configuration* configuration, void (*handler)(const char* sectionName, void* user), void* user);
|
||||
|
|
|
@ -11,10 +11,10 @@
|
|||
CXX_GUARD_START
|
||||
|
||||
#ifdef COLOR_16_BIT
|
||||
typedef uint16_t color_t;
|
||||
typedef uint16_t mColor;
|
||||
#define BYTES_PER_PIXEL 2
|
||||
#else
|
||||
typedef uint32_t color_t;
|
||||
typedef uint32_t mColor;
|
||||
#define BYTES_PER_PIXEL 4
|
||||
#endif
|
||||
|
||||
|
@ -114,12 +114,16 @@ struct VFile;
|
|||
struct mImage* mImageCreate(unsigned width, unsigned height, enum mColorFormat format);
|
||||
struct mImage* mImageCreateWithStride(unsigned width, unsigned height, unsigned stride, enum mColorFormat format);
|
||||
struct mImage* mImageCreateFromConstBuffer(unsigned width, unsigned height, unsigned stride, enum mColorFormat format, const void* pixels);
|
||||
#ifdef ENABLE_VFS
|
||||
struct mImage* mImageLoad(const char* path);
|
||||
#endif
|
||||
struct mImage* mImageLoadVF(struct VFile* vf);
|
||||
struct mImage* mImageConvertToFormat(const struct mImage*, enum mColorFormat format);
|
||||
void mImageDestroy(struct mImage*);
|
||||
|
||||
#ifdef ENABLE_VFS
|
||||
bool mImageSave(const struct mImage*, const char* path, const char* format);
|
||||
#endif
|
||||
bool mImageSaveVF(const struct mImage*, struct VFile* vf, const char* format);
|
||||
|
||||
uint32_t mImageGetPixel(const struct mImage* image, unsigned x, unsigned y);
|
||||
|
@ -206,18 +210,18 @@ static inline bool mColorFormatHasAlpha(enum mColorFormat format) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static inline color_t mColorFrom555(uint16_t value) {
|
||||
static inline mColor mColorFrom555(uint16_t value) {
|
||||
#ifdef COLOR_16_BIT
|
||||
#ifdef COLOR_5_6_5
|
||||
color_t color = 0;
|
||||
mColor color = 0;
|
||||
color |= (value & 0x001F) << 11;
|
||||
color |= (value & 0x03E0) << 1;
|
||||
color |= (value & 0x7C00) >> 10;
|
||||
#else
|
||||
color_t color = value;
|
||||
mColor color = value;
|
||||
#endif
|
||||
#else
|
||||
color_t color = M_RGB5_TO_BGR8(value);
|
||||
mColor color = M_RGB5_TO_BGR8(value);
|
||||
color |= (color >> 5) & 0x070707;
|
||||
#endif
|
||||
return color;
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/* Copyright (c) 2013-2024 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef M_INTERPOLATOR_H
|
||||
#define M_INTERPOLATOR_H
|
||||
|
||||
#include <mgba-util/common.h>
|
||||
|
||||
CXX_GUARD_START
|
||||
|
||||
enum mInterpolatorType {
|
||||
mINTERPOLATOR_SINC,
|
||||
mINTERPOLATOR_COSINE,
|
||||
};
|
||||
|
||||
struct mInterpolationData {
|
||||
int16_t (*at)(int index, const void* context);
|
||||
void* context;
|
||||
};
|
||||
|
||||
struct mInterpolator {
|
||||
int16_t (*interpolate)(const struct mInterpolator* interp, const struct mInterpolationData* data, double time, double sampleStep);
|
||||
};
|
||||
|
||||
struct mInterpolatorSinc {
|
||||
struct mInterpolator d;
|
||||
|
||||
unsigned resolution;
|
||||
unsigned width;
|
||||
double* sincLut;
|
||||
double* windowLut;
|
||||
};
|
||||
|
||||
struct mInterpolatorCosine {
|
||||
struct mInterpolator d;
|
||||
|
||||
unsigned resolution;
|
||||
double* lut;
|
||||
};
|
||||
|
||||
void mInterpolatorSincInit(struct mInterpolatorSinc* interp, unsigned resolution, unsigned width);
|
||||
void mInterpolatorSincDeinit(struct mInterpolatorSinc* interp);
|
||||
|
||||
void mInterpolatorCosineInit(struct mInterpolatorCosine* interp, unsigned resolution);
|
||||
void mInterpolatorCosineDeinit(struct mInterpolatorCosine* interp);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
|
@ -9,7 +9,7 @@
|
|||
#include <psp2/kernel/threadmgr.h>
|
||||
|
||||
typedef SceUID Thread;
|
||||
typedef SceUID Mutex;
|
||||
typedef SceKernelLwMutexWork Mutex;
|
||||
typedef struct {
|
||||
Mutex mutex;
|
||||
SceUID semaphore;
|
||||
|
@ -20,28 +20,23 @@ typedef THREAD_ENTRY (*ThreadEntry)(void*);
|
|||
#define THREAD_EXIT(RES) return RES
|
||||
|
||||
static inline int MutexInit(Mutex* mutex) {
|
||||
Mutex id = sceKernelCreateMutex("mutex", 0, 0, 0);
|
||||
if (id < 0) {
|
||||
return id;
|
||||
}
|
||||
*mutex = id;
|
||||
return 0;
|
||||
return sceKernelCreateLwMutex(mutex, "mutex", 0, 0, 0);
|
||||
}
|
||||
|
||||
static inline int MutexDeinit(Mutex* mutex) {
|
||||
return sceKernelDeleteMutex(*mutex);
|
||||
return sceKernelDeleteLwMutex(mutex);
|
||||
}
|
||||
|
||||
static inline int MutexLock(Mutex* mutex) {
|
||||
return sceKernelLockMutex(*mutex, 1, 0);
|
||||
return sceKernelLockLwMutex(mutex, 1, 0);
|
||||
}
|
||||
|
||||
static inline int MutexTryLock(Mutex* mutex) {
|
||||
return sceKernelTryLockMutex(*mutex, 1);
|
||||
return sceKernelTryLockLwMutex(mutex, 1);
|
||||
}
|
||||
|
||||
static inline int MutexUnlock(Mutex* mutex) {
|
||||
return sceKernelUnlockMutex(*mutex, 1);
|
||||
return sceKernelUnlockLwMutex(mutex, 1);
|
||||
}
|
||||
|
||||
static inline int ConditionInit(Condition* cond) {
|
||||
|
|
|
@ -234,7 +234,7 @@ static inline Socket SocketOpenTCP(int port, const struct Address* bindAddress)
|
|||
#else
|
||||
err = bind(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo));
|
||||
#endif
|
||||
#if !defined(__3DS__) && !defined(GEKKO)
|
||||
#ifdef HAS_IPV6
|
||||
} else {
|
||||
struct sockaddr_in6 bindInfo;
|
||||
memset(&bindInfo, 0, sizeof(bindInfo));
|
||||
|
@ -333,7 +333,7 @@ static inline Socket SocketAccept(Socket socket, struct Address* address) {
|
|||
#else
|
||||
return accept(socket, (struct sockaddr*) &addrInfo, &len);
|
||||
#endif
|
||||
#if !defined(__3DS__) && !defined(GEKKO)
|
||||
#ifdef HAS_IPV6
|
||||
} else {
|
||||
struct sockaddr_in6 addrInfo;
|
||||
memset(&addrInfo, 0, sizeof(addrInfo));
|
||||
|
|
|
@ -112,6 +112,7 @@ CXX_GUARD_START
|
|||
} \
|
||||
|
||||
DECLARE_VECTOR(IntList, int);
|
||||
DECLARE_VECTOR(UIntList, unsigned);
|
||||
DECLARE_VECTOR(SInt8List, int8_t);
|
||||
DECLARE_VECTOR(SInt16List, int16_t);
|
||||
DECLARE_VECTOR(SInt32List, int32_t);
|
||||
|
|
|
@ -50,6 +50,7 @@ struct VFile {
|
|||
bool (*sync)(struct VFile* vf, void* buffer, size_t size);
|
||||
};
|
||||
|
||||
#ifdef ENABLE_VFS
|
||||
struct VDirEntry {
|
||||
const char* (*name)(struct VDirEntry* vde);
|
||||
enum VFSType (*type)(struct VDirEntry* vde);
|
||||
|
@ -65,17 +66,26 @@ struct VDir {
|
|||
};
|
||||
|
||||
struct VFile* VFileOpen(const char* path, int flags);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_VFS_FD
|
||||
struct VFile* VFileOpenFD(const char* path, int flags);
|
||||
struct VFile* VFileFromFD(int fd);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_VFS_FILE
|
||||
struct VFile* VFileFOpen(const char* path, const char* mode);
|
||||
struct VFile* VFileFromFILE(FILE* file);
|
||||
#endif
|
||||
|
||||
struct VFile* VFileFromMemory(void* mem, size_t size);
|
||||
struct VFile* VFileFromConstMemory(const void* mem, size_t size);
|
||||
struct VFile* VFileMemChunk(const void* mem, size_t size);
|
||||
|
||||
struct CircleBuffer;
|
||||
struct VFile* VFileFIFO(struct CircleBuffer* backing);
|
||||
struct mCircleBuffer;
|
||||
struct VFile* VFileFIFO(struct mCircleBuffer* backing);
|
||||
|
||||
#ifdef ENABLE_VFS
|
||||
struct VDir* VDirOpen(const char* path);
|
||||
struct VDir* VDirOpenArchive(const char* path);
|
||||
|
||||
|
@ -92,10 +102,8 @@ struct VDir* VDeviceList(void);
|
|||
#endif
|
||||
|
||||
bool VDirCreate(const char* path);
|
||||
|
||||
#ifdef USE_VFS_FILE
|
||||
struct VFile* VFileFOpen(const char* path, const char* mode);
|
||||
struct VFile* VFileFromFILE(FILE* file);
|
||||
struct VFile* VDirFindFirst(struct VDir* dir, bool (*filter)(struct VFile*));
|
||||
struct VFile* VDirFindNextAvailable(struct VDir*, const char* basename, const char* infix, const char* suffix, int mode);
|
||||
#endif
|
||||
|
||||
void separatePath(const char* path, char* dirname, char* basename, char* extension);
|
||||
|
@ -103,9 +111,6 @@ void separatePath(const char* path, char* dirname, char* basename, char* extensi
|
|||
bool isAbsolute(const char* path);
|
||||
void makeAbsolute(const char* path, const char* base, char* out);
|
||||
|
||||
struct VFile* VDirFindFirst(struct VDir* dir, bool (*filter)(struct VFile*));
|
||||
struct VFile* VDirFindNextAvailable(struct VDir*, const char* basename, const char* infix, const char* suffix, int mode);
|
||||
|
||||
ssize_t VFileReadline(struct VFile* vf, char* buffer, size_t size);
|
||||
|
||||
ssize_t VFileWrite32LE(struct VFile* vf, int32_t word);
|
||||
|
|
|
@ -29,13 +29,13 @@ struct mBitmapCacheEntry {
|
|||
};
|
||||
|
||||
struct mBitmapCache {
|
||||
color_t* cache;
|
||||
mColor* cache;
|
||||
struct mBitmapCacheEntry* status;
|
||||
|
||||
uint32_t globalPaletteVersion;
|
||||
|
||||
uint8_t* vram;
|
||||
color_t* palette;
|
||||
mColor* palette;
|
||||
|
||||
uint32_t bitsSize;
|
||||
uint32_t bitsStart[2];
|
||||
|
@ -53,11 +53,11 @@ void mBitmapCacheDeinit(struct mBitmapCache* cache);
|
|||
void mBitmapCacheConfigure(struct mBitmapCache* cache, mBitmapCacheConfiguration config);
|
||||
void mBitmapCacheConfigureSystem(struct mBitmapCache* cache, mBitmapCacheSystemInfo config);
|
||||
void mBitmapCacheWriteVRAM(struct mBitmapCache* cache, uint32_t address);
|
||||
void mBitmapCacheWritePalette(struct mBitmapCache* cache, uint32_t entry, color_t color);
|
||||
void mBitmapCacheWritePalette(struct mBitmapCache* cache, uint32_t entry, mColor color);
|
||||
|
||||
void mBitmapCacheCleanRow(struct mBitmapCache* cache, struct mBitmapCacheEntry* entry, unsigned y);
|
||||
bool mBitmapCacheCheckRow(struct mBitmapCache* cache, const struct mBitmapCacheEntry* entry, unsigned y);
|
||||
const color_t* mBitmapCacheGetRow(struct mBitmapCache* cache, unsigned y);
|
||||
const mColor* mBitmapCacheGetRow(struct mBitmapCache* cache, unsigned y);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
/** \file
|
||||
Sample buffer that resamples from input clock rate to output sample rate */
|
||||
|
||||
/* blip_buf 1.1.0 */
|
||||
#ifndef BLIP_BUF_H
|
||||
#define BLIP_BUF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** First parameter of most functions is blip_t*, or const blip_t* if nothing
|
||||
is changed. */
|
||||
typedef struct blip_t blip_t;
|
||||
|
||||
/** Creates new buffer that can hold at most sample_count samples. Sets rates
|
||||
so that there are blip_max_ratio clocks per sample. Returns pointer to new
|
||||
buffer, or NULL if insufficient memory. */
|
||||
blip_t* blip_new( int sample_count );
|
||||
|
||||
/** Sets approximate input clock rate and output sample rate. For every
|
||||
clock_rate input clocks, approximately sample_rate samples are generated. */
|
||||
void blip_set_rates( blip_t*, double clock_rate, double sample_rate );
|
||||
|
||||
enum { /** Maximum clock_rate/sample_rate ratio. For a given sample_rate,
|
||||
clock_rate must not be greater than sample_rate*blip_max_ratio. */
|
||||
blip_max_ratio = 0x100000 };
|
||||
|
||||
/** Clears entire buffer. Afterwards, blip_samples_avail() == 0. */
|
||||
void blip_clear( blip_t* );
|
||||
|
||||
/** Adds positive/negative delta into buffer at specified clock time. */
|
||||
void blip_add_delta( blip_t*, unsigned int clock_time, int delta );
|
||||
|
||||
/** Same as blip_add_delta(), but uses faster, lower-quality synthesis. */
|
||||
void blip_add_delta_fast( blip_t*, unsigned int clock_time, int delta );
|
||||
|
||||
/** Length of time frame, in clocks, needed to make sample_count additional
|
||||
samples available. */
|
||||
int blip_clocks_needed( const blip_t*, int sample_count );
|
||||
|
||||
enum { /** Maximum number of samples that can be generated from one time frame. */
|
||||
blip_max_frame = 4000 };
|
||||
|
||||
/** Makes input clocks before clock_duration available for reading as output
|
||||
samples. Also begins new time frame at clock_duration, so that clock time 0 in
|
||||
the new time frame specifies the same clock as clock_duration in the old time
|
||||
frame specified. Deltas can have been added slightly past clock_duration (up to
|
||||
however many clocks there are in two output samples). */
|
||||
void blip_end_frame( blip_t*, unsigned int clock_duration );
|
||||
|
||||
/** Number of buffered samples available for reading. */
|
||||
int blip_samples_avail( const blip_t* );
|
||||
|
||||
/** Reads and removes at most 'count' samples and writes them to 'out'. If
|
||||
'stereo' is true, writes output to every other element of 'out', allowing easy
|
||||
interleaving of two buffers into a stereo sample stream. Outputs 16-bit signed
|
||||
samples. Returns number of samples actually read. */
|
||||
int blip_read_samples( blip_t*, short out [], int count, int stereo );
|
||||
|
||||
/** Frees buffer. No effect if NULL is passed. */
|
||||
void blip_delete( blip_t* );
|
||||
|
||||
|
||||
/* Deprecated */
|
||||
typedef blip_t blip_buffer_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -31,7 +31,7 @@ void mCacheSetDeinit(struct mCacheSet*);
|
|||
void mCacheSetAssignVRAM(struct mCacheSet*, void* vram);
|
||||
|
||||
void mCacheSetWriteVRAM(struct mCacheSet*, uint32_t address);
|
||||
void mCacheSetWritePalette(struct mCacheSet*, uint32_t entry, color_t color);
|
||||
void mCacheSetWritePalette(struct mCacheSet*, uint32_t entry, mColor color);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ bool mCheatSaveFile(struct mCheatDevice*, struct VFile*);
|
|||
bool mCheatParseLibretroFile(struct mCheatDevice*, struct VFile*);
|
||||
bool mCheatParseEZFChtFile(struct mCheatDevice*, struct VFile*);
|
||||
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
#ifdef ENABLE_VFS
|
||||
void mCheatAutosave(struct mCheatDevice*);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ struct mCoreOptions {
|
|||
void mCoreConfigInit(struct mCoreConfig*, const char* port);
|
||||
void mCoreConfigDeinit(struct mCoreConfig*);
|
||||
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
#ifdef ENABLE_VFS
|
||||
bool mCoreConfigLoad(struct mCoreConfig*);
|
||||
bool mCoreConfigSave(const struct mCoreConfig*);
|
||||
bool mCoreConfigLoadPath(struct mCoreConfig*, const char* path);
|
||||
|
|
|
@ -11,14 +11,14 @@
|
|||
CXX_GUARD_START
|
||||
|
||||
#include <mgba/core/config.h>
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
#ifdef ENABLE_VFS
|
||||
#include <mgba/core/directories.h>
|
||||
#endif
|
||||
#ifndef MINIMAL_CORE
|
||||
#include <mgba/core/input.h>
|
||||
#endif
|
||||
#include <mgba/core/interface.h>
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
#include <mgba/debugger/debugger.h>
|
||||
#endif
|
||||
|
||||
|
@ -32,6 +32,7 @@ enum mCoreChecksumType {
|
|||
mCHECKSUM_CRC32,
|
||||
};
|
||||
|
||||
struct mAudioBuffer;
|
||||
struct mCoreConfig;
|
||||
struct mCoreSync;
|
||||
struct mDebuggerSymbols;
|
||||
|
@ -45,7 +46,7 @@ struct mCore {
|
|||
struct mDebuggerSymbols* symbolTable;
|
||||
struct mVideoLogger* videoLogger;
|
||||
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
#ifdef ENABLE_VFS
|
||||
struct mDirectorySet dirs;
|
||||
#endif
|
||||
#ifndef MINIMAL_CORE
|
||||
|
@ -72,13 +73,14 @@ struct mCore {
|
|||
unsigned (*videoScale)(const struct mCore*);
|
||||
size_t (*screenRegions)(const struct mCore*, const struct mCoreScreenRegion**);
|
||||
|
||||
void (*setVideoBuffer)(struct mCore*, color_t* buffer, size_t stride);
|
||||
void (*setVideoBuffer)(struct mCore*, mColor* buffer, size_t stride);
|
||||
void (*setVideoGLTex)(struct mCore*, unsigned texid);
|
||||
|
||||
void (*getPixels)(struct mCore*, const void** buffer, size_t* stride);
|
||||
void (*putPixels)(struct mCore*, const void* buffer, size_t stride);
|
||||
|
||||
struct blip_t* (*getAudioChannel)(struct mCore*, int ch);
|
||||
unsigned (*audioSampleRate)(const struct mCore*);
|
||||
struct mAudioBuffer* (*getAudioBuffer)(struct mCore*);
|
||||
void (*setAudioBufferSize)(struct mCore*, size_t samples);
|
||||
size_t (*getAudioBufferSize)(struct mCore*);
|
||||
|
||||
|
@ -107,6 +109,8 @@ struct mCore {
|
|||
size_t (*stateSize)(struct mCore*);
|
||||
bool (*loadState)(struct mCore*, const void* state);
|
||||
bool (*saveState)(struct mCore*, void* state);
|
||||
bool (*loadExtraState)(struct mCore*, const struct mStateExtdata*);
|
||||
bool (*saveExtraState)(struct mCore*, struct mStateExtdata*);
|
||||
|
||||
void (*setKeys)(struct mCore*, uint32_t keys);
|
||||
void (*addKeys)(struct mCore*, uint32_t keys);
|
||||
|
@ -117,8 +121,7 @@ struct mCore {
|
|||
int32_t (*frameCycles)(const struct mCore*);
|
||||
int32_t (*frequency)(const struct mCore*);
|
||||
|
||||
void (*getGameTitle)(const struct mCore*, char* title);
|
||||
void (*getGameCode)(const struct mCore*, char* title);
|
||||
void (*getGameInfo)(const struct mCore*, struct mGameInfo* info);
|
||||
|
||||
void (*setPeripheral)(struct mCore*, int type, void*);
|
||||
void* (*getPeripheral)(struct mCore*, int type);
|
||||
|
@ -146,7 +149,7 @@ struct mCore {
|
|||
bool (*readRegister)(const struct mCore*, const char* name, void* out);
|
||||
bool (*writeRegister)(struct mCore*, const char* name, const void* in);
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
bool (*supportsDebuggerType)(struct mCore*, enum mDebuggerType);
|
||||
struct mDebuggerPlatform* (*debuggerPlatform)(struct mCore*);
|
||||
struct CLIDebuggerSystem* (*cliDebuggerSystem)(struct mCore*);
|
||||
|
@ -174,7 +177,7 @@ struct mCore {
|
|||
#endif
|
||||
};
|
||||
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
#ifdef ENABLE_VFS
|
||||
struct mCore* mCoreFind(const char* path);
|
||||
bool mCoreLoadFile(struct mCore* core, const char* path);
|
||||
|
||||
|
@ -216,10 +219,12 @@ void* mCoreGetMemoryBlock(struct mCore* core, uint32_t start, size_t* size);
|
|||
void* mCoreGetMemoryBlockMasked(struct mCore* core, uint32_t start, size_t* size, uint32_t mask);
|
||||
const struct mCoreMemoryBlock* mCoreGetMemoryBlockInfo(struct mCore* core, uint32_t address);
|
||||
|
||||
double mCoreCalculateFramerateRatio(const struct mCore* core, double desiredFrameRate);
|
||||
|
||||
#ifdef USE_ELF
|
||||
struct ELF;
|
||||
bool mCoreLoadELF(struct mCore* core, struct ELF* elf);
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
void mCoreLoadELFSymbols(struct mDebuggerSymbols* symbols, struct ELF*);
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
CXX_GUARD_START
|
||||
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
#ifdef ENABLE_VFS
|
||||
struct VDir;
|
||||
|
||||
struct mDirectorySet {
|
||||
|
|
|
@ -16,12 +16,20 @@ CXX_GUARD_START
|
|||
struct mCore;
|
||||
struct mStateExtdataItem;
|
||||
|
||||
struct blip_t;
|
||||
struct mAudioBuffer;
|
||||
|
||||
enum mCoreFeature {
|
||||
mCORE_FEATURE_OPENGL = 1,
|
||||
};
|
||||
|
||||
struct mGameInfo {
|
||||
char title[17];
|
||||
char system[4];
|
||||
char code[5];
|
||||
char maker[3];
|
||||
uint8_t version;
|
||||
};
|
||||
|
||||
struct mCoreCallbacks {
|
||||
void* context;
|
||||
void (*videoFrameStarted)(void* context);
|
||||
|
@ -39,9 +47,9 @@ DECLARE_VECTOR(mCoreCallbacksList, struct mCoreCallbacks);
|
|||
struct mAVStream {
|
||||
void (*videoDimensionsChanged)(struct mAVStream*, unsigned width, unsigned height);
|
||||
void (*audioRateChanged)(struct mAVStream*, unsigned rate);
|
||||
void (*postVideoFrame)(struct mAVStream*, const color_t* buffer, size_t stride);
|
||||
void (*postVideoFrame)(struct mAVStream*, const mColor* buffer, size_t stride);
|
||||
void (*postAudioFrame)(struct mAVStream*, int16_t left, int16_t right);
|
||||
void (*postAudioBuffer)(struct mAVStream*, struct blip_t* left, struct blip_t* right);
|
||||
void (*postAudioBuffer)(struct mAVStream*, struct mAudioBuffer*);
|
||||
};
|
||||
|
||||
struct mStereoSample {
|
||||
|
@ -110,9 +118,22 @@ struct mRTCGenericState {
|
|||
void mRTCGenericSourceInit(struct mRTCGenericSource* rtc, struct mCore* core);
|
||||
|
||||
struct mRumble {
|
||||
void (*setRumble)(struct mRumble*, int enable);
|
||||
void (*reset)(struct mRumble*, bool enable);
|
||||
void (*setRumble)(struct mRumble*, bool enable, uint32_t sinceLast);
|
||||
void (*integrate)(struct mRumble*, uint32_t period);
|
||||
};
|
||||
|
||||
struct mRumbleIntegrator {
|
||||
struct mRumble d;
|
||||
bool state;
|
||||
uint32_t timeOn;
|
||||
uint32_t totalTime;
|
||||
|
||||
void (*setRumble)(struct mRumbleIntegrator*, float value);
|
||||
};
|
||||
|
||||
void mRumbleIntegratorInit(struct mRumbleIntegrator*);
|
||||
|
||||
struct mCoreChannelInfo {
|
||||
size_t id;
|
||||
const char* internalName;
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
CXX_GUARD_START
|
||||
|
||||
#ifdef ENABLE_VFS
|
||||
|
||||
#include <mgba/core/core.h>
|
||||
#include <mgba-util/vector.h>
|
||||
|
||||
|
@ -48,6 +50,8 @@ void mLibraryAttachGameDB(struct mLibrary* library, const struct NoIntroDB* db);
|
|||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
||||
|
|
|
@ -44,7 +44,7 @@ struct mMapCacheEntry {
|
|||
struct mTileCache;
|
||||
struct mTileCacheEntry;
|
||||
struct mMapCache {
|
||||
color_t* cache;
|
||||
mColor* cache;
|
||||
struct mTileCache* tileCache;
|
||||
struct mMapCacheEntry* status;
|
||||
|
||||
|
@ -75,7 +75,7 @@ bool mMapCacheCheckTile(struct mMapCache* cache, const struct mMapCacheEntry* en
|
|||
void mMapCacheCleanTile(struct mMapCache* cache, struct mMapCacheEntry* entry, unsigned x, unsigned y);
|
||||
|
||||
void mMapCacheCleanRow(struct mMapCache* cache, unsigned y);
|
||||
const color_t* mMapCacheGetRow(struct mMapCache* cache, unsigned y);
|
||||
const mColor* mMapCacheGetRow(struct mMapCache* cache, unsigned y);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
CXX_GUARD_START
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
#include <mgba/debugger/debugger.h>
|
||||
#endif
|
||||
#include <mgba/script/macros.h>
|
||||
|
@ -20,8 +20,6 @@ struct mCore;
|
|||
struct mScriptTextBuffer;
|
||||
mSCRIPT_DECLARE_STRUCT(mCore);
|
||||
mSCRIPT_DECLARE_STRUCT(mLogger);
|
||||
mSCRIPT_DECLARE_STRUCT(mScriptConsole);
|
||||
mSCRIPT_DECLARE_STRUCT(mScriptTextBuffer);
|
||||
|
||||
struct mScriptBridge;
|
||||
struct VFile;
|
||||
|
@ -35,42 +33,26 @@ struct mScriptEngine {
|
|||
void (*run)(struct mScriptEngine*);
|
||||
bool (*lookupSymbol)(struct mScriptEngine*, const char* name, int32_t* out);
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
void (*debuggerEntered)(struct mScriptEngine*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*);
|
||||
#endif
|
||||
};
|
||||
|
||||
struct mScriptTextBuffer {
|
||||
void (*init)(struct mScriptTextBuffer*, const char* name);
|
||||
void (*deinit)(struct mScriptTextBuffer*);
|
||||
|
||||
void (*setName)(struct mScriptTextBuffer*, const char* text);
|
||||
|
||||
uint32_t (*getX)(const struct mScriptTextBuffer*);
|
||||
uint32_t (*getY)(const struct mScriptTextBuffer*);
|
||||
uint32_t (*cols)(const struct mScriptTextBuffer*);
|
||||
uint32_t (*rows)(const struct mScriptTextBuffer*);
|
||||
|
||||
void (*print)(struct mScriptTextBuffer*, const char* text);
|
||||
void (*clear)(struct mScriptTextBuffer*);
|
||||
void (*setSize)(struct mScriptTextBuffer*, uint32_t cols, uint32_t rows);
|
||||
void (*moveCursor)(struct mScriptTextBuffer*, uint32_t x, uint32_t y);
|
||||
void (*advance)(struct mScriptTextBuffer*, int32_t);
|
||||
};
|
||||
|
||||
struct mScriptBridge* mScriptBridgeCreate(void);
|
||||
void mScriptBridgeDestroy(struct mScriptBridge*);
|
||||
|
||||
void mScriptBridgeInstallEngine(struct mScriptBridge*, struct mScriptEngine*);
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
void mScriptBridgeSetDebugger(struct mScriptBridge*, struct mDebugger*);
|
||||
struct mDebugger* mScriptBridgeGetDebugger(struct mScriptBridge*);
|
||||
void mScriptBridgeDebuggerEntered(struct mScriptBridge*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*);
|
||||
#endif
|
||||
|
||||
void mScriptBridgeRun(struct mScriptBridge*);
|
||||
#ifdef ENABLE_VFS
|
||||
bool mScriptBridgeLoadScript(struct mScriptBridge*, const char* name);
|
||||
#endif
|
||||
|
||||
bool mScriptBridgeLookupSymbol(struct mScriptBridge*, const char* name, int32_t* out);
|
||||
|
||||
|
@ -78,13 +60,6 @@ struct mScriptContext;
|
|||
void mScriptContextAttachCore(struct mScriptContext*, struct mCore*);
|
||||
void mScriptContextDetachCore(struct mScriptContext*);
|
||||
|
||||
struct mLogger;
|
||||
void mScriptContextAttachLogger(struct mScriptContext*, struct mLogger*);
|
||||
void mScriptContextDetachLogger(struct mScriptContext*);
|
||||
|
||||
typedef struct mScriptTextBuffer* (*mScriptContextBufferFactory)(void*);
|
||||
void mScriptContextSetTextBufferFactory(struct mScriptContext*, mScriptContextBufferFactory factory, void* cbContext);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,6 +17,8 @@ enum mStateExtdataTag {
|
|||
EXTDATA_CHEATS = 3,
|
||||
EXTDATA_RTC = 4,
|
||||
EXTDATA_SCREENSHOT_DIMENSIONS = 5,
|
||||
EXTDATA_SUBSYSTEM_START = 0x40,
|
||||
EXTDATA_SUBSYSTEM_MAX = 0x7F,
|
||||
EXTDATA_META_TIME = 0x101,
|
||||
EXTDATA_META_CREATOR = 0x102,
|
||||
EXTDATA_MAX
|
||||
|
@ -42,7 +44,7 @@ struct mStateExtdata {
|
|||
void mStateExtdataInit(struct mStateExtdata*);
|
||||
void mStateExtdataDeinit(struct mStateExtdata*);
|
||||
void mStateExtdataPut(struct mStateExtdata*, enum mStateExtdataTag, struct mStateExtdataItem*);
|
||||
bool mStateExtdataGet(struct mStateExtdata*, enum mStateExtdataTag, struct mStateExtdataItem*);
|
||||
bool mStateExtdataGet(const struct mStateExtdata*, enum mStateExtdataTag, struct mStateExtdataItem*);
|
||||
|
||||
struct VFile;
|
||||
bool mStateExtdataSerialize(struct mStateExtdata* extdata, struct VFile* vf);
|
||||
|
|
|
@ -22,6 +22,7 @@ struct mCoreSync {
|
|||
bool audioWait;
|
||||
Condition audioRequiredCond;
|
||||
Mutex audioBufferMutex;
|
||||
size_t audioHighWater;
|
||||
|
||||
float fpsTarget;
|
||||
};
|
||||
|
@ -32,8 +33,8 @@ bool mCoreSyncWaitFrameStart(struct mCoreSync* sync);
|
|||
void mCoreSyncWaitFrameEnd(struct mCoreSync* sync);
|
||||
void mCoreSyncSetVideoSync(struct mCoreSync* sync, bool wait);
|
||||
|
||||
struct blip_t;
|
||||
bool mCoreSyncProduceAudio(struct mCoreSync* sync, const struct blip_t*, size_t samples);
|
||||
struct mAudioBuffer;
|
||||
bool mCoreSyncProduceAudio(struct mCoreSync* sync, const struct mAudioBuffer*);
|
||||
void mCoreSyncLockAudio(struct mCoreSync* sync);
|
||||
void mCoreSyncUnlockAudio(struct mCoreSync* sync);
|
||||
void mCoreSyncConsumeAudio(struct mCoreSync* sync);
|
||||
|
|
|
@ -87,7 +87,8 @@ struct mCoreThreadInternal {
|
|||
int requested;
|
||||
|
||||
Mutex stateMutex;
|
||||
Condition stateCond;
|
||||
Condition stateOnThreadCond;
|
||||
Condition stateOffThreadCond;
|
||||
int interruptDepth;
|
||||
bool frameWasOn;
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ struct mTileCacheEntry {
|
|||
};
|
||||
|
||||
struct mTileCache {
|
||||
color_t* cache;
|
||||
mColor* cache;
|
||||
struct mTileCacheEntry* status;
|
||||
uint32_t* globalPaletteVersion;
|
||||
|
||||
|
@ -39,8 +39,8 @@ struct mTileCache {
|
|||
unsigned bpp;
|
||||
|
||||
uint16_t* vram;
|
||||
color_t* palette;
|
||||
color_t temporaryTile[64];
|
||||
mColor* palette;
|
||||
mColor temporaryTile[64];
|
||||
|
||||
mTileCacheConfiguration config;
|
||||
mTileCacheSystemInfo sysConfig;
|
||||
|
@ -51,11 +51,11 @@ void mTileCacheDeinit(struct mTileCache* cache);
|
|||
void mTileCacheConfigure(struct mTileCache* cache, mTileCacheConfiguration config);
|
||||
void mTileCacheConfigureSystem(struct mTileCache* cache, mTileCacheSystemInfo config, uint32_t tileBase, uint32_t paletteBase);
|
||||
void mTileCacheWriteVRAM(struct mTileCache* cache, uint32_t address);
|
||||
void mTileCacheWritePalette(struct mTileCache* cache, uint32_t entry, color_t color);
|
||||
void mTileCacheWritePalette(struct mTileCache* cache, uint32_t entry, mColor color);
|
||||
|
||||
const color_t* mTileCacheGetTile(struct mTileCache* cache, unsigned tileId, unsigned paletteId);
|
||||
const color_t* mTileCacheGetTileIfDirty(struct mTileCache* cache, struct mTileCacheEntry* entry, unsigned tileId, unsigned paletteId);
|
||||
const color_t* mTileCacheGetPalette(struct mTileCache* cache, unsigned paletteId);
|
||||
const mColor* mTileCacheGetTile(struct mTileCache* cache, unsigned tileId, unsigned paletteId);
|
||||
const mColor* mTileCacheGetTileIfDirty(struct mTileCache* cache, struct mTileCacheEntry* entry, unsigned tileId, unsigned paletteId);
|
||||
const mColor* mTileCacheGetPalette(struct mTileCache* cache, unsigned paletteId);
|
||||
const uint16_t* mTileCacheGetVRAM(struct mTileCache* cache, unsigned tileId);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
|
|
@ -38,6 +38,8 @@ union mVideoBackendCommandData {
|
|||
struct {
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
unsigned maxW;
|
||||
unsigned maxH;
|
||||
} u;
|
||||
const void* image;
|
||||
};
|
||||
|
|
|
@ -48,7 +48,7 @@ struct VideoBackend {
|
|||
void (*layerDimensions)(const struct VideoBackend*, enum VideoLayer, struct mRectangle*);
|
||||
void (*swap)(struct VideoBackend*);
|
||||
void (*clear)(struct VideoBackend*);
|
||||
void (*contextResized)(struct VideoBackend*, unsigned w, unsigned h);
|
||||
void (*contextResized)(struct VideoBackend*, unsigned w, unsigned h, unsigned maxW, unsigned maxH);
|
||||
void (*setImageSize)(struct VideoBackend*, enum VideoLayer, int w, int h);
|
||||
void (*imageSize)(struct VideoBackend*, enum VideoLayer, int* w, int* h);
|
||||
void (*setImage)(struct VideoBackend*, enum VideoLayer, const void* frame);
|
||||
|
|
|
@ -35,6 +35,8 @@ enum mVideoLoggerEvent {
|
|||
LOGGER_EVENT_DEINIT,
|
||||
LOGGER_EVENT_RESET,
|
||||
LOGGER_EVENT_GET_PIXELS,
|
||||
LOGGER_EVENT_LOAD_STATE,
|
||||
LOGGER_EVENT_SAVE_STATE,
|
||||
};
|
||||
|
||||
enum mVideoLoggerInjectionPoint {
|
||||
|
@ -85,6 +87,10 @@ struct mVideoLogger {
|
|||
|
||||
const void* pixelBuffer;
|
||||
size_t pixelStride;
|
||||
|
||||
void* stateBuffer;
|
||||
size_t stateSize;
|
||||
bool stateStatus;
|
||||
};
|
||||
|
||||
void mVideoLoggerRendererCreate(struct mVideoLogger* logger, bool readonly);
|
||||
|
|
|
@ -21,12 +21,12 @@ enum {
|
|||
};
|
||||
|
||||
enum GBASIOMode {
|
||||
SIO_NORMAL_8 = 0,
|
||||
SIO_NORMAL_32 = 1,
|
||||
SIO_MULTI = 2,
|
||||
SIO_UART = 3,
|
||||
SIO_GPIO = 8,
|
||||
SIO_JOYBUS = 12
|
||||
GBA_SIO_NORMAL_8 = 0,
|
||||
GBA_SIO_NORMAL_32 = 1,
|
||||
GBA_SIO_MULTI = 2,
|
||||
GBA_SIO_UART = 3,
|
||||
GBA_SIO_GPIO = 8,
|
||||
GBA_SIO_JOYBUS = 12
|
||||
};
|
||||
|
||||
enum GBASIOJOYCommand {
|
||||
|
@ -139,7 +139,7 @@ struct GBA;
|
|||
void GBACartEReaderQueueCard(struct GBA* gba, const void* data, size_t size);
|
||||
|
||||
struct EReaderScan;
|
||||
#ifdef USE_PNG
|
||||
#if defined(USE_PNG) && defined(ENABLE_VFS)
|
||||
MGBA_EXPORT struct EReaderScan* EReaderScanLoadImagePNG(const char* filename);
|
||||
#endif
|
||||
MGBA_EXPORT struct EReaderScan* EReaderScanLoadImage(const void* pixels, unsigned width, unsigned height, unsigned stride);
|
||||
|
@ -149,7 +149,9 @@ MGBA_EXPORT void EReaderScanDestroy(struct EReaderScan*);
|
|||
|
||||
MGBA_EXPORT bool EReaderScanCard(struct EReaderScan*);
|
||||
MGBA_EXPORT void EReaderScanOutputBitmap(const struct EReaderScan*, void* output, size_t stride);
|
||||
#ifdef ENABLE_VFS
|
||||
MGBA_EXPORT bool EReaderScanSaveRaw(const struct EReaderScan*, const char* filename, bool strict);
|
||||
#endif
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
|
|
|
@ -134,6 +134,12 @@ struct ARMMemory {
|
|||
void (*setActiveRegion)(struct ARMCore*, uint32_t address);
|
||||
};
|
||||
|
||||
struct ARMCoprocessor {
|
||||
int32_t (*mrc)(struct ARMCore*, int crn, int crm, int opcode1, int opcode2);
|
||||
void (*mcr)(struct ARMCore*, int crn, int crm, int opcode1, int opcode2, int32_t value);
|
||||
void (*cdp)(struct ARMCore*, int crn, int crm, int crd, int opcode1, int opcode2);
|
||||
};
|
||||
|
||||
struct ARMInterruptHandler {
|
||||
void (*reset)(struct ARMCore* cpu);
|
||||
void (*processEvents)(struct ARMCore* cpu);
|
||||
|
@ -179,6 +185,7 @@ struct ARMCore {
|
|||
|
||||
struct ARMMemory memory;
|
||||
struct ARMInterruptHandler irqh;
|
||||
struct ARMCoprocessor cp[16];
|
||||
|
||||
struct mCPUComponent* master;
|
||||
|
||||
|
|
|
@ -221,7 +221,7 @@ bool ARMDecodeThumbCombine(struct ARMInstructionInfo* info1, struct ARMInstructi
|
|||
struct ARMInstructionInfo* out);
|
||||
uint32_t ARMResolveMemoryAccess(struct ARMInstructionInfo* info, struct ARMRegisterFile* regs, uint32_t pc);
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
struct mDebuggerSymbols;
|
||||
int ARMDisassemble(const struct ARMInstructionInfo* info, struct ARMCore* core, const struct mDebuggerSymbols* symbols, uint32_t pc, char* buffer, int blen);
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2013-2014 Jeffrey Pfau
|
||||
/* Copyright (c) 2013-2024 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
|
@ -67,269 +67,270 @@
|
|||
DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME)), \
|
||||
DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME))
|
||||
|
||||
#define DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, NAME1, NAME2) \
|
||||
DO_8(DO_8(DO_INTERLACE(DECLARE_INSTRUCTION_ARM(EMITTER, NAME1), DECLARE_INSTRUCTION_ARM(EMITTER, NAME2))))
|
||||
#define DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, NAME1, NAME2, NAME3) \
|
||||
DO_8(DO_INTERLACE( \
|
||||
DO_8(DO_INTERLACE(DECLARE_INSTRUCTION_ARM(EMITTER, NAME1), DECLARE_INSTRUCTION_ARM(EMITTER, NAME2))), \
|
||||
DO_8(DO_INTERLACE(DECLARE_INSTRUCTION_ARM(EMITTER, NAME1), DECLARE_INSTRUCTION_ARM(EMITTER, NAME3)))))
|
||||
|
||||
#define DECLARE_ARM_SWI_BLOCK(EMITTER) \
|
||||
DO_256(DECLARE_INSTRUCTION_ARM(EMITTER, SWI))
|
||||
|
||||
#define DECLARE_ARM_EMITTER_BLOCK(EMITTER) \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, AND, MUL, STRH, ILL, ILL), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, ANDS, MULS, LDRH, LDRSB, LDRSH), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, EOR, MLA, STRH, ILL, ILL), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, EORS, MLAS, LDRH, LDRSB, LDRSH), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, SUB, ILL, STRHI, ILL, ILL), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, SUBS, ILL, LDRHI, LDRSBI, LDRSHI), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, RSB, ILL, STRHI, ILL, ILL), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, RSBS, ILL, LDRHI, LDRSBI, LDRSHI), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, ADD, UMULL, STRHU, ILL, ILL), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, ADDS, UMULLS, LDRHU, LDRSBU, LDRSHU), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, ADC, UMLAL, STRHU, ILL, ILL), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, ADCS, UMLALS, LDRHU, LDRSBU, LDRSHU), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, SBC, SMULL, STRHIU, ILL, ILL), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, SBCS, SMULLS, LDRHIU, LDRSBIU, LDRSHIU), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, RSC, SMLAL, STRHIU, ILL, ILL), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, RSCS, SMLALS, LDRHIU, LDRSBIU, LDRSHIU), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, MRS), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, SWP), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, STRHP), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, TST, ILL, LDRHP, LDRSBP, LDRSHP), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, MSR), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, BX), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, BKPT), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, STRHPW), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, TEQ, ILL, LDRHPW, LDRSBPW, LDRSHPW), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, MRSR), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, SWPB), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, STRHIP), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, CMP, ILL, LDRHIP, LDRSBIP, LDRSHIP), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, MSRR), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, STRHIPW), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, CMN, ILL, LDRHIPW, LDRSBIPW, LDRSHIPW), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, ORR, SMLAL, STRHPU, ILL, ILL), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, ORRS, SMLALS, LDRHPU, LDRSBPU, LDRSHPU), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, MOV, SMLAL, STRHPUW, ILL, ILL), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, MOVS, SMLALS, LDRHPUW, LDRSBPUW, LDRSHPUW), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, BIC, SMLAL, STRHIPU, ILL, ILL), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, BICS, SMLALS, LDRHIPU, LDRSBIPU, LDRSHIPU), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, MVN, SMLAL, STRHIPUW, ILL, ILL), \
|
||||
DECLARE_ARM_ALU_BLOCK(EMITTER, MVNS, SMLALS, LDRHIPUW, LDRSBIPUW, LDRSHIPUW), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, AND), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ANDS), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, EOR), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, EORS), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SUB), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SUBS), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSB), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSBS), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADD), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADDS), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADC), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADCS), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SBC), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SBCS), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSC), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSCS), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, TST), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, TST), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MSR), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, TEQ), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, CMP), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, CMP), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MSRR), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, CMN), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ORR), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ORRS), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MOV), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MOVS), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, BIC), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, BICS), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MVN), \
|
||||
DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MVNS), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, , , ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, , , ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRT, , , ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRT, , , ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, , , ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, , , ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRBT, , , ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRBT, , , ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, , U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, , U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRT, , U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRT, , U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, , U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, , U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRBT, , U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRBT, , U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, , ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, , ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, , W), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, , W), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, , ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, , ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, , W), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, , W), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, U, W), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, U, W), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, U, W), \
|
||||
DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, U, W), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, , , ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, , , ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRT, , , ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRT, , , ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, , , ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, , , ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRBT, , , ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRBT, , , ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, , U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, , U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRT, , U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRT, , U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, , U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, , U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRBT, , U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRBT, , U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, , ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, , ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, , W), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, , W), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, , ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, , ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, , W), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, , W), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, U, W), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, U, W), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, U, ), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, U, W), \
|
||||
DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, U, W), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DA, ), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DA, ), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DA, W), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DA, W), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DA, ), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DA, ), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DA, W), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DA, W), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IA, ), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IA, ), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IA, W), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IA, W), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IA, ), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IA, ), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IA, W), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IA, W), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DB, ), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DB, ), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DB, W), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DB, W), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DB, ), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DB, ), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DB, W), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DB, W), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IB, ), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IB, ), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IB, W), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IB, W), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IB, ), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IB, ), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IB, W), \
|
||||
DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IB, W), \
|
||||
DECLARE_ARM_BRANCH_BLOCK(EMITTER, B), \
|
||||
DECLARE_ARM_BRANCH_BLOCK(EMITTER, BL), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , , ), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , , ), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , , W), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , , W), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , N, ), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , N, ), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , N, W), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , N, W), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, , ), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, , ), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, , W), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, , W), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, N, ), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, N, ), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, N, W), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, N, W), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , , ), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , , ), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , , W), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , , W), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, ), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, ), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, W), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, W), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , N, ), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , N, ), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , N, W), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , N, W), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, ), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, ), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, W), \
|
||||
DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, W), \
|
||||
DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, CDP, MCR), \
|
||||
DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, CDP, MRC), \
|
||||
DECLARE_ARM_SWI_BLOCK(EMITTER)
|
||||
/* -00---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, AND, MUL, STRH, ILL, ILL), \
|
||||
/* -01---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, ANDS, MULS, LDRH, LDRSB, LDRSH), \
|
||||
/* -02---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, EOR, MLA, STRH, ILL, ILL), \
|
||||
/* -03---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, EORS, MLAS, LDRH, LDRSB, LDRSH), \
|
||||
/* -04---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, SUB, ILL, STRHI, ILL, ILL), \
|
||||
/* -05---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, SUBS, ILL, LDRHI, LDRSBI, LDRSHI), \
|
||||
/* -06---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, RSB, ILL, STRHI, ILL, ILL), \
|
||||
/* -07---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, RSBS, ILL, LDRHI, LDRSBI, LDRSHI), \
|
||||
/* -08---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, ADD, UMULL, STRHU, ILL, ILL), \
|
||||
/* -09---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, ADDS, UMULLS, LDRHU, LDRSBU, LDRSHU), \
|
||||
/* -0A---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, ADC, UMLAL, STRHU, ILL, ILL), \
|
||||
/* -0B---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, ADCS, UMLALS, LDRHU, LDRSBU, LDRSHU), \
|
||||
/* -0C---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, SBC, SMULL, STRHIU, ILL, ILL), \
|
||||
/* -0D---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, SBCS, SMULLS, LDRHIU, LDRSBIU, LDRSHIU), \
|
||||
/* -0E---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, RSC, SMLAL, STRHIU, ILL, ILL), \
|
||||
/* -0F---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, RSCS, SMLALS, LDRHIU, LDRSBIU, LDRSHIU), \
|
||||
/* -10---0- */ DECLARE_INSTRUCTION_ARM(EMITTER, MRS), \
|
||||
/* -10---1- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -10---2- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -10---3- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -10---4- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -10---5- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -10---6- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -10---7- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -10---8- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -10---9- */ DECLARE_INSTRUCTION_ARM(EMITTER, SWP), \
|
||||
/* -10---A- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -10---B- */ DECLARE_INSTRUCTION_ARM(EMITTER, STRHP), \
|
||||
/* -10---C- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -10---D- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -10---E- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -10---F- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -11---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, TST, ILL, LDRHP, LDRSBP, LDRSHP), \
|
||||
/* -12---0- */ DECLARE_INSTRUCTION_ARM(EMITTER, MSR), \
|
||||
/* -12---1- */ DECLARE_INSTRUCTION_ARM(EMITTER, BX), \
|
||||
/* -12---2- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -12---3- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -12---4- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -12---5- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -12---6- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -12---7- */ DECLARE_INSTRUCTION_ARM(EMITTER, BKPT), \
|
||||
/* -12---8- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -12---9- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -12---A- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -12---B- */ DECLARE_INSTRUCTION_ARM(EMITTER, STRHPW), \
|
||||
/* -12---C- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -12---D- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -12---E- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -12---F- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -13---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, TEQ, ILL, LDRHPW, LDRSBPW, LDRSHPW), \
|
||||
/* -14---0- */ DECLARE_INSTRUCTION_ARM(EMITTER, MRSR), \
|
||||
/* -14---1- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -14---2- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -14---3- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -14---4- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -14---5- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -14---6- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -14---7- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -14---8- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -14---9- */ DECLARE_INSTRUCTION_ARM(EMITTER, SWPB), \
|
||||
/* -14---A- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -14---B- */ DECLARE_INSTRUCTION_ARM(EMITTER, STRHIP), \
|
||||
/* -14---C- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -14---D- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -14---E- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -14---F- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -15---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, CMP, ILL, LDRHIP, LDRSBIP, LDRSHIP), \
|
||||
/* -16---0- */ DECLARE_INSTRUCTION_ARM(EMITTER, MSRR), \
|
||||
/* -16---1- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -16---2- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -16---3- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -16---4- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -16---5- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -16---6- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -16---7- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -16---8- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -16---9- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -16---A- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -16---B- */ DECLARE_INSTRUCTION_ARM(EMITTER, STRHIPW), \
|
||||
/* -16---C- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -16---D- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -16---E- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -16---F- */ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
|
||||
/* -17---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, CMN, ILL, LDRHIPW, LDRSBIPW, LDRSHIPW), \
|
||||
/* -18---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, ORR, SMLAL, STRHPU, ILL, ILL), \
|
||||
/* -19---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, ORRS, SMLALS, LDRHPU, LDRSBPU, LDRSHPU), \
|
||||
/* -1A---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, MOV, SMLAL, STRHPUW, ILL, ILL), \
|
||||
/* -1B---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, MOVS, SMLALS, LDRHPUW, LDRSBPUW, LDRSHPUW), \
|
||||
/* -1C---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, BIC, SMLAL, STRHIPU, ILL, ILL), \
|
||||
/* -1D---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, BICS, SMLALS, LDRHIPU, LDRSBIPU, LDRSHIPU), \
|
||||
/* -1E---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, MVN, SMLAL, STRHIPUW, ILL, ILL), \
|
||||
/* -1F---X- */ DECLARE_ARM_ALU_BLOCK(EMITTER, MVNS, SMLALS, LDRHIPUW, LDRSBIPUW, LDRSHIPUW), \
|
||||
/* -20---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, AND), \
|
||||
/* -21---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ANDS), \
|
||||
/* -22---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, EOR), \
|
||||
/* -23---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, EORS), \
|
||||
/* -24---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SUB), \
|
||||
/* -25---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SUBS), \
|
||||
/* -26---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSB), \
|
||||
/* -27---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSBS), \
|
||||
/* -28---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADD), \
|
||||
/* -29---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADDS), \
|
||||
/* -2A---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADC), \
|
||||
/* -2B---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADCS), \
|
||||
/* -2C---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SBC), \
|
||||
/* -2D---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SBCS), \
|
||||
/* -2E---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSC), \
|
||||
/* -2F---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSCS), \
|
||||
/* -30---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, TST), \
|
||||
/* -31---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, TST), \
|
||||
/* -32---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MSR), \
|
||||
/* -33---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, TEQ), \
|
||||
/* -34---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, CMP), \
|
||||
/* -35---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, CMP), \
|
||||
/* -36---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MSRR), \
|
||||
/* -37---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, CMN), \
|
||||
/* -38---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ORR), \
|
||||
/* -39---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ORRS), \
|
||||
/* -3A---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MOV), \
|
||||
/* -3B---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MOVS), \
|
||||
/* -3C---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, BIC), \
|
||||
/* -3D---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, BICS), \
|
||||
/* -3E---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MVN), \
|
||||
/* -3F---X- */ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MVNS), \
|
||||
/* -40---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, , , ), \
|
||||
/* -41---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, , , ), \
|
||||
/* -42---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRT, , , ), \
|
||||
/* -43---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRT, , , ), \
|
||||
/* -44---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, , , ), \
|
||||
/* -45---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, , , ), \
|
||||
/* -46---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRBT, , , ), \
|
||||
/* -47---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRBT, , , ), \
|
||||
/* -48---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, , U, ), \
|
||||
/* -49---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, , U, ), \
|
||||
/* -4A---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRT, , U, ), \
|
||||
/* -4B---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRT, , U, ), \
|
||||
/* -4C---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, , U, ), \
|
||||
/* -4D---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, , U, ), \
|
||||
/* -4E---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRBT, , U, ), \
|
||||
/* -4F---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRBT, , U, ), \
|
||||
/* -50---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, , ), \
|
||||
/* -51---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, , ), \
|
||||
/* -52---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, , W), \
|
||||
/* -53---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, , W), \
|
||||
/* -54---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, , ), \
|
||||
/* -55---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, , ), \
|
||||
/* -56---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, , W), \
|
||||
/* -57---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, , W), \
|
||||
/* -58---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, U, ), \
|
||||
/* -59---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, U, ), \
|
||||
/* -5A---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, U, W), \
|
||||
/* -5B---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, U, W), \
|
||||
/* -5C---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, U, ), \
|
||||
/* -5D---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, U, ), \
|
||||
/* -5E---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, U, W), \
|
||||
/* -5F---X- */ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, U, W), \
|
||||
/* -60---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, , , ), \
|
||||
/* -61---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, , , ), \
|
||||
/* -62---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRT, , , ), \
|
||||
/* -63---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRT, , , ), \
|
||||
/* -64---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, , , ), \
|
||||
/* -65---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, , , ), \
|
||||
/* -66---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRBT, , , ), \
|
||||
/* -67---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRBT, , , ), \
|
||||
/* -68---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, , U, ), \
|
||||
/* -69---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, , U, ), \
|
||||
/* -6A---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRT, , U, ), \
|
||||
/* -6B---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRT, , U, ), \
|
||||
/* -6C---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, , U, ), \
|
||||
/* -6D---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, , U, ), \
|
||||
/* -6E---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRBT, , U, ), \
|
||||
/* -6F---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRBT, , U, ), \
|
||||
/* -70---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, , ), \
|
||||
/* -71---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, , ), \
|
||||
/* -72---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, , W), \
|
||||
/* -73---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, , W), \
|
||||
/* -74---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, , ), \
|
||||
/* -75---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, , ), \
|
||||
/* -76---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, , W), \
|
||||
/* -77---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, , W), \
|
||||
/* -78---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, U, ), \
|
||||
/* -79---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, U, ), \
|
||||
/* -7A---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, U, W), \
|
||||
/* -7B---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, U, W), \
|
||||
/* -7C---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, U, ), \
|
||||
/* -7D---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, U, ), \
|
||||
/* -7E---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, U, W), \
|
||||
/* -7F---X- */ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, U, W), \
|
||||
/* -80---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DA, ), \
|
||||
/* -81---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DA, ), \
|
||||
/* -82---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DA, W), \
|
||||
/* -83---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DA, W), \
|
||||
/* -84---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DA, ), \
|
||||
/* -85---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DA, ), \
|
||||
/* -86---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DA, W), \
|
||||
/* -87---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DA, W), \
|
||||
/* -88---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IA, ), \
|
||||
/* -89---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IA, ), \
|
||||
/* -8A---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IA, W), \
|
||||
/* -8B---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IA, W), \
|
||||
/* -8C---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IA, ), \
|
||||
/* -8D---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IA, ), \
|
||||
/* -8E---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IA, W), \
|
||||
/* -8F---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IA, W), \
|
||||
/* -90---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DB, ), \
|
||||
/* -91---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DB, ), \
|
||||
/* -92---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DB, W), \
|
||||
/* -93---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DB, W), \
|
||||
/* -94---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DB, ), \
|
||||
/* -95---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DB, ), \
|
||||
/* -96---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DB, W), \
|
||||
/* -97---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DB, W), \
|
||||
/* -98---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IB, ), \
|
||||
/* -99---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IB, ), \
|
||||
/* -9A---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IB, W), \
|
||||
/* -9B---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IB, W), \
|
||||
/* -9C---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IB, ), \
|
||||
/* -9D---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IB, ), \
|
||||
/* -9E---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IB, W), \
|
||||
/* -9F---X- */ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IB, W), \
|
||||
/* -AX---X- */ DECLARE_ARM_BRANCH_BLOCK(EMITTER, B), \
|
||||
/* -BX---X- */ DECLARE_ARM_BRANCH_BLOCK(EMITTER, BL), \
|
||||
/* -C0---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , , ), \
|
||||
/* -C1---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , , ), \
|
||||
/* -C2---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , , W), \
|
||||
/* -C3---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , , W), \
|
||||
/* -C4---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , N, ), \
|
||||
/* -C5---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , N, ), \
|
||||
/* -C6---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , N, W), \
|
||||
/* -C7---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , N, W), \
|
||||
/* -C8---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, , ), \
|
||||
/* -C9---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, , ), \
|
||||
/* -CA---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, , W), \
|
||||
/* -CB---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, , W), \
|
||||
/* -CC---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, N, ), \
|
||||
/* -CD---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, N, ), \
|
||||
/* -CE---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, N, W), \
|
||||
/* -CF---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, N, W), \
|
||||
/* -D0---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , , ), \
|
||||
/* -D1---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , , ), \
|
||||
/* -D2---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , , W), \
|
||||
/* -D3---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , , W), \
|
||||
/* -D4---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, ), \
|
||||
/* -D5---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, ), \
|
||||
/* -D6---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, W), \
|
||||
/* -D7---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, W), \
|
||||
/* -D8---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , N, ), \
|
||||
/* -D9---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , N, ), \
|
||||
/* -DA---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , N, W), \
|
||||
/* -DB---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , N, W), \
|
||||
/* -DC---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, ), \
|
||||
/* -DD---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, ), \
|
||||
/* -DE---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, W), \
|
||||
/* -DF---X- */ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, W), \
|
||||
/* -EX---X- */ DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, CDP, MCR, MRC), \
|
||||
/* -FX---X- */ DECLARE_ARM_SWI_BLOCK(EMITTER)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,6 +12,7 @@ CXX_GUARD_START
|
|||
|
||||
#include <mgba/core/interface.h>
|
||||
#include <mgba/core/timing.h>
|
||||
#include <mgba-util/audio-buffer.h>
|
||||
|
||||
#define GB_MAX_SAMPLES 32
|
||||
|
||||
|
@ -166,14 +167,9 @@ struct GBAudio {
|
|||
struct GBAudioWaveChannel ch3;
|
||||
struct GBAudioNoiseChannel ch4;
|
||||
|
||||
struct blip_t* left;
|
||||
struct blip_t* right;
|
||||
int16_t lastLeft;
|
||||
int16_t lastRight;
|
||||
struct mAudioBuffer buffer;
|
||||
int32_t capLeft;
|
||||
int32_t capRight;
|
||||
int clock;
|
||||
int32_t clockRate;
|
||||
|
||||
uint8_t volumeRight;
|
||||
uint8_t volumeLeft;
|
||||
|
|
|
@ -190,8 +190,7 @@ void GBSavedataUnmask(struct GB* gb);
|
|||
struct Patch;
|
||||
void GBApplyPatch(struct GB* gb, struct Patch* patch);
|
||||
|
||||
void GBGetGameTitle(const struct GB* gba, char* out);
|
||||
void GBGetGameCode(const struct GB* gba, char* out);
|
||||
void GBGetGameInfo(const struct GB* gba, struct mGameInfo* info);
|
||||
|
||||
void GBTestKeypadIRQ(struct GB* gb);
|
||||
|
||||
|
|
|
@ -339,6 +339,7 @@ struct GBMemory {
|
|||
struct mRTCSource* rtc;
|
||||
struct mRotationSource* rotation;
|
||||
struct mRumble* rumble;
|
||||
int32_t lastRumble;
|
||||
struct mImageSource* cam;
|
||||
};
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ struct GBVideoProxyRenderer {
|
|||
enum GBModel model;
|
||||
};
|
||||
|
||||
void GBVideoProxyRendererCreate(struct GBVideoProxyRenderer* renderer, struct GBVideoRenderer* backend);
|
||||
void GBVideoProxyRendererCreate(struct GBVideoProxyRenderer* renderer, struct GBVideoRenderer* backend, struct mVideoLogger* logger);
|
||||
void GBVideoProxyRendererShim(struct GBVideo* video, struct GBVideoProxyRenderer* renderer);
|
||||
void GBVideoProxyRendererUnshim(struct GBVideo* video, struct GBVideoProxyRenderer* renderer);
|
||||
|
||||
|
|
|
@ -22,13 +22,13 @@ struct GBVideoRendererSprite {
|
|||
struct GBVideoSoftwareRenderer {
|
||||
struct GBVideoRenderer d;
|
||||
|
||||
color_t* outputBuffer;
|
||||
mColor* outputBuffer;
|
||||
int outputBufferStride;
|
||||
|
||||
// TODO: Implement the pixel FIFO
|
||||
uint16_t row[GB_VIDEO_HORIZONTAL_PIXELS + 8];
|
||||
|
||||
color_t palette[192];
|
||||
mColor palette[192];
|
||||
uint8_t lookup[192];
|
||||
|
||||
uint32_t* temporaryBuffer;
|
||||
|
|
|
@ -109,7 +109,7 @@ struct GBVideoRenderer {
|
|||
bool highlightBG;
|
||||
bool highlightOBJ[GB_VIDEO_MAX_OBJ];
|
||||
bool highlightWIN;
|
||||
color_t highlightColor;
|
||||
mColor highlightColor;
|
||||
uint8_t highlightAmount;
|
||||
};
|
||||
|
||||
|
|
|
@ -56,7 +56,6 @@ DECL_BITFIELD(GBARegisterSOUNDBIAS, uint16_t);
|
|||
DECL_BITS(GBARegisterSOUNDBIAS, Bias, 0, 10);
|
||||
DECL_BITS(GBARegisterSOUNDBIAS, Resolution, 14, 2);
|
||||
|
||||
struct GBAAudioMixer;
|
||||
struct GBAAudio {
|
||||
struct GBA* p;
|
||||
|
||||
|
@ -64,10 +63,6 @@ struct GBAAudio {
|
|||
struct GBAAudioFIFO chA;
|
||||
struct GBAAudioFIFO chB;
|
||||
|
||||
int16_t lastLeft;
|
||||
int16_t lastRight;
|
||||
int clock;
|
||||
|
||||
uint8_t volume;
|
||||
bool volumeChA;
|
||||
bool volumeChB;
|
||||
|
@ -82,12 +77,10 @@ struct GBAAudio {
|
|||
size_t samples;
|
||||
GBARegisterSOUNDBIAS soundbias;
|
||||
|
||||
struct GBAAudioMixer* mixer;
|
||||
bool externalMixing;
|
||||
int32_t sampleInterval;
|
||||
|
||||
int32_t lastSample;
|
||||
int sampleIndex;
|
||||
unsigned sampleIndex;
|
||||
struct mStereoSample currentSamples[GBA_MAX_SAMPLES];
|
||||
|
||||
bool forceDisableChA;
|
||||
|
@ -253,32 +246,12 @@ struct GBAMP2kTrack {
|
|||
struct GBAMP2kMusicPlayerTrack track;
|
||||
struct GBAMP2kSoundChannel* channel;
|
||||
uint8_t lastCommand;
|
||||
struct CircleBuffer buffer;
|
||||
struct mCircleBuffer buffer;
|
||||
uint32_t samplePlaying;
|
||||
float currentOffset;
|
||||
bool waiting;
|
||||
};
|
||||
|
||||
struct GBAAudioMixer {
|
||||
struct mCPUComponent d;
|
||||
struct GBAAudio* p;
|
||||
|
||||
uint32_t contextAddress;
|
||||
|
||||
bool (*engage)(struct GBAAudioMixer* mixer, uint32_t address);
|
||||
void (*vblank)(struct GBAAudioMixer* mixer);
|
||||
void (*step)(struct GBAAudioMixer* mixer);
|
||||
|
||||
struct GBAMP2kContext context;
|
||||
struct GBAMP2kMusicPlayerInfo player;
|
||||
struct GBAMP2kTrack activeTracks[MP2K_MAX_SOUND_CHANNELS];
|
||||
|
||||
double tempo;
|
||||
double frame;
|
||||
|
||||
struct mStereoSample last;
|
||||
};
|
||||
|
||||
void GBAAudioInit(struct GBAAudio* audio, size_t samples);
|
||||
void GBAAudioReset(struct GBAAudio* audio);
|
||||
void GBAAudioDeinit(struct GBAAudio* audio);
|
||||
|
@ -313,8 +286,6 @@ struct GBASerializedState;
|
|||
void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState* state);
|
||||
void GBAAudioDeserialize(struct GBAAudio* audio, const struct GBASerializedState* state);
|
||||
|
||||
float GBAAudioCalculateRatio(float inputSampleRate, float desiredFPS, float desiredSampleRatio);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,10 +13,13 @@
|
|||
|
||||
CXX_GUARD_START
|
||||
|
||||
#define DIGIMON_SAPPHIRE_CHINESE_CRC32 0x793A328F
|
||||
|
||||
enum GBAVFameCartType {
|
||||
VFAME_NO = 0,
|
||||
VFAME_STANDARD = 1,
|
||||
VFAME_GEORGE = 2
|
||||
VFAME_GEORGE = 2,
|
||||
VFAME_ALTERNATE = 3,
|
||||
};
|
||||
|
||||
struct GBAVFameCart {
|
||||
|
@ -28,7 +31,7 @@ struct GBAVFameCart {
|
|||
};
|
||||
|
||||
void GBAVFameInit(struct GBAVFameCart* cart);
|
||||
void GBAVFameDetect(struct GBAVFameCart* cart, uint32_t* rom, size_t romSize);
|
||||
void GBAVFameDetect(struct GBAVFameCart* cart, uint32_t* rom, size_t romSize, uint32_t crc32);
|
||||
void GBAVFameSramWrite(struct GBAVFameCart* cart, uint32_t address, uint8_t value, uint8_t* sramData);
|
||||
uint32_t GBAVFameModifyRomAddress(struct GBAVFameCart* cart, uint32_t address, size_t romSize);
|
||||
uint32_t GBAVFameGetPatternValue(uint32_t address, int bits);
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
/* Copyright (c) 2013-2017 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef GBA_AUDIO_MIXER_H
|
||||
#define GBA_AUDIO_MIXER_H
|
||||
|
||||
#include <mgba-util/common.h>
|
||||
|
||||
CXX_GUARD_START
|
||||
|
||||
#include <mgba/internal/gba/audio.h>
|
||||
|
||||
void GBAAudioMixerCreate(struct GBAAudioMixer* mixer);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
|
@ -81,7 +81,6 @@ struct GBA {
|
|||
|
||||
struct GBATimer timers[4];
|
||||
|
||||
int springIRQ;
|
||||
struct mTimingEvent irqEvent;
|
||||
|
||||
uint32_t biosChecksum;
|
||||
|
@ -91,6 +90,7 @@ struct GBA {
|
|||
struct GBALuminanceSource* luminanceSource;
|
||||
struct mRTCSource* rtcSource;
|
||||
struct mRumble* rumble;
|
||||
int32_t lastRumble;
|
||||
|
||||
bool isPristine;
|
||||
size_t pristineRomSize;
|
||||
|
@ -160,7 +160,7 @@ struct ELF;
|
|||
bool GBAVerifyELFEntry(struct ELF* elf, uint32_t target);
|
||||
#endif
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
struct mDebugger;
|
||||
void GBAAttachDebugger(struct GBA* gba, struct mDebugger* debugger);
|
||||
void GBADetachDebugger(struct GBA* gba);
|
||||
|
@ -182,8 +182,7 @@ void GBAUnloadMB(struct GBA* gba);
|
|||
|
||||
bool GBALoadNull(struct GBA* gba);
|
||||
|
||||
void GBAGetGameCode(const struct GBA* gba, char* out);
|
||||
void GBAGetGameTitle(const struct GBA* gba, char* out);
|
||||
void GBAGetGameInfo(const struct GBA* gba, struct mGameInfo* info);
|
||||
|
||||
void GBATestKeypadIRQ(struct GBA* gba);
|
||||
|
||||
|
|
|
@ -118,6 +118,8 @@ enum {
|
|||
GBA_GL_WIN_FLAGS,
|
||||
GBA_GL_WIN_WIN0,
|
||||
GBA_GL_WIN_WIN1,
|
||||
GBA_GL_WIN_CIRCLE0,
|
||||
GBA_GL_WIN_CIRCLE1,
|
||||
|
||||
GBA_GL_FINALIZE_SCALE = 2,
|
||||
GBA_GL_FINALIZE_LAYERS,
|
||||
|
|
|
@ -19,7 +19,7 @@ struct GBAVideoProxyRenderer {
|
|||
struct mVideoLogger* logger;
|
||||
};
|
||||
|
||||
void GBAVideoProxyRendererCreate(struct GBAVideoProxyRenderer* renderer, struct GBAVideoRenderer* backend);
|
||||
void GBAVideoProxyRendererCreate(struct GBAVideoProxyRenderer* renderer, struct GBAVideoRenderer* backend, struct mVideoLogger* logger);
|
||||
void GBAVideoProxyRendererShim(struct GBAVideo* video, struct GBAVideoProxyRenderer* renderer);
|
||||
void GBAVideoProxyRendererUnshim(struct GBAVideo* video, struct GBAVideoProxyRenderer* renderer);
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ struct Window {
|
|||
struct GBAVideoSoftwareRenderer {
|
||||
struct GBAVideoRenderer d;
|
||||
|
||||
color_t* outputBuffer;
|
||||
mColor* outputBuffer;
|
||||
int outputBufferStride;
|
||||
|
||||
uint32_t* temporaryBuffer;
|
||||
|
@ -100,10 +100,10 @@ struct GBAVideoSoftwareRenderer {
|
|||
unsigned target2Bd;
|
||||
bool blendDirty;
|
||||
enum GBAVideoBlendEffect blendEffect;
|
||||
color_t normalPalette[512];
|
||||
color_t variantPalette[512];
|
||||
color_t highlightPalette[512];
|
||||
color_t highlightVariantPalette[512];
|
||||
mColor normalPalette[512];
|
||||
mColor variantPalette[512];
|
||||
mColor highlightPalette[512];
|
||||
mColor highlightVariantPalette[512];
|
||||
|
||||
uint16_t blda;
|
||||
uint16_t bldb;
|
||||
|
@ -118,6 +118,7 @@ struct GBAVideoSoftwareRenderer {
|
|||
struct WindowControl control;
|
||||
int16_t offsetX;
|
||||
int16_t offsetY;
|
||||
bool on;
|
||||
} winN[2];
|
||||
|
||||
struct WindowControl winout;
|
||||
|
@ -142,6 +143,7 @@ struct GBAVideoSoftwareRenderer {
|
|||
struct ScanlineCache {
|
||||
uint16_t io[GBA_REG(SOUND1CNT_LO)];
|
||||
int32_t scale[2][2];
|
||||
bool windowOn[2];
|
||||
} cache[GBA_VIDEO_VERTICAL_PIXELS];
|
||||
int nextY;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ extern MGBA_EXPORT const uint32_t GBASavestateVersion;
|
|||
mLOG_DECLARE_CATEGORY(GBA_STATE);
|
||||
|
||||
/* Savestate format:
|
||||
* 0x00000 - 0x00003: Version Magic (0x01000006)
|
||||
* 0x00000 - 0x00003: Version Magic (0x01000007)
|
||||
* 0x00004 - 0x00007: BIOS checksum (e.g. 0xBAAE187F for official BIOS)
|
||||
* 0x00008 - 0x0000B: ROM CRC32
|
||||
* 0x0000C - 0x0000F: Master cycles
|
||||
|
@ -107,6 +107,9 @@ mLOG_DECLARE_CATEGORY(GBA_STATE);
|
|||
* | 0x001E0 - 0x001E3: Last sample
|
||||
* | 0x001E4 - 0x001E7: Additional audio flags
|
||||
* | bits 0 - 3: Current sample index
|
||||
* | bits 4 - 5: Channel A DMA source
|
||||
* | bits 6 - 7: Channel B DMA source
|
||||
* | bits 8 - 31: Reserved
|
||||
* | 0x001E8 - 0x001EF: Reserved
|
||||
* 0x001F0 - 0x001FF: Video miscellaneous state
|
||||
* | 0x001F0 - 0x001F3: Reserved
|
||||
|
@ -232,7 +235,8 @@ mLOG_DECLARE_CATEGORY(GBA_STATE);
|
|||
* 0x00370 - 0x0037F: Audio FIFO A samples
|
||||
* 0x00380 - 0x0038F: Audio FIFO B samples
|
||||
* 0x00390 - 0x003CF: Audio rendered samples
|
||||
* 0x003D0 - 0x003FF: Reserved (leave zero)
|
||||
* 0x003D0 - 0x003D3: Memory bus value
|
||||
* 0x003D4 - 0x003FF: Reserved (leave zero)
|
||||
* 0x00400 - 0x007FF: I/O memory
|
||||
* 0x00800 - 0x00BFF: Palette
|
||||
* 0x00C00 - 0x00FFF: OAM
|
||||
|
@ -250,6 +254,8 @@ DECL_BITS(GBASerializedAudioFlags, FIFOSamplesA, 7, 3);
|
|||
|
||||
DECL_BITFIELD(GBASerializedAudioFlags2, uint32_t);
|
||||
DECL_BITS(GBASerializedAudioFlags2, SampleIndex, 0, 4);
|
||||
DECL_BITS(GBASerializedAudioFlags2, ChASource, 4, 2);
|
||||
DECL_BITS(GBASerializedAudioFlags2, ChBSource, 6, 2);
|
||||
|
||||
DECL_BITFIELD(GBASerializedVideoFlags, uint32_t);
|
||||
DECL_BITS(GBASerializedVideoFlags, Mode, 0, 2);
|
||||
|
@ -279,6 +285,11 @@ DECL_BIT(GBASerializedMiscFlags, IrqPending, 2);
|
|||
DECL_BIT(GBASerializedMiscFlags, Blocked, 3);
|
||||
DECL_BITS(GBASerializedMiscFlags, KeyIRQKeys, 4, 11);
|
||||
|
||||
enum {
|
||||
GBA_SUBSYSTEM_VIDEO_RENDERER = 0,
|
||||
GBA_SUBSYSTEM_MAX,
|
||||
};
|
||||
|
||||
struct GBASerializedState {
|
||||
uint32_t versionMagic;
|
||||
uint32_t biosChecksum;
|
||||
|
@ -405,7 +416,9 @@ struct GBASerializedState {
|
|||
|
||||
struct mStereoSample currentSamples[GBA_MAX_SAMPLES];
|
||||
|
||||
uint32_t reserved[12];
|
||||
uint32_t bus;
|
||||
|
||||
uint32_t reserved[11];
|
||||
|
||||
uint16_t io[GBA_SIZE_IO >> 1];
|
||||
uint16_t pram[GBA_SIZE_PALETTE_RAM >> 1];
|
||||
|
|
|
@ -16,6 +16,12 @@ CXX_GUARD_START
|
|||
|
||||
mLOG_DECLARE_CATEGORY(GBA_VIDEO);
|
||||
|
||||
#define GBA_VSTALL_T4(X) (0x011 << (X))
|
||||
#define GBA_VSTALL_T8(X) (0x010 << (X))
|
||||
#define GBA_VSTALL_A2 0x100
|
||||
#define GBA_VSTALL_A3 0x200
|
||||
#define GBA_VSTALL_B 0x400
|
||||
|
||||
enum {
|
||||
VIDEO_HBLANK_PIXELS = 68,
|
||||
VIDEO_HDRAW_LENGTH = 1008,
|
||||
|
@ -176,6 +182,10 @@ struct GBAVideoRenderer {
|
|||
void (*reset)(struct GBAVideoRenderer* renderer);
|
||||
void (*deinit)(struct GBAVideoRenderer* renderer);
|
||||
|
||||
uint32_t (*rendererId)(const struct GBAVideoRenderer* renderer);
|
||||
bool (*loadState)(struct GBAVideoRenderer* renderer, const void* state, size_t size);
|
||||
void (*saveState)(struct GBAVideoRenderer* renderer, void** state, size_t* size);
|
||||
|
||||
uint16_t (*writeVideoRegister)(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value);
|
||||
void (*writeVRAM)(struct GBAVideoRenderer* renderer, uint32_t address);
|
||||
void (*writePalette)(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value);
|
||||
|
@ -198,7 +208,7 @@ struct GBAVideoRenderer {
|
|||
|
||||
bool highlightBG[4];
|
||||
bool highlightOBJ[128];
|
||||
color_t highlightColor;
|
||||
mColor highlightColor;
|
||||
uint8_t highlightAmount;
|
||||
};
|
||||
|
||||
|
@ -208,7 +218,7 @@ struct GBAVideo {
|
|||
struct mTimingEvent event;
|
||||
|
||||
int vcount;
|
||||
int shouldStall;
|
||||
unsigned stallMask;
|
||||
|
||||
uint16_t palette[512];
|
||||
uint16_t* vram;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <mgba/script/base.h>
|
||||
#include <mgba/script/canvas.h>
|
||||
#include <mgba/script/console.h>
|
||||
#include <mgba/script/context.h>
|
||||
#include <mgba/script/input.h>
|
||||
#include <mgba/script/macros.h>
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/* Copyright (c) 2013-2024 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef M_SCRIPT_CONSOLE_H
|
||||
#define M_SCRIPT_CONSOLE_H
|
||||
|
||||
#include <mgba-util/common.h>
|
||||
|
||||
CXX_GUARD_START
|
||||
|
||||
#include <mgba/script/context.h>
|
||||
#include <mgba/script/macros.h>
|
||||
#include <mgba/script/types.h>
|
||||
|
||||
struct mCore;
|
||||
struct mScriptTextBuffer;
|
||||
mSCRIPT_DECLARE_STRUCT(mCore);
|
||||
mSCRIPT_DECLARE_STRUCT(mLogger);
|
||||
mSCRIPT_DECLARE_STRUCT(mScriptConsole);
|
||||
mSCRIPT_DECLARE_STRUCT(mScriptTextBuffer);
|
||||
|
||||
struct mScriptTextBuffer {
|
||||
void (*init)(struct mScriptTextBuffer*, const char* name);
|
||||
void (*deinit)(struct mScriptTextBuffer*);
|
||||
|
||||
void (*setName)(struct mScriptTextBuffer*, const char* text);
|
||||
|
||||
uint32_t (*getX)(const struct mScriptTextBuffer*);
|
||||
uint32_t (*getY)(const struct mScriptTextBuffer*);
|
||||
uint32_t (*cols)(const struct mScriptTextBuffer*);
|
||||
uint32_t (*rows)(const struct mScriptTextBuffer*);
|
||||
|
||||
void (*print)(struct mScriptTextBuffer*, const char* text);
|
||||
void (*clear)(struct mScriptTextBuffer*);
|
||||
void (*setSize)(struct mScriptTextBuffer*, uint32_t cols, uint32_t rows);
|
||||
void (*moveCursor)(struct mScriptTextBuffer*, uint32_t x, uint32_t y);
|
||||
void (*advance)(struct mScriptTextBuffer*, int32_t);
|
||||
};
|
||||
|
||||
struct mLogger;
|
||||
void mScriptContextAttachLogger(struct mScriptContext*, struct mLogger*);
|
||||
void mScriptContextDetachLogger(struct mScriptContext*);
|
||||
|
||||
typedef struct mScriptTextBuffer* (*mScriptContextBufferFactory)(void*);
|
||||
void mScriptContextSetTextBufferFactory(struct mScriptContext*, mScriptContextBufferFactory factory, void* cbContext);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
|
@ -109,7 +109,9 @@ const char* mScriptEngineGetDocstring(struct mScriptEngineContext*, const char*
|
|||
|
||||
struct VFile;
|
||||
bool mScriptContextLoadVF(struct mScriptContext*, const char* name, struct VFile* vf);
|
||||
#ifdef ENABLE_VFS
|
||||
bool mScriptContextLoadFile(struct mScriptContext*, const char* path);
|
||||
#endif
|
||||
|
||||
struct mScriptContext* mScriptActiveContext(void);
|
||||
bool mScriptContextActivate(struct mScriptContext*);
|
||||
|
|
|
@ -323,7 +323,7 @@ CXX_GUARD_START
|
|||
} \
|
||||
|
||||
#define _mSCRIPT_DECLARE_STRUCT_OVERLOADED_METHOD_BINDING(TYPE, NAME, T) \
|
||||
static const struct mScriptFunctionOverload _mSTStructBindingOverloads_ ## TYPE ## _ ## NAME[]; \
|
||||
static const struct mScriptFunctionOverload _mSTStructBindingOverloads_ ## TYPE ## _ ## NAME[mSCRIPT_OVERLOADS_MAX]; \
|
||||
static bool _mSTStructBinding_ ## TYPE ## _ ## NAME(struct mScriptFrame* frame, void* ctx) { \
|
||||
UNUSED(ctx); \
|
||||
const struct mScriptFunctionOverload* overload = mScriptFunctionFindOverload(_mSTStructBindingOverloads_ ## TYPE ## _ ## NAME, &frame->arguments); \
|
||||
|
@ -468,7 +468,7 @@ CXX_GUARD_START
|
|||
#define mSCRIPT_DEFINE_DEFAULTS_END }
|
||||
|
||||
#define mSCRIPT_DEFINE_STRUCT_METHOD_OVERLOADS(STRUCT, METHOD) \
|
||||
static const struct mScriptFunctionOverload _mSTStructBindingOverloads_ ## STRUCT ## _ ## METHOD[] = { \
|
||||
static const struct mScriptFunctionOverload _mSTStructBindingOverloads_ ## STRUCT ## _ ## METHOD[mSCRIPT_OVERLOADS_MAX] = { \
|
||||
|
||||
#define mSCRIPT_DEFINE_STRUCT_METHOD_OVERLOAD(TYPE, FUNCTION) { \
|
||||
.type = &_mSTStructBindingType_ ## TYPE ## _ ## FUNCTION, \
|
||||
|
|
|
@ -16,6 +16,7 @@ CXX_GUARD_START
|
|||
|
||||
#define mSCRIPT_VALUE_UNREF -1
|
||||
#define mSCRIPT_PARAMS_MAX 8
|
||||
#define mSCRIPT_OVERLOADS_MAX 8
|
||||
|
||||
#define mSCRIPT_VALUE_DOC_FUNCTION(NAME) (&_mScriptDoc_ ## NAME)
|
||||
|
||||
|
|
|
@ -1,504 +0,0 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
11625
res/nointro.dat
11625
res/nointro.dat
File diff suppressed because it is too large
Load Diff
|
@ -45,6 +45,7 @@ void ARMSetPrivilegeMode(struct ARMCore* cpu, enum PrivilegeMode mode) {
|
|||
}
|
||||
|
||||
void ARMInit(struct ARMCore* cpu) {
|
||||
memset(cpu->cp, 0, sizeof(cpu->cp));
|
||||
cpu->master->init(cpu, cpu->master);
|
||||
size_t i;
|
||||
for (i = 0; i < cpu->numComponents; ++i) {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include <mgba/internal/debugger/symbols.h>
|
||||
#include <mgba-util/string.h>
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
#define ADVANCE(AMOUNT) \
|
||||
if (AMOUNT >= blen) { \
|
||||
buffer[blen - 1] = '\0'; \
|
||||
|
|
|
@ -655,11 +655,44 @@ DEFINE_INSTRUCTION_ARM(BX,
|
|||
|
||||
// Begin coprocessor definitions
|
||||
|
||||
DEFINE_INSTRUCTION_ARM(CDP, ARM_STUB)
|
||||
#define DEFINE_COPROCESSOR_INSTRUCTION(NAME, BODY) \
|
||||
DEFINE_INSTRUCTION_ARM(NAME, \
|
||||
int op1 = (opcode >> 21) & 7; \
|
||||
int op2 = (opcode >> 5) & 7; \
|
||||
int rd = (opcode >> 12) & 0xF; \
|
||||
int cp = (opcode >> 8) & 0xF; \
|
||||
int crn = (opcode >> 16) & 0xF; \
|
||||
int crm = opcode & 0xF; \
|
||||
UNUSED(op1); \
|
||||
UNUSED(op2); \
|
||||
UNUSED(rd); \
|
||||
UNUSED(crn); \
|
||||
UNUSED(crm); \
|
||||
BODY;)
|
||||
|
||||
DEFINE_COPROCESSOR_INSTRUCTION(MRC,
|
||||
if (cpu->cp[cp].mrc) {
|
||||
cpu->gprs[rd] = cpu->cp[cp].mrc(cpu, crn, crm, op1, op2);
|
||||
} else {
|
||||
ARM_ILL;
|
||||
})
|
||||
|
||||
DEFINE_COPROCESSOR_INSTRUCTION(MCR,
|
||||
if (cpu->cp[cp].mcr) {
|
||||
cpu->cp[cp].mcr(cpu, crn, crm, op1, op2, cpu->gprs[rd]);
|
||||
} else {
|
||||
ARM_ILL;
|
||||
})
|
||||
|
||||
DEFINE_COPROCESSOR_INSTRUCTION(CDP,
|
||||
if (cpu->cp[cp].cdp) {
|
||||
cpu->cp[cp].cdp(cpu, crn, crm, rd, op1, op2);
|
||||
} else {
|
||||
ARM_ILL;
|
||||
})
|
||||
|
||||
DEFINE_INSTRUCTION_ARM(LDC, ARM_STUB)
|
||||
DEFINE_INSTRUCTION_ARM(STC, ARM_STUB)
|
||||
DEFINE_INSTRUCTION_ARM(MCR, ARM_STUB)
|
||||
DEFINE_INSTRUCTION_ARM(MRC, ARM_STUB)
|
||||
|
||||
// Begin miscellaneous definitions
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ set(SOURCE_FILES
|
|||
directories.c
|
||||
input.c
|
||||
interface.c
|
||||
library.c
|
||||
lockstep.c
|
||||
log.c
|
||||
map-cache.c
|
||||
|
@ -23,6 +22,11 @@ set(SOURCE_FILES
|
|||
set(TEST_FILES
|
||||
test/core.c)
|
||||
|
||||
if(ENABLE_VFS)
|
||||
list(APPEND SOURCE_FILES
|
||||
library.c)
|
||||
endif()
|
||||
|
||||
if(ENABLE_SCRIPTING)
|
||||
set(SCRIPTING_FILES
|
||||
scripting.c)
|
||||
|
|
|
@ -20,7 +20,7 @@ void mBitmapCacheInit(struct mBitmapCache* cache) {
|
|||
static void _freeCache(struct mBitmapCache* cache) {
|
||||
size_t size = mBitmapCacheSystemInfoGetHeight(cache->sysConfig) * mBitmapCacheSystemInfoGetBuffers(cache->sysConfig);
|
||||
if (cache->cache) {
|
||||
mappedMemoryFree(cache->cache, mBitmapCacheSystemInfoGetWidth(cache->sysConfig) * size * sizeof(color_t));
|
||||
mappedMemoryFree(cache->cache, mBitmapCacheSystemInfoGetWidth(cache->sysConfig) * size * sizeof(mColor));
|
||||
cache->cache = NULL;
|
||||
}
|
||||
if (cache->status) {
|
||||
|
@ -39,10 +39,10 @@ static void _redoCacheSize(struct mBitmapCache* cache) {
|
|||
}
|
||||
|
||||
size_t size = mBitmapCacheSystemInfoGetHeight(cache->sysConfig) * mBitmapCacheSystemInfoGetBuffers(cache->sysConfig);
|
||||
cache->cache = anonymousMemoryMap(mBitmapCacheSystemInfoGetWidth(cache->sysConfig) * size * sizeof(color_t));
|
||||
cache->cache = anonymousMemoryMap(mBitmapCacheSystemInfoGetWidth(cache->sysConfig) * size * sizeof(mColor));
|
||||
cache->status = anonymousMemoryMap(size * sizeof(*cache->status));
|
||||
if (mBitmapCacheSystemInfoIsUsesPalette(cache->sysConfig)) {
|
||||
cache->palette = calloc((1 << (1 << mBitmapCacheSystemInfoGetEntryBPP(cache->sysConfig))), sizeof(color_t));
|
||||
cache->palette = calloc((1 << (1 << mBitmapCacheSystemInfoGetEntryBPP(cache->sysConfig))), sizeof(mColor));
|
||||
} else {
|
||||
cache->palette = NULL;
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ void mBitmapCacheWriteVRAM(struct mBitmapCache* cache, uint32_t address) {
|
|||
}
|
||||
}
|
||||
|
||||
void mBitmapCacheWritePalette(struct mBitmapCache* cache, uint32_t entry, color_t color) {
|
||||
void mBitmapCacheWritePalette(struct mBitmapCache* cache, uint32_t entry, mColor color) {
|
||||
if (!mBitmapCacheSystemInfoIsUsesPalette(cache->sysConfig)) {
|
||||
return;
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ uint32_t _lookupEntry15(void* vram, uint32_t offset) {
|
|||
}
|
||||
|
||||
void mBitmapCacheCleanRow(struct mBitmapCache* cache, struct mBitmapCacheEntry* entry, unsigned y) {
|
||||
color_t* row = &cache->cache[(cache->buffer * mBitmapCacheSystemInfoGetHeight(cache->sysConfig) + y) * mBitmapCacheSystemInfoGetWidth(cache->sysConfig)];
|
||||
mColor* row = &cache->cache[(cache->buffer * mBitmapCacheSystemInfoGetHeight(cache->sysConfig) + y) * mBitmapCacheSystemInfoGetWidth(cache->sysConfig)];
|
||||
size_t location = cache->buffer + mBitmapCacheSystemInfoGetBuffers(cache->sysConfig) * y;
|
||||
struct mBitmapCacheEntry* status = &cache->status[location];
|
||||
struct mBitmapCacheEntry desiredStatus = {
|
||||
|
@ -181,7 +181,7 @@ bool mBitmapCacheCheckRow(struct mBitmapCache* cache, const struct mBitmapCacheE
|
|||
return memcmp(&entry[location], &desiredStatus, sizeof(*entry)) == 0;
|
||||
}
|
||||
|
||||
const color_t* mBitmapCacheGetRow(struct mBitmapCache* cache, unsigned y) {
|
||||
color_t* row = &cache->cache[(cache->buffer * mBitmapCacheSystemInfoGetHeight(cache->sysConfig) + y) * mBitmapCacheSystemInfoGetWidth(cache->sysConfig)];
|
||||
const mColor* mBitmapCacheGetRow(struct mBitmapCache* cache, unsigned y) {
|
||||
mColor* row = &cache->cache[(cache->buffer * mBitmapCacheSystemInfoGetHeight(cache->sysConfig) + y) * mBitmapCacheSystemInfoGetWidth(cache->sysConfig)];
|
||||
return row;
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ void mCacheSetWriteVRAM(struct mCacheSet* cache, uint32_t address) {
|
|||
}
|
||||
}
|
||||
|
||||
void mCacheSetWritePalette(struct mCacheSet* cache, uint32_t entry, color_t color) {
|
||||
void mCacheSetWritePalette(struct mCacheSet* cache, uint32_t entry, mColor color) {
|
||||
size_t i;
|
||||
for (i = 0; i < mBitmapCacheSetSize(&cache->bitmaps); ++i) {
|
||||
mBitmapCacheWritePalette(mBitmapCacheSetGetPointer(&cache->bitmaps, i), entry, color);
|
||||
|
|
|
@ -282,14 +282,14 @@ bool mCheatParseFile(struct mCheatDevice* device, struct VFile* vf) {
|
|||
StringListDeinit(&directives);
|
||||
return false;
|
||||
}
|
||||
while (isspace((int) cheat[i])) {
|
||||
while (isspace((unsigned) cheat[i])) {
|
||||
++i;
|
||||
}
|
||||
switch (cheat[i]) {
|
||||
case '#':
|
||||
do {
|
||||
++i;
|
||||
} while (isspace((int) cheat[i]));
|
||||
} while (isspace((unsigned) cheat[i]));
|
||||
newSet = device->createSet(device, &cheat[i]);
|
||||
newSet->enabled = !nextDisabled;
|
||||
nextDisabled = false;
|
||||
|
@ -305,7 +305,7 @@ bool mCheatParseFile(struct mCheatDevice* device, struct VFile* vf) {
|
|||
case '!':
|
||||
do {
|
||||
++i;
|
||||
} while (isspace((int) cheat[i]));
|
||||
} while (isspace((unsigned) cheat[i]));
|
||||
if (strcasecmp(&cheat[i], "disabled") == 0) {
|
||||
nextDisabled = true;
|
||||
break;
|
||||
|
@ -384,7 +384,7 @@ bool mCheatParseLibretroFile(struct mCheatDevice* device, struct VFile* vf) {
|
|||
return false;
|
||||
}
|
||||
++eq;
|
||||
while (isspace((int) eq[0])) {
|
||||
while (isspace((unsigned) eq[0])) {
|
||||
if (eq[0] == '\0') {
|
||||
return false;
|
||||
}
|
||||
|
@ -393,7 +393,7 @@ bool mCheatParseLibretroFile(struct mCheatDevice* device, struct VFile* vf) {
|
|||
|
||||
char* end;
|
||||
unsigned long nCheats = strtoul(eq, &end, 10);
|
||||
if (end[0] != '\0' && !isspace(end[0])) {
|
||||
if (end[0] != '\0' && !isspace((unsigned) end[0])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -423,7 +423,7 @@ bool mCheatParseLibretroFile(struct mCheatDevice* device, struct VFile* vf) {
|
|||
return false;
|
||||
}
|
||||
++eq;
|
||||
while (isspace((int) eq[0])) {
|
||||
while (isspace((unsigned) eq[0])) {
|
||||
if (eq[0] == '\0') {
|
||||
return false;
|
||||
}
|
||||
|
@ -622,7 +622,7 @@ bool mCheatSaveFile(struct mCheatDevice* device, struct VFile* vf) {
|
|||
return true;
|
||||
}
|
||||
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
#ifdef ENABLE_VFS
|
||||
void mCheatAutosave(struct mCheatDevice* device) {
|
||||
if (!device->autosave) {
|
||||
return;
|
||||
|
|
|
@ -167,7 +167,7 @@ void mCoreConfigDeinit(struct mCoreConfig* config) {
|
|||
free(config->port);
|
||||
}
|
||||
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
#ifdef ENABLE_VFS
|
||||
bool mCoreConfigLoad(struct mCoreConfig* config) {
|
||||
char path[PATH_MAX + 1];
|
||||
mCoreConfigDirectory(path, PATH_MAX);
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
#include <mgba-util/elf-read.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_PNG
|
||||
#include <mgba-util/image/png-io.h>
|
||||
#endif
|
||||
|
||||
#ifdef M_CORE_GB
|
||||
#include <mgba/gb/core.h>
|
||||
#include <mgba/gb/interface.h>
|
||||
|
@ -86,9 +90,7 @@ struct mCore* mCoreCreate(enum mPlatform platform) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
#include <mgba-util/image/png-io.h>
|
||||
|
||||
#ifdef ENABLE_VFS
|
||||
#ifdef PSP2
|
||||
#include <psp2/photoexport.h>
|
||||
#endif
|
||||
|
@ -381,7 +383,7 @@ void mCoreInitConfig(struct mCore* core, const char* port) {
|
|||
}
|
||||
|
||||
void mCoreLoadConfig(struct mCore* core) {
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
#ifdef ENABLE_VFS
|
||||
mCoreConfigLoad(&core->config);
|
||||
#endif
|
||||
mCoreLoadForeignConfig(core, &core->config);
|
||||
|
@ -389,7 +391,7 @@ void mCoreLoadConfig(struct mCore* core) {
|
|||
|
||||
void mCoreLoadForeignConfig(struct mCore* core, const struct mCoreConfig* config) {
|
||||
mCoreConfigMap(config, &core->opts);
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
#ifdef ENABLE_VFS
|
||||
mDirectorySetMapOptions(&core->dirs, &core->opts);
|
||||
#endif
|
||||
if (core->opts.audioBuffers) {
|
||||
|
@ -442,6 +444,12 @@ const struct mCoreMemoryBlock* mCoreGetMemoryBlockInfo(struct mCore* core, uint3
|
|||
return NULL;
|
||||
}
|
||||
|
||||
double mCoreCalculateFramerateRatio(const struct mCore* core, double desiredFrameRate) {
|
||||
uint32_t clockRate = core->frequency(core);
|
||||
uint32_t frameCycles = core->frameCycles(core);
|
||||
return clockRate / (desiredFrameRate * frameCycles);
|
||||
}
|
||||
|
||||
#ifdef USE_ELF
|
||||
bool mCoreLoadELF(struct mCore* core, struct ELF* elf) {
|
||||
struct ELFProgramHeaders ph;
|
||||
|
@ -467,7 +475,7 @@ bool mCoreLoadELF(struct mCore* core, struct ELF* elf) {
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
void mCoreLoadELFSymbols(struct mDebuggerSymbols* symbols, struct ELF* elf) {
|
||||
size_t symIndex = ELFFindSection(elf, ".symtab");
|
||||
size_t names = ELFFindSection(elf, ".strtab");
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <mgba/core/config.h>
|
||||
#include <mgba-util/vfs.h>
|
||||
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
#ifdef ENABLE_VFS
|
||||
void mDirectorySetInit(struct mDirectorySet* dirs) {
|
||||
dirs->base = NULL;
|
||||
dirs->archive = NULL;
|
||||
|
|
|
@ -49,14 +49,34 @@
|
|||
|
||||
// ENABLE flags
|
||||
|
||||
#ifndef ENABLE_DEBUGGERS
|
||||
#cmakedefine ENABLE_DEBUGGERS
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_GDB_STUB
|
||||
#cmakedefine ENABLE_GDB_STUB
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_SCRIPTING
|
||||
#cmakedefine ENABLE_SCRIPTING
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_VFS
|
||||
#cmakedefine ENABLE_VFS
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_VFS_FD
|
||||
#cmakedefine ENABLE_VFS_FD
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_VFS_FILE
|
||||
#cmakedefine ENABLE_VFS_FILE
|
||||
#endif
|
||||
|
||||
// USE flags
|
||||
|
||||
#ifndef USE_DEBUGGERS
|
||||
#cmakedefine USE_DEBUGGERS
|
||||
#ifndef USE_DISCORD_RPC
|
||||
#cmakedefine USE_DISCORD_RPC
|
||||
#endif
|
||||
|
||||
#ifndef USE_EDITLINE
|
||||
|
@ -75,10 +95,6 @@
|
|||
#cmakedefine USE_FFMPEG
|
||||
#endif
|
||||
|
||||
#ifndef USE_GDB_STUB
|
||||
#cmakedefine USE_GDB_STUB
|
||||
#endif
|
||||
|
||||
#ifndef USE_JSON_C
|
||||
#cmakedefine USE_JSON_C
|
||||
#endif
|
||||
|
@ -133,6 +149,10 @@
|
|||
#cmakedefine HAVE_CRC32
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_LOCALE
|
||||
#cmakedefine HAVE_LOCALE
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_LOCALTIME_R
|
||||
#cmakedefine HAVE_LOCALTIME_R
|
||||
#endif
|
||||
|
@ -149,6 +169,10 @@
|
|||
#cmakedefine HAVE_PTHREAD_SETNAME_NP
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SNPRINTF_L
|
||||
#cmakedefine HAVE_SNPRINTF_L
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRDUP
|
||||
#cmakedefine HAVE_STRDUP
|
||||
#endif
|
||||
|
|
|
@ -101,11 +101,50 @@ static bool _rtcGenericDeserialize(struct mRTCSource* source, const struct mStat
|
|||
}
|
||||
|
||||
void mRTCGenericSourceInit(struct mRTCGenericSource* rtc, struct mCore* core) {
|
||||
memset(rtc, 0, sizeof(*rtc));
|
||||
rtc->p = core;
|
||||
rtc->override = RTC_NO_OVERRIDE;
|
||||
rtc->value = 0;
|
||||
rtc->d.sample = _rtcGenericSample;
|
||||
rtc->d.unixTime = _rtcGenericCallback;
|
||||
rtc->d.serialize = _rtcGenericSerialize;
|
||||
rtc->d.deserialize = _rtcGenericDeserialize;
|
||||
}
|
||||
|
||||
static void mRumbleIntegratorReset(struct mRumble* rumble, bool enable) {
|
||||
struct mRumbleIntegrator* integrator = (struct mRumbleIntegrator*) rumble;
|
||||
integrator->state = enable;
|
||||
integrator->timeOn = 0;
|
||||
integrator->totalTime = 0;
|
||||
}
|
||||
|
||||
static void mRumbleIntegratorSetRumble(struct mRumble* rumble, bool enable, uint32_t sinceLast) {
|
||||
struct mRumbleIntegrator* integrator = (struct mRumbleIntegrator*) rumble;
|
||||
|
||||
if (integrator->state) {
|
||||
integrator->timeOn += sinceLast;
|
||||
}
|
||||
integrator->totalTime += sinceLast;
|
||||
integrator->state = enable;
|
||||
}
|
||||
|
||||
static void mRumbleIntegratorIntegrate(struct mRumble* rumble, uint32_t period) {
|
||||
if (!period) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct mRumbleIntegrator* integrator = (struct mRumbleIntegrator*) rumble;
|
||||
if (integrator->state) {
|
||||
integrator->timeOn += period - integrator->totalTime;
|
||||
}
|
||||
integrator->setRumble(integrator, fminf(integrator->timeOn / (float) period, 1.0f));
|
||||
|
||||
integrator->totalTime = 0;
|
||||
integrator->timeOn = 0;
|
||||
}
|
||||
|
||||
void mRumbleIntegratorInit(struct mRumbleIntegrator* integrator) {
|
||||
memset(integrator, 0, sizeof(*integrator));
|
||||
integrator->d.reset = mRumbleIntegratorReset;
|
||||
integrator->d.setRumble = mRumbleIntegratorSetRumble;
|
||||
integrator->d.integrate = mRumbleIntegratorIntegrate;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <mgba/core/library.h>
|
||||
|
||||
#include <mgba/core/core.h>
|
||||
#include <mgba-util/string.h>
|
||||
#include <mgba-util/vfs.h>
|
||||
|
||||
#ifdef USE_SQLITE3
|
||||
|
@ -291,8 +292,10 @@ bool _mLibraryAddEntry(struct mLibrary* library, const char* filename, const cha
|
|||
core->init(core);
|
||||
core->loadROM(core, vf);
|
||||
|
||||
core->getGameTitle(core, entry.internalTitle);
|
||||
core->getGameCode(core, entry.internalCode);
|
||||
struct mGameInfo info;
|
||||
core->getGameInfo(core, &info);
|
||||
snprintf(entry.internalCode, sizeof(entry.internalCode), "%s-%s", info.system, info.code);
|
||||
strlcpy(entry.internalTitle, info.title, sizeof(entry.internalTitle));
|
||||
core->checksum(core, &entry.crc32, mCHECKSUM_CRC32);
|
||||
entry.platform = core->platform(core);
|
||||
entry.title = NULL;
|
||||
|
|
|
@ -278,15 +278,16 @@ void mStandardLoggerDeinit(struct mStandardLogger* logger) {
|
|||
}
|
||||
|
||||
void mStandardLoggerConfig(struct mStandardLogger* logger, struct mCoreConfig* config) {
|
||||
#ifdef ENABLE_VFS
|
||||
bool logToFile = false;
|
||||
const char* logFile = mCoreConfigGetValue(config, "logFile");
|
||||
mCoreConfigGetBoolValue(config, "logToStdout", &logger->logToStdout);
|
||||
mCoreConfigGetBoolValue(config, "logToFile", &logToFile);
|
||||
|
||||
if (logToFile && logFile) {
|
||||
logger->logFile = VFileOpen(logFile, O_WRONLY | O_CREAT | O_APPEND);
|
||||
}
|
||||
|
||||
#endif
|
||||
mCoreConfigGetBoolValue(config, "logToStdout", &logger->logToStdout);
|
||||
mLogFilterLoad(logger->d.filter, config);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ void mMapCacheInit(struct mMapCache* cache) {
|
|||
static void _freeCache(struct mMapCache* cache) {
|
||||
size_t tiles = (1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig)) * (1 << mMapCacheSystemInfoGetTilesHigh(cache->sysConfig));
|
||||
if (cache->cache) {
|
||||
mappedMemoryFree(cache->cache, 8 * 8 * sizeof(color_t) * tiles);
|
||||
mappedMemoryFree(cache->cache, 8 * 8 * sizeof(mColor) * tiles);
|
||||
cache->cache = NULL;
|
||||
}
|
||||
if (cache->status) {
|
||||
|
@ -33,7 +33,7 @@ static void _redoCacheSize(struct mMapCache* cache) {
|
|||
}
|
||||
|
||||
size_t tiles = mMapCacheTileCount(cache);
|
||||
cache->cache = anonymousMemoryMap(8 * 8 * sizeof(color_t) * tiles);
|
||||
cache->cache = anonymousMemoryMap(8 * 8 * sizeof(mColor) * tiles);
|
||||
cache->status = anonymousMemoryMap(tiles * sizeof(*cache->status));
|
||||
}
|
||||
|
||||
|
@ -87,19 +87,19 @@ void mMapCacheWriteVRAM(struct mMapCache* cache, uint32_t address) {
|
|||
}
|
||||
}
|
||||
|
||||
static inline void _cleanTile(struct mMapCache* cache, const color_t* tile, color_t* mapOut, const struct mMapCacheEntry* status) {
|
||||
static inline void _cleanTile(struct mMapCache* cache, const mColor* tile, mColor* mapOut, const struct mMapCacheEntry* status) {
|
||||
size_t stride = 8 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig);
|
||||
int x, y;
|
||||
switch (mMapCacheEntryFlagsGetMirror(status->flags)) {
|
||||
case 0:
|
||||
memcpy(mapOut, tile, sizeof(color_t) * 8);
|
||||
memcpy(&mapOut[stride], &tile[0x08], sizeof(color_t) * 8);
|
||||
memcpy(&mapOut[stride * 2], &tile[0x10], sizeof(color_t) * 8);
|
||||
memcpy(&mapOut[stride * 3], &tile[0x18], sizeof(color_t) * 8);
|
||||
memcpy(&mapOut[stride * 4], &tile[0x20], sizeof(color_t) * 8);
|
||||
memcpy(&mapOut[stride * 5], &tile[0x28], sizeof(color_t) * 8);
|
||||
memcpy(&mapOut[stride * 6], &tile[0x30], sizeof(color_t) * 8);
|
||||
memcpy(&mapOut[stride * 7], &tile[0x38], sizeof(color_t) * 8);
|
||||
memcpy(mapOut, tile, sizeof(mColor) * 8);
|
||||
memcpy(&mapOut[stride], &tile[0x08], sizeof(mColor) * 8);
|
||||
memcpy(&mapOut[stride * 2], &tile[0x10], sizeof(mColor) * 8);
|
||||
memcpy(&mapOut[stride * 3], &tile[0x18], sizeof(mColor) * 8);
|
||||
memcpy(&mapOut[stride * 4], &tile[0x20], sizeof(mColor) * 8);
|
||||
memcpy(&mapOut[stride * 5], &tile[0x28], sizeof(mColor) * 8);
|
||||
memcpy(&mapOut[stride * 6], &tile[0x30], sizeof(mColor) * 8);
|
||||
memcpy(&mapOut[stride * 7], &tile[0x38], sizeof(mColor) * 8);
|
||||
break;
|
||||
case 1:
|
||||
for (y = 0; y < 8; ++y) {
|
||||
|
@ -109,14 +109,14 @@ static inline void _cleanTile(struct mMapCache* cache, const color_t* tile, colo
|
|||
}
|
||||
break;
|
||||
case 2:
|
||||
memcpy(&mapOut[stride * 7], tile, sizeof(color_t) * 8);
|
||||
memcpy(&mapOut[stride * 6], &tile[0x08], sizeof(color_t) * 8);
|
||||
memcpy(&mapOut[stride * 5], &tile[0x10], sizeof(color_t) * 8);
|
||||
memcpy(&mapOut[stride * 4], &tile[0x18], sizeof(color_t) * 8);
|
||||
memcpy(&mapOut[stride * 3], &tile[0x20], sizeof(color_t) * 8);
|
||||
memcpy(&mapOut[stride * 2], &tile[0x28], sizeof(color_t) * 8);
|
||||
memcpy(&mapOut[stride], &tile[0x30], sizeof(color_t) * 8);
|
||||
memcpy(mapOut, &tile[0x38], sizeof(color_t) * 8);
|
||||
memcpy(&mapOut[stride * 7], tile, sizeof(mColor) * 8);
|
||||
memcpy(&mapOut[stride * 6], &tile[0x08], sizeof(mColor) * 8);
|
||||
memcpy(&mapOut[stride * 5], &tile[0x10], sizeof(mColor) * 8);
|
||||
memcpy(&mapOut[stride * 4], &tile[0x18], sizeof(mColor) * 8);
|
||||
memcpy(&mapOut[stride * 3], &tile[0x20], sizeof(mColor) * 8);
|
||||
memcpy(&mapOut[stride * 2], &tile[0x28], sizeof(mColor) * 8);
|
||||
memcpy(&mapOut[stride], &tile[0x30], sizeof(mColor) * 8);
|
||||
memcpy(mapOut, &tile[0x38], sizeof(mColor) * 8);
|
||||
break;
|
||||
case 3:
|
||||
for (y = 0; y < 8; ++y) {
|
||||
|
@ -146,7 +146,7 @@ uint32_t mMapCacheTileId(struct mMapCache* cache, unsigned x, unsigned y) {
|
|||
void mMapCacheCleanTile(struct mMapCache* cache, struct mMapCacheEntry* entry, unsigned x, unsigned y) {
|
||||
size_t location = mMapCacheTileId(cache, x, y);
|
||||
struct mMapCacheEntry* status = &cache->status[location];
|
||||
const color_t* tile = NULL;
|
||||
const mColor* tile = NULL;
|
||||
if (!mMapCacheEntryFlagsIsVramClean(status->flags)) {
|
||||
status->flags = mMapCacheEntryFlagsFillVramClean(status->flags);
|
||||
cache->mapParser(cache, status, &cache->vram[cache->mapStart + (location << mMapCacheSystemInfoGetMapAlign(cache->sysConfig))]);
|
||||
|
@ -164,7 +164,7 @@ void mMapCacheCleanTile(struct mMapCache* cache, struct mMapCacheEntry* entry, u
|
|||
}
|
||||
|
||||
size_t stride = 8 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig);
|
||||
color_t* mapOut = &cache->cache[(y * stride + x) * 8];
|
||||
mColor* mapOut = &cache->cache[(y * stride + x) * 8];
|
||||
_cleanTile(cache, tile, mapOut, status);
|
||||
entry[location] = *status;
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ bool mMapCacheCheckTile(struct mMapCache* cache, const struct mMapCacheEntry* en
|
|||
size_t location = mMapCacheTileId(cache, x, y);
|
||||
struct mMapCacheEntry* status = &cache->status[location];
|
||||
int paletteId = mMapCacheEntryFlagsGetPaletteId(status->flags);
|
||||
const color_t* tile = NULL;
|
||||
const mColor* tile = NULL;
|
||||
if (mMapCacheEntryFlagsIsVramClean(status->flags) && memcmp(status, &entry[location], sizeof(*entry)) == 0) {
|
||||
unsigned tileId = status->tileId + cache->tileStart;
|
||||
if (tileId >= mTileCacheSystemInfoGetMaxTiles(cache->tileCache->sysConfig)) {
|
||||
|
@ -207,13 +207,13 @@ void mMapCacheCleanRow(struct mMapCache* cache, unsigned y) {
|
|||
if (tileId >= mTileCacheSystemInfoGetMaxTiles(cache->tileCache->sysConfig)) {
|
||||
tileId = 0;
|
||||
}
|
||||
const color_t* tile = mTileCacheGetTile(cache->tileCache, tileId, mMapCacheEntryFlagsGetPaletteId(status->flags));
|
||||
color_t* mapOut = &cache->cache[(y * stride + x) * 8];
|
||||
const mColor* tile = mTileCacheGetTile(cache->tileCache, tileId, mMapCacheEntryFlagsGetPaletteId(status->flags));
|
||||
mColor* mapOut = &cache->cache[(y * stride + x) * 8];
|
||||
_cleanTile(cache, tile, mapOut, status);
|
||||
}
|
||||
}
|
||||
|
||||
const color_t* mMapCacheGetRow(struct mMapCache* cache, unsigned y) {
|
||||
const mColor* mMapCacheGetRow(struct mMapCache* cache, unsigned y) {
|
||||
size_t stride = 8 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig);
|
||||
return &cache->cache[y * stride];
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ static void _seRun(const char* key, void* value, void* user) {
|
|||
se->run(se);
|
||||
}
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
struct mScriptDebuggerEntry {
|
||||
enum mDebuggerEntryReason reason;
|
||||
struct mDebuggerEntryInfo* info;
|
||||
|
@ -98,7 +98,7 @@ void mScriptBridgeInstallEngine(struct mScriptBridge* sb, struct mScriptEngine*
|
|||
HashTableInsert(&sb->engines, name, se);
|
||||
}
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
void mScriptBridgeSetDebugger(struct mScriptBridge* sb, struct mDebugger* debugger) {
|
||||
if (sb->debugger == debugger) {
|
||||
return;
|
||||
|
@ -129,6 +129,7 @@ void mScriptBridgeRun(struct mScriptBridge* sb) {
|
|||
HashTableEnumerate(&sb->engines, _seRun, NULL);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_VFS
|
||||
bool mScriptBridgeLoadScript(struct mScriptBridge* sb, const char* name) {
|
||||
struct VFile* vf = VFileOpen(name, O_RDONLY);
|
||||
if (!vf) {
|
||||
|
@ -143,6 +144,7 @@ bool mScriptBridgeLoadScript(struct mScriptBridge* sb, const char* name) {
|
|||
vf->close(vf);
|
||||
return info.success;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool mScriptBridgeLookupSymbol(struct mScriptBridge* sb, const char* name, int32_t* out) {
|
||||
struct mScriptSymbol info = {
|
||||
|
@ -159,7 +161,7 @@ struct mScriptMemoryDomain {
|
|||
struct mCoreMemoryBlock block;
|
||||
};
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
struct mScriptBreakpointName {
|
||||
uint32_t address;
|
||||
uint32_t maxAddress;
|
||||
|
@ -182,6 +184,7 @@ struct mScriptDebugger {
|
|||
struct Table cbidMap;
|
||||
struct Table bpidMap;
|
||||
int64_t nextBreakpoint;
|
||||
bool reentered;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -189,10 +192,11 @@ struct mScriptCoreAdapter {
|
|||
struct mCore* core;
|
||||
struct mScriptContext* context;
|
||||
struct mScriptValue memory;
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
struct mScriptDebugger debugger;
|
||||
#endif
|
||||
struct mRumble rumble;
|
||||
struct mRumbleIntegrator rumbleIntegrator;
|
||||
struct mRumble* oldRumble;
|
||||
struct mRotationSource rotation;
|
||||
struct mScriptValue* rotationCbTable;
|
||||
|
@ -204,12 +208,6 @@ struct mScriptCoreAdapter {
|
|||
#endif
|
||||
};
|
||||
|
||||
struct mScriptConsole {
|
||||
struct mLogger* logger;
|
||||
mScriptContextBufferFactory textBufferFactory;
|
||||
void* textBufferContext;
|
||||
};
|
||||
|
||||
#define CALCULATE_SEGMENT_INFO \
|
||||
uint32_t segmentSize = adapter->block.end - adapter->block.start; \
|
||||
uint32_t segmentStart = adapter->block.segmentStart - adapter->block.start; \
|
||||
|
@ -334,15 +332,15 @@ mSCRIPT_DEFINE_STRUCT(mScriptMemoryDomain)
|
|||
mSCRIPT_DEFINE_END;
|
||||
|
||||
static struct mScriptValue* _mScriptCoreGetGameTitle(const struct mCore* core) {
|
||||
char title[32] = {0};
|
||||
core->getGameTitle(core, title);
|
||||
return mScriptStringCreateFromASCII(title);
|
||||
struct mGameInfo info;
|
||||
core->getGameInfo(core, &info);
|
||||
return mScriptStringCreateFromASCII(info.title);
|
||||
}
|
||||
|
||||
static struct mScriptValue* _mScriptCoreGetGameCode(const struct mCore* core) {
|
||||
char code[16] = {0};
|
||||
core->getGameCode(core, code);
|
||||
return mScriptStringCreateFromASCII(code);
|
||||
struct mGameInfo info;
|
||||
core->getGameInfo(core, &info);
|
||||
return mScriptStringCreateFromASCII(info.code);
|
||||
}
|
||||
|
||||
static struct mScriptValue* _mScriptCoreChecksum(const struct mCore* core, int t) {
|
||||
|
@ -416,6 +414,7 @@ static struct mScriptValue* _mScriptCoreSaveState(struct mCore* core, int32_t fl
|
|||
return value;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_VFS
|
||||
static int _mScriptCoreSaveStateFile(struct mCore* core, const char* path, int flags) {
|
||||
struct VFile* vf = VFileOpen(path, O_WRONLY | O_TRUNC | O_CREAT);
|
||||
if (!vf) {
|
||||
|
@ -426,13 +425,6 @@ static int _mScriptCoreSaveStateFile(struct mCore* core, const char* path, int f
|
|||
return ok;
|
||||
}
|
||||
|
||||
static int32_t _mScriptCoreLoadState(struct mCore* core, struct mScriptString* buffer, int32_t flags) {
|
||||
struct VFile* vf = VFileFromConstMemory(buffer->buffer, buffer->size);
|
||||
int ret = mCoreLoadStateNamed(core, vf, flags);
|
||||
vf->close(vf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _mScriptCoreLoadStateFile(struct mCore* core, const char* path, int flags) {
|
||||
struct VFile* vf = VFileOpen(path, O_RDONLY);
|
||||
if (!vf) {
|
||||
|
@ -455,6 +447,14 @@ static void _mScriptCoreTakeScreenshot(struct mCore* core, const char* filename)
|
|||
mCoreTakeScreenshot(core);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int32_t _mScriptCoreLoadState(struct mCore* core, struct mScriptString* buffer, int32_t flags) {
|
||||
struct VFile* vf = VFileFromConstMemory(buffer->buffer, buffer->size);
|
||||
int ret = mCoreLoadStateNamed(core, vf, flags);
|
||||
vf->close(vf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct mScriptValue* _mScriptCoreTakeScreenshotToImage(struct mCore* core) {
|
||||
size_t stride;
|
||||
|
@ -479,10 +479,12 @@ static struct mScriptValue* _mScriptCoreTakeScreenshotToImage(struct mCore* core
|
|||
return result;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_VFS
|
||||
// Loading functions
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD(mCore, BOOL, loadFile, mCoreLoadFile, 1, CHARP, path);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD(mCore, BOOL, autoloadSave, mCoreAutoloadSave, 0);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD(mCore, BOOL, loadSaveFile, mCoreLoadSaveFile, 2, CHARP, path, BOOL, temporary);
|
||||
#endif
|
||||
|
||||
// Info functions
|
||||
mSCRIPT_DECLARE_STRUCT_CD_METHOD(mCore, S32, platform, 0);
|
||||
|
@ -522,27 +524,31 @@ mSCRIPT_DECLARE_STRUCT_METHOD(mCore, WSTR, readRegister, _mScriptCoreReadRegiste
|
|||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mCore, writeRegister, _mScriptCoreWriteRegister, 2, CHARP, regName, S32, value);
|
||||
|
||||
// Savestate functions
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, BOOL, saveStateSlot, mCoreSaveState, 2, S32, slot, S32, flags);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, WSTR, saveStateBuffer, _mScriptCoreSaveState, 1, S32, flags);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, BOOL, loadStateBuffer, _mScriptCoreLoadState, 2, STR, buffer, S32, flags);
|
||||
#ifdef ENABLE_VFS
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, BOOL, saveStateSlot, mCoreSaveState, 2, S32, slot, S32, flags);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, BOOL, saveStateFile, _mScriptCoreSaveStateFile, 2, CHARP, path, S32, flags);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, BOOL, loadStateSlot, mCoreLoadState, 2, S32, slot, S32, flags);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, BOOL, loadStateBuffer, _mScriptCoreLoadState, 2, STR, buffer, S32, flags);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, BOOL, loadStateFile, _mScriptCoreLoadStateFile, 2, CHARP, path, S32, flags);
|
||||
|
||||
// Miscellaneous functions
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD_WITH_DEFAULTS(mCore, screenshot, _mScriptCoreTakeScreenshot, 1, CHARP, filename);
|
||||
#endif
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD(mCore, W(mImage), screenshotToImage, _mScriptCoreTakeScreenshotToImage, 0);
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT(mCore)
|
||||
mSCRIPT_DEFINE_CLASS_DOCSTRING(
|
||||
"An instance of an emulator core."
|
||||
)
|
||||
#ifdef ENABLE_VFS
|
||||
mSCRIPT_DEFINE_DOCSTRING("Load a ROM file into the current state of this core")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, loadFile)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Load the save data associated with the currently loaded ROM file")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, autoloadSave)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Load save data from the given path. If the `temporary` flag is set, the given save data will not be written back to disk")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, loadSaveFile)
|
||||
#endif
|
||||
|
||||
mSCRIPT_DEFINE_DOCSTRING("Get which platform is being emulated. See C.PLATFORM for possible values")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, platform)
|
||||
|
@ -604,21 +610,23 @@ mSCRIPT_DEFINE_STRUCT(mCore)
|
|||
mSCRIPT_DEFINE_DOCSTRING("Write the value of the register with the given name")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, writeRegister)
|
||||
|
||||
mSCRIPT_DEFINE_DOCSTRING("Save state to the slot number. See C.SAVESTATE for possible values for `flags`")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, saveStateSlot)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Save state and return as a buffer. See C.SAVESTATE for possible values for `flags`")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, saveStateBuffer)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Load state from a buffer. See C.SAVESTATE for possible values for `flags`")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, loadStateBuffer)
|
||||
#ifdef ENABLE_VFS
|
||||
mSCRIPT_DEFINE_DOCSTRING("Save state to the slot number. See C.SAVESTATE for possible values for `flags`")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, saveStateSlot)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Save state to the given path. See C.SAVESTATE for possible values for `flags`")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, saveStateFile)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Load state from the slot number. See C.SAVESTATE for possible values for `flags`")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, loadStateSlot)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Load state from a buffer. See C.SAVESTATE for possible values for `flags`")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, loadStateBuffer)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Load state from the given path. See C.SAVESTATE for possible values for `flags`")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, loadStateFile)
|
||||
|
||||
mSCRIPT_DEFINE_DOCSTRING("Save a screenshot to a file")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, screenshot)
|
||||
#endif
|
||||
mSCRIPT_DEFINE_DOCSTRING("Get a screenshot in an struct::mImage")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mCore, screenshotToImage)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
@ -701,7 +709,7 @@ static void _rebuildMemoryMap(struct mScriptContext* context, struct mScriptCore
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
static void _freeBreakpoint(void* bp) {
|
||||
struct mScriptBreakpoint* point = bp;
|
||||
HashTableDeinit(&point->callbacks);
|
||||
|
@ -779,6 +787,7 @@ static void _scriptDebuggerInit(struct mDebuggerModule* debugger) {
|
|||
struct mScriptDebugger* scriptDebugger = (struct mScriptDebugger*) debugger;
|
||||
debugger->isPaused = false;
|
||||
debugger->needsCallback = false;
|
||||
scriptDebugger->reentered = false;
|
||||
|
||||
HashTableInit(&scriptDebugger->breakpoints, 0, _freeBreakpoint);
|
||||
HashTableInit(&scriptDebugger->cbidMap, 0, NULL);
|
||||
|
@ -812,6 +821,11 @@ static void _scriptDebuggerEntered(struct mDebuggerModule* debugger, enum mDebug
|
|||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (scriptDebugger->reentered) {
|
||||
return;
|
||||
}
|
||||
|
||||
_runCallbacks(scriptDebugger, point);
|
||||
debugger->isPaused = false;
|
||||
}
|
||||
|
@ -924,12 +938,16 @@ static bool _mScriptCoreAdapterClearBreakpoint(struct mScriptCoreAdapter* adapte
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t _mScriptCoreAdapterCurrentCycle(struct mScriptCoreAdapter* adapter) {
|
||||
return mTimingGlobalTime(adapter->core->timing);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void _mScriptCoreAdapterDeinit(struct mScriptCoreAdapter* adapter) {
|
||||
_clearMemoryMap(adapter->context, adapter, false);
|
||||
adapter->memory.type->free(&adapter->memory);
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
if (adapter->core->debugger) {
|
||||
mDebuggerDetachModule(adapter->core->debugger, &adapter->debugger.d);
|
||||
}
|
||||
|
@ -976,18 +994,106 @@ static void _mScriptCoreAdapterSetLuminanceCb(struct mScriptCoreAdapter* adapter
|
|||
adapter->luminanceCb = callback;
|
||||
}
|
||||
|
||||
static uint32_t _mScriptCoreAdapterRead8(struct mScriptCoreAdapter* adapter, uint32_t address) {
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
adapter->debugger.reentered = true;
|
||||
#endif
|
||||
uint32_t value = adapter->core->busRead8(adapter->core, address);
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
adapter->debugger.reentered = false;
|
||||
#endif
|
||||
return value;
|
||||
}
|
||||
|
||||
static uint32_t _mScriptCoreAdapterRead16(struct mScriptCoreAdapter* adapter, uint32_t address) {
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
adapter->debugger.reentered = true;
|
||||
#endif
|
||||
uint32_t value = adapter->core->busRead16(adapter->core, address);
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
adapter->debugger.reentered = false;
|
||||
#endif
|
||||
return value;
|
||||
}
|
||||
|
||||
static uint32_t _mScriptCoreAdapterRead32(struct mScriptCoreAdapter* adapter, uint32_t address) {
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
adapter->debugger.reentered = true;
|
||||
#endif
|
||||
uint32_t value = adapter->core->busRead32(adapter->core, address);
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
adapter->debugger.reentered = false;
|
||||
#endif
|
||||
return value;
|
||||
}
|
||||
|
||||
static struct mScriptValue* _mScriptCoreAdapterReadRange(struct mScriptCoreAdapter* adapter, uint32_t address, uint32_t length) {
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
adapter->debugger.reentered = true;
|
||||
#endif
|
||||
struct mScriptValue* value = mScriptStringCreateEmpty(length);
|
||||
char* buffer = value->value.string->buffer;
|
||||
uint32_t i;
|
||||
for (i = 0; i < length; ++i, ++address) {
|
||||
buffer[i] = adapter->core->busRead8(adapter->core, address);
|
||||
}
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
adapter->debugger.reentered = false;
|
||||
#endif
|
||||
return value;
|
||||
}
|
||||
|
||||
static void _mScriptCoreAdapterWrite8(struct mScriptCoreAdapter* adapter, uint32_t address, uint8_t value) {
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
adapter->debugger.reentered = true;
|
||||
#endif
|
||||
adapter->core->busWrite8(adapter->core, address, value);
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
adapter->debugger.reentered = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void _mScriptCoreAdapterWrite16(struct mScriptCoreAdapter* adapter, uint32_t address, uint16_t value) {
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
adapter->debugger.reentered = true;
|
||||
#endif
|
||||
adapter->core->busWrite16(adapter->core, address, value);
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
adapter->debugger.reentered = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void _mScriptCoreAdapterWrite32(struct mScriptCoreAdapter* adapter, uint32_t address, uint32_t value) {
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
adapter->debugger.reentered = true;
|
||||
#endif
|
||||
adapter->core->busWrite32(adapter->core, address, value);
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
adapter->debugger.reentered = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
mSCRIPT_DECLARE_STRUCT(mScriptCoreAdapter);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD(mScriptCoreAdapter, W(mCore), _get, _mScriptCoreAdapterGet, 1, CHARP, name);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptCoreAdapter, _deinit, _mScriptCoreAdapterDeinit, 0);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptCoreAdapter, reset, _mScriptCoreAdapterReset, 0);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD(mScriptCoreAdapter, WTABLE, setRotationCallbacks, _mScriptCoreAdapterSetRotationCbTable, 1, WTABLE, cbTable);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptCoreAdapter, setSolarSensorCallback, _mScriptCoreAdapterSetLuminanceCb, 1, WRAPPER, callback);
|
||||
#ifdef USE_DEBUGGERS
|
||||
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD(mScriptCoreAdapter, U32, read8, _mScriptCoreAdapterRead8, 1, U32, address);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD(mScriptCoreAdapter, U32, read16, _mScriptCoreAdapterRead16, 1, U32, address);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD(mScriptCoreAdapter, U32, read32, _mScriptCoreAdapterRead32, 1, U32, address);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD(mScriptCoreAdapter, WSTR, readRange, _mScriptCoreAdapterReadRange, 2, U32, address, U32, length);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptCoreAdapter, write8, _mScriptCoreAdapterWrite8, 2, U32, address, U8, value);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptCoreAdapter, write16, _mScriptCoreAdapterWrite16, 2, U32, address, U16, value);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptCoreAdapter, write32, _mScriptCoreAdapterWrite32, 2, U32, address, U32, value);
|
||||
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD(mScriptCoreAdapter, U64, currentCycle, _mScriptCoreAdapterCurrentCycle, 0);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mScriptCoreAdapter, S64, setBreakpoint, _mScriptCoreAdapterSetBreakpoint, 3, WRAPPER, callback, U32, address, S32, segment);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mScriptCoreAdapter, S64, setWatchpoint, _mScriptCoreAdapterSetWatchpoint, 4, WRAPPER, callback, U32, address, S32, type, S32, segment);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mScriptCoreAdapter, S64, setRangeWatchpoint, _mScriptCoreAdapterSetRangeWatchpoint, 5, WRAPPER, callback, U32, minAddress, U32, maxAddress, S32, type, S32, segment);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD(mScriptCoreAdapter, BOOL, clearBreakpoint, _mScriptCoreAdapterClearBreakpoint, 1, S64, cbid);
|
||||
#endif
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mScriptCoreAdapter, setBreakpoint)
|
||||
mSCRIPT_NO_DEFAULT,
|
||||
|
@ -1009,6 +1115,7 @@ mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mScriptCoreAdapter, setRangeWatchpoint)
|
|||
mSCRIPT_NO_DEFAULT,
|
||||
mSCRIPT_S32(-1)
|
||||
mSCRIPT_DEFINE_DEFAULTS_END;
|
||||
#endif
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT(mScriptCoreAdapter)
|
||||
mSCRIPT_DEFINE_CLASS_DOCSTRING(
|
||||
|
@ -1040,7 +1147,16 @@ mSCRIPT_DEFINE_STRUCT(mScriptCoreAdapter)
|
|||
"Note that the full range of values is not used by games, and the exact range depends on the calibration done by the game itself."
|
||||
)
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptCoreAdapter, setSolarSensorCallback)
|
||||
#ifdef USE_DEBUGGERS
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptCoreAdapter, read8)
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptCoreAdapter, read16)
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptCoreAdapter, read32)
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptCoreAdapter, readRange)
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptCoreAdapter, write8)
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptCoreAdapter, write16)
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptCoreAdapter, write32)
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
mSCRIPT_DEFINE_DOCSTRING("Get the current execution cycle")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptCoreAdapter, currentCycle)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Set a breakpoint at a given address")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptCoreAdapter, setBreakpoint)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Clear a breakpoint or watchpoint for a given id returned by a previous call")
|
||||
|
@ -1057,16 +1173,22 @@ mSCRIPT_DEFINE_STRUCT(mScriptCoreAdapter)
|
|||
mSCRIPT_DEFINE_STRUCT_CAST_TO_MEMBER(mScriptCoreAdapter, CS(mCore), _core)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
static void _setRumble(struct mRumble* rumble, int enable) {
|
||||
static void _setRumble(struct mRumble* rumble, bool enable, uint32_t timeSince) {
|
||||
struct mScriptCoreAdapter* adapter = containerof(rumble, struct mScriptCoreAdapter, rumble);
|
||||
|
||||
if (adapter->oldRumble) {
|
||||
adapter->oldRumble->setRumble(adapter->oldRumble, enable);
|
||||
adapter->oldRumble->setRumble(adapter->oldRumble, enable, timeSince);
|
||||
}
|
||||
|
||||
adapter->rumbleIntegrator.d.setRumble(&adapter->rumbleIntegrator.d, enable, timeSince);
|
||||
}
|
||||
|
||||
static void _setRumbleFloat(struct mRumbleIntegrator* integrator, float level) {
|
||||
struct mScriptCoreAdapter* adapter = containerof(integrator, struct mScriptCoreAdapter, rumbleIntegrator);
|
||||
|
||||
struct mScriptList args;
|
||||
mScriptListInit(&args, 1);
|
||||
*mScriptListAppend(&args) = mSCRIPT_MAKE_BOOL(!!enable);
|
||||
*mScriptListAppend(&args) = mSCRIPT_MAKE_F32(level);
|
||||
mScriptContextTriggerCallback(adapter->context, "rumble", &args);
|
||||
mScriptListDeinit(&args);
|
||||
}
|
||||
|
@ -1185,6 +1307,8 @@ void mScriptContextAttachCore(struct mScriptContext* context, struct mCore* core
|
|||
adapter->memory.type = mSCRIPT_TYPE_MS_TABLE;
|
||||
adapter->memory.type->alloc(&adapter->memory);
|
||||
|
||||
mRumbleIntegratorInit(&adapter->rumbleIntegrator);
|
||||
adapter->rumbleIntegrator.setRumble = _setRumbleFloat;
|
||||
adapter->rumble.setRumble = _setRumble;
|
||||
adapter->rotation.sample = _rotationSample;
|
||||
adapter->rotation.readTiltX = _rotationReadTiltX;
|
||||
|
@ -1240,130 +1364,3 @@ void mScriptContextDetachCore(struct mScriptContext* context) {
|
|||
|
||||
mScriptContextRemoveGlobal(context, "emu");
|
||||
}
|
||||
|
||||
static struct mScriptTextBuffer* _mScriptConsoleCreateBuffer(struct mScriptConsole* lib, const char* name) {
|
||||
struct mScriptTextBuffer* buffer = lib->textBufferFactory(lib->textBufferContext);
|
||||
buffer->init(buffer, name);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void mScriptConsoleLog(struct mScriptConsole* console, const char* msg) {
|
||||
if (console->logger) {
|
||||
mLogExplicit(console->logger, _mLOG_CAT_SCRIPT, mLOG_INFO, "%s", msg);
|
||||
} else {
|
||||
mLog(_mLOG_CAT_SCRIPT, mLOG_INFO, "%s", msg);
|
||||
}
|
||||
}
|
||||
|
||||
static void mScriptConsoleWarn(struct mScriptConsole* console, const char* msg) {
|
||||
if (console->logger) {
|
||||
mLogExplicit(console->logger, _mLOG_CAT_SCRIPT, mLOG_WARN, "%s", msg);
|
||||
} else {
|
||||
mLog(_mLOG_CAT_SCRIPT, mLOG_WARN, "%s", msg);
|
||||
}
|
||||
}
|
||||
|
||||
static void mScriptConsoleError(struct mScriptConsole* console, const char* msg) {
|
||||
if (console->logger) {
|
||||
mLogExplicit(console->logger, _mLOG_CAT_SCRIPT, mLOG_ERROR, "%s", msg);
|
||||
} else {
|
||||
mLog(_mLOG_CAT_SCRIPT, mLOG_ERROR, "%s", msg);
|
||||
}
|
||||
}
|
||||
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptConsole, log, mScriptConsoleLog, 1, CHARP, msg);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptConsole, warn, mScriptConsoleWarn, 1, CHARP, msg);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptConsole, error, mScriptConsoleError, 1, CHARP, msg);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mScriptConsole, S(mScriptTextBuffer), createBuffer, _mScriptConsoleCreateBuffer, 1, CHARP, name);
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT(mScriptConsole)
|
||||
mSCRIPT_DEFINE_CLASS_DOCSTRING(
|
||||
"A global singleton object `console` that can be used for presenting textual information to the user via a console."
|
||||
)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Print a log to the console")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptConsole, log)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Print a warning to the console")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptConsole, warn)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Print an error to the console")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptConsole, error)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Create a text buffer that can be used to display custom information")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptConsole, createBuffer)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mScriptConsole, createBuffer)
|
||||
mSCRIPT_CHARP(NULL)
|
||||
mSCRIPT_DEFINE_DEFAULTS_END;
|
||||
|
||||
static struct mScriptConsole* _ensureConsole(struct mScriptContext* context) {
|
||||
struct mScriptValue* value = mScriptContextGetGlobal(context, "console");
|
||||
if (value) {
|
||||
return value->value.opaque;
|
||||
}
|
||||
struct mScriptConsole* console = calloc(1, sizeof(*console));
|
||||
value = mScriptValueAlloc(mSCRIPT_TYPE_MS_S(mScriptConsole));
|
||||
value->value.opaque = console;
|
||||
value->flags = mSCRIPT_VALUE_FLAG_FREE_BUFFER;
|
||||
mScriptContextSetGlobal(context, "console", value);
|
||||
mScriptContextSetDocstring(context, "console", "Singleton instance of struct::mScriptConsole");
|
||||
return console;
|
||||
}
|
||||
|
||||
void mScriptContextAttachLogger(struct mScriptContext* context, struct mLogger* logger) {
|
||||
struct mScriptConsole* console = _ensureConsole(context);
|
||||
console->logger = logger;
|
||||
}
|
||||
|
||||
void mScriptContextDetachLogger(struct mScriptContext* context) {
|
||||
struct mScriptValue* value = mScriptContextGetGlobal(context, "console");
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
struct mScriptConsole* console = value->value.opaque;
|
||||
console->logger = mLogGetContext();
|
||||
}
|
||||
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_D_METHOD(mScriptTextBuffer, deinit, 0);
|
||||
mSCRIPT_DECLARE_STRUCT_CD_METHOD(mScriptTextBuffer, U32, getX, 0);
|
||||
mSCRIPT_DECLARE_STRUCT_CD_METHOD(mScriptTextBuffer, U32, getY, 0);
|
||||
mSCRIPT_DECLARE_STRUCT_CD_METHOD(mScriptTextBuffer, U32, cols, 0);
|
||||
mSCRIPT_DECLARE_STRUCT_CD_METHOD(mScriptTextBuffer, U32, rows, 0);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_D_METHOD(mScriptTextBuffer, print, 1, CHARP, text);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_D_METHOD(mScriptTextBuffer, clear, 0);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_D_METHOD(mScriptTextBuffer, setSize, 2, U32, cols, U32, rows);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_D_METHOD(mScriptTextBuffer, moveCursor, 2, U32, x, U32, y);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_D_METHOD(mScriptTextBuffer, advance, 1, S32, adv);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_D_METHOD(mScriptTextBuffer, setName, 1, CHARP, name);
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT(mScriptTextBuffer)
|
||||
mSCRIPT_DEFINE_CLASS_DOCSTRING(
|
||||
"An object that can be used to present texual data to the user. It is displayed monospaced, "
|
||||
"and text can be edited after sending by moving the cursor or clearing the buffer."
|
||||
)
|
||||
mSCRIPT_DEFINE_STRUCT_DEINIT_NAMED(mScriptTextBuffer, deinit)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Get the current x position of the cursor")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptTextBuffer, getX)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Get the current y position of the cursor")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptTextBuffer, getY)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Get number of columns in the buffer")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptTextBuffer, cols)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Get number of rows in the buffer")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptTextBuffer, rows)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Print a string to the buffer")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptTextBuffer, print)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Clear the buffer")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptTextBuffer, clear)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Set the number of rows and columns")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptTextBuffer, setSize)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Set the position of the cursor")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptTextBuffer, moveCursor)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Advance the cursor a number of columns")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptTextBuffer, advance)
|
||||
mSCRIPT_DEFINE_DOCSTRING("Set the user-visible name of this buffer")
|
||||
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptTextBuffer, setName)
|
||||
mSCRIPT_DEFINE_END;
|
||||
|
||||
void mScriptContextSetTextBufferFactory(struct mScriptContext* context, mScriptContextBufferFactory factory, void* cbContext) {
|
||||
struct mScriptConsole* console = _ensureConsole(context);
|
||||
console->textBufferFactory = factory;
|
||||
console->textBufferContext = cbContext;
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ void mStateExtdataPut(struct mStateExtdata* extdata, enum mStateExtdataTag tag,
|
|||
extdata->data[tag] = *item;
|
||||
}
|
||||
|
||||
bool mStateExtdataGet(struct mStateExtdata* extdata, enum mStateExtdataTag tag, struct mStateExtdataItem* item) {
|
||||
bool mStateExtdataGet(const struct mStateExtdata* extdata, enum mStateExtdataTag tag, struct mStateExtdataItem* item) {
|
||||
if (tag == EXTDATA_NONE || tag >= EXTDATA_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
@ -131,6 +131,9 @@ bool mStateExtdataDeserialize(struct mStateExtdata* extdata, struct VFile* vf) {
|
|||
if (vf->seek(vf, header.offset, SEEK_SET) < 0) {
|
||||
return false;
|
||||
}
|
||||
if (header.size <= 0) {
|
||||
continue;
|
||||
}
|
||||
struct mStateExtdataItem item = {
|
||||
.data = malloc(header.size),
|
||||
.size = header.size,
|
||||
|
@ -371,6 +374,7 @@ bool mCoreSaveStateNamed(struct mCore* core, struct VFile* vf, int flags) {
|
|||
mStateExtdataInit(&extdata);
|
||||
size_t stateSize = core->stateSize(core);
|
||||
|
||||
core->saveExtraState(core, &extdata);
|
||||
if (flags & SAVESTATE_METADATA) {
|
||||
uint64_t* creationUsec = malloc(sizeof(*creationUsec));
|
||||
if (creationUsec) {
|
||||
|
@ -528,6 +532,8 @@ bool mCoreLoadStateNamed(struct mCore* core, struct VFile* vf, int flags) {
|
|||
bool success = core->loadState(core, state);
|
||||
mappedMemoryFree(state, core->stateSize(core));
|
||||
|
||||
core->loadExtraState(core, &extdata);
|
||||
|
||||
unsigned width, height;
|
||||
core->currentVideoSize(core, &width, &height);
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include <mgba/core/sync.h>
|
||||
|
||||
#include <mgba/core/blip_buf.h>
|
||||
#include <mgba-util/audio-buffer.h>
|
||||
|
||||
static void _changeVideoSync(struct mCoreSync* sync, bool wait) {
|
||||
// Make sure the video thread can process events while the GBA thread is paused
|
||||
|
@ -79,17 +79,17 @@ void mCoreSyncSetVideoSync(struct mCoreSync* sync, bool wait) {
|
|||
_changeVideoSync(sync, wait);
|
||||
}
|
||||
|
||||
bool mCoreSyncProduceAudio(struct mCoreSync* sync, const struct blip_t* buf, size_t samples) {
|
||||
bool mCoreSyncProduceAudio(struct mCoreSync* sync, const struct mAudioBuffer* buf) {
|
||||
if (!sync) {
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t produced = blip_samples_avail(buf);
|
||||
size_t produced = mAudioBufferAvailable(buf);
|
||||
size_t producedNew = produced;
|
||||
while (sync->audioWait && producedNew >= samples) {
|
||||
while (sync->audioWait && sync->audioHighWater && producedNew >= sync->audioHighWater) {
|
||||
ConditionWait(&sync->audioRequiredCond, &sync->audioBufferMutex);
|
||||
produced = producedNew;
|
||||
producedNew = blip_samples_avail(buf);
|
||||
producedNew = mAudioBufferAvailable(buf);
|
||||
}
|
||||
MutexUnlock(&sync->audioBufferMutex);
|
||||
return producedNew != produced;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <mgba/core/core.h>
|
||||
#include <mgba-util/vfs.h>
|
||||
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
#ifdef ENABLE_VFS
|
||||
M_TEST_DEFINE(findNullPath) {
|
||||
struct mCore* core = mCoreFind(NULL);
|
||||
assert_null(core);
|
||||
|
@ -29,7 +29,7 @@ M_TEST_DEFINE(findEmpty) {
|
|||
}
|
||||
|
||||
M_TEST_SUITE_DEFINE(mCore,
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
#ifdef ENABLE_VFS
|
||||
cmocka_unit_test(findNullPath),
|
||||
#endif
|
||||
cmocka_unit_test(findNullVF),
|
||||
|
|
|
@ -312,7 +312,7 @@ M_TEST_DEFINE(logging) {
|
|||
M_TEST_DEFINE(screenshot) {
|
||||
SETUP_LUA;
|
||||
CREATE_CORE;
|
||||
color_t* buffer = malloc(240 * 160 * sizeof(color_t));
|
||||
mColor* buffer = malloc(240 * 160 * sizeof(mColor));
|
||||
core->setVideoBuffer(core, buffer, 240);
|
||||
core->reset(core);
|
||||
core->runFrame(core);
|
||||
|
@ -327,7 +327,7 @@ M_TEST_DEFINE(screenshot) {
|
|||
TEARDOWN_CORE;
|
||||
}
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
void _setupBp(struct mCore* core) {
|
||||
switch (core->platform(core)) {
|
||||
#ifdef M_CORE_GBA
|
||||
|
@ -547,6 +547,40 @@ M_TEST_DEFINE(basicWatchpoint) {
|
|||
mDebuggerDeinit(&debugger);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(watchpointReentrant) {
|
||||
SETUP_LUA;
|
||||
mScriptContextAttachStdlib(&context);
|
||||
CREATE_CORE;
|
||||
struct mDebugger debugger;
|
||||
core->reset(core);
|
||||
mScriptContextAttachCore(&context, core);
|
||||
|
||||
mDebuggerInit(&debugger);
|
||||
mDebuggerAttach(&debugger, core);
|
||||
|
||||
TEST_PROGRAM(
|
||||
"hit = 0\n"
|
||||
"function bkpt()\n"
|
||||
" hit = hit + 1\n"
|
||||
"end"
|
||||
);
|
||||
struct mScriptValue base = mSCRIPT_MAKE_S32(RAM_BASE);
|
||||
lua->setGlobal(lua, "base", &base);
|
||||
TEST_PROGRAM("assert(0 < emu:setWatchpoint(bkpt, base, C.WATCHPOINT_TYPE.READ))");
|
||||
|
||||
TEST_PROGRAM("hit = 0");
|
||||
core->busRead8(core, RAM_BASE);
|
||||
TEST_PROGRAM("assert(hit == 1)");
|
||||
TEST_PROGRAM("emu:read8(base)");
|
||||
TEST_PROGRAM("assert(hit == 1)");
|
||||
core->busRead8(core, RAM_BASE);
|
||||
TEST_PROGRAM("assert(hit == 2)");
|
||||
|
||||
mScriptContextDeinit(&context);
|
||||
TEARDOWN_CORE;
|
||||
mDebuggerDeinit(&debugger);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(removeBreakpoint) {
|
||||
SETUP_LUA;
|
||||
mScriptContextAttachStdlib(&context);
|
||||
|
@ -727,7 +761,7 @@ M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptCore,
|
|||
cmocka_unit_test(memoryWrite),
|
||||
cmocka_unit_test(logging),
|
||||
cmocka_unit_test(screenshot),
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
#ifdef M_CORE_GBA
|
||||
cmocka_unit_test(basicBreakpointGBA),
|
||||
#endif
|
||||
|
@ -736,6 +770,7 @@ M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptCore,
|
|||
#endif
|
||||
cmocka_unit_test(multipleBreakpoint),
|
||||
cmocka_unit_test(basicWatchpoint),
|
||||
cmocka_unit_test(watchpointReentrant),
|
||||
cmocka_unit_test(removeBreakpoint),
|
||||
cmocka_unit_test(overlappingBreakpoint),
|
||||
cmocka_unit_test(overlappingWatchpoint),
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include <mgba/core/thread.h>
|
||||
|
||||
#include <mgba/core/blip_buf.h>
|
||||
#include <mgba/core/core.h>
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
#include <mgba/script/context.h>
|
||||
|
@ -44,12 +43,12 @@ static void _mCoreLog(struct mLogger* logger, int category, enum mLogLevel level
|
|||
|
||||
static void _changeState(struct mCoreThreadInternal* threadContext, enum mCoreThreadState newState) {
|
||||
threadContext->state = newState;
|
||||
ConditionWake(&threadContext->stateCond);
|
||||
ConditionWake(&threadContext->stateOffThreadCond);
|
||||
}
|
||||
|
||||
static void _waitOnInterrupt(struct mCoreThreadInternal* threadContext) {
|
||||
while (threadContext->state == mTHREAD_INTERRUPTED || threadContext->state == mTHREAD_INTERRUPTING) {
|
||||
ConditionWait(&threadContext->stateCond, &threadContext->stateMutex);
|
||||
ConditionWait(&threadContext->stateOnThreadCond, &threadContext->stateMutex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,14 +102,14 @@ static void _wait(struct mCoreThreadInternal* threadContext) {
|
|||
MutexUnlock(&threadContext->sync.audioBufferMutex);
|
||||
}
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
if (threadContext->core && threadContext->core->debugger) {
|
||||
mDebuggerInterrupt(threadContext->core->debugger);
|
||||
}
|
||||
#endif
|
||||
|
||||
MutexLock(&threadContext->stateMutex);
|
||||
ConditionWake(&threadContext->stateCond);
|
||||
ConditionWake(&threadContext->stateOnThreadCond);
|
||||
}
|
||||
|
||||
static void _waitOnRequest(struct mCoreThreadInternal* threadContext, enum mCoreThreadRequest request) {
|
||||
|
@ -140,7 +139,7 @@ static void _sendRequest(struct mCoreThreadInternal* threadContext, enum mCoreTh
|
|||
static void _cancelRequest(struct mCoreThreadInternal* threadContext, enum mCoreThreadRequest request) {
|
||||
threadContext->requested &= ~request;
|
||||
_pokeRequest(threadContext);
|
||||
ConditionWake(&threadContext->stateCond);
|
||||
ConditionWake(&threadContext->stateOnThreadCond);
|
||||
}
|
||||
|
||||
void _frameStarted(void* context) {
|
||||
|
@ -330,7 +329,7 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
|
|||
|
||||
MutexLock(&impl->stateMutex);
|
||||
while (impl->state < mTHREAD_EXITING) {
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
struct mDebugger* debugger = core->debugger;
|
||||
if (debugger) {
|
||||
MutexUnlock(&impl->stateMutex);
|
||||
|
@ -351,25 +350,24 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
|
|||
|
||||
while (impl->state >= mTHREAD_MIN_WAITING && impl->state < mTHREAD_EXITING) {
|
||||
if (impl->state == mTHREAD_INTERRUPTING) {
|
||||
impl->state = mTHREAD_INTERRUPTED;
|
||||
ConditionWake(&impl->stateCond);
|
||||
_changeState(impl, mTHREAD_INTERRUPTED);
|
||||
}
|
||||
|
||||
while (impl->state >= mTHREAD_MIN_WAITING && impl->state <= mTHREAD_MAX_WAITING) {
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
if (debugger && debugger->state != DEBUGGER_SHUTDOWN) {
|
||||
mDebuggerUpdate(debugger);
|
||||
ConditionWaitTimed(&impl->stateCond, &impl->stateMutex, 10);
|
||||
ConditionWaitTimed(&impl->stateOnThreadCond, &impl->stateMutex, 10);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
ConditionWait(&impl->stateCond, &impl->stateMutex);
|
||||
ConditionWait(&impl->stateOnThreadCond, &impl->stateMutex);
|
||||
}
|
||||
|
||||
if (impl->sync.audioWait) {
|
||||
MutexUnlock(&impl->stateMutex);
|
||||
mCoreSyncLockAudio(&impl->sync);
|
||||
mCoreSyncProduceAudio(&impl->sync, core->getAudioChannel(core, 0), core->getAudioBufferSize(core));
|
||||
mCoreSyncProduceAudio(&impl->sync, core->getAudioBuffer(core));
|
||||
MutexLock(&impl->stateMutex);
|
||||
}
|
||||
}
|
||||
|
@ -392,14 +390,13 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
|
|||
if (impl->state == mTHREAD_REQUEST) {
|
||||
if (pendingRequests) {
|
||||
if (pendingRequests & mTHREAD_REQ_PAUSE) {
|
||||
impl->state = mTHREAD_PAUSED;
|
||||
_changeState(impl, mTHREAD_PAUSED);
|
||||
}
|
||||
if (pendingRequests & mTHREAD_REQ_WAIT) {
|
||||
impl->state = mTHREAD_PAUSED;
|
||||
_changeState(impl, mTHREAD_PAUSED);
|
||||
}
|
||||
} else {
|
||||
impl->state = mTHREAD_RUNNING;
|
||||
ConditionWake(&threadContext->impl->stateCond);
|
||||
_changeState(impl, mTHREAD_RUNNING);
|
||||
}
|
||||
}
|
||||
MutexUnlock(&impl->stateMutex);
|
||||
|
@ -433,13 +430,14 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
|
|||
threadContext->run(threadContext);
|
||||
}
|
||||
}
|
||||
MutexLock(&impl->stateMutex);
|
||||
}
|
||||
|
||||
while (impl->state < mTHREAD_SHUTDOWN) {
|
||||
MutexLock(&impl->stateMutex);
|
||||
if (impl->state < mTHREAD_SHUTDOWN) {
|
||||
impl->state = mTHREAD_SHUTDOWN;
|
||||
MutexUnlock(&impl->stateMutex);
|
||||
}
|
||||
ConditionWake(&threadContext->impl->stateOffThreadCond);
|
||||
MutexUnlock(&impl->stateMutex);
|
||||
|
||||
if (core->opts.rewindEnable) {
|
||||
mCoreRewindContextDeinit(&impl->rewind);
|
||||
|
@ -461,11 +459,11 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
|
|||
}
|
||||
logger->filter = NULL;
|
||||
|
||||
return 0;
|
||||
THREAD_EXIT(0);
|
||||
}
|
||||
|
||||
bool mCoreThreadStart(struct mCoreThread* threadContext) {
|
||||
threadContext->impl = calloc(sizeof(*threadContext->impl), 1);
|
||||
threadContext->impl = calloc(1, sizeof(*threadContext->impl));
|
||||
threadContext->impl->state = mTHREAD_INITIALIZED;
|
||||
threadContext->impl->requested = 0;
|
||||
threadContext->logger.p = threadContext;
|
||||
|
@ -477,7 +475,8 @@ bool mCoreThreadStart(struct mCoreThread* threadContext) {
|
|||
}
|
||||
|
||||
MutexInit(&threadContext->impl->stateMutex);
|
||||
ConditionInit(&threadContext->impl->stateCond);
|
||||
ConditionInit(&threadContext->impl->stateOnThreadCond);
|
||||
ConditionInit(&threadContext->impl->stateOffThreadCond);
|
||||
|
||||
MutexInit(&threadContext->impl->sync.videoFrameMutex);
|
||||
ConditionInit(&threadContext->impl->sync.videoFrameAvailableCond);
|
||||
|
@ -498,11 +497,12 @@ bool mCoreThreadStart(struct mCoreThread* threadContext) {
|
|||
threadContext->impl->sync.audioWait = threadContext->core->opts.audioSync;
|
||||
threadContext->impl->sync.videoFrameWait = threadContext->core->opts.videoSync;
|
||||
threadContext->impl->sync.fpsTarget = threadContext->core->opts.fpsTarget;
|
||||
threadContext->impl->sync.audioHighWater = 512;
|
||||
|
||||
MutexLock(&threadContext->impl->stateMutex);
|
||||
ThreadCreate(&threadContext->impl->thread, _mCoreThreadRun, threadContext);
|
||||
while (threadContext->impl->state < mTHREAD_RUNNING) {
|
||||
ConditionWait(&threadContext->impl->stateCond, &threadContext->impl->stateMutex);
|
||||
ConditionWait(&threadContext->impl->stateOffThreadCond, &threadContext->impl->stateMutex);
|
||||
}
|
||||
MutexUnlock(&threadContext->impl->stateMutex);
|
||||
|
||||
|
@ -544,7 +544,7 @@ bool mCoreThreadHasCrashed(struct mCoreThread* threadContext) {
|
|||
|
||||
void mCoreThreadMarkCrashed(struct mCoreThread* threadContext) {
|
||||
MutexLock(&threadContext->impl->stateMutex);
|
||||
threadContext->impl->state = mTHREAD_CRASHED;
|
||||
_changeState(threadContext->impl, mTHREAD_CRASHED);
|
||||
MutexUnlock(&threadContext->impl->stateMutex);
|
||||
}
|
||||
|
||||
|
@ -552,7 +552,7 @@ void mCoreThreadClearCrashed(struct mCoreThread* threadContext) {
|
|||
MutexLock(&threadContext->impl->stateMutex);
|
||||
if (threadContext->impl->state == mTHREAD_CRASHED) {
|
||||
threadContext->impl->state = mTHREAD_REQUEST;
|
||||
ConditionWake(&threadContext->impl->stateCond);
|
||||
ConditionWake(&threadContext->impl->stateOnThreadCond);
|
||||
}
|
||||
MutexUnlock(&threadContext->impl->stateMutex);
|
||||
}
|
||||
|
@ -561,7 +561,7 @@ void mCoreThreadEnd(struct mCoreThread* threadContext) {
|
|||
MutexLock(&threadContext->impl->stateMutex);
|
||||
_waitOnInterrupt(threadContext->impl);
|
||||
threadContext->impl->state = mTHREAD_EXITING;
|
||||
ConditionWake(&threadContext->impl->stateCond);
|
||||
ConditionWake(&threadContext->impl->stateOnThreadCond);
|
||||
MutexUnlock(&threadContext->impl->stateMutex);
|
||||
MutexLock(&threadContext->impl->sync.audioBufferMutex);
|
||||
threadContext->impl->sync.audioWait = 0;
|
||||
|
@ -590,7 +590,8 @@ void mCoreThreadJoin(struct mCoreThread* threadContext) {
|
|||
ThreadJoin(&threadContext->impl->thread);
|
||||
|
||||
MutexDeinit(&threadContext->impl->stateMutex);
|
||||
ConditionDeinit(&threadContext->impl->stateCond);
|
||||
ConditionDeinit(&threadContext->impl->stateOnThreadCond);
|
||||
ConditionDeinit(&threadContext->impl->stateOffThreadCond);
|
||||
|
||||
MutexDeinit(&threadContext->impl->sync.videoFrameMutex);
|
||||
ConditionWake(&threadContext->impl->sync.videoFrameAvailableCond);
|
||||
|
@ -642,7 +643,6 @@ void mCoreThreadInterruptFromThread(struct mCoreThread* threadContext) {
|
|||
return;
|
||||
}
|
||||
threadContext->impl->state = mTHREAD_INTERRUPTING;
|
||||
ConditionWake(&threadContext->impl->stateCond);
|
||||
MutexUnlock(&threadContext->impl->stateMutex);
|
||||
}
|
||||
|
||||
|
@ -658,7 +658,7 @@ void mCoreThreadContinue(struct mCoreThread* threadContext) {
|
|||
} else {
|
||||
threadContext->impl->state = mTHREAD_RUNNING;
|
||||
}
|
||||
ConditionWake(&threadContext->impl->stateCond);
|
||||
ConditionWake(&threadContext->impl->stateOnThreadCond);
|
||||
}
|
||||
MutexUnlock(&threadContext->impl->stateMutex);
|
||||
}
|
||||
|
@ -718,7 +718,7 @@ void mCoreThreadSetRewinding(struct mCoreThread* threadContext, bool rewinding)
|
|||
threadContext->impl->rewinding = rewinding;
|
||||
if (rewinding && threadContext->impl->state == mTHREAD_CRASHED) {
|
||||
threadContext->impl->state = mTHREAD_REQUEST;
|
||||
ConditionWake(&threadContext->impl->stateCond);
|
||||
ConditionWake(&threadContext->impl->stateOnThreadCond);
|
||||
}
|
||||
MutexUnlock(&threadContext->impl->stateMutex);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ static void _freeCache(struct mTileCache* cache) {
|
|||
unsigned size = 1 << mTileCacheSystemInfoGetPaletteCount(cache->sysConfig);
|
||||
unsigned tiles = mTileCacheSystemInfoGetMaxTiles(cache->sysConfig);
|
||||
if (cache->cache) {
|
||||
mappedMemoryFree(cache->cache, 8 * 8 * sizeof(color_t) * tiles * size);
|
||||
mappedMemoryFree(cache->cache, 8 * 8 * sizeof(mColor) * tiles * size);
|
||||
cache->cache = NULL;
|
||||
}
|
||||
if (cache->status) {
|
||||
|
@ -44,7 +44,7 @@ static void _redoCacheSize(struct mTileCache* cache) {
|
|||
size = 1 << size;
|
||||
cache->entriesPerTile = size;
|
||||
unsigned tiles = mTileCacheSystemInfoGetMaxTiles(cache->sysConfig);
|
||||
cache->cache = anonymousMemoryMap(8 * 8 * sizeof(color_t) * tiles * size);
|
||||
cache->cache = anonymousMemoryMap(8 * 8 * sizeof(mColor) * tiles * size);
|
||||
cache->status = anonymousMemoryMap(tiles * size * sizeof(*cache->status));
|
||||
cache->globalPaletteVersion = calloc(size, sizeof(*cache->globalPaletteVersion));
|
||||
cache->palette = calloc(size * bpp, sizeof(*cache->palette));
|
||||
|
@ -89,7 +89,7 @@ void mTileCacheWriteVRAM(struct mTileCache* cache, uint32_t address) {
|
|||
}
|
||||
}
|
||||
|
||||
void mTileCacheWritePalette(struct mTileCache* cache, uint32_t entry, color_t color) {
|
||||
void mTileCacheWritePalette(struct mTileCache* cache, uint32_t entry, mColor color) {
|
||||
if (entry < cache->paletteBase) {
|
||||
return;
|
||||
}
|
||||
|
@ -103,10 +103,10 @@ void mTileCacheWritePalette(struct mTileCache* cache, uint32_t entry, color_t co
|
|||
++cache->globalPaletteVersion[entry];
|
||||
}
|
||||
|
||||
static void _regenerateTile4(struct mTileCache* cache, color_t* tile, unsigned tileId, unsigned paletteId) {
|
||||
static void _regenerateTile4(struct mTileCache* cache, mColor* tile, unsigned tileId, unsigned paletteId) {
|
||||
uint8_t* start = (uint8_t*) &cache->vram[tileId << 3];
|
||||
paletteId <<= 2;
|
||||
color_t* palette = &cache->palette[paletteId];
|
||||
mColor* palette = &cache->palette[paletteId];
|
||||
int i;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
uint8_t tileDataLower = start[0];
|
||||
|
@ -133,10 +133,10 @@ static void _regenerateTile4(struct mTileCache* cache, color_t* tile, unsigned t
|
|||
}
|
||||
}
|
||||
|
||||
static void _regenerateTile16(struct mTileCache* cache, color_t* tile, unsigned tileId, unsigned paletteId) {
|
||||
static void _regenerateTile16(struct mTileCache* cache, mColor* tile, unsigned tileId, unsigned paletteId) {
|
||||
uint32_t* start = (uint32_t*) &cache->vram[tileId << 4];
|
||||
paletteId <<= 4;
|
||||
color_t* palette = &cache->palette[paletteId];
|
||||
mColor* palette = &cache->palette[paletteId];
|
||||
int i;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
uint32_t line = *start;
|
||||
|
@ -162,10 +162,10 @@ static void _regenerateTile16(struct mTileCache* cache, color_t* tile, unsigned
|
|||
}
|
||||
}
|
||||
|
||||
static void _regenerateTile256(struct mTileCache* cache, color_t* tile, unsigned tileId, unsigned paletteId) {
|
||||
static void _regenerateTile256(struct mTileCache* cache, mColor* tile, unsigned tileId, unsigned paletteId) {
|
||||
uint32_t* start = (uint32_t*) &cache->vram[tileId << 5];
|
||||
paletteId <<= 8;
|
||||
color_t* palette = &cache->palette[paletteId];
|
||||
mColor* palette = &cache->palette[paletteId];
|
||||
int i;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
uint32_t line = *start;
|
||||
|
@ -194,24 +194,18 @@ static void _regenerateTile256(struct mTileCache* cache, color_t* tile, unsigned
|
|||
}
|
||||
}
|
||||
|
||||
static inline color_t* _tileLookup(struct mTileCache* cache, unsigned tileId, unsigned paletteId) {
|
||||
static inline mColor* _tileLookup(struct mTileCache* cache, unsigned tileId, unsigned paletteId) {
|
||||
if (mTileCacheConfigurationIsShouldStore(cache->config)) {
|
||||
unsigned tiles = mTileCacheSystemInfoGetMaxTiles(cache->sysConfig);
|
||||
#ifndef NDEBUG
|
||||
if (tileId >= tiles) {
|
||||
abort();
|
||||
}
|
||||
if (paletteId >= 1U << mTileCacheSystemInfoGetPaletteCount(cache->sysConfig)) {
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
mASSERT(tileId < tiles);
|
||||
mASSERT_DEBUG(paletteId < 1U << mTileCacheSystemInfoGetPaletteCount(cache->sysConfig));
|
||||
return &cache->cache[(tileId + paletteId * tiles) << 6];
|
||||
} else {
|
||||
return cache->temporaryTile;
|
||||
}
|
||||
}
|
||||
|
||||
const color_t* mTileCacheGetTile(struct mTileCache* cache, unsigned tileId, unsigned paletteId) {
|
||||
const mColor* mTileCacheGetTile(struct mTileCache* cache, unsigned tileId, unsigned paletteId) {
|
||||
unsigned count = cache->entriesPerTile;
|
||||
unsigned bpp = cache->bpp;
|
||||
struct mTileCacheEntry* status = &cache->status[tileId * count + paletteId];
|
||||
|
@ -221,7 +215,7 @@ const color_t* mTileCacheGetTile(struct mTileCache* cache, unsigned tileId, unsi
|
|||
.vramClean = 1,
|
||||
.paletteId = paletteId
|
||||
};
|
||||
color_t* tile = _tileLookup(cache, tileId, paletteId);
|
||||
mColor* tile = _tileLookup(cache, tileId, paletteId);
|
||||
if (!mTileCacheConfigurationIsShouldStore(cache->config) || memcmp(status, &desiredStatus, sizeof(*status))) {
|
||||
switch (bpp) {
|
||||
case 0:
|
||||
|
@ -241,7 +235,7 @@ const color_t* mTileCacheGetTile(struct mTileCache* cache, unsigned tileId, unsi
|
|||
return tile;
|
||||
}
|
||||
|
||||
const color_t* mTileCacheGetTileIfDirty(struct mTileCache* cache, struct mTileCacheEntry* entry, unsigned tileId, unsigned paletteId) {
|
||||
const mColor* mTileCacheGetTileIfDirty(struct mTileCache* cache, struct mTileCacheEntry* entry, unsigned tileId, unsigned paletteId) {
|
||||
unsigned count = cache->entriesPerTile;
|
||||
unsigned bpp = cache->bpp;
|
||||
struct mTileCacheEntry* status = &cache->status[tileId * count + paletteId];
|
||||
|
@ -251,7 +245,7 @@ const color_t* mTileCacheGetTileIfDirty(struct mTileCache* cache, struct mTileCa
|
|||
.vramClean = 1,
|
||||
.paletteId = paletteId
|
||||
};
|
||||
color_t* tile = NULL;
|
||||
mColor* tile = NULL;
|
||||
if (memcmp(status, &desiredStatus, sizeof(*status))) {
|
||||
tile = _tileLookup(cache, tileId, paletteId);
|
||||
switch (bpp) {
|
||||
|
@ -276,7 +270,7 @@ const color_t* mTileCacheGetTileIfDirty(struct mTileCache* cache, struct mTileCa
|
|||
return tile;
|
||||
}
|
||||
|
||||
const color_t* mTileCacheGetPalette(struct mTileCache* cache, unsigned paletteId) {
|
||||
const mColor* mTileCacheGetPalette(struct mTileCache* cache, unsigned paletteId) {
|
||||
return &cache->palette[paletteId << (1 << cache->bpp)];
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ if(USE_EDITLINE)
|
|||
list(APPEND SOURCE_FILES cli-el-backend.c)
|
||||
endif()
|
||||
|
||||
if(USE_GDB_STUB)
|
||||
if(ENABLE_GDB_STUB)
|
||||
list(APPEND SOURCE_FILES gdb-stub.c)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -75,13 +75,15 @@ static void _dumpByte(struct CLIDebugger*, struct CLIDebugVector*);
|
|||
static void _dumpHalfword(struct CLIDebugger*, struct CLIDebugVector*);
|
||||
static void _dumpWord(struct CLIDebugger*, struct CLIDebugVector*);
|
||||
static void _events(struct CLIDebugger*, struct CLIDebugVector*);
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
static void _source(struct CLIDebugger*, struct CLIDebugVector*);
|
||||
#endif
|
||||
static void _backtrace(struct CLIDebugger*, struct CLIDebugVector*);
|
||||
static void _finish(struct CLIDebugger*, struct CLIDebugVector*);
|
||||
static void _setStackTraceMode(struct CLIDebugger*, struct CLIDebugVector*);
|
||||
#ifdef ENABLE_VFS
|
||||
static void _loadSymbols(struct CLIDebugger*, struct CLIDebugVector*);
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
static void _source(struct CLIDebugger*, struct CLIDebugVector*);
|
||||
#endif
|
||||
#endif
|
||||
static void _setSymbol(struct CLIDebugger*, struct CLIDebugVector*);
|
||||
static void _findSymbol(struct CLIDebugger*, struct CLIDebugVector*);
|
||||
|
||||
|
@ -96,6 +98,9 @@ static struct CLIDebuggerCommandSummary _debuggerCommands[] = {
|
|||
{ "help", _printHelp, "S", "Print help" },
|
||||
{ "listb", _listBreakpoints, "", "List breakpoints" },
|
||||
{ "listw", _listWatchpoints, "", "List watchpoints" },
|
||||
#ifdef ENABLE_VFS
|
||||
{ "load-symbols", _loadSymbols, "S", "Load symbols from an external file" },
|
||||
#endif
|
||||
{ "next", _next, "", "Execute next instruction" },
|
||||
{ "print", _print, "S+", "Print a value" },
|
||||
{ "print/t", _printBin, "S+", "Print a value as binary" },
|
||||
|
@ -106,10 +111,12 @@ static struct CLIDebuggerCommandSummary _debuggerCommands[] = {
|
|||
{ "r/2", _readHalfword, "I", "Read a halfword from a specified offset" },
|
||||
{ "r/4", _readWord, "I", "Read a word from a specified offset" },
|
||||
{ "set", _setSymbol, "SI", "Assign a symbol to an address" },
|
||||
#if defined(ENABLE_SCRIPTING) && defined(ENABLE_VFS)
|
||||
{ "source", _source, "S", "Load a script" },
|
||||
#endif
|
||||
{ "stack", _setStackTraceMode, "S", "Change the stack tracing mode" },
|
||||
{ "status", _printStatus, "", "Print the current status" },
|
||||
{ "symbol", _findSymbol, "I", "Find the symbol name for an address" },
|
||||
{ "load-symbols", _loadSymbols, "S", "Load symbols from an external file" },
|
||||
{ "trace", _trace, "Is", "Trace a number of instructions" },
|
||||
{ "w/1", _writeByte, "II", "Write a byte at a specified offset" },
|
||||
{ "w/2", _writeHalfword, "II", "Write a halfword at a specified offset" },
|
||||
|
@ -126,9 +133,6 @@ static struct CLIDebuggerCommandSummary _debuggerCommands[] = {
|
|||
{ "x/1", _dumpByte, "Ii", "Examine bytes at a specified offset" },
|
||||
{ "x/2", _dumpHalfword, "Ii", "Examine halfwords at a specified offset" },
|
||||
{ "x/4", _dumpWord, "Ii", "Examine words at a specified offset" },
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
{ "source", _source, "S", "Load a script" },
|
||||
#endif
|
||||
#if !defined(NDEBUG) && !defined(_WIN32)
|
||||
{ "!", _breakInto, "", "Break into attached debugger (for developers)" },
|
||||
#endif
|
||||
|
@ -586,7 +590,7 @@ static void _dumpWord(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
#if defined(ENABLE_SCRIPTING) && defined(ENABLE_VFS)
|
||||
static void _source(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
|
||||
if (!dv) {
|
||||
debugger->backend->printf(debugger->backend, "Needs a filename\n");
|
||||
|
@ -615,7 +619,7 @@ static struct ParseTree* _parseTree(const char** string) {
|
|||
struct ParseTree* tree = NULL;
|
||||
if (!error) {
|
||||
tree = parseTreeCreate();
|
||||
parseLexedExpression(tree, &lv);
|
||||
error = !parseLexedExpression(tree, &lv);
|
||||
}
|
||||
lexFree(&lv);
|
||||
LexVectorClear(&lv);
|
||||
|
@ -829,9 +833,11 @@ static void _trace(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
|
|||
if (debugger->traceRemaining == 0) {
|
||||
return;
|
||||
}
|
||||
#ifdef ENABLE_VFS
|
||||
if (dv->next && dv->next->charValue) {
|
||||
debugger->traceVf = VFileOpen(dv->next->charValue, O_CREAT | O_WRONLY | O_APPEND);
|
||||
}
|
||||
#endif
|
||||
if (_doTrace(debugger)) {
|
||||
debugger->d.isPaused = false;
|
||||
mDebuggerUpdatePaused(debugger->d.p);
|
||||
|
@ -1398,6 +1404,7 @@ static void _setStackTraceMode(struct CLIDebugger* debugger, struct CLIDebugVect
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_VFS
|
||||
static void _loadSymbols(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
|
||||
struct mDebuggerSymbols* symbolTable = debugger->d.p->core->symbolTable;
|
||||
if (!symbolTable) {
|
||||
|
@ -1420,9 +1427,7 @@ static void _loadSymbols(struct CLIDebugger* debugger, struct CLIDebugVector* dv
|
|||
#ifdef USE_ELF
|
||||
struct ELF* elf = ELFOpen(vf);
|
||||
if (elf) {
|
||||
#ifdef USE_DEBUGGERS
|
||||
mCoreLoadELFSymbols(symbolTable, elf);
|
||||
#endif
|
||||
ELFClose(elf);
|
||||
} else
|
||||
#endif
|
||||
|
@ -1431,6 +1436,7 @@ static void _loadSymbols(struct CLIDebugger* debugger, struct CLIDebugVector* dv
|
|||
}
|
||||
vf->close(vf);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void _setSymbol(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
|
||||
struct mDebuggerSymbols* symbolTable = debugger->d.p->core->symbolTable;
|
||||
|
|
|
@ -85,6 +85,7 @@ static void CLIDebuggerEditLineInit(struct CLIDebuggerBackend* be) {
|
|||
history(elbe->histate, &ev, H_SETSIZE, 200);
|
||||
el_set(elbe->elstate, EL_HIST, history, elbe->histate);
|
||||
|
||||
#ifdef ENABLE_VFS
|
||||
char path[PATH_MAX + 1];
|
||||
mCoreConfigDirectory(path, PATH_MAX);
|
||||
if (path[0]) {
|
||||
|
@ -99,6 +100,7 @@ static void CLIDebuggerEditLineInit(struct CLIDebuggerBackend* be) {
|
|||
vf->close(vf);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
MutexInit(&elbe->promptMutex);
|
||||
ConditionInit(&elbe->promptRead);
|
||||
|
@ -120,6 +122,7 @@ static void CLIDebuggerEditLineDeinit(struct CLIDebuggerBackend* be) {
|
|||
MutexUnlock(&elbe->promptMutex);
|
||||
ThreadJoin(&elbe->promptThread);
|
||||
|
||||
#ifdef ENABLE_VFS
|
||||
char path[PATH_MAX + 1];
|
||||
mCoreConfigDirectory(path, PATH_MAX);
|
||||
if (path[0]) {
|
||||
|
@ -139,6 +142,7 @@ static void CLIDebuggerEditLineDeinit(struct CLIDebuggerBackend* be) {
|
|||
vf->close(vf);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
history_end(elbe->histate);
|
||||
el_end(elbe->elstate);
|
||||
free(elbe);
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include <mgba/internal/debugger/cli-debugger.h>
|
||||
#include <mgba/internal/debugger/symbols.h>
|
||||
|
||||
#ifdef USE_GDB_STUB
|
||||
#ifdef ENABLE_GDB_STUB
|
||||
#include <mgba/internal/debugger/gdb-stub.h>
|
||||
#endif
|
||||
|
||||
|
@ -37,7 +37,7 @@ struct mDebuggerModule* mDebuggerCreateModule(enum mDebuggerType type, struct mC
|
|||
union DebugUnion {
|
||||
struct mDebuggerModule d;
|
||||
struct CLIDebugger cli;
|
||||
#ifdef USE_GDB_STUB
|
||||
#ifdef ENABLE_GDB_STUB
|
||||
struct GDBStub gdb;
|
||||
#endif
|
||||
};
|
||||
|
@ -52,7 +52,7 @@ struct mDebuggerModule* mDebuggerCreateModule(enum mDebuggerType type, struct mC
|
|||
CLIDebuggerAttachSystem(&debugger->cli, sys);
|
||||
break;
|
||||
case DEBUGGER_GDB:
|
||||
#ifdef USE_GDB_STUB
|
||||
#ifdef ENABLE_GDB_STUB
|
||||
GDBStubCreate(&debugger->gdb);
|
||||
struct Address localHost = {
|
||||
.version = IPV4,
|
||||
|
|
|
@ -3,10 +3,14 @@ set(SOURCE_FILES
|
|||
commandline.c
|
||||
proxy-backend.c
|
||||
thread-proxy.c
|
||||
updater.c
|
||||
video-backend.c
|
||||
video-logger.c)
|
||||
|
||||
if(ENABLE_VFS)
|
||||
list(APPEND SOURCE_FILES
|
||||
updater.c)
|
||||
endif()
|
||||
|
||||
set(GUI_FILES
|
||||
gui/cheats.c
|
||||
gui/gui-config.c
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include <mgba-util/string.h>
|
||||
#include <mgba-util/vfs.h>
|
||||
|
||||
#ifdef USE_GDB_STUB
|
||||
#ifdef ENABLE_GDB_STUB
|
||||
#include <mgba/internal/debugger/gdb-stub.h>
|
||||
#endif
|
||||
#ifdef USE_EDITLINE
|
||||
|
@ -40,7 +40,7 @@ static const struct option _options[] = {
|
|||
#ifdef USE_EDITLINE
|
||||
{ "debug", no_argument, 0, 'd' },
|
||||
#endif
|
||||
#ifdef USE_GDB_STUB
|
||||
#ifdef ENABLE_GDB_STUB
|
||||
{ "gdb", no_argument, 0, 'g' },
|
||||
#endif
|
||||
{ "help", no_argument, 0, 'h' },
|
||||
|
@ -85,7 +85,7 @@ bool mArgumentsParse(struct mArguments* args, int argc, char* const* argv, struc
|
|||
#ifdef USE_EDITLINE
|
||||
"d"
|
||||
#endif
|
||||
#ifdef USE_GDB_STUB
|
||||
#ifdef ENABLE_GDB_STUB
|
||||
"g"
|
||||
#endif
|
||||
;
|
||||
|
@ -151,7 +151,7 @@ bool mArgumentsParse(struct mArguments* args, int argc, char* const* argv, struc
|
|||
args->debugCli = true;
|
||||
break;
|
||||
#endif
|
||||
#ifdef USE_GDB_STUB
|
||||
#ifdef ENABLE_GDB_STUB
|
||||
case 'g':
|
||||
args->debugAtStart = true;
|
||||
args->debugGdb = true;
|
||||
|
@ -217,9 +217,12 @@ void mArgumentsApply(const struct mArguments* args, struct mSubParser* subparser
|
|||
}
|
||||
|
||||
bool mArgumentsApplyDebugger(const struct mArguments* args, struct mCore* core, struct mDebugger* debugger) {
|
||||
UNUSED(args);
|
||||
UNUSED(core);
|
||||
UNUSED(debugger);
|
||||
bool hasDebugger = false;
|
||||
|
||||
#ifdef USE_EDITLINE
|
||||
#ifdef USE_EDITLINE
|
||||
if (args->debugCli) {
|
||||
struct mDebuggerModule* module = mDebuggerCreateModule(DEBUGGER_CLI, core);
|
||||
if (module) {
|
||||
|
@ -231,7 +234,7 @@ bool mArgumentsApplyDebugger(const struct mArguments* args, struct mCore* core,
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_GDB_STUB
|
||||
#ifdef ENABLE_GDB_STUB
|
||||
if (args->debugGdb) {
|
||||
struct mDebuggerModule* module = mDebuggerCreateModule(DEBUGGER_GDB, core);
|
||||
if (module) {
|
||||
|
@ -245,6 +248,7 @@ bool mArgumentsApplyDebugger(const struct mArguments* args, struct mCore* core,
|
|||
}
|
||||
|
||||
void mArgumentsApplyFileLoads(const struct mArguments* args, struct mCore* core) {
|
||||
#ifdef ENABLE_VFS
|
||||
if (args->patch) {
|
||||
struct VFile* patch = VFileOpen(args->patch, O_RDONLY);
|
||||
if (patch) {
|
||||
|
@ -266,6 +270,10 @@ void mArgumentsApplyFileLoads(const struct mArguments* args, struct mCore* core)
|
|||
} else {
|
||||
mCoreAutoloadCheats(core);
|
||||
}
|
||||
#else
|
||||
UNUSED(args);
|
||||
UNUSED(core);
|
||||
#endif
|
||||
}
|
||||
|
||||
void mArgumentsDeinit(struct mArguments* args) {
|
||||
|
@ -355,7 +363,7 @@ void usage(const char* arg0, const char* prologue, const char* epilogue, const s
|
|||
#ifdef USE_EDITLINE
|
||||
" -d, --debug Use command-line debugger\n"
|
||||
#endif
|
||||
#ifdef USE_GDB_STUB
|
||||
#ifdef ENABLE_GDB_STUB
|
||||
" -g, --gdb Start GDB session (default port 2345)\n"
|
||||
#endif
|
||||
" -l, --log-level N Log level mask\n"
|
||||
|
|
|
@ -190,7 +190,7 @@ bool FFmpegDecoderRead(struct FFmpegDecoder* decoder) {
|
|||
}
|
||||
int stride = decoder->width * BYTES_PER_PIXEL;
|
||||
sws_scale(decoder->scaleContext, (const uint8_t* const*) decoder->videoFrame->data, decoder->videoFrame->linesize, 0, decoder->videoFrame->height, &decoder->pixels, &stride);
|
||||
decoder->out->postVideoFrame(decoder->out, (const color_t*) decoder->pixels, decoder->width);
|
||||
decoder->out->postVideoFrame(decoder->out, (const mColor*) decoder->pixels, decoder->width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#endif
|
||||
#include <libswscale/swscale.h>
|
||||
|
||||
static void _ffmpegPostVideoFrame(struct mAVStream*, const color_t* pixels, size_t stride);
|
||||
static void _ffmpegPostVideoFrame(struct mAVStream*, const mColor* pixels, size_t stride);
|
||||
static void _ffmpegPostAudioFrame(struct mAVStream*, int16_t left, int16_t right);
|
||||
static void _ffmpegSetVideoDimensions(struct mAVStream*, unsigned width, unsigned height);
|
||||
static void _ffmpegSetAudioRate(struct mAVStream*, unsigned rate);
|
||||
|
@ -784,7 +784,7 @@ bool _ffmpegWriteAudioFrame(struct FFmpegEncoder* encoder, struct AVFrame* audio
|
|||
return gotData;
|
||||
}
|
||||
|
||||
void _ffmpegPostVideoFrame(struct mAVStream* stream, const color_t* pixels, size_t stride) {
|
||||
void _ffmpegPostVideoFrame(struct mAVStream* stream, const mColor* pixels, size_t stride) {
|
||||
struct FFmpegEncoder* encoder = (struct FFmpegEncoder*) stream;
|
||||
if (!encoder->context || !encoder->videoCodec) {
|
||||
return;
|
||||
|
|
|
@ -123,7 +123,7 @@ static void _drawState(struct GUIBackground* background, void* id) {
|
|||
struct mGUIBackground* gbaBackground = (struct mGUIBackground*) background;
|
||||
unsigned stateId = ((uint32_t) id) >> 16;
|
||||
if (gbaBackground->p->drawScreenshot) {
|
||||
color_t* pixels = gbaBackground->image;
|
||||
mColor* pixels = gbaBackground->image;
|
||||
if (pixels && gbaBackground->screenshotId == (stateId | SCREENSHOT_VALID)) {
|
||||
gbaBackground->p->drawScreenshot(gbaBackground->p, pixels, gbaBackground->w, gbaBackground->h, true);
|
||||
return;
|
||||
|
@ -220,7 +220,7 @@ void mGUIInit(struct mGUIRunner* runner, const char* port) {
|
|||
runner->fps = 0;
|
||||
runner->lastFpsCheck = 0;
|
||||
runner->totalDelta = 0;
|
||||
CircleBufferInit(&runner->fpsBuffer, FPS_BUFFER_SIZE * sizeof(uint32_t));
|
||||
mCircleBufferInit(&runner->fpsBuffer, FPS_BUFFER_SIZE * sizeof(uint32_t));
|
||||
|
||||
mInputMapInit(&runner->params.keyMap, &_mGUIKeyInfo);
|
||||
mCoreConfigInit(&runner->config, runner->port);
|
||||
|
@ -284,7 +284,7 @@ void mGUIDeinit(struct mGUIRunner* runner) {
|
|||
if (runner->teardown) {
|
||||
runner->teardown(runner);
|
||||
}
|
||||
CircleBufferDeinit(&runner->fpsBuffer);
|
||||
mCircleBufferDeinit(&runner->fpsBuffer);
|
||||
mInputMapDeinit(&runner->params.keyMap);
|
||||
mCoreConfigDeinit(&runner->config);
|
||||
if (logger.vf) {
|
||||
|
@ -502,7 +502,7 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) {
|
|||
runner->fps = 0;
|
||||
bool fastForward = false;
|
||||
while (running) {
|
||||
CircleBufferClear(&runner->fpsBuffer);
|
||||
mCircleBufferClear(&runner->fpsBuffer);
|
||||
runner->totalDelta = 0;
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, 0);
|
||||
|
@ -610,17 +610,17 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) {
|
|||
uint64_t delta = t - runner->lastFpsCheck;
|
||||
runner->lastFpsCheck = t;
|
||||
if (delta > 0x7FFFFFFFLL) {
|
||||
CircleBufferClear(&runner->fpsBuffer);
|
||||
mCircleBufferClear(&runner->fpsBuffer);
|
||||
runner->fps = 0;
|
||||
}
|
||||
if (CircleBufferSize(&runner->fpsBuffer) == CircleBufferCapacity(&runner->fpsBuffer)) {
|
||||
if (mCircleBufferSize(&runner->fpsBuffer) == mCircleBufferCapacity(&runner->fpsBuffer)) {
|
||||
int32_t last;
|
||||
CircleBufferRead32(&runner->fpsBuffer, &last);
|
||||
mCircleBufferRead32(&runner->fpsBuffer, &last);
|
||||
runner->totalDelta -= last;
|
||||
}
|
||||
CircleBufferWrite32(&runner->fpsBuffer, delta);
|
||||
mCircleBufferWrite32(&runner->fpsBuffer, delta);
|
||||
runner->totalDelta += delta;
|
||||
runner->fps = (CircleBufferSize(&runner->fpsBuffer) * FPS_GRANULARITY * 1000000.0f) / (runner->totalDelta * sizeof(uint32_t));
|
||||
runner->fps = (mCircleBufferSize(&runner->fpsBuffer) * FPS_GRANULARITY * 1000000.0f) / (runner->totalDelta * sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
if (frame % (AUTOSAVE_GRANULARITY * (fastForwarding ? 2 : 1)) == 0) {
|
||||
|
|
|
@ -31,7 +31,7 @@ struct mGUIBackground {
|
|||
struct GUIBackground d;
|
||||
struct mGUIRunner* p;
|
||||
|
||||
color_t* image;
|
||||
mColor* image;
|
||||
size_t imageSize;
|
||||
uint16_t w;
|
||||
uint16_t h;
|
||||
|
@ -78,7 +78,7 @@ struct mGUIRunner {
|
|||
float fps;
|
||||
int64_t lastFpsCheck;
|
||||
int32_t totalDelta;
|
||||
struct CircleBuffer fpsBuffer;
|
||||
struct mCircleBuffer fpsBuffer;
|
||||
|
||||
void (*setup)(struct mGUIRunner*);
|
||||
void (*teardown)(struct mGUIRunner*);
|
||||
|
@ -86,7 +86,7 @@ struct mGUIRunner {
|
|||
void (*gameUnloaded)(struct mGUIRunner*);
|
||||
void (*prepareForFrame)(struct mGUIRunner*);
|
||||
void (*drawFrame)(struct mGUIRunner*, bool faded);
|
||||
void (*drawScreenshot)(struct mGUIRunner*, const color_t* pixels, unsigned width, unsigned height, bool faded);
|
||||
void (*drawScreenshot)(struct mGUIRunner*, const mColor* pixels, unsigned width, unsigned height, bool faded);
|
||||
void (*paused)(struct mGUIRunner*);
|
||||
void (*unpaused)(struct mGUIRunner*);
|
||||
void (*incrementScreenMode)(struct mGUIRunner*);
|
||||
|
|
|
@ -61,7 +61,7 @@ static void _mVideoProxyBackendClear(struct VideoBackend* v) {
|
|||
mVideoProxyBackendSubmit(proxy, &cmd, NULL);
|
||||
}
|
||||
|
||||
static void _mVideoProxyBackendContextResized(struct VideoBackend* v, unsigned w, unsigned h) {
|
||||
static void _mVideoProxyBackendContextResized(struct VideoBackend* v, unsigned w, unsigned h, unsigned maxW, unsigned maxH) {
|
||||
struct mVideoProxyBackend* proxy = (struct mVideoProxyBackend*) v;
|
||||
struct mVideoBackendCommand cmd = {
|
||||
.cmd = mVB_CMD_CONTEXT_RESIZED,
|
||||
|
@ -69,6 +69,8 @@ static void _mVideoProxyBackendContextResized(struct VideoBackend* v, unsigned w
|
|||
.u = {
|
||||
.width = w,
|
||||
.height = h,
|
||||
.maxW = maxW,
|
||||
.maxH = maxH,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -139,8 +141,8 @@ void mVideoProxyBackendInit(struct mVideoProxyBackend* proxy, struct VideoBacken
|
|||
proxy->d.drawFrame = _mVideoProxyBackendDrawFrame;
|
||||
proxy->backend = backend;
|
||||
|
||||
RingFIFOInit(&proxy->in, 0x400);
|
||||
RingFIFOInit(&proxy->out, 0x400);
|
||||
RingFIFOInit(&proxy->in, sizeof(union mVideoBackendCommandData) * 0x80);
|
||||
RingFIFOInit(&proxy->out, sizeof(union mVideoBackendCommandData) * 0x80);
|
||||
MutexInit(&proxy->inLock);
|
||||
MutexInit(&proxy->outLock);
|
||||
ConditionInit(&proxy->inWait);
|
||||
|
@ -209,7 +211,7 @@ bool mVideoProxyBackendRun(struct mVideoProxyBackend* proxy, bool block) {
|
|||
proxy->backend->clear(proxy->backend);
|
||||
break;
|
||||
case mVB_CMD_CONTEXT_RESIZED:
|
||||
proxy->backend->contextResized(proxy->backend, cmd.data.u.width, cmd.data.u.height);
|
||||
proxy->backend->contextResized(proxy->backend, cmd.data.u.width, cmd.data.u.height, cmd.data.u.maxW, cmd.data.u.maxH);
|
||||
break;
|
||||
case mVB_CMD_SET_IMAGE_SIZE:
|
||||
proxy->backend->setImageSize(proxy->backend, cmd.layer, cmd.data.s.width, cmd.data.s.height);
|
||||
|
@ -229,7 +231,7 @@ bool mVideoProxyBackendRun(struct mVideoProxyBackend* proxy, bool block) {
|
|||
}
|
||||
ok = true;
|
||||
}
|
||||
} while (block);
|
||||
} while (block && !ok);
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,9 @@ struct NoIntroDB* NoIntroDBLoad(const char* path) {
|
|||
"flags INTEGER DEFAULT 0,"
|
||||
"gid INTEGER NOT NULL REFERENCES games(gid) ON DELETE CASCADE"
|
||||
");\n"
|
||||
"CREATE INDEX IF NOT EXISTS crc32 ON roms (crc32);";
|
||||
"CREATE INDEX IF NOT EXISTS crc32 ON roms (crc32);\n"
|
||||
"CREATE INDEX IF NOT EXISTS md5 ON roms (md5);\n"
|
||||
"CREATE INDEX IF NOT EXISTS sha1 ON roms (sha1);\n";
|
||||
if (sqlite3_exec(db->db, createTables, NULL, NULL, NULL)) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -70,6 +72,7 @@ bool NoIntroDBLoadClrMamePro(struct NoIntroDB* db, struct VFile* vf) {
|
|||
|
||||
sqlite3_stmt* gamedbTable = NULL;
|
||||
sqlite3_stmt* gamedbDrop = NULL;
|
||||
sqlite3_stmt* gamedbSelect = NULL;
|
||||
sqlite3_stmt* gameTable = NULL;
|
||||
sqlite3_stmt* romTable = NULL;
|
||||
char* fieldName = NULL;
|
||||
|
@ -89,6 +92,11 @@ bool NoIntroDBLoadClrMamePro(struct NoIntroDB* db, struct VFile* vf) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static const char selectGamedb[] = "SELECT * FROM gamedb WHERE name = ? AND version >= ?;";
|
||||
if (sqlite3_prepare_v2(db->db, selectGamedb, -1, &gamedbSelect, NULL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char insertGame[] = "INSERT INTO games (dbid, name) VALUES (?, ?);";
|
||||
if (sqlite3_prepare_v2(db->db, insertGame, -1, &gameTable, NULL)) {
|
||||
return false;
|
||||
|
@ -159,18 +167,24 @@ bool NoIntroDBLoadClrMamePro(struct NoIntroDB* db, struct VFile* vf) {
|
|||
break;
|
||||
case ')':
|
||||
if (currentDb < 0 && dbType && dbVersion) {
|
||||
sqlite3_clear_bindings(gamedbDrop);
|
||||
sqlite3_reset(gamedbDrop);
|
||||
sqlite3_bind_text(gamedbDrop, 1, dbType, -1, SQLITE_TRANSIENT);
|
||||
sqlite3_bind_text(gamedbDrop, 2, dbVersion, -1, SQLITE_TRANSIENT);
|
||||
sqlite3_step(gamedbDrop);
|
||||
sqlite3_clear_bindings(gamedbSelect);
|
||||
sqlite3_reset(gamedbSelect);
|
||||
sqlite3_bind_text(gamedbSelect, 1, dbType, -1, SQLITE_TRANSIENT);
|
||||
sqlite3_bind_text(gamedbSelect, 2, dbVersion, -1, SQLITE_TRANSIENT);
|
||||
if (sqlite3_step(gamedbSelect) != SQLITE_ROW) {
|
||||
sqlite3_clear_bindings(gamedbDrop);
|
||||
sqlite3_reset(gamedbDrop);
|
||||
sqlite3_bind_text(gamedbDrop, 1, dbType, -1, SQLITE_TRANSIENT);
|
||||
sqlite3_bind_text(gamedbDrop, 2, dbVersion, -1, SQLITE_TRANSIENT);
|
||||
sqlite3_step(gamedbDrop);
|
||||
|
||||
sqlite3_clear_bindings(gamedbTable);
|
||||
sqlite3_reset(gamedbTable);
|
||||
sqlite3_bind_text(gamedbTable, 1, dbType, -1, SQLITE_TRANSIENT);
|
||||
sqlite3_bind_text(gamedbTable, 2, dbVersion, -1, SQLITE_TRANSIENT);
|
||||
if (sqlite3_step(gamedbTable) == SQLITE_DONE) {
|
||||
currentDb = sqlite3_last_insert_rowid(db->db);
|
||||
sqlite3_clear_bindings(gamedbTable);
|
||||
sqlite3_reset(gamedbTable);
|
||||
sqlite3_bind_text(gamedbTable, 1, dbType, -1, SQLITE_TRANSIENT);
|
||||
sqlite3_bind_text(gamedbTable, 2, dbVersion, -1, SQLITE_TRANSIENT);
|
||||
if (sqlite3_step(gamedbTable) == SQLITE_DONE) {
|
||||
currentDb = sqlite3_last_insert_rowid(db->db);
|
||||
}
|
||||
}
|
||||
free((void*) dbType);
|
||||
free((void*) dbVersion);
|
||||
|
@ -270,6 +284,7 @@ bool NoIntroDBLoadClrMamePro(struct NoIntroDB* db, struct VFile* vf) {
|
|||
|
||||
sqlite3_finalize(gamedbTable);
|
||||
sqlite3_finalize(gamedbDrop);
|
||||
sqlite3_finalize(gamedbSelect);
|
||||
sqlite3_finalize(gameTable);
|
||||
sqlite3_finalize(romTable);
|
||||
|
||||
|
|
|
@ -87,8 +87,8 @@ struct mVideoLogChannel {
|
|||
enum mVideoLoggerInjectionPoint injectionPoint;
|
||||
uint32_t ignorePackets;
|
||||
|
||||
struct CircleBuffer injectedBuffer;
|
||||
struct CircleBuffer buffer;
|
||||
struct mCircleBuffer injectedBuffer;
|
||||
struct mCircleBuffer buffer;
|
||||
};
|
||||
|
||||
struct mVideoLogContext {
|
||||
|
@ -511,9 +511,13 @@ struct mVideoLogContext* mVideoLogContextCreate(struct mCore* core) {
|
|||
#endif
|
||||
|
||||
if (core) {
|
||||
context->initialStateSize = core->stateSize(core);
|
||||
struct VFile* vf = VFileMemChunk(NULL, core->stateSize(core));
|
||||
mCoreSaveStateNamed(core, vf, 0);
|
||||
context->initialStateSize = vf->size(vf);
|
||||
context->initialState = anonymousMemoryMap(context->initialStateSize);
|
||||
core->saveState(core, context->initialState);
|
||||
vf->seek(vf, 0, SEEK_SET);
|
||||
vf->read(vf, context->initialState, context->initialStateSize);
|
||||
vf->close(vf);
|
||||
core->startVideoLog(core, context);
|
||||
}
|
||||
|
||||
|
@ -662,8 +666,8 @@ bool mVideoLogContextLoad(struct mVideoLogContext* context, struct VFile* vf) {
|
|||
|
||||
size_t i;
|
||||
for (i = 0; i < context->nChannels; ++i) {
|
||||
CircleBufferInit(&context->channels[i].injectedBuffer, BUFFER_BASE_SIZE);
|
||||
CircleBufferInit(&context->channels[i].buffer, BUFFER_BASE_SIZE);
|
||||
mCircleBufferInit(&context->channels[i].injectedBuffer, BUFFER_BASE_SIZE);
|
||||
mCircleBufferInit(&context->channels[i].buffer, BUFFER_BASE_SIZE);
|
||||
context->channels[i].bufferRemaining = 0;
|
||||
context->channels[i].currentPointer = pointer;
|
||||
context->channels[i].p = context;
|
||||
|
@ -676,8 +680,8 @@ bool mVideoLogContextLoad(struct mVideoLogContext* context, struct VFile* vf) {
|
|||
|
||||
#ifdef USE_ZLIB
|
||||
static void _flushBufferCompressed(struct mVideoLogContext* context) {
|
||||
struct CircleBuffer* buffer = &context->channels[context->activeChannel].buffer;
|
||||
if (!CircleBufferSize(buffer)) {
|
||||
struct mCircleBuffer* buffer = &context->channels[context->activeChannel].buffer;
|
||||
if (!mCircleBufferSize(buffer)) {
|
||||
return;
|
||||
}
|
||||
struct VFile* vfm = VFileMemChunk(NULL, 0);
|
||||
|
@ -707,20 +711,20 @@ static void _flushBuffer(struct mVideoLogContext* context) {
|
|||
}
|
||||
#endif
|
||||
|
||||
struct CircleBuffer* buffer = &context->channels[context->activeChannel].buffer;
|
||||
if (!CircleBufferSize(buffer)) {
|
||||
struct mCircleBuffer* buffer = &context->channels[context->activeChannel].buffer;
|
||||
if (!mCircleBufferSize(buffer)) {
|
||||
return;
|
||||
}
|
||||
struct mVLBlockHeader header = { 0 };
|
||||
STORE_32LE(mVL_BLOCK_DATA, 0, &header.blockType);
|
||||
STORE_32LE(CircleBufferSize(buffer), 0, &header.length);
|
||||
STORE_32LE(mCircleBufferSize(buffer), 0, &header.length);
|
||||
STORE_32LE(context->activeChannel, 0, &header.channelId);
|
||||
|
||||
context->backing->write(context->backing, &header, sizeof(header));
|
||||
|
||||
uint8_t writeBuffer[0x800];
|
||||
while (CircleBufferSize(buffer)) {
|
||||
size_t read = CircleBufferRead(buffer, writeBuffer, sizeof(writeBuffer));
|
||||
while (mCircleBufferSize(buffer)) {
|
||||
size_t read = mCircleBufferRead(buffer, writeBuffer, sizeof(writeBuffer));
|
||||
context->backing->write(context->backing, writeBuffer, read);
|
||||
}
|
||||
}
|
||||
|
@ -743,8 +747,8 @@ void mVideoLogContextDestroy(struct mCore* core, struct mVideoLogContext* contex
|
|||
|
||||
size_t i;
|
||||
for (i = 0; i < context->nChannels; ++i) {
|
||||
CircleBufferDeinit(&context->channels[i].injectedBuffer);
|
||||
CircleBufferDeinit(&context->channels[i].buffer);
|
||||
mCircleBufferDeinit(&context->channels[i].injectedBuffer);
|
||||
mCircleBufferDeinit(&context->channels[i].buffer);
|
||||
#ifdef USE_ZLIB
|
||||
if (context->channels[i].inflating) {
|
||||
inflateEnd(&context->channels[i].inflateStream);
|
||||
|
@ -763,23 +767,23 @@ void mVideoLogContextDestroy(struct mCore* core, struct mVideoLogContext* contex
|
|||
void mVideoLogContextRewind(struct mVideoLogContext* context, struct mCore* core) {
|
||||
_readHeader(context);
|
||||
if (core) {
|
||||
size_t size = core->stateSize(core);
|
||||
if (size <= context->initialStateSize) {
|
||||
core->loadState(core, context->initialState);
|
||||
struct VFile* vf;
|
||||
if (context->initialStateSize < core->stateSize(core)) {
|
||||
vf = VFileMemChunk(NULL, core->stateSize(core));
|
||||
vf->write(vf, context->initialState, context->initialStateSize);
|
||||
} else {
|
||||
void* extendedState = anonymousMemoryMap(size);
|
||||
memcpy(extendedState, context->initialState, context->initialStateSize);
|
||||
core->loadState(core, extendedState);
|
||||
mappedMemoryFree(extendedState, size);
|
||||
vf = VFileFromConstMemory(context->initialState, context->initialStateSize);
|
||||
}
|
||||
mCoreLoadStateNamed(core, vf, 0);
|
||||
vf->close(vf);
|
||||
}
|
||||
|
||||
off_t pointer = context->backing->seek(context->backing, 0, SEEK_CUR);
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < context->nChannels; ++i) {
|
||||
CircleBufferClear(&context->channels[i].injectedBuffer);
|
||||
CircleBufferClear(&context->channels[i].buffer);
|
||||
mCircleBufferClear(&context->channels[i].injectedBuffer);
|
||||
mCircleBufferClear(&context->channels[i].buffer);
|
||||
context->channels[i].bufferRemaining = 0;
|
||||
context->channels[i].currentPointer = pointer;
|
||||
#ifdef USE_ZLIB
|
||||
|
@ -805,8 +809,8 @@ int mVideoLoggerAddChannel(struct mVideoLogContext* context) {
|
|||
int chid = context->nChannels;
|
||||
++context->nChannels;
|
||||
context->channels[chid].p = context;
|
||||
CircleBufferInit(&context->channels[chid].injectedBuffer, BUFFER_BASE_SIZE);
|
||||
CircleBufferInit(&context->channels[chid].buffer, BUFFER_BASE_SIZE);
|
||||
mCircleBufferInit(&context->channels[chid].injectedBuffer, BUFFER_BASE_SIZE);
|
||||
mCircleBufferInit(&context->channels[chid].buffer, BUFFER_BASE_SIZE);
|
||||
context->channels[chid].injecting = false;
|
||||
context->channels[chid].injectionPoint = LOGGER_INJECTION_IMMEDIATE;
|
||||
context->channels[chid].ignorePackets = 0;
|
||||
|
@ -898,7 +902,7 @@ static size_t _readBufferCompressed(struct VFile* vf, struct mVideoLogChannel* c
|
|||
}
|
||||
}
|
||||
|
||||
thisWrite = CircleBufferWrite(&channel->buffer, zbuffer, thisWrite - channel->inflateStream.avail_out);
|
||||
thisWrite = mCircleBufferWrite(&channel->buffer, zbuffer, thisWrite - channel->inflateStream.avail_out);
|
||||
length -= thisWrite;
|
||||
read += thisWrite;
|
||||
|
||||
|
@ -921,7 +925,7 @@ static void _readBuffer(struct VFile* vf, struct mVideoLogChannel* channel, size
|
|||
if (thisRead <= 0) {
|
||||
return;
|
||||
}
|
||||
size_t thisWrite = CircleBufferWrite(&channel->buffer, buffer, thisRead);
|
||||
size_t thisWrite = mCircleBufferWrite(&channel->buffer, buffer, thisRead);
|
||||
length -= thisWrite;
|
||||
channel->bufferRemaining -= thisWrite;
|
||||
channel->currentPointer += thisWrite;
|
||||
|
@ -986,16 +990,16 @@ static ssize_t mVideoLoggerReadChannel(struct mVideoLogChannel* channel, void* d
|
|||
if (channelId >= mVL_MAX_CHANNELS) {
|
||||
return 0;
|
||||
}
|
||||
struct CircleBuffer* buffer = &channel->buffer;
|
||||
struct mCircleBuffer* buffer = &channel->buffer;
|
||||
if (channel->injecting) {
|
||||
buffer = &channel->injectedBuffer;
|
||||
}
|
||||
if (CircleBufferSize(buffer) >= length) {
|
||||
return CircleBufferRead(buffer, data, length);
|
||||
if (mCircleBufferSize(buffer) >= length) {
|
||||
return mCircleBufferRead(buffer, data, length);
|
||||
}
|
||||
ssize_t size = 0;
|
||||
if (CircleBufferSize(buffer)) {
|
||||
size = CircleBufferRead(buffer, data, CircleBufferSize(buffer));
|
||||
if (mCircleBufferSize(buffer)) {
|
||||
size = mCircleBufferRead(buffer, data, mCircleBufferSize(buffer));
|
||||
if (size <= 0) {
|
||||
return size;
|
||||
}
|
||||
|
@ -1005,7 +1009,7 @@ static ssize_t mVideoLoggerReadChannel(struct mVideoLogChannel* channel, void* d
|
|||
if (channel->injecting || !_fillBuffer(context, channelId, BUFFER_BASE_SIZE)) {
|
||||
return size;
|
||||
}
|
||||
size += CircleBufferRead(buffer, data, length);
|
||||
size += mCircleBufferRead(buffer, data, length);
|
||||
return size;
|
||||
}
|
||||
|
||||
|
@ -1019,20 +1023,20 @@ static ssize_t mVideoLoggerWriteChannel(struct mVideoLogChannel* channel, const
|
|||
_flushBuffer(context);
|
||||
context->activeChannel = channelId;
|
||||
}
|
||||
struct CircleBuffer* buffer = &channel->buffer;
|
||||
struct mCircleBuffer* buffer = &channel->buffer;
|
||||
if (channel->injecting) {
|
||||
buffer = &channel->injectedBuffer;
|
||||
}
|
||||
if (CircleBufferCapacity(buffer) - CircleBufferSize(buffer) < length) {
|
||||
if (mCircleBufferCapacity(buffer) - mCircleBufferSize(buffer) < length) {
|
||||
_flushBuffer(context);
|
||||
if (CircleBufferCapacity(buffer) < length) {
|
||||
CircleBufferDeinit(buffer);
|
||||
CircleBufferInit(buffer, toPow2(length << 1));
|
||||
if (mCircleBufferCapacity(buffer) < length) {
|
||||
mCircleBufferDeinit(buffer);
|
||||
mCircleBufferInit(buffer, toPow2(length << 1));
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t read = CircleBufferWrite(buffer, data, length);
|
||||
if (CircleBufferCapacity(buffer) == CircleBufferSize(buffer)) {
|
||||
ssize_t read = mCircleBufferWrite(buffer, data, length);
|
||||
if (mCircleBufferCapacity(buffer) == mCircleBufferSize(buffer)) {
|
||||
_flushBuffer(context);
|
||||
}
|
||||
return read;
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include <mgba/internal/gb/audio.h>
|
||||
|
||||
#include <mgba/core/blip_buf.h>
|
||||
#include <mgba/core/interface.h>
|
||||
#include <mgba/core/sync.h>
|
||||
#include <mgba/internal/gb/gb.h>
|
||||
|
@ -15,15 +14,10 @@
|
|||
#include <mgba/internal/gba/audio.h>
|
||||
#endif
|
||||
|
||||
#ifdef __3DS__
|
||||
#define blip_add_delta blip_add_delta_fast
|
||||
#endif
|
||||
|
||||
#define AUDIO_BUFFER_SAMPLES 0x4000
|
||||
#define FRAME_CYCLES (DMG_SM83_FREQUENCY >> 9)
|
||||
|
||||
const uint32_t DMG_SM83_FREQUENCY = 0x400000;
|
||||
static const int CLOCKS_PER_BLIP_FRAME = 0x1000;
|
||||
static const unsigned BLIP_BUFFER_SIZE = 0x4000;
|
||||
static const int SAMPLE_INTERVAL = 32;
|
||||
static const int FILTER = 65368;
|
||||
const int GB_AUDIO_VOLUME_MAX = 0x100;
|
||||
|
@ -57,12 +51,7 @@ static const int _squareChannelDuty[4][8] = {
|
|||
|
||||
void GBAudioInit(struct GBAudio* audio, size_t samples, uint8_t* nr52, enum GBAudioStyle style) {
|
||||
audio->samples = samples;
|
||||
audio->left = blip_new(BLIP_BUFFER_SIZE);
|
||||
audio->right = blip_new(BLIP_BUFFER_SIZE);
|
||||
audio->clockRate = DMG_SM83_FREQUENCY;
|
||||
// Guess too large; we hang producing extra samples if we guess too low
|
||||
blip_set_rates(audio->left, DMG_SM83_FREQUENCY, 96000);
|
||||
blip_set_rates(audio->right, DMG_SM83_FREQUENCY, 96000);
|
||||
mAudioBufferInit(&audio->buffer, AUDIO_BUFFER_SAMPLES, 2);
|
||||
audio->forceDisableCh[0] = false;
|
||||
audio->forceDisableCh[1] = false;
|
||||
audio->forceDisableCh[2] = false;
|
||||
|
@ -86,8 +75,7 @@ void GBAudioInit(struct GBAudio* audio, size_t samples, uint8_t* nr52, enum GBAu
|
|||
}
|
||||
|
||||
void GBAudioDeinit(struct GBAudio* audio) {
|
||||
blip_delete(audio->left);
|
||||
blip_delete(audio->right);
|
||||
mAudioBufferDeinit(&audio->buffer);
|
||||
}
|
||||
|
||||
void GBAudioReset(struct GBAudio* audio) {
|
||||
|
@ -123,11 +111,9 @@ void GBAudioReset(struct GBAudio* audio) {
|
|||
audio->sampleInterval = SAMPLE_INTERVAL * GB_MAX_SAMPLES;
|
||||
audio->lastSample = 0;
|
||||
audio->sampleIndex = 0;
|
||||
audio->lastLeft = 0;
|
||||
audio->lastRight = 0;
|
||||
audio->capLeft = 0;
|
||||
audio->capRight = 0;
|
||||
audio->clock = 0;
|
||||
mAudioBufferClear(&audio->buffer);
|
||||
audio->playingCh1 = false;
|
||||
audio->playingCh2 = false;
|
||||
audio->playingCh3 = false;
|
||||
|
@ -140,14 +126,8 @@ void GBAudioReset(struct GBAudio* audio) {
|
|||
}
|
||||
|
||||
void GBAudioResizeBuffer(struct GBAudio* audio, size_t samples) {
|
||||
if (samples > BLIP_BUFFER_SIZE / 2) {
|
||||
samples = BLIP_BUFFER_SIZE / 2;
|
||||
}
|
||||
mCoreSyncLockAudio(audio->p->sync);
|
||||
audio->samples = samples;
|
||||
blip_clear(audio->left);
|
||||
blip_clear(audio->right);
|
||||
audio->clock = 0;
|
||||
mCoreSyncConsumeAudio(audio->p->sync);
|
||||
}
|
||||
|
||||
|
@ -622,7 +602,7 @@ void GBAudioRun(struct GBAudio* audio, int32_t timestamp, int channels) {
|
|||
int32_t last = 0;
|
||||
int samples = 0;
|
||||
int positiveSamples = 0;
|
||||
int lsb;
|
||||
int lsb = 0;
|
||||
int coeff;
|
||||
if (audio->ch4.power) {
|
||||
// TODO: Can this be batched too?
|
||||
|
@ -842,38 +822,26 @@ static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) {
|
|||
GBAudioSample(audio, mTimingCurrentTime(audio->timing));
|
||||
|
||||
mCoreSyncLockAudio(audio->p->sync);
|
||||
unsigned produced;
|
||||
int i;
|
||||
for (i = 0; i < GB_MAX_SAMPLES; ++i) {
|
||||
int16_t sampleLeft = audio->currentSamples[i].left;
|
||||
int16_t sampleRight = audio->currentSamples[i].right;
|
||||
if ((size_t) blip_samples_avail(audio->left) < audio->samples) {
|
||||
blip_add_delta(audio->left, audio->clock, sampleLeft - audio->lastLeft);
|
||||
blip_add_delta(audio->right, audio->clock, sampleRight - audio->lastRight);
|
||||
audio->lastLeft = sampleLeft;
|
||||
audio->lastRight = sampleRight;
|
||||
audio->clock += SAMPLE_INTERVAL;
|
||||
if (audio->clock >= CLOCKS_PER_BLIP_FRAME) {
|
||||
blip_end_frame(audio->left, CLOCKS_PER_BLIP_FRAME);
|
||||
blip_end_frame(audio->right, CLOCKS_PER_BLIP_FRAME);
|
||||
audio->clock -= CLOCKS_PER_BLIP_FRAME;
|
||||
mAudioBufferWrite(&audio->buffer, (int16_t*) audio->currentSamples, GB_MAX_SAMPLES);
|
||||
if (audio->p->stream) {
|
||||
if (audio->p->stream->postAudioFrame) {
|
||||
int i;
|
||||
for (i = 0; i < GB_MAX_SAMPLES; ++i) {
|
||||
audio->p->stream->postAudioFrame(audio->p->stream, audio->currentSamples[i].left,audio->currentSamples[i].right);
|
||||
}
|
||||
}
|
||||
if (audio->p->stream && audio->p->stream->postAudioFrame) {
|
||||
audio->p->stream->postAudioFrame(audio->p->stream, sampleLeft, sampleRight);
|
||||
if (audio->p->stream->postAudioBuffer) {
|
||||
unsigned produced = mAudioBufferAvailable(&audio->buffer);
|
||||
bool wait = produced >= audio->samples;
|
||||
if (wait) {
|
||||
audio->p->stream->postAudioBuffer(audio->p->stream, &audio->buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
produced = blip_samples_avail(audio->left);
|
||||
bool wait = produced >= audio->samples;
|
||||
if (!mCoreSyncProduceAudio(audio->p->sync, audio->left, audio->samples)) {
|
||||
if (!mCoreSyncProduceAudio(audio->p->sync, &audio->buffer)) {
|
||||
// Interrupted
|
||||
audio->p->earlyExit = true;
|
||||
}
|
||||
|
||||
if (wait && audio->p->stream && audio->p->stream->postAudioBuffer) {
|
||||
audio->p->stream->postAudioBuffer(audio->p->stream, audio->left, audio->right);
|
||||
}
|
||||
mTimingSchedule(timing, &audio->sampleEvent, audio->sampleInterval * audio->timingFactor - cyclesLate);
|
||||
}
|
||||
|
||||
|
|
|
@ -149,7 +149,7 @@ static bool _GBCoreInit(struct mCore* core) {
|
|||
gbcore->keys = 0;
|
||||
gb->keySource = &gbcore->keys;
|
||||
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
#ifdef ENABLE_VFS
|
||||
mDirectorySetInit(&core->dirs);
|
||||
#endif
|
||||
|
||||
|
@ -161,10 +161,10 @@ static void _GBCoreDeinit(struct mCore* core) {
|
|||
GBDestroy(core->board);
|
||||
mappedMemoryFree(core->cpu, sizeof(struct SM83Core));
|
||||
mappedMemoryFree(core->board, sizeof(struct GB));
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
#ifdef ENABLE_VFS
|
||||
mDirectorySetDeinit(&core->dirs);
|
||||
#endif
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
if (core->symbolTable) {
|
||||
mDebuggerSymbolTableDestroy(core->symbolTable);
|
||||
}
|
||||
|
@ -407,7 +407,7 @@ static size_t _GBCoreScreenRegions(const struct mCore* core, const struct mCoreS
|
|||
}
|
||||
}
|
||||
|
||||
static void _GBCoreSetVideoBuffer(struct mCore* core, color_t* buffer, size_t stride) {
|
||||
static void _GBCoreSetVideoBuffer(struct mCore* core, mColor* buffer, size_t stride) {
|
||||
struct GBCore* gbcore = (struct GBCore*) core;
|
||||
gbcore->renderer.outputBuffer = buffer;
|
||||
gbcore->renderer.outputBufferStride = stride;
|
||||
|
@ -428,16 +428,9 @@ static void _GBCorePutPixels(struct mCore* core, const void* buffer, size_t stri
|
|||
gbcore->renderer.d.putPixels(&gbcore->renderer.d, stride, buffer);
|
||||
}
|
||||
|
||||
static struct blip_t* _GBCoreGetAudioChannel(struct mCore* core, int ch) {
|
||||
static struct mAudioBuffer* _GBCoreGetAudioBuffer(struct mCore* core) {
|
||||
struct GB* gb = core->board;
|
||||
switch (ch) {
|
||||
case 0:
|
||||
return gb->audio.left;
|
||||
case 1:
|
||||
return gb->audio.right;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
return &gb->audio.buffer;
|
||||
}
|
||||
|
||||
static void _GBCoreSetAudioBufferSize(struct mCore* core, size_t samples) {
|
||||
|
@ -445,6 +438,11 @@ static void _GBCoreSetAudioBufferSize(struct mCore* core, size_t samples) {
|
|||
GBAudioResizeBuffer(&gb->audio, samples);
|
||||
}
|
||||
|
||||
static unsigned _GBCoreAudioSampleRate(const struct mCore* core) {
|
||||
UNUSED(core);
|
||||
return 131072;
|
||||
}
|
||||
|
||||
static size_t _GBCoreGetAudioBufferSize(struct mCore* core) {
|
||||
struct GB* gb = core->board;
|
||||
return gb->audio.samples;
|
||||
|
@ -599,7 +597,7 @@ static void _GBCoreReset(struct mCore* core) {
|
|||
}
|
||||
}
|
||||
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
#ifdef ENABLE_VFS
|
||||
if (!gb->biosVf && core->opts.useBios) {
|
||||
struct VFile* bios = NULL;
|
||||
bool found = false;
|
||||
|
@ -745,6 +743,18 @@ static bool _GBCoreSaveState(struct mCore* core, void* state) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool _GBCoreLoadExtraState(struct mCore* core, const struct mStateExtdata* extdata) {
|
||||
UNUSED(core);
|
||||
UNUSED(extdata);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _GBCoreSaveExtraState(struct mCore* core, struct mStateExtdata* extdata) {
|
||||
UNUSED(core);
|
||||
UNUSED(extdata);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void _GBCoreSetKeys(struct mCore* core, uint32_t keys) {
|
||||
struct GBCore* gbcore = (struct GBCore*) core;
|
||||
gbcore->keys = keys;
|
||||
|
@ -783,12 +793,8 @@ static int32_t _GBCoreFrequency(const struct mCore* core) {
|
|||
return DMG_SM83_FREQUENCY;
|
||||
}
|
||||
|
||||
static void _GBCoreGetGameTitle(const struct mCore* core, char* title) {
|
||||
GBGetGameTitle(core->board, title);
|
||||
}
|
||||
|
||||
static void _GBCoreGetGameCode(const struct mCore* core, char* title) {
|
||||
GBGetGameCode(core->board, title);
|
||||
static void _GBCoreGetGameInfo(const struct mCore* core, struct mGameInfo* info) {
|
||||
GBGetGameInfo(core->board, info);
|
||||
}
|
||||
|
||||
static void _GBCoreSetPeripheral(struct mCore* core, int type, void* periph) {
|
||||
|
@ -1060,7 +1066,7 @@ static bool _GBCoreWriteRegister(struct mCore* core, const char* name, const voi
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
static bool _GBCoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) {
|
||||
UNUSED(core);
|
||||
switch (type) {
|
||||
|
@ -1109,8 +1115,10 @@ static void _GBCoreDetachDebugger(struct mCore* core) {
|
|||
}
|
||||
|
||||
static void _GBCoreLoadSymbols(struct mCore* core, struct VFile* vf) {
|
||||
core->symbolTable = mDebuggerSymbolTableCreate();
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
if (!core->symbolTable) {
|
||||
core->symbolTable = mDebuggerSymbolTableCreate();
|
||||
}
|
||||
#ifdef ENABLE_VFS
|
||||
if (!vf && core->dirs.base) {
|
||||
vf = mDirectorySetOpenSuffix(&core->dirs, core->dirs.base, ".sym", O_RDONLY);
|
||||
}
|
||||
|
@ -1258,12 +1266,12 @@ static void _GBCoreStartVideoLog(struct mCore* core, struct mVideoLogContext* co
|
|||
gbcore->logContext = context;
|
||||
|
||||
int channelId = mVideoLoggerAddChannel(context);
|
||||
gbcore->proxyRenderer.logger = malloc(sizeof(struct mVideoLogger));
|
||||
mVideoLoggerRendererCreate(gbcore->proxyRenderer.logger, false);
|
||||
mVideoLoggerAttachChannel(gbcore->proxyRenderer.logger, context, channelId);
|
||||
gbcore->proxyRenderer.logger->block = false;
|
||||
struct mVideoLogger* logger = malloc(sizeof(*logger));
|
||||
mVideoLoggerRendererCreate(logger, false);
|
||||
mVideoLoggerAttachChannel(logger, context, channelId);
|
||||
logger->block = false;
|
||||
|
||||
GBVideoProxyRendererCreate(&gbcore->proxyRenderer, &gbcore->renderer.d);
|
||||
GBVideoProxyRendererCreate(&gbcore->proxyRenderer, &gbcore->renderer.d, logger);
|
||||
GBVideoProxyRendererShim(&gb->video, &gbcore->proxyRenderer);
|
||||
}
|
||||
|
||||
|
@ -1302,7 +1310,8 @@ struct mCore* GBCoreCreate(void) {
|
|||
core->setVideoGLTex = _GBCoreSetVideoGLTex;
|
||||
core->getPixels = _GBCoreGetPixels;
|
||||
core->putPixels = _GBCorePutPixels;
|
||||
core->getAudioChannel = _GBCoreGetAudioChannel;
|
||||
core->audioSampleRate = _GBCoreAudioSampleRate;
|
||||
core->getAudioBuffer = _GBCoreGetAudioBuffer;
|
||||
core->setAudioBufferSize = _GBCoreSetAudioBufferSize;
|
||||
core->getAudioBufferSize = _GBCoreGetAudioBufferSize;
|
||||
core->setAVStream = _GBCoreSetAVStream;
|
||||
|
@ -1324,6 +1333,8 @@ struct mCore* GBCoreCreate(void) {
|
|||
core->stateSize = _GBCoreStateSize;
|
||||
core->loadState = _GBCoreLoadState;
|
||||
core->saveState = _GBCoreSaveState;
|
||||
core->loadExtraState = _GBCoreLoadExtraState;
|
||||
core->saveExtraState = _GBCoreSaveExtraState;
|
||||
core->setKeys = _GBCoreSetKeys;
|
||||
core->addKeys = _GBCoreAddKeys;
|
||||
core->clearKeys = _GBCoreClearKeys;
|
||||
|
@ -1331,8 +1342,7 @@ struct mCore* GBCoreCreate(void) {
|
|||
core->frameCounter = _GBCoreFrameCounter;
|
||||
core->frameCycles = _GBCoreFrameCycles;
|
||||
core->frequency = _GBCoreFrequency;
|
||||
core->getGameTitle = _GBCoreGetGameTitle;
|
||||
core->getGameCode = _GBCoreGetGameCode;
|
||||
core->getGameInfo = _GBCoreGetGameInfo;
|
||||
core->setPeripheral = _GBCoreSetPeripheral;
|
||||
core->getPeripheral = _GBCoreGetPeripheral;
|
||||
core->busRead8 = _GBCoreBusRead8;
|
||||
|
@ -1352,7 +1362,7 @@ struct mCore* GBCoreCreate(void) {
|
|||
core->listRegisters = _GBCoreListRegisters;
|
||||
core->readRegister = _GBCoreReadRegister;
|
||||
core->writeRegister = _GBCoreWriteRegister;
|
||||
#ifdef USE_DEBUGGERS
|
||||
#ifdef ENABLE_DEBUGGERS
|
||||
core->supportsDebuggerType = _GBCoreSupportsDebuggerType;
|
||||
core->debuggerPlatform = _GBCoreDebuggerPlatform;
|
||||
core->cliDebuggerSystem = _GBCoreCliDebuggerSystem;
|
||||
|
@ -1395,9 +1405,9 @@ static bool _GBVLPInit(struct mCore* core) {
|
|||
if (!_GBCoreInit(core)) {
|
||||
return false;
|
||||
}
|
||||
gbcore->proxyRenderer.logger = malloc(sizeof(struct mVideoLogger));
|
||||
mVideoLoggerRendererCreate(gbcore->proxyRenderer.logger, true);
|
||||
GBVideoProxyRendererCreate(&gbcore->proxyRenderer, NULL);
|
||||
struct mVideoLogger* logger = malloc(sizeof(*logger));
|
||||
mVideoLoggerRendererCreate(logger, true);
|
||||
GBVideoProxyRendererCreate(&gbcore->proxyRenderer, NULL, logger);
|
||||
memset(&gbcore->logCallbacks, 0, sizeof(gbcore->logCallbacks));
|
||||
gbcore->logCallbacks.videoFrameStarted = _GBVLPStartFrameCallback;
|
||||
gbcore->logCallbacks.context = core;
|
||||
|
|
|
@ -16,14 +16,14 @@ static void _GBCLIDebuggerInit(struct CLIDebuggerSystem*);
|
|||
static bool _GBCLIDebuggerCustom(struct CLIDebuggerSystem*);
|
||||
|
||||
static void _frame(struct CLIDebugger*, struct CLIDebugVector*);
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
#ifdef ENABLE_VFS
|
||||
static void _load(struct CLIDebugger*, struct CLIDebugVector*);
|
||||
static void _save(struct CLIDebugger*, struct CLIDebugVector*);
|
||||
#endif
|
||||
|
||||
struct CLIDebuggerCommandSummary _GBCLIDebuggerCommands[] = {
|
||||
{ "frame", _frame, "", "Frame advance" },
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
#ifdef ENABLE_VFS
|
||||
{ "load", _load, "*", "Load a savestate" },
|
||||
{ "save", _save, "*", "Save a savestate" },
|
||||
#endif
|
||||
|
@ -78,7 +78,7 @@ static void _frame(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
|
|||
gbDebugger->inVblank = GBRegisterSTATGetMode(((struct GB*) gbDebugger->core->board)->memory.io[GB_REG_STAT]) == 1;
|
||||
}
|
||||
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
#ifdef ENABLE_VFS
|
||||
static void _load(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
|
||||
struct CLIDebuggerBackend* be = debugger->backend;
|
||||
if (!dv || dv->type != CLIDV_INT_TYPE) {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue